Пример #1
0
def set_blockchain_params(genesis_block):
    assert 'spawn' in multiprocessing.get_all_start_methods(), 'Not found spawn method.'
    setting_tx = genesis_block.txs[0]
    params = bjson.loads(setting_tx.message)
    V.BLOCK_GENESIS_HASH = genesis_block.hash
    V.BLOCK_PREFIX = params.get('prefix')
    V.BLOCK_CONTRACT_PREFIX = params.get('contract_prefix')
    V.BLOCK_GENESIS_TIME = params.get('genesis_time')
    V.BLOCK_ALL_SUPPLY = params.get('all_supply')
    V.BLOCK_TIME_SPAN = params.get('block_span')
    V.BLOCK_REWARD = params.get('block_reward')
    V.CONTRACT_VALIDATOR_ADDRESS = params.get('validator_address')
    V.COIN_DIGIT = params.get('digit_number')
    V.COIN_MINIMUM_PRICE = params.get('minimum_price')
    V.CONTRACT_MINIMUM_AMOUNT = params.get('contract_minimum_amount')
    consensus = params.get('consensus')
    if isinstance(consensus, dict):
        V.BLOCK_CONSENSUS = consensus
        V.BLOCK_BASE_CONSENSUS = min(consensus.keys())
    else:
        # TODO: remove after test
        pow_ratio = params.get('pow_ratio')
        V.BLOCK_CONSENSUS = {C.BLOCK_YES_POW: pow_ratio, C.BLOCK_POS: 100 - pow_ratio}
        V.BLOCK_BASE_CONSENSUS = C.BLOCK_YES_POW
    GompertzCurve.setup_params()
Пример #2
0
async def chain_info(request):
    best_height = builder.best_block.height
    best_block = builder.best_block
    old_block_height = builder.best_chain[0].height - 1
    old_block_hash = hexlify(builder.get_block_hash(old_block_height)).decode()
    data = {'best': best_block.getinfo()}
    difficulty = dict()
    for consensus, ratio in V.BLOCK_CONSENSUSES.items():
        name = C.consensus2name[consensus]
        target = get_bits_by_hash(previous_hash=best_block.hash, consensus=consensus)[1]
        block_time = round(V.BLOCK_TIME_SPAN / ratio * 100)
        diff = (MAX_256_INT // target) / 100000000
        bias = get_bias_by_hash(previous_hash=best_block.previous_hash, consensus=consensus)
        difficulty[name] = {
            'number': consensus,
            'diff': round(diff / 100000000, 8),
            'bias': round(bias, 8),
            'fixed_diff': round(diff / bias, 8),
            'hashrate(kh/s)': round((MAX_256_INT//target)/block_time/1000, 3),
            'is_base': V.BLOCK_BASE_CONSENSUS == consensus,
        }
    data['mining'] = difficulty
    data['size'] = best_block.getsize()
    data['checkpoint'] = {'height': old_block_height, 'blockhash': old_block_hash}
    data['money_supply'] = GompertzCurve.calc_total_supply(best_height)
    data['total_supply'] = GompertzCurve.k
    return web_base.json_res(data)
Пример #3
0
def check_tx_pow_reward(tx, include_block):
    if not (len(tx.inputs) == 0 and len(tx.outputs) == 1):
        raise BlockChainError('Inout is 0, output is 1 len.')
    elif include_block.txs.index(tx) != 0:
        raise BlockChainError('Proof tx is index 0.')
    elif not (tx.gas_price == 0 and tx.gas_amount == 0):
        raise BlockChainError('Pow gas info is wrong. [{}, {}]'.format(
            tx.gas_price, tx.gas_amount))
    elif len(tx.message) > 96:
        raise BlockChainError('Pow msg is less than 96bytes. [{}b>96b]'.format(
            len(tx.message)))

    address, coin_id, amount = tx.outputs[0]
    reward = GompertzCurve.calc_block_reward(include_block.height)
    fees = sum(tx.gas_amount * tx.gas_price for tx in include_block.txs)

    if not (include_block.time == tx.time == tx.deadline - 10800):
        raise BlockChainError('TX time is wrong 3. [{}={}={}-10800]'.format(
            include_block.time, tx.time, tx.deadline))
    elif not (coin_id == 0 and amount <= reward + fees):
        raise BlockChainError(
            'Input and output is wrong coin={} [{}<={}+{}]'.format(
                coin_id, amount, reward, fees))
    elif not include_block.pow_check():
        include_block.work2diff()
        include_block.target2diff()
        print(include_block.getinfo())
        raise BlockChainError('Proof of work check is failed. [{}<{}]'.format(
            include_block.difficulty, include_block.work_difficulty))
Пример #4
0
def create_mining_block(consensus):
    global mining_address
    # setup mining address for PoW
    with mining_address_lock:
        if mining_address is None:
            if V.MINING_ADDRESS is None:
                with create_db(V.DB_ACCOUNT_PATH) as db:
                    cur = db.cursor()
                    mining_address = generate_new_address_by_userid(
                        C.ANT_UNKNOWN, cur)
                    db.commit()
            else:
                mining_address = V.MINING_ADDRESS
    if unconfirmed_txs is None:
        raise FailedGenerateWarning('unconfirmed_txs is None')
    if previous_block is None:
        raise FailedGenerateWarning('previous_block is None')
    # create proof_tx
    reward = GompertzCurve.calc_block_reward(previous_block.height + 1)
    fees = sum(tx.gas_amount * tx.gas_price for tx in unconfirmed_txs)
    proof_tx = TX.from_dict(
        tx={
            'type': C.TX_POW_REWARD,
            'inputs': list(),
            'outputs': [(mining_address, 0, reward + fees)],
            'gas_price': 0,
            'gas_amount': 0,
            'message_type': C.MSG_NONE,
            'message': b''
        })
    proof_tx.update_time()
    # create mining block
    bits, target = get_bits_by_hash(previous_hash=previous_block.hash,
                                    consensus=consensus)
    mining_block = Block.from_dict(
        block={
            'merkleroot': b'\xff' * 32,
            'time': 0,
            'previous_hash': previous_block.hash,
            'bits': bits,
            'nonce': b'\xff\xff\xff\xff'
        })
    proof_tx.height = previous_block.height + 1
    mining_block.height = proof_tx.height
    mining_block.flag = consensus
    mining_block.bits2target()
    mining_block.txs.append(proof_tx)
    if unconfirmed_txs is None:
        raise FailedGenerateWarning('unconfirmed_txs is None')
    mining_block.txs.extend(unconfirmed_txs)
    mining_block.update_merkleroot()
    mining_block.update_time(proof_tx.time)
    return mining_block
Пример #5
0
def check_tx_pos_reward(tx, include_block):
    # POS報酬TXの検査
    if not (len(tx.inputs) == len(tx.outputs) == 1):
        raise BlockChainError('Inputs and outputs is only 1 len.')
    elif include_block.txs.index(tx) != 0:
        raise BlockChainError('Proof tx is index 0.')
    elif not (tx.gas_price == 0 and tx.gas_amount == 0):
        raise BlockChainError('Pos gas info is wrong. [{}, {}]'.format(
            tx.gas_price, tx.gas_amount))
    elif not (tx.message_type == C.MSG_NONE and tx.message == b''):
        raise BlockChainError('Pos msg is None type. [{},{}]'.format(
            tx.message_type, tx.message))

    txhash, txindex = tx.inputs[0]
    base_tx = tx_builder.get_tx(txhash)
    if base_tx is None:
        print(list(tx_builder.chained_tx.values()))
        raise BlockChainError('Not found PosBaseTX:{} of {}.'.format(
            hexlify(txhash).decode(), tx))
    input_address, input_coin_id, input_amount = base_tx.outputs[txindex]
    tx.pos_amount = input_amount
    output_address, output_coin_id, output_amount = tx.outputs[0]
    reward = GompertzCurve.calc_block_reward(include_block.height)
    include_block.bits2target()

    if input_address != output_address:
        raise BlockChainError(
            'Input address differ from output address. [{}!={}]'.format(
                input_address, output_address))
    elif not (input_coin_id == output_coin_id == 0):
        raise BlockChainError('Input and output coinID is zero.')
    elif input_amount + reward != output_amount:
        raise BlockChainError('Inout amount wrong [{}+{}!={}]'.format(
            input_amount, reward, output_amount))
    elif tx.version != __chain_version__ or tx.message_type != C.MSG_NONE:
        raise BlockChainError('Not correct tx version or msg_type.')
    elif base_tx.height is None:
        raise BlockChainError('Source TX is unconfirmed. {}'.format(base_tx))
    elif not (include_block.height > base_tx.height + C.MATURE_HEIGHT):
        raise BlockChainError(
            'Source TX height is too young. [{}>{}+{}]'.format(
                include_block.height, base_tx.height, C.MATURE_HEIGHT))
    elif not (include_block.time == tx.time == tx.deadline - 10800):
        raise BlockChainError('TX time is wrong 1. [{}={}={}-10800]'.format(
            include_block.time, tx.time, tx.deadline))
    elif not tx.pos_check(include_block.previous_hash,
                          include_block.target_hash):
        raise BlockChainError('Proof of stake check is failed.')
Пример #6
0
async def chain_info(request):
    try:
        best_height = chain_builder.best_block.height
        best_block = chain_builder.best_block
        old_block_height = chain_builder.best_chain[0].height - 1
        old_block_hash = chain_builder.get_block_hash(old_block_height).hex()
        data = {'best': best_block.getinfo()}
        difficulty = dict()
        for consensus, ratio in V.BLOCK_CONSENSUSES.items():
            name = C.consensus2name[consensus]
            bits, target = get_bits_by_hash(previous_hash=best_block.hash,
                                            consensus=consensus)
            target = float(target)
            block_time = round(V.BLOCK_TIME_SPAN / ratio * 100)
            diff = round(DEFAULT_TARGET / target, 8)
            bias = get_bias_by_hash(previous_hash=best_block.previous_hash,
                                    consensus=consensus)
            difficulty[name] = {
                'number':
                consensus,
                'bits':
                bits.to_bytes(4, 'big').hex(),
                'diff':
                round(diff, 8),
                'bias':
                round(bias, 8),
                'fixed_diff':
                round(diff / bias, 8),
                'hashrate(kh/s)':
                round((MAX_256_FLOAT / target) / block_time / 1000, 3)
            }
        data['mining'] = difficulty
        data['size'] = best_block.size
        data['checkpoint'] = {
            'height': old_block_height,
            'blockhash': old_block_hash
        }
        data['money_supply'] = GompertzCurve.calc_total_supply(best_height)
        data['total_supply'] = GompertzCurve.k
        if F_ADD_CASHE_INFO:
            data['cashe'] = {
                'get_bits_by_hash': str(get_bits_by_hash.cache_info()),
                'get_bias_by_hash': str(get_bias_by_hash.cache_info())
            }
        return utils.json_res(data)
    except Exception:
        return utils.error_res()
Пример #7
0
def create_mining_block(consensus):
    global mining_address
    # create proof_tx
    mining_address = mining_address or V.MINING_ADDRESS or new_key()
    reward = GompertzCurve.calc_block_reward(previous_block.height + 1)
    fees = sum(tx.gas_amount * tx.gas_price for tx in unconfirmed_txs)
    proof_tx = TX(
        tx={
            'type': C.TX_POW_REWARD,
            'inputs': list(),
            'outputs': [(mining_address, 0, reward + fees)],
            'gas_price': 0,
            'gas_amount': 0,
            'message_type': C.MSG_PLAIN if V.MINING_MESSAGE else C.MSG_NONE,
            'message': V.MINING_MESSAGE if V.MINING_MESSAGE else b''
        })
    proof_tx.update_time()
    # create mining block
    bits, target = get_bits_by_hash(previous_hash=previous_block.hash,
                                    consensus=consensus)
    mining_block = Block(
        block={
            'merkleroot': b'\xff' * 32,
            'time': 0,
            'previous_hash': previous_block.hash,
            'bits': bits,
            'nonce': b'\xff\xff\xff\xff'
        })
    proof_tx.height = previous_block.height + 1
    mining_block.height = proof_tx.height
    mining_block.flag = consensus
    mining_block.bits2target()
    mining_block.txs.append(proof_tx)
    mining_block.txs.extend(unconfirmed_txs)
    mining_block.update_merkleroot()
    mining_block.update_time(proof_tx.time)
    return mining_block
Пример #8
0
 def proof_of_stake(self):
     global staking_limit
     limit_deque = deque(maxlen=10)
     self.event_close.set()
     while self.event_close.is_set():
         # check start mining
         if previous_block is None or unconfirmed_txs is None or unspents_txs is None:
             sleep(0.1)
             continue
         if len(unspents_txs) == 0:
             logging.info("No unspents for staking, wait 180s..")
             sleep(180)
             continue
         start = time()
         # create staking block
         bits, target = get_bits_by_hash(previous_hash=previous_block.hash,
                                         consensus=C.BLOCK_POS)
         reward = GompertzCurve.calc_block_reward(previous_block.height + 1)
         staking_block = Block(
             block={
                 'merkleroot': b'\xff' * 32,
                 'time': 0,
                 'previous_hash': previous_block.hash,
                 'bits': bits,
                 'nonce': b'\xff\xff\xff\xff'
             })
         staking_block.height = previous_block.height + 1
         staking_block.flag = C.BLOCK_POS
         staking_block.bits2target()
         staking_block.txs.append(None)  # Dummy proof tx
         staking_block.txs.extend(unconfirmed_txs)
         calculate_nam = 0
         for proof_tx in unspents_txs.copy():
             address = proof_tx.outputs[0][0]
             proof_tx.outputs[0] = (address, 0,
                                    proof_tx.pos_amount + reward)
             proof_tx.update_time()
             calculate_nam += 1
             # next check block
             if previous_block is None or unconfirmed_txs is None or unspents_txs is None:
                 logging.debug("Reset by \"nothing params found\"")
                 sleep(1)
                 break
             elif previous_block.hash != staking_block.previous_hash:
                 logging.debug("Reset by \"Don't match previous_hash\"")
                 sleep(1)
                 break
             elif not proof_tx.pos_check(
                     previous_hash=previous_block.hash,
                     pos_target_hash=staking_block.target_hash):
                 continue
             else:
                 # Staked yay!!
                 proof_tx.height = staking_block.height
                 proof_tx.signature = [
                     message2signature(proof_tx.b, proof_tx.outputs[0][0])
                 ]
                 staking_block.txs[0] = proof_tx
                 # Fit block size
                 while staking_block.getsize() > C.SIZE_BLOCK_LIMIT:
                     tx = staking_block.txs.pop()
                     if tx.type == C.TX_FINISH_CONTRACT:
                         staking_block.txs.pop()
                 staking_block.update_time(proof_tx.time)
                 staking_block.update_merkleroot()
                 confirmed_generating_block(staking_block)
                 break
         else:
             # check time
             used = time() - start
             remain = 1.0 - used
             max_limit = max(50, int(calculate_nam / max(0.0001, used)))
             limit_deque.append(int(max_limit * self.power_limit))
             staking_limit = sum(limit_deque) // len(limit_deque)
             if int(time()) % 90 == 0:
                 logging.info("Staking... margin={}% limit={}".format(
                     round(remain * 100, 1), staking_limit))
             self.hashrate = (calculate_nam, time())
             sleep(max(0.0, remain))
     logging.info("Close signal")
Пример #9
0
    def proof_of_capacity(self):
        dir_path: str = self.config.get('path',
                                        os.path.join(V.DB_HOME_DIR, 'plots'))
        while self.f_enable:
            # check start mining
            if previous_block is None or unconfirmed_txs is None:
                sleep(0.1)
                continue
            if not os.path.exists(dir_path):
                sleep(30)
                continue
            s = time()
            previous_hash = previous_block.hash
            height = previous_block.height + 1
            block_time = int(s - V.BLOCK_GENESIS_TIME)
            bits, target = get_bits_by_hash(previous_hash=previous_hash,
                                            consensus=C.BLOCK_CAP_POS)
            reward = GompertzCurve.calc_block_reward(height)

            # start staking by capacity
            count = 0
            for file_name in os.listdir(dir_path):
                m = optimize_file_name_re.match(file_name)
                if m is None:
                    continue
                count += int(m.group(3)) - int(m.group(2))
            if count < 1:
                log.debug("not found plot file, wait 60 sec")
                sleep(60)
                continue

            # let's seek files
            nonce, work_hash, address = multi_seek(dir=dir_path,
                                                   previous_hash=previous_hash,
                                                   target=target.to_bytes(
                                                       32, 'little'),
                                                   time=block_time,
                                                   worker=os.cpu_count())
            if work_hash is None:
                # return failed => (None, None, err-msg)
                if int(s) % 300 == 0:
                    log.debug("PoC mining info by \"{}\"".format(address))
            else:
                # return success => (nonce, workhash, address)
                if previous_block is None or unconfirmed_txs is None:
                    continue
                if previous_block.hash != previous_hash:
                    continue
                # Staked by capacity yay!!
                total_fee = sum(tx.gas_price * tx.gas_amount
                                for tx in unconfirmed_txs)
                staked_block = Block.from_dict(
                    block={
                        'version': 0,  # always 0
                        'previous_hash': previous_hash,
                        'merkleroot': b'\x00' * 32,
                        'time': 0,
                        'bits': bits,
                        'nonce': nonce,
                        'height': height,
                        'flag': C.BLOCK_CAP_POS
                    })
                staked_proof_tx = TX.from_dict(
                    tx={
                        'type': C.TX_POS_REWARD,
                        'time': block_time,
                        'deadline': block_time + 10800,
                        'gas_price': 0,
                        'gas_amount': 0,
                        'outputs': [(address, 0, reward + total_fee)]
                    })
                staked_block.txs.append(staked_proof_tx)
                staked_block.txs.extend(unconfirmed_txs)
                while staked_block.size > C.SIZE_BLOCK_LIMIT:
                    staked_block.txs.pop()
                staked_block.update_time(staked_proof_tx.time)
                staked_block.update_merkleroot()
                staked_block.work_hash = work_hash
                signature = sign_message_by_address(raw=staked_block.b,
                                                    address=address)
                staked_proof_tx.signature.append(signature)
                confirmed_generating_block(staked_block)

            # finish all
            used_time = time() - s
            self.hashrate = (count, time())
            sleep(max(1 - used_time, 0))
        log.info("Close signal")
Пример #10
0
 def proof_of_stake(self):
     global staking_limit
     limit_deque = deque(maxlen=10)
     while self.f_enable:
         # check start mining
         if previous_block is None or unconfirmed_txs is None or unspents_txs is None:
             sleep(0.1)
             continue
         if len(unspents_txs) == 0:
             log.info("No unspents for staking, wait 180s")
             sleep(180)
             continue
         start = time()
         # create staking block
         bits, target = get_bits_by_hash(previous_hash=previous_block.hash,
                                         consensus=C.BLOCK_COIN_POS)
         reward = GompertzCurve.calc_block_reward(previous_block.height + 1)
         staking_block = Block.from_dict(
             block={
                 'version': 0,  # always 0
                 'merkleroot': b'\xff' * 32,
                 'time': 0,
                 'previous_hash': previous_block.hash,
                 'bits': bits,
                 'nonce': b'\xff\xff\xff\xff'
             })
         staking_block.height = previous_block.height + 1
         staking_block.flag = C.BLOCK_COIN_POS
         staking_block.bits2target()
         staking_block.txs.append(None)  # Dummy proof tx
         if unconfirmed_txs is None:
             raise FailedGenerateWarning('unconfirmed_txs is None')
         staking_block.txs.extend(unconfirmed_txs)
         calculate_nam = 0
         for proof_tx in unspents_txs.copy():
             address = proof_tx.outputs[0][0]
             proof_tx.outputs[0] = (address, 0,
                                    proof_tx.pos_amount + reward)
             proof_tx.update_time()
             calculate_nam += 1
             # next check block
             if previous_block is None or unconfirmed_txs is None or unspents_txs is None:
                 log.debug("Reset by \"nothing params found\"")
                 sleep(1)
                 break
             elif previous_block.hash != staking_block.previous_hash:
                 log.debug("Reset by \"Don't match previous_hash\"")
                 sleep(1)
                 break
             elif not stake_coin_check(
                     tx=proof_tx,
                     previous_hash=previous_block.hash,
                     target_hash=staking_block.target_hash):
                 continue
             else:
                 # Staked yay!!
                 proof_tx.height = staking_block.height
                 staking_block.txs[0] = proof_tx
                 # Fit block size
                 while staking_block.size > C.SIZE_BLOCK_LIMIT:
                     staking_block.txs.pop()
                 staking_block.update_time(proof_tx.time)
                 staking_block.update_merkleroot()
                 signature = sign_message_by_address(raw=staking_block.b,
                                                     address=address)
                 proof_tx.signature.append(signature)
                 confirmed_generating_block(staking_block)
                 break
         else:
             # check time
             used = time() - start
             remain = 1.0 - used
             max_limit = max(50, int(calculate_nam / max(0.0001, used)))
             limit_deque.append(int(max_limit * self.power_limit))
             staking_limit = sum(limit_deque) // len(limit_deque)
             if int(time()) % 90 == 0:
                 log.info("Staking... margin={}% limit={}".format(
                     round(remain * 100, 1), staking_limit))
             self.hashrate = (calculate_nam, time())
             sleep(max(0.0, remain + random() - 0.5))
     log.info("Close signal")