def target(_candidate_block, queue): # Miner registered but no work is sent yet. import copy candidate_block = copy.deepcopy(_candidate_block) try: if candidate_block is None: return if 'nonce' in candidate_block: candidate_block.pop('nonce') halfHash = tools.det_hash(candidate_block) candidate_block['nonce'] = random.randint( 0, 10000000000000000000000000000000000000000) current_hash = tools.det_hash({ 'nonce': candidate_block['nonce'], 'halfHash': halfHash }) while current_hash > candidate_block['target']: candidate_block['nonce'] += 1 current_hash = tools.det_hash({ 'nonce': candidate_block['nonce'], 'halfHash': halfHash }) if current_hash <= candidate_block['target']: queue.put(candidate_block) except Exception as e: tools.log('miner f****d up' + str(e)) pass
def make_block(self, prev_block, txs, pubkey): """ After mempool changes at 0.011c version, make block must select valid transactions. Mempool is mixed and not all transactions may be valid at the same time. Miner creates a block by adding transactions that are valid together. :param prev_block: :param txs: :param pubkey: :return: """ leng = int(prev_block['length']) + 1 target_ = self.blockchain.target(leng) diffLength = tools.hex_sum(prev_block['diffLength'], tools.hex_invert(target_)) txs = self.statedb.get_valid_txs_for_next_block(txs, leng) txs = [self.make_mint(pubkey)] + txs out = { 'version': custom.version, 'txs': txs, 'length': leng, 'time': time.time(), 'diffLength': diffLength, 'target': target_, 'prevHash': tools.det_hash(prev_block) } return out
def fork_check(newblocks, length, top_block_on_chain): """ Check whether a fork happens while adding these blocks. If a fork is detected, return the index of last matched block. :param newblocks: Received blocks. :param length: :param top_block_on_chain: :return: """ recent_hash = tools.det_hash(top_block_on_chain) their_hashes = list( map(lambda x: x['prevHash'] if x['length'] > 0 else 0, newblocks)) their_hashes += [tools.det_hash(newblocks[-1])] b = ( recent_hash not in their_hashes ) and newblocks[0]['length'] - 1 < length < newblocks[-1]['length'] return b
def target(candidate_block, queue): # Miner registered but no work is sent yet. try: if candidate_block is None: return if 'nonce' in candidate_block: candidate_block.pop('nonce') halfHash = tools.det_hash(candidate_block) candidate_block['nonce'] = random.randint( 0, 10000000000000000000000000000000000000000) current_hash = tools.det_hash({ 'nonce': candidate_block['nonce'], 'halfHash': halfHash }) while current_hash > candidate_block['target']: candidate_block['nonce'] += 1 current_hash = tools.det_hash({ 'nonce': candidate_block['nonce'], 'halfHash': halfHash }) if current_hash <= candidate_block['target']: queue.put(candidate_block) except Exception as e: pass
def make_block(self, prev_block, txs, pubkey): leng = int(prev_block['length']) + 1 target_ = self.blockchain.target(leng) diffLength = tools.hex_sum(prev_block['diffLength'], tools.hex_invert(target_)) out = { 'version': custom.version, 'txs': txs + [self.make_mint(pubkey)], 'length': leng, 'time': time.time(), 'diffLength': diffLength, 'target': target_, 'prevHash': tools.det_hash(prev_block) } return out
def tx_signature_check(tx): tx_copy = copy.deepcopy(tx) if 'signatures' not in tx or not isinstance(tx['signatures'], (list, )): tools.log('no signatures') return False if 'pubkeys' not in tx or not isinstance(tx['pubkeys'], (list, )): tools.log('no pubkeys') return False if len(tx['pubkeys']) == 0: tools.log('pubkey error') return False if len(tx['signatures']) > len(tx['pubkeys']): tools.log('there are more signatures than required') return False tx_copy.pop('signatures') msg = tools.det_hash(tx_copy) if not BlockchainService.sigs_match(copy.deepcopy(tx['signatures']), copy.deepcopy(tx['pubkeys']), msg): tools.log('sigs do not match') return False return True
def add_block(self, block): """Attempts adding a new block to the blockchain. Median is good for weeding out liars, so long as the liars don't have 51% hashpower. """ length = self.db.get('length') if int(block['length']) < int(length) + 1: return 1 elif int(block['length']) > int(length) + 1: return 2 if (length >= 0 and block['diffLength'] != tools.hex_sum(self.db.get('diffLength'), tools.hex_invert(block['target']))) \ or (length < 0 and block['diffLength'] != tools.hex_invert(block['target'])): tools.log(block['diffLength']) tools.log( tools.hex_sum(self.db.get('diffLength'), tools.hex_invert(block['target']))) tools.log(block['length']) tools.log('difflength is wrong') return 3 if length >= 0 and tools.det_hash( self.db.get(length)) != block['prevHash']: tools.log('prevhash different') return 3 nonce_and_hash = tools.hash_without_nonce(block) if tools.det_hash(nonce_and_hash) > block['target']: tools.log('hash value does not match the target') return 3 if block['target'] != self.target(block['length']): tools.log('block: ' + str(block)) tools.log('target: ' + str(self.target(block['length']))) tools.log('wrong target') return 3 recent_time_values = self.recent_blockthings( 'times', custom.median_block_time_limit, self.db.get('length')) median_block = tools.median(recent_time_values) if block['time'] < median_block: tools.log('Received block is generated earlier than median.') return 3 if not self.account.update_accounts_with_block( block, add_flag=True, simulate=True): tools.log('Received block failed transactions check.') return 3 self.db.put(block['length'], block) self.db.put('length', block['length']) self.db.put('diffLength', block['diffLength']) orphans = self.tx_pool_pop_all() self.account.update_accounts_with_block(block, add_flag=True) for orphan in sorted(orphans, key=lambda x: x['count']): self.add_tx(orphan) return 0
def add_block(self, block): """Attempts adding a new block to the blockchain. Median is good for weeding out liars, so long as the liars don't have 51% hashpower. """ length = self.db.get('length') block_at_length = self.get_block(length) if int(block['length']) < int(length) + 1: return 1 elif int(block['length']) > int(length) + 1: return 2 tools.echo('add block: ' + str(block['length'])) if (length >= 0 and block['diffLength'] != tools.hex_sum(block_at_length['diffLength'], tools.hex_invert(block['target']))) \ or (length < 0 and block['diffLength'] != tools.hex_invert(block['target'])): tools.log(block['diffLength']) tools.log( tools.hex_sum(self.db.get('diffLength'), tools.hex_invert(block['target']))) tools.log(block['length']) tools.log('difflength is wrong') return 3 if length >= 0 and tools.det_hash( block_at_length) != block['prevHash']: tools.log('prevhash different') return 3 nonce_and_hash = tools.hash_without_nonce(block) if tools.det_hash(nonce_and_hash) > block['target']: tools.log('hash value does not match the target') return 3 if block['target'] != self.target(block['length']): tools.log('block: ' + str(block)) tools.log('target: ' + str(self.target(block['length']))) tools.log('wrong target') return 3 """ recent_time_values = self.recent_blockthings('times', custom.median_block_time_limit) median_block = tools.median(recent_time_values) if block['time'] < median_block: tools.log('Received block is generated earlier than median.') return 3 """ # Check that block includes exactly one mint transaction if 'txs' not in block: tools.log( 'Received block does not include txs. At least a coinbase tx must be present' ) return 3 # Sum of all mint type transactions must be one mint_present = sum( [0 if tx['type'] != 'mint' else 1 for tx in block['txs']]) if mint_present != 1: tools.log('Received block includes wrong amount of mint txs') return 3 for tx in block['txs']: if not BlockchainService.tx_integrity_check(tx).getFlag(): tools.log('Received block failed special txs check.') return 3 if not self.statedb.update_database_with_block(block): return 3 self.put_block(block['length'], block) self.db.put('length', block['length']) self.db.put('diffLength', block['diffLength']) orphans = self.tx_pool_pop_all() for orphan in sorted(orphans, key=lambda x: x['count'] if 'count' in x else -1): self.tx_queue.put(orphan) tools.techo('add block: ' + str(block['length'])) return 0
def send(): from halocoin.model.wallet import Wallet amount = int(request.values.get('amount', 0)) address = request.values.get('address', None) message = request.values.get('message', '') wallet_name = request.values.get('wallet_name', None) password = request.values.get('password', None) if wallet_name is None: default_wallet = engine.instance.account.get_default_wallet() if default_wallet is not None: wallet_name = default_wallet['wallet_name'] response = {"success": False} if amount <= 0: response['error'] = "Amount cannot be lower than or equalto 0" return generate_json_response(response) elif address is None: response[ 'error'] = "You need to specify a receiving address for transaction" return generate_json_response(response) elif wallet_name is None: response[ 'error'] = "Wallet name is not given and there is no default wallet" return generate_json_response(response) elif password is None: response['error'] = "Password missing!" return generate_json_response(response) tx = { 'type': 'spend', 'amount': int(amount), 'to': address, 'message': message } encrypted_wallet_content = engine.instance.account.get_wallet(wallet_name) if encrypted_wallet_content is not None: try: wallet = Wallet.from_string( tools.decrypt(password, encrypted_wallet_content)) except: response['error'] = "Wallet password incorrect" return generate_json_response(response) else: response['error'] = "Error occurred" return generate_json_response(response) if 'count' not in tx: try: tx['count'] = engine.instance.account.known_tx_count( wallet.address) except: tx['count'] = 0 if 'pubkeys' not in tx: tx['pubkeys'] = [wallet.get_pubkey_str()] # We use pubkey as string if 'signatures' not in tx: tx['signatures'] = [tools.sign(tools.det_hash(tx), wallet.privkey)] engine.instance.blockchain.tx_queue.put(tx) response["success"] = True response["message"] = 'Tx amount:{} to:{} added to the pool'.format( tx['amount'], tx['to']) return generate_json_response(response)