示例#1
0
 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
示例#2
0
 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
示例#3
0
 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
示例#4
0
 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
示例#5
0
 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
示例#6
0
    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
示例#7
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')

        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
示例#9
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)