def collect_winnings_check(tx, txs, out, DB): if not transactions.signature_check(tx): out[0]+='signature check' return False if not E_check(tx, 'address', [str, unicode]): out[0]+='no address error' return False acc=tools.db_get(tx['address'], DB) if not E_check(tx, 'PM_id', [str, unicode]): out[0]+='no PM_id error' return False if tx['PM_id'] not in acc['shares']: out[0]+='you do not own any shares for this PM' return False if not tx['shares']==acc['shares'][tx['PM_id']]: out[0]+='that is not how many shares you have 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 for dec in pm['decisions']: decision = tools.db_get(dec, DB) if decision['state'] not in ['yes', 'no']: out[0]+='we have not yet reached consensus on the outcome of this market error' return False return True
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 delete_block(DB): """ Removes the most recent block from the blockchain. """ length=tools.local_get('length') if length < 0: return try: ts=tools.local_get('targets') ts.pop(str(length)) tools.local_put('targets', ts) except: pass try: ts=tools.local_get('times') ts.pop(str(length)) tools.local_put('times', ts) except: pass block = tools.db_get(length, DB) orphans = tools.local_get('txs') orphans=filter(lambda t: t['type']!='mint', orphans) tools.local_put('txs', []) for tx in block['txs']: orphans.append(tx) tools.local_put('add_block', False) transactions.update[tx['type']](tx, DB, False) tools.db_delete(length, DB) length-=1 tools.local_put('length', length) if length>=0: block=tools.db_get(length) tools.local_put('height', filter(lambda t: t['type']=='mint', block['txs'])[0]['height']) else: tools.local_put('height', -1) for orphan in orphans: add_tx(orphan, DB)
def create_reward_tx(): tx={} tx['type']='reward' length=tools.local_get('length') tx['on_block']=length-custom.long_time+random.randint(-custom.medium_time/2, custom.medium_time/2) if tx['on_block']<=0: time.sleep(1) return {'error':'no rewards to collect'} address=tools.local_get('address') acc=tools.db_get(address) if str(tx['on_block']) in acc['entropy']: return {'error':'already collected that reward'} zeroths=tools.local_get('txs') zeroths=filter(lambda t: tools.addr(t)==address, zeroths) zeroths=filter(lambda t: t['type']=='reward', zeroths) if len(zeroths)>0: {'error':'already made the tx to collect that reward'} txs=tools.db_get(tx['on_block'])['txs'] txs=filter(lambda t: t['type']=='sign', txs) #tools.log('on block: ' +str(tx['on_block'])) #tools.log('txs: ' +str(txs)) sign_tx=filter(lambda t: tools.addr(t)==address, txs)[0] #tools.log('txs: ' +str(sign_tx)) relative_reward=tools.relative_reward(tx['on_block'], address) tx['amount']=relative_reward+sign_tx['amount'] tx['reveal']=tools.local_get('secrets')[str(tx['on_block'])] tx['jackpots']=len(sign_tx['jackpots']) return tx
def main_once(DB): DB['heart_queue'].put('peers check') pr=tools.db_get('peers_ranked') pr=sorted(pr, key=lambda r: r[2]) pr.reverse() time.sleep(0.05) if DB['suggested_blocks'].empty() and tools.db_get('length')>3: time.sleep(10) i=0 while not DB['suggested_blocks'].empty(): i+=1 time.sleep(0.1) if i%100==0: DB['heart_queue'].put('peers check') DB['heart_queue'].put('peers check') i=exponential_random(3.0/4)%len(pr) t1=time.time() r=peer_check(i, pr, DB) t2=time.time() pr[i][1]*=0.8 if r==0: pr[i][1]+=0.2*(t2-t1) else: pr[i][1]+=0.2*30 tools.db_put('peers_ranked', pr) DB['heart_queue'].put('peers check')
def peer_check(i, peers, DB): peer=peers[i][0] block_count = cmd(peer, {'type': 'blockCount'}) if not isinstance(block_count, dict): return if 'error' in block_count.keys(): return peers[i][2]=block_count['diffLength'] peers[i][3]=block_count['length'] length = tools.db_get('length') diffLength= tools.db_get('diffLength') size = max(len(diffLength), len(block_count['diffLength'])) us = tools.buffer_(diffLength, size) them = tools.buffer_(block_count['diffLength'], size) if them < us: give_block(peer, DB, block_count['length']) elif us == them: try: ask_for_txs(peer, DB) except Exception as exc: tools.log('ask for tx error') tools.log(exc) else: download_blocks(peer, DB, block_count, length) F=False my_peers=tools.db_get('peers_ranked') their_peers=cmd(peer, {'type':'peers'}) if type(my_peers)==list: for p in their_peers: if p not in my_peers: F=True my_peers.append(p) if F: tools.db_put('peers_ranked', my_peers)
def blockCount(dic, DB): length = tools.db_get('length') if length >= 0: return {'length': length, 'diffLength': tools.db_get('diffLength')} else: return {'length': -1, 'diffLength': '0'}
def peer_check(peer, DB): peers=tools.db_get('peers') if peers[peer]['length']==0 or random.random()<0.1: ask_for_count(peer) out=trade_peers(peer) if type(out)==dict and 'error' in out: return 1 peers=tools.db_get('peers') length = tools.db_get('length') diffLength= tools.db_get('diffLength') size = max(len(diffLength), len(peers[peer]['diffLength'])) us = tools.buffer_(diffLength, size) them = tools.buffer_(peers[peer]['diffLength'], size) if them < us: return give_block(peer, DB, peers[peer]['length']) elif us == them: try: ask_for_count(peer) trade_peers(peer) return ask_for_txs(peer, DB) except Exception as exc: tools.log('ask for tx error') tools.log(exc) else: return download_blocks(peer, DB, peers[peer]['length'], length)
def delete_block(DB): """ Removes the most recent block from the blockchain. """ if DB['length'] < 0: return try: targets.pop(str(DB['length'])) except: pass try: times.pop(str(DB['length'])) except: pass block = tools.db_get(DB['length'], DB) orphans = copy.deepcopy(DB['txs']) DB['txs'] = [] for tx in block['txs']: orphans.append(tx) DB['add_block']=False transactions.update[tx['type']](tx, DB) tools.db_delete(DB['length'], DB) DB['length'] -= 1 if DB['length'] == -1: DB['diffLength'] = '0' else: block = tools.db_get(DB['length'], DB) DB['diffLength'] = block['diffLength'] for orphan in sorted(orphans, key=lambda x: x['count']): add_tx(orphan, DB)
def my_balance(args, address='default'): if address == 'default': address = tools.db_get('address') try: return tools.db_get(address)['amount'] - tools.cost_0(tools.db_get('txs'), address) except: return 0
def delete_block(DB): """ Removes the most recent block from the blockchain. """ length = tools.db_get('length') if length < 0: return try: ts = tools.db_get('times') ts.pop(str(length)) tools.db_put('times', ts) except: pass block = tools.db_get(length, DB) orphans = tools.db_get('txs') tools.db_put('txs', []) for tx in block['txs']: orphans.append(tx) tools.db_put('add_block', False) transactions.update[tx['type']](tx, DB, False) tools.db_delete(length, DB) length -= 1 tools.db_put('length', length) if length == -1: tools.db_put('diffLength', '0') else: block = tools.db_get(length, DB) for orphan in sorted(orphans, key=lambda x: x['count']): add_tx(orphan, DB)
def recent_blockthings(key, size, length=0): # get the storage from DB which was originally recorded as "key" storage = tools.db_get(key) def get_val(length): leng = str(length) if not leng in storage: block = tools.db_get(leng) if block == database.default_entry(): if leng == tools.db_get('length'): tools.db_put('length', int(leng) - 1) block = tools.db_get(leng) # try: storage[leng] = tools.db_get(leng)[key[:-1]] tools.db_put(key, storage) return storage[leng] # pop from storage till you reach the end def clean_up(storage, end): if end < 0: return if not str(end) in storage: return else: storage.pop(str(end)) return clean_up(storage, end - 1) # DB returns the blockchain length from 'length' key if length == 0: length = tools.db_get('length') start = max((length - size), 0) clean_up(storage, length - max(custom.mmm, custom.history_length) - 100) return map(get_val, range(start, length))
def recent_blockthings(key, size, length=0): storage = tools.db_get(key) def get_val(length): leng = str(length) if not leng in storage: block=tools.db_get(leng) if block==tools.default_entry: if leng==tools.db_get('length'): tools.db_put('length', int(leng)-1) block=tools.db_get(leng) else: error() #try: storage[leng] = tools.db_get(leng)[key[:-1]] tools.db_put(key, storage) return storage[leng] def clean_up(storage, end): if end<0: return if not str(end) in storage: return else: storage.pop(str(end)) return clean_up(storage, end-1) if length == 0: length = tools.db_get('length') start = max((length-size), 0) clean_up(storage, length-max(custom.mmm, custom.history_length)-100) return map(get_val, range(start, length))
def slasher_jury_vote_check(tx, txs, out, DB): address=addr(tx) if tools.reveal_time_p(DB): out[0]+='reveal time check slasher' return False if not transactions.signature_check(tx): out[0]+='signature check' return False if not E_check(tx, 'amount', int): out[0]+='how many votecoins are we confiscating?' return False if not E_check(tx, 'reveal', dict): out[0]+='no reveal' return False if not reveal_jury_vote_check(tx['reveal'], txs, DB): out[0]+='this is an invalid reveal tx' return False victim=tools.db_get(addr(tx['reveal']), DB) decision=tx['reveal']['decision_id'] decision=tools.db_get(decision, DB) if victim['votecoin'][tx['reveal']['vote_id']]!=tx['amount']: out[0]+='that is not how many votecoins they have' return False return True
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 info(DB, args): if len(args)<1: return ('not enough inputs') if args[0]=='my_address': address=tools.db_get('address') else: address=args[0] return(tools.db_get(address, DB))
def info(args): if len(args) < 1: return 'not enough inputs' if args[0] == 'my_address': address = tools.db_get('address') else: address = args[0] return tools.db_get(address)
def give_block(peer, DB, block_count_peer): blocks=[] b=[max(block_count_peer-5, 0), min(tools.db_get('length'), block_count_peer+custom.download_many)] for i in range(b[0], b[1]+1): blocks.append(tools.db_get(i, DB)) cmd(peer, {'type': 'pushblock', 'blocks': blocks}) return 0
def sign_verify(tx, txs, out, DB):#check the validity of a transaction of type sign. a=tools.addr(tx) B=tx['B']#verify a proof that addr(tx) actually owned that much money long*2-medium ago. M=custom.all_money address=tools.addr(tx) block=tools.db_get(tx['on_block']) num=max(0,tx['on_block']-(custom.long_time*2-custom.medium_time)) election_block=tools.db_get(num) if not signature_check(tx): out[0]+='signature check' return False if 'root_hash' not in election_block: out[0]+='no root hash' return False v=tools.db_verify(election_block['root_hash'], address, tx['proof']) if v==False: tools.log('your address did not exist that long ago.') return False if v['amount']!=tx['B']: tools.log('that is not how much money you had that long ago') return False if 'secret_hash' not in tx: tools.log('need the hash of a secret') return False for t in txs: if tools.addr(t)==address and t['type']=='sign': #tools.log('can only have one sign tx per block') return False if len(tx['jackpots'])<1: tools.log('insufficient jackpots') return False if not signature_check(tx): out[0]+='signature check' return False length=tools.local_get('length') if int(tx['on_block'])!=int(length+1): out[0]+='this tx is for the wrong block. have '+str(length+1) +' need: ' +str(tx['on_block']) return False if tx['on_block']>0: if not tx['prev']==tools.db_get(length)['block_hash']: tools.log('must give hash of previous block') return False ran=tools.det_random(tx['on_block']) for j in tx['jackpots']: if type(j)!=int or j not in range(200): tools.log('bad jackpot') return False if len(filter(lambda x: x==j, tx['jackpots']))!=1: tools.log('no repeated jackpots') return False if not tools.winner(B, M, ran, address, j): tools.log('that jackpot is not valid: '+str(j)) return False if tx['amount']<custom.minimum_deposit: tools.log('you have to deposit more than that') return False return True
def weights(vote_id, DB, jury='default'): out=[] if jury=='default': jury=tools.db_get(jury, DB) if 'members' not in jury: return 'error' for member in jury['members']: acc=tools.db_get(member, DB) out.append([acc['votecoin'][vote_id]]) return out
def collect_winnings(DB, args): if len(args)<1: return ('not enough arguments') tools.log('collect_winnings 1') add=tools.db_get('address') acc=tools.db_get(add, DB) tx={'type':'collect_winnings', 'PM_id':args[0], 'address':add} tx['shares']=acc['shares'][tx['PM_id']] tools.log('collect_winnings 2') return easy_add_transaction(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 sign_verify(tx, txs, out, DB): # check the validity of a transaction of type sign. a = tools.addr(tx) acc = tools.db_get(a) if a["amount"] < tx["B"]: tools.log("you do not have that much money") B = tx["B"] M = custom.all_money address = tools.addr(tx) block = tools.db_get(tx["on_block"]) num = max(0, tx["on_block"] - (custom.long_time * 2 - custom.medium_time)) election_block = tools.db_get(num) if "root_hash" not in election_block: out[0] += "no root hash" return False v = tools.db_verify(election_block["root_hash"], address, tx["proof"]) if v == False: tools.log("your address did not exist that long ago.") return False if v["amount"] != tx["B"]: tools.log("that is not how much money you had that long ago") return False if "secret_hash" not in tx: tools.log("need the hash of a secret") return False for t in txs: if tools.addr(t) == address and t["type"] == "sign": # tools.log('can only have one sign tx per block') return False if len(tx["jackpots"]) < 1: tools.log("insufficient jackpots") return False length = tools.local_get("length") if int(tx["on_block"]) != int(length + 1): out[0] += "this tx is for the wrong block. have " + str(length + 1) + " need: " + str(tx["on_block"]) return False if tx["on_block"] > 0: if not tx["prev"] == tools.db_get(length)["block_hash"]: tools.log("must give hash of previous block") return False ran = tools.det_random(tx["on_block"]) for j in tx["jackpots"]: if type(j) != int or j not in range(200): tools.log("bad jackpot") return False if len(filter(lambda x: x == j, tx["jackpots"])) != 1: tools.log("no repeated jackpots") return False if not tools.winner(B, M, ran, address, j): tools.log("that jackpot is not valid: " + str(j)) return False if tx["amount"] < custom.minimum_deposit: tools.log("you have to deposit more than that") return False return True
def total_received_value(args): total = 0 address = tools.db_get('address') length = tools.db_get('length') for i in range(length + 1): block = tools.db_get(i) txs = block[u'txs'] for tx in txs: if tx[u'type'] == 'spend' and address == tx[u'to']: total += tx[u'amount'] return total
def total_spend_value(args): total = 0 pubkey = tools.db_get('pubkey') length = tools.db_get('length') for i in range(length + 1): block = tools.db_get(i) txs = block[u'txs'] for tx in txs: if tx[u'type'] == 'spend' and pubkey in tx[u'pubkeys']: total += tx[u'amount'] + custom.fee return total
def total_mine_value(args): total = 0 pubkey = tools.db_get('pubkey') length = tools.db_get('length') for i in range(length + 1): block = tools.db_get(i) txs = block[u'txs'] for tx in txs: if tx[u'type'] == 'mint' and pubkey in tx[u'pubkeys']: total += custom.block_reward return total
def target(length=0): """ Returns the target difficulty at a paticular blocklength. """ db_length=tools.db_get('length') if length == 0: length = db_length if length < 4: return '0' * 4 + 'f' * 60 # Use same difficulty for first few blocks. trgs=tools.db_get('targets') if length <= db_length and str(length) in trgs: return trgs[str(length)] def targetTimesFloat(target, number): a = int(str(target), 16) b = int(a * number)#this should be rational multiplication followed by integer estimation return tools.buffer_(str(hex(b))[2: -1], 64) def multiply_things(things): out=1 while len(things)>0: out=out*things[0] things=things[1:] return out def weights(length):#uses float #returns from small to big out=memoized_weights[:length] out.reverse() return out def estimate_target(): """ We are actually interested in the average number of hashes required to mine a block. number of hashes required is inversely proportional to target. So we average over inverse-targets, and inverse the final answer. """ def sumTargets(l): if len(l) < 1: return 0 while len(l) > 1: l = [blockchain.hexSum(l[0], l[1])] + l[2:] return l[0] targets = blockchain.recent_blockthings('targets', custom.history_length) w = weights(len(targets))#should be rat instead of float tw = sum(w) targets = map(blockchain.hexInvert, targets) def weighted_multiply(i): return targetTimesFloat(targets[i], w[i]/tw)#this should use rat division instead weighted_targets = [weighted_multiply(i) for i in range(len(targets))] return blockchain.hexInvert(sumTargets(weighted_targets)) def estimate_time(): times = blockchain.recent_blockthings('times', custom.history_length)#should be deterministally turned into rats times=map(cdecimal.Decimal, times) blocklengths = [times[i] - times[i - 1] for i in range(1, len(times))] w = weights(len(blocklengths)) # Geometric weighting tw = sum(w) return sum([w[i] * blocklengths[i] / tw for i in range(len(blocklengths))]) retarget = estimate_time() / custom.blocktime return targetTimesFloat(estimate_target(), retarget)
def get_val(length): leng = str(length) if not leng in storage: block = tools.db_get(leng) if block == database.default_entry(): if leng == tools.db_get('length'): tools.db_put('length', int(leng) - 1) block = tools.db_get(leng) # try: storage[leng] = tools.db_get(leng)[key[:-1]] tools.db_put(key, storage) return storage[leng]
def txs_history(args): txs_hist = [] pubkey = tools.db_get('pubkey') address = tools.db_get('address') length = tools.db_get('length') for i in range(length + 1): block = tools.db_get(i) txs = block[u'txs'] for tx in txs: if tx[u'type'] == 'spend' and (pubkey in tx[u'pubkeys'] or address == tx[u'to']): txs_hist.append(tx) print len(txs_hist) return txs_hist
def peer_check(i, peers): peer = peers[i][0] # request their blockcount block_count = network_cmd(peer, {'type': 'blockCount'}) if not isinstance(block_count, dict): return if 'error' in block_count.keys(): return peers[i][2] = block_count['length'] # tools.db_put('peers_ranked', peers) us_length = tools.db_get('length') their_length = block_count['length'] # simple, if we are ahead, we give them our blocks if their_length < us_length: give_block(peer, custom.queues, their_length) elif their_length == us_length: # If we are at the same amount of block, we ask for new transaction they know try: ask_for_txs(peer, custom.queues) except Exception as exc: tools.log('ask for tx error') tools.log(exc) # request blocks # we are back else: download_blocks(peer, custom.queues, block_count, us_length) F = False # Send and receive peers my_peers = tools.db_get('peers_ranked') their_peers = network_cmd(peer, {'type': 'peers'}) if type(their_peers) == list: for p in their_peers: if p not in my_peers: F = True my_peers.append(p) for p in my_peers: if p not in their_peers: network_cmd(peer, {'type': 'recieve_peer', 'peer': p}) if F: my_peers = np.array(my_peers) tools.update_peers(my_peers[:, 0]) return 0
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 f(blocks_queue, txs_queue): def bb(): return blocks_queue.empty() def tb(): return txs_queue.empty() def ff(queue, g, b, s): while not b(): time.sleep(0.0001) try: g(queue.get(False)) except Exception as exc: tools.log('suggestions ' + s) tools.log(exc) while True: time.sleep(0.1) if tools.db_get('stop'): tools.dump_out(blocks_queue) tools.dump_out(txs_queue) return while not bb() or not tb(): ff(blocks_queue, add_block, bb, 'block') ff(txs_queue, add_tx, tb, 'tx')
def f(blocks_queue, txs_queue): def bb(): return blocks_queue.empty() def tb(): return txs_queue.empty() def ff(queue, g, b, s): while not b(): time.sleep(0.0001) try: g(queue.get(False)) except Exception as exc: tools.log('suggestions ' + s) tools.log(exc) while True: try: time.sleep(0.1) l=tools.local_get('length')+1 v=range(l-10, l) v=filter(lambda x: x>0, v) v=map(lambda x: tools.db_get(x), v) v=map(lambda x: x['block_hash'], v) if tools.local_get('stop'): tools.dump_out(blocks_queue) tools.dump_out(txs_queue) return while not bb() or not tb(): ff(blocks_queue, lambda x: add_block(x, v), bb, 'block') ff(txs_queue, add_tx, tb, 'tx') except Exception as exc: tools.log(exc)
def main(pubkey, DB): num_cores = multiprocessing.cpu_count() solution_queue = multiprocessing.Queue() workers = [new_worker(solution_queue) for _ in range(num_cores)] try: while True: DB['heart_queue'].put('miner') if tools.db_get('stop'): #restart_workers(workers) return elif tools.db_get('mine'): main_once(pubkey, DB, num_cores, solution_queue, workers) else: time.sleep(1) except: tools.log('miner main: ' + str(sys.exc_info()))
def create_jury_check(tx, txs, out, DB): address=addr(tx) if not transactions.signature_check(tx): out[0]+='signature check' return False if not E_check(tx, 'vote_id', [str, unicode]): out[0]+='vote id error' return False if tools.is_number(tx['vote_id']): out[0]+='vote_id can not be a number' return False if len(tx['vote_id'])>1000: return False if tools.db_existence(tx['vote_id'], DB): out[0]+='this vote_id is already being used' return False if not tools.db_existence(address, DB): out[0]+='this address is not used by anyone' return False acc=tools.db_get(address, DB) for t in txs: if 'jury_id' in t: if t['jury_id']==tx['jury_id']: out[0]+='this zeroth confirmation transaction already exists' return False if not txs_tools.fee_check(tx, txs, DB): 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 manage_queues(blocks_queue, txs_queue): def is_blocks_queue_empty(): return blocks_queue.empty() def is_txs_queue_empty(): return txs_queue.empty() def add_from_queue(queue, add_function, is_queue_empty, queue_name): # while the queue is not empty, in other words there are suggested blocks or transactions, call the corresponding add function while not is_queue_empty(): time.sleep(0.0001) try: add_function(queue.get(False)) except Exception as exc: tools.log('suggestions ' + queue_name) tools.log(exc) # start the loop until it gets stopped while True: time.sleep(0.1) if tools.db_get('stop'): # Free the queues tools.dump_out(blocks_queue) tools.dump_out(txs_queue) return while not is_blocks_queue_empty() or not is_txs_queue_empty(): add_from_queue(blocks_queue, add_block, is_blocks_queue_empty, 'block') add_from_queue(txs_queue, add_tx, is_txs_queue_empty, 'tx')
def jury_vote_check(tx, txs, out, DB): if not transactions.signature_check(tx): out[0]+='signature check' return False if not E_check(tx, 'decision_id', [str, unicode]): return False if not E_check(tx, 'vote_id', [str, unicode]): return False if is_number(tx['vote_id']) or is_number(tx['decision_id']): out[0]+='that can not be a number' return False if not E_check(tx, 'old_vote', [str, unicode]): return False if not E_check(tx, 'new_vote', [str, unicode]): return False decision=tools.db_get(tx['decision_id'], DB) if 'state' not in decision: out[0]+='that is not a decision_id' out[0]+='decision: ' +str(decision) out[0]+='tx: ' +str(tx) return False if decision['state']!='proposed': out[0]+='this decision has already been decided' return False if not tools.db_existence(tx['decision_id'], DB): out[0]+='decision error' return False if tools.reveal_time_p(DB): out[0]+='reveal time check' return False if len(tx['new_vote'])<4: out[0]+='secret too short error' return False if not txs_tools.fee_check(tx, txs, DB): return False return True
def SVD_consensus_check(tx, txs, out, DB): if not E_check(tx, 'vote_id', [str, unicode]): return False if not E_check(tx, 'decisions', [list]): return False if not tools.reveal_time_p(DB, 5): out[0]+='this is not the correct time to do SVD' return False if is_number(tx['vote_id']): out[0]+='that can not be a number' return False jury=tools.db_get(tx['vote_id'], DB) if len(tx['decisions'])<5: out[0]+='need at least 5 decisions to compute SVD' return False if not E_check(jury, 'members', [list]): out[0]+='that jury has not been created yet' return False if len(jury['members'])<3: out[0]+='need at least 3 voters in order to compute SVD' return False try: matrix=txs_tools.decision_matrix(jury, tx['decisions'], DB) except: tools.log(sys.exc_info()) tools.log('matrix failure') return False w=txs_tools.weights(tx['vote_id'], DB, jury) k=txs_tools.decisions_keepers(tx['vote_id'], jury, DB) for decision in tx['decisions']: if not decision in k: out[0]+='one of the decisions has insufficient participation*certainty: ' +str(decision) return False if not txs_tools.fee_check(tx, txs, DB): out[0]+='you do not have enough money' return False return True
def sign_transaction(length, address): if length <= 0: return {'secret_hash': 0} txs = tools.db_get(length)['txs'] txs = filter(lambda t: t['type'] == 'sign', txs) txs = filter(lambda t: tools.addr(t) == address, txs) return (txs[0])
def repeat_check(tx, txs): if tx['type']=='sign': return True l=tools.local_get('length') if l<=1: return True if 'recent_hash' not in tx: tools.log('no recent hash: ' +str(tx)) return False h=tx['recent_hash'] r=range(l-10, l) r=filter(lambda l: l>0, r) recent_blocks=map(lambda x:tools.db_get(x), r) recent_hashes=map(lambda x: x['block_hash'], recent_blocks) if h not in recent_hashes: tools.log('have : ' +str(h)) tools.log('need: ' +str(recent_hashes)) tools.log('recent hash error') return False recent_txs=[]#should be memoized? def f(b, recent_txs=recent_txs): recent_txs=recent_txs+b['txs'] map(f, recent_blocks) recent_txs+=txs def f(d): d=copy.deepcopy(d) d.pop('signatures') return tools.det_hash(d) if f(tx) in map(f, recent_txs): tools.log('no repeated tx') return False return True
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 info(DB): if len(DB['args'])<1: return ('not enough inputs') if DB['args'][0]=='my_address': address=DB['address'] else: address=DB['args'][0] return(str(tools.db_get(address, DB)))
def main(peers, DB): # Check on the peers to see if they know about more blocks than we do. #DB['peers_ranked']=[] p = tools.db_get('peers_ranked') if type(p) != list: time.sleep(3) return main(peers, DB) for peer in peers: tools.add_peer(peer, p) tools.db_put('peers_ranked', p) try: while True: if tools.db_get('stop'): return if len(peers) > 0: main_once(DB) except Exception as exc: tools.log(exc)
def mine(DB, args): m = not (tools.db_get('mine')) tools.db_put('mine', m) if m: m = 'on' else: m = 'off' return ('miner is currently: ' + m)
def fee_check(tx, txs, DB): address = addr(tx) truthcoin_cost = cost_0(txs, DB) acc=tools.db_get(address, DB) if int(acc['amount']) < truthcoin_cost: tools.log('insufficient truthcoin') return False return True
def longest_peer(): if not tools.db_existence('peers'): return 1000000 peers = tools.db_get('peers') peers = map(lambda p: peers[p], peers.keys()) peers = filter(lambda x: x['blacklist'] < 500, peers) peers = sorted(peers, key=lambda x: x['diffLength']) return peers[-1]['length']
def pushblock(dic): length = tools.db_get('length') block = tools.db_get(length, custom.queues) if 'peer' in dic: peer = dic['peer'] else: peer = False if 'blocks' in dic: for i in range(20): if tools.fork_check(dic['blocks'], custom.queues, length, block): blockchain.delete_block(custom.queues) length -= 1 for block in dic['blocks']: custom.queues['suggested_blocks'].put([block, peer]) else: custom.queues['suggested_blocks'].put([dic['block'], peer]) return 'success'
def download_blocks(peer, DB, peers_block_count, length): b = [ max(0, length - 10), min(peers_block_count, length + custom.download_many) ] blocks = cmd(peer, {'type': 'rangeRequest', 'range': b}) if type(blocks) != list: return -1 if not isinstance(blocks, list): return [] length = tools.db_get('length') block = tools.db_get(length) for i in range(10): #this part should be re-written so badly if tools.fork_check(blocks, DB, length, block): blockchain.delete_block(DB) length -= 1 for block in blocks: DB['suggested_blocks'].put([block, peer]) return 0
def patty_info(DB, args): if len(args) < 1: return ('not enough inputs') if args[0] == 'my_address': address = tools.local_get('address') else: address = args[0] return (tools.db_get(address, DB))
def prediction_market_check(tx, txs, out, DB): if not transactions.signature_check(tx): out[0]+='signature check' return False address=addr(tx) for l in ['states', 'states_combinatory', 'decisions']: if not E_check(tx, l, list): out[0]+=str(l)+ ' error' return False for dec in tx['decisions']: if not tools.db_existence(dec, DB): out[0]+='decision is not in the database: ' +str(dec) return False if is_number(dec): out[0]+='decision_id can not be a number' return False if is_number(tx['PM_id']): out[0]+='PM_id can not be a number' return False if len(tx['states'])>200: out[0]+='too many states' return False if not E_check(tx, 'B', int): out[0]+='B error' return False for comb in tx['states_combinatory']: if len(comb)!=len(tx['decisions']): out[0]+=str(comb)+' comb error' return False for l in [tx['states_combinatory'], tx['states'], tx['decisions']]: for comb in l: copies=len(filter(lambda comb2: comb==comb2, l)) if copies!=1: out[0]+=str(comb)+' not mutually exclusive' return False if len(tx['states'])!=len(tx['states_combinatory'])+1: out[0]+='wrong number of possible states?' return False if not E_check(tx, 'PM_id', [str, unicode]): out[0]+='PM_id error' return False if len(tx['PM_id'])>1000: out[0]+='PM_id too long' return False if tools.db_existence(tx['PM_id'], DB): #out[0]+='PM: ' +str(tools.db_get(tx['PM_id'], DB)) out[0]+='this PM_id is already being used' return False for t in txs: if 'PM_id' in t: if t['PM_id']==tx['PM_id']: out[0]+='Someone used that PM in this block already' return False acc=tools.db_get(address, DB) if not txs_tools.fee_check(tx, txs, DB): out[0]+='you do not have enough money' 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 main_once(): # put the peers check in heart queue. custom.queues['heart_queue'].put('peers check') # sort by rank in decreasing order peers = tools.db_get('peers_ranked') peers = sorted(peers, key=lambda r: r[2]) peers.reverse() time.sleep(0.05) if custom.queues['suggested_blocks'].empty(): time.sleep(2) i = 0 # wait while suggested blocks are not empty # they are needed to be taken care of while not custom.queues['suggested_blocks'].empty() and not tools.db_get( 'stop'): i += 1 time.sleep(0.1) if i % 100 == 0: custom.queues['heart_queue'].put('peers check') if tools.db_get('stop'): return custom.queues['heart_queue'].put('peers check') peer_id = exponential_random(3.0 / 4) % len(peers) t1 = time.time() r = peer_check(peer_id, peers, custom.queues) t2 = time.time() a_peer = peers[peer_id][0] peers = tools.db_get('peers_ranked') for peer in peers: if peer[0] == a_peer: peers[peer_id][1] *= 0.8 if r == 0: peers[peer_id][1] += 0.2 * (t2 - t1) else: peers[peer_id][1] += 0.2 * 30 tools.db_put('peers_ranked', peers) custom.queues['heart_queue'].put('peers check')
def jury_vote(tx, DB): address=addr(tx) acc=tools.db_get(address, DB) if tx['decision_id'] not in acc['votes']: acc['votes'][tx['decision_id']]='unsure' tools.db_put(address, acc, DB) adjust_int(['count'], address, 1, DB) adjust_int(['amount'], address, -custom.jury_vote_fee, DB) adjust_string(['votes', tx['decision_id']], address, tx['old_vote'], tx['new_vote'], DB)
def pushblock(dic, DB): length = tools.db_get('length') block = tools.db_get(length, DB) if 'peer' in dic: peer = dic['peer'] else: peer = False if 'blocks' in dic: if peer != False: a = tools.package(peer) not in blacklist if a not in blacklist or blacklist[a] < 500: for i in range(20): if tools.fork_check(dic['blocks'], DB, length, block): blockchain.delete_block(DB) length -= 1 for block in dic['blocks']: DB['suggested_blocks'].put([block, peer]) else: DB['suggested_blocks'].put([dic['block'], peer]) return 'success'
def f(): time.sleep(0.1) l = tools.db_get('length') + 1 v = range(l - 10, l) v = filter(lambda x: x > 0, v) v = map(lambda x: tools.db_get(x), v) try: v = map(lambda x: x['prevHash'], v) except: #tools.log('v: ' +str(v)) return if tools.db_get('stop'): tools.dump_out(blocks_queue) tools.dump_out(txs_queue) return while not bb() or not tb(): ff(blocks_queue, lambda x: add_block(x, v), bb, 'block') ff(txs_queue, add_tx, tb, 'tx')
def jury_vote(tx, DB, add_block):#while votes exist, should not be able to send votecoins address=addr(tx) acc=tools.db_get(address, DB) if tx['decision_id'] not in acc['votes']: acc['votes'][tx['decision_id']]='unsure' tools.db_put(address, acc, DB) adjust_int(['count'], address, 1, DB, add_block) adjust_int(['amount'], address, -custom.jury_vote_fee, DB, add_block) adjust_string(['votes', tx['decision_id']], address, tx['old_vote'], tx['new_vote'], DB, add_block)
def add_tx(tx, DB={}): # Attempt to add a new transaction into the pool. #print('top of add_tx') out = [''] if type(tx) != type({'a': 1}): return False address = tools.make_address(tx['pubkeys'], len(tx['signatures'])) def verify_count(tx, txs): return tx['count'] != tools.count(address, DB) def type_check(tx, txs): if not tools.E_check(tx, 'type', [str, unicode]): out[0] += 'blockchain type' return False if tx['type'] == 'mint': return False if tx['type'] not in transactions.tx_check: out[0] += 'bad type' return False return True def too_big_block(tx, txs): return len( tools.package(txs + [tx])) > networking.MAX_MESSAGE_SIZE - 5000 def verify_tx(tx, txs, out): if not type_check(tx, txs): out[0] += 'type error' return False if tx in txs: out[0] += 'no duplicates' return False if verify_count(tx, txs): out[0] += 'count error' return False if too_big_block(tx, txs): out[0] += 'too many txs' return False try: if not transactions.tx_check[tx['type']](tx, txs, out, DB): out[0] += 'tx: ' + str(tx) return False except Exception as exc: out[0] += 'badly formatted tx caused error: ' + str(tx) return False return True #tools.log('attempt to add tx: ' +str(tx)) T = tools.db_get('txs') if verify_tx(tx, T, out): T.append(tx) tools.db_put('txs', T) return (tx) else: return ('failed to add tx because: ' + out[0])
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 main(pubkey): try: while True: custom.queues['heart_queue'].put('miner') if tools.db_get('stop'): tools.log('shutting off miner') return # if mining is open elif tools.db_get('mine'): if tools.is_authority(pubkey=tools.db_get('pubkey')): mine_server(pubkey) else: mine_client(pubkey) else: time.sleep(1) except Exception as exc: print 'miner main gave an exception', str(exc) tools.log('miner main: ') tools.log(exc)