Exemple #1
0
def load_boot_file():
    normal_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                               'boot.dat')
    extra_path = os.path.join(V.DB_HOME_DIR, 'boot.dat')
    if os.path.exists(normal_path):
        with open(normal_path, mode='br') as fp:
            data = bjson.loads(
                b64decode(fp.read().replace(b'\n', b'').replace(b'\r', b'')))
    elif os.path.exists(extra_path):
        with open(extra_path, mode='br') as fp:
            data = bjson.loads(
                b64decode(fp.read().replace(b'\n', b'').replace(b'\r', b'')))
    else:
        raise FileNotFoundError('Cannot find boot.dat "{}" or "{}" ?'.format(
            normal_path, extra_path))
    genesis_block = Block(binary=data['block'])
    genesis_block.flag = C.BLOCK_GENESIS
    genesis_block.height = 0
    for b_tx in data['txs']:
        tx = TX(binary=b_tx)
        tx.height = 0
        genesis_block.txs.append(tx)
    connections = data.get('connections', list())
    network_ver = data['network_ver']
    return genesis_block, network_ver, connections
Exemple #2
0
def put_to_block_stack(r, before_waiter):
    block_tmp = dict()
    batch_txs = list()
    for block_b, block_height, block_flag, txs in r:
        block = Block(binary=block_b)
        block.height = block_height
        block.flag = block_flag
        for tx_b, tx_signature in txs:
            tx = TX(binary=tx_b)
            tx.height = None
            tx.signature = tx_signature
            tx_from_database = tx_builder.get_tx(txhash=tx.hash)
            if tx_from_database:
                block.txs.append(tx_from_database)
            else:
                block.txs.append(tx)
        block_tmp[block_height] = block
        batch_txs.extend(block.txs)
    # check
    if len(block_tmp) == 0:
        return None
    batch_sign_cashe(batch_txs)
    before_waiter.wait()
    with write_protect_lock:
        block_stack.update(block_tmp)
    return batch_workhash(tuple(block_tmp.values()))
Exemple #3
0
def check_block(block: Block):
    # 挿入前にBlockの正当性チェック
    if block.f_orphan:
        raise BlockChainError('Block is orphan.')
    elif len(block.txs) == 0:
        raise BlockChainError('Block don\'t have any txs.')
    elif block.getsize() > C.SIZE_BLOCK_LIMIT:
        raise BlockChainError('Block size is too large [{}b>{}b]'.format(block.getsize(), C.SIZE_BLOCK_LIMIT))
    bits = get_bits_by_hash(previous_hash=block.previous_hash, consensus=block.flag)[0]
    if block.bits != bits:
        raise BlockChainError('Block bits differ from calc. [{}!={}]'.format(block.bits, bits))
    logging.debug("Checked block {}.".format(block))
Exemple #4
0
async def getwork(*args, **kwargs):
    # https://en.bitcoin.it/wiki/Getwork
    if len(args) == 0:
        now = int(time() - V.BLOCK_GENESIS_TIME)
        for block in getwork_cashe.values():
            if block.previous_hash != builder.best_block.hash:
                continue
            if now - block.time < 10:
                mining_block = block
                break
        else:
            mining_block = await get_mining_block(**kwargs)
            getwork_cashe[mining_block.merkleroot] = mining_block
            mining_block.bits2target()
        # Pre-processed SHA-2 input chunks
        data = mining_block.b  # 80 bytes
        data += unhexlify(b'800000000000000000000000000000000000000000000000'
                          b'000000000000000000000000000000000000000000000280'
                          )  # 48+80=128bytes
        new_data = b''
        for i in range(0, 128, 4):
            new_data += data[i:i + 4][::-1]
        if extra_target:
            return {
                "data": hexlify(new_data).decode(),
                "target": hexlify(extra_target.to_bytes(32, 'big')).decode()
            }
        else:
            return {
                "data": hexlify(new_data).decode(),
                "target": hexlify(mining_block.target_hash).decode()
            }
    else:
        data = unhexlify(args[0].encode())
        new_data = b''
        for i in range(0, 128, 4):
            new_data += data[i:i + 4][::-1]
        block = Block(binary=new_data[:80])
        if block.previous_hash != builder.best_block.hash:
            return 'PreviousHash don\'t match.'
        if block.merkleroot in getwork_cashe:
            block.txs.extend(getwork_cashe[block.merkleroot].txs)
            result = await submitblock(block, **kwargs)
            if result is None:
                return True
            elif extra_target and block.pow_check(extra_target=extra_target):
                return True
            else:
                logging.debug("GetWorkReject by \"{}\"".format(result))
                return result
        else:
            logging.debug("GetWorkReject by \"Not found merkleroot.\"")
            return 'Not found merkleroot.'
Exemple #5
0
async def submitblock(block_hex_or_obj, **kwargs):
    if isinstance(block_hex_or_obj, str):
        block_bin = unhexlify(block_hex_or_obj.encode())
        # Block
        mined_block = Block(binary=block_bin[:80])
        if mined_block.previous_hash != builder.best_block.hash:
            return 'PreviousHash don\'t match.'
        previous_block = builder.get_block(mined_block.previous_hash)
        mined_block.height = previous_block.height + 1
        mined_block.flag = int(kwargs['password'])
        # tx length
        storage_flag = int.from_bytes(block_bin[80:81], 'little')
        if storage_flag < 0xfd:
            tx_len = storage_flag
            pos = 81
        elif storage_flag == 0xfd:
            tx_len = int.from_bytes(block_bin[81:83], 'little')
            pos = 83
        elif storage_flag == 0xfe:
            tx_len = int.from_bytes(block_bin[81:85], 'little')
            pos = 85
        else:  # == 0xff
            tx_len = int.from_bytes(block_bin[81:89], 'little')
            pos = 89
        if F_HEAVY_DEBUG:
            logging.debug("RpcSubmit block: pos={}, tx_len={}".format(
                pos, tx_len))
        # correct txs
        while len(block_bin) > pos:
            tx = TX()
            tx.b = block_bin
            tx.deserialize(first_pos=pos, f_raise=False)
            if tx.version != __chain_version__:
                return 'tx_ver do not match [{}!={}]'.format(
                    tx.version, __chain_version__)
            pos += len(tx.b)
            mined_block.txs.append(
                tx_builder.get_tx(txhash=tx.hash, default=tx))
            # check
            if tx_len != len(mined_block.txs):
                return 'Do not match txlen [{}!={}]'.format(
                    tx_len, len(mined_block.txs))
            if pos != len(block_bin):
                return 'Do not match pos [{}!={}]'.format(pos, len(block_bin))
    elif isinstance(block_hex_or_obj, Block):
        mined_block = block_hex_or_obj
        previous_block = builder.get_block(mined_block.previous_hash)
        mined_block.height = previous_block.height + 1
        mined_block.flag = int(kwargs['password'])
    else:
        return 'Unknown input? -> {}'.format(block_hex_or_obj)
    mined_block.update_pow()
    if mined_block.pow_check():
        confirmed_generating_block(mined_block)
        return None  # accepted
    else:
        return 'not satisfied work.'
Exemple #6
0
def make_block_by_node(blockhash):
    """ create Block by outside node """
    r = ask_node(cmd=DirectCmd.BLOCK_BY_HASH, data={'blockhash': blockhash})
    if isinstance(r, str):
        raise BlockChainError('make_block_by_node() failed, by "{}"'.format(hexlify(blockhash).decode(), r))
    block = Block(binary=r['block'])
    block.flag = r['flag']
    before_block = builder.get_block(blockhash=block.previous_hash)
    if before_block is None:
        raise BlockChainError('Not found BeforeBeforeBlock {}'.format(hexlify(block.previous_hash).decode()))
    block.height = before_block.height + 1
    for tx in r['txs']:
        _tx = TX(binary=tx['tx'])
        _tx.height = block.height
        _tx.signature = tx['sign']
        block.txs.append(_tx)
    return block
Exemple #7
0
def fill_newblock_info(data):
    new_block = Block(binary=data['block'])
    logging.debug("Fill newblock={}".format(hexlify(new_block.hash).decode()))
    proof = TX(binary=data['proof'])
    new_block.txs.append(proof)
    new_block.flag = data['block_flag']
    proof.signature = data['sign']
    # Check the block is correct info
    if not new_block.pow_check():
        raise BlockChainError('Proof of work is not satisfied.')
    my_block = builder.get_block(new_block.hash)
    if my_block:
        raise BlockChainError('Already inserted block {}'.format(my_block))
    before_block = builder.get_block(new_block.previous_hash)
    if before_block is None:
        logging.debug("Cannot find beforeBlock {}, try to ask outside node."
                      .format(hexlify(new_block.previous_hash).decode()))
        # not found beforeBlock, need to check other node have the the block
        new_block.inner_score *= 0.70  # unknown previousBlock, score down
        before_block = make_block_by_node(blockhash=new_block.previous_hash)
        if not new_insert_block(before_block, time_check=True):
            # require time_check, it was generated only a few seconds ago
            # print([block for block in builder.chain.values()])
            raise BlockChainError('Failed insert beforeBlock {}'.format(before_block))
    new_height = before_block.height + 1
    proof.height = new_height
    new_block.height = new_height
    # Append general txs
    for txhash in data['txs'][1:]:
        tx = tx_builder.get_tx(txhash)
        if tx is None:
            new_block.inner_score *= 0.75  # unknown tx, score down
            logging.debug("Unknown tx, try to download.")
            r = ask_node(cmd=DirectCmd.TX_BY_HASH, data={'txhash': txhash}, f_continue_asking=True)
            if isinstance(r, str):
                raise BlockChainError('Failed unknown tx download "{}"'.format(r))
            tx = TX(binary=r['tx'])
            tx.signature = r['sign']
            check_tx(tx, include_block=None)
            tx_builder.put_unconfirmed(tx)
            logging.debug("Success unknown tx download {}".format(tx))
        tx.height = new_height
        new_block.txs.append(tx)
    return new_block
Exemple #8
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
Exemple #9
0
 def read_block(self, blockhash):
     if self.is_batch_thread() and blockhash in self.batch['_block']:
         b = self.batch['_block'][blockhash]
     elif is_plyvel:
         b = self._block.get(blockhash, default=None)
     else:
         b = self._block.Get(blockhash, default=None)
     if b is None:
         return None
     b = bytes(b)
     height, _time, work, b_block, flag, tx_len = struct_block.unpack_from(
         b)
     idx = struct_block.size
     assert len(b) == idx + tx_len, 'Not correct size. [{}={}]'.format(
         len(b), idx + tx_len)
     block = Block(binary=b_block)
     block.height = height
     block.work_hash = work
     block.flag = flag
     # block.txs = [self.read_tx(b[idx+32*i:idx+32*i+32]) for i in range(tx_len//32)]
     block.txs = [
         tx_builder.get_tx(b[idx + 32 * i:idx + 32 * i + 32])
         for i in range(tx_len // 32)
     ]
     return block
Exemple #10
0
async def getwork(*args, **kwargs):
    """
    https://en.bitcoin.it/wiki/Getwork
    Result:
        1. "data"       (hex string, required) block data
        2. "target"     (hex string, required) little endian hash target
    """
    if len(args) == 0:
        now = int(time() - V.BLOCK_GENESIS_TIME)
        for block in getwork_cashe.values():
            if block.previous_hash != chain_builder.best_block.hash:
                continue
            if now - block.time < 10:
                mining_block = block
                break
        else:
            mining_block = await get_mining_block(int(kwargs['password']))
            getwork_cashe[mining_block.merkleroot] = mining_block
            mining_block.bits2target()
        # Pre-processed SHA-2 input chunks
        data = mining_block.b  # 80 bytes
        data += a2b_hex('800000000000000000000000000000000000000000000000'
                        '000000000000000000000000000000000000000000000280')  # 48+80=128bytes
        new_data = b''
        for i in range(0, 128, 4):
            new_data += data[i:i + 4][::-1]
        if extra_target:
            return {"data": new_data.hex(), "target": extra_target.to_bytes(32, 'big').hex()}
        else:
            return {"data": new_data.hex(), "target": mining_block.target_hash.hex()}
    else:
        data = a2b_hex(args[0])
        new_data = b''
        for i in range(0, 128, 4):
            new_data += data[i:i + 4][::-1]
        block = Block.from_binary(binary=new_data[:80])
        if block.previous_hash != chain_builder.best_block.hash:
            return 'PreviousHash don\'t match'
        if block.merkleroot in getwork_cashe:
            block.txs.extend(getwork_cashe[block.merkleroot].txs)
            result = await submitblock(block, **kwargs)
            if result is None:
                return True
            elif extra_target and block.pow_check(extra_target=extra_target):
                return True
            else:
                log.debug("GetWorkReject by \"{}\"".format(result))
                return result
        else:
            log.debug("GetWorkReject by \"Not found merkleroot.\"")
            return 'Not found merkleroot'
Exemple #11
0
def fill_newblock_info(data):
    new_block = Block(binary=data['block'])
    proof = TX(binary=data['proof'])
    new_block.txs.append(proof)
    new_block.flag = data['block_flag']
    proof.signature = data['sign']
    # Check the block is correct info
    if not new_block.pow_check():
        raise BlockChainError('Proof of work is not satisfied.')
    if builder.get_block(new_block.hash):
        raise BlockChainError('Already inserted block.')
    before_block = builder.get_block(new_block.previous_hash)
    if before_block is None:
        raise BlockChainError('Not found beforeBlock {}.'.format(
            hexlify(new_block.previous_hash).decode()))
    new_height = before_block.height + 1
    proof.height = new_height
    new_block.height = new_height
    # Append general txs
    for txhash in data['txs'][1:]:
        tx = tx_builder.get_tx(txhash)
        if tx is None:
            new_block.inner_score *= 0.75  # unknown tx, score down
            logging.debug("Unknown tx, try to download.")
            r = ask_node(cmd=DirectCmd.TX_BY_HASH,
                         data={'txhash': txhash},
                         f_continue_asking=True)
            if isinstance(r, str):
                raise BlockChainError(
                    'Failed unknown tx download "{}"'.format(r))
            tx = TX(binary=r['tx'])
            tx.signature = r['sign']
            check_tx(tx, include_block=None)
            tx_builder.put_unconfirmed(tx)
            logging.debug("Success unknown tx download {}".format(tx))
        tx.height = new_height
        new_block.txs.append(tx)
    return new_block
Exemple #12
0
def check_unconfirmed_order(best_block, ordered_unconfirmed_txs):
    if len(ordered_unconfirmed_txs) == 0:
        return None
    s = time()
    dummy_proof_tx = TX()
    dummy_proof_tx.type = C.TX_POW_REWARD,
    dummy_block = Block()
    dummy_block.height = best_block.height + 1
    dummy_block.previous_hash = best_block.hash
    dummy_block.txs.append(dummy_proof_tx)  # dummy for proof tx
    dummy_block.txs.extend(ordered_unconfirmed_txs)
    tx = None
    try:
        for tx in ordered_unconfirmed_txs:
            if tx.type == C.TX_GENESIS:
                pass
            elif tx.type == C.TX_POS_REWARD:
                pass
            elif tx.type == C.TX_POW_REWARD:
                pass
            elif tx.type == C.TX_TRANSFER:
                pass
            elif tx.type == C.TX_MINT_COIN:
                check_tx_mint_coin(tx=tx, include_block=dummy_block)
            elif tx.type == C.TX_VALIDATOR_EDIT:
                check_tx_validator_edit(tx=tx, include_block=dummy_block)
            elif tx.type == C.TX_CONCLUDE_CONTRACT:
                check_tx_contract_conclude(tx=tx, include_block=dummy_block)
            else:
                raise BlockChainError('Unknown tx type "{}"'.format(tx.type))
        else:
            log.debug('Finish unconfirmed order check {}mSec'.format(
                int((time() - s) * 1000)))
            return None
    except Exception as e:
        log.warning(e, exc_info=True)
    # return errored tx
    return tx
Exemple #13
0
def get_submit_data(job: Job, extranonce1: bytes, extranonce2: bytes, nonce: bytes, difficulty: float) \
        -> (Optional[bytes], bytes, bool, bool):
    """check client submit data and generate node submit data"""
    assert len(extranonce1) == 4 and len(extranonce2) == 4
    coinbase = job.coinbase1 + extranonce1 + extranonce2 + job.coinbase2
    coinbase_hash = sha256d_hash(coinbase)
    merkleroot_list = [coinbase_hash] + [tx[0] for tx in job.unconfirmed]
    merkleroot = merkleroot_hash(merkleroot_list)
    block = Block.from_dict({
        'version': job.version,
        'previous_hash': job.previous_hash,
        'merkleroot': merkleroot,
        'time': job.ntime,
        'bits': int.from_bytes(job.bits, 'big'),
        'nonce': nonce,
        # meta
        'height': job.height,
        'flag': job.algorithm,
    })
    # check fulfill target or share
    update_work_hash(block)
    f_mined = block.pow_check()
    f_shared = block.pow_check(int(DEFAULT_TARGET / difficulty))
    log.debug(f"block -> {block.height} {block.hash.hex()}")
    log.debug(f"coinbase -> {coinbase.hex()}")
    log.debug(f"header -> {block.b.hex()}")
    log.debug(f"merkleroot -> {len(merkleroot_list)} {merkleroot.hex()}")
    log.debug(
        f"workhash -> {block.work_hash.hex()} mined:{f_mined} shared:{f_shared}"
    )
    # generate submit data when mined
    if f_mined:
        submit_data = block.b
        tx_len = len(job.unconfirmed) + 1
        if tx_len < 0xfd:
            submit_data += tx_len.to_bytes(1, 'little')
        elif tx_len <= 0xffff:
            submit_data += b'\xfd' + tx_len.to_bytes(2, 'little')
        elif tx_len <= 0xffffffff:
            submit_data += b'\xfe' + tx_len.to_bytes(4, 'little')
        elif tx_len <= 0xffffffffffffffff:  # == 0xff
            submit_data += b'\xff' + tx_len.to_bytes(8, 'little')
        else:
            raise Exception(f"overflowed tx length {tx_len}")
        submit_data += coinbase
        for tx in job.unconfirmed:
            submit_data += tx[1]
    else:
        submit_data = None
    return submit_data, block, f_mined, f_shared
Exemple #14
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
Exemple #15
0
def fill_newblock_info(data):
    new_block: Block = Block.from_binary(binary=data['binary'])
    log.debug("fill newblock height={} newblock={}".format(
        data.get('height'), new_block.hash.hex()))
    proof: TX = data['proof']
    new_block.txs.append(proof)
    new_block.flag = data['block_flag']
    my_block = chain_builder.get_block(new_block.hash)
    if my_block:
        raise BlockChainError('Already inserted block {}'.format(my_block))
    before_block = chain_builder.get_block(new_block.previous_hash)
    if before_block is None:
        log.debug("Cannot find beforeBlock, try to ask outside node")
        # not found beforeBlock, need to check other node have the the block
        new_block.inner_score *= 0.70  # unknown previousBlock, score down
        before_block = make_block_by_node(blockhash=new_block.previous_hash,
                                          depth=0)
    new_height = before_block.height + 1
    proof.height = new_height
    new_block.height = new_height
    # work check
    # TODO: correct position?
    if not new_block.pow_check():
        raise BlockChainError('Proof of work is not satisfied')
    # Append general txs
    for txhash in data['txs'][1:]:
        tx = tx_builder.get_tx(txhash)
        if tx is None:
            new_block.inner_score *= 0.75  # unknown tx, score down
            log.debug("Unknown tx, try to download")
            r = ask_node(cmd=DirectCmd.TX_BY_HASH,
                         data={'txhash': txhash},
                         f_continue_asking=True)
            if isinstance(r, str):
                raise BlockChainError(
                    'Failed unknown tx download "{}"'.format(r))
            tx: TX = r
            tx.height = None
            check_tx(tx, include_block=None)
            tx_builder.put_unconfirmed(tx)
            log.debug("Success unknown tx download {}".format(tx))
        tx.height = new_height
        new_block.txs.append(tx)
    return new_block
Exemple #16
0
def load_boot_file(url=None):
    normal_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                               'boot.json')
    extra_path = os.path.join(V.DB_HOME_DIR, 'boot.json')
    if url:
        data = requests.get(url=url).json()
    elif os.path.exists(normal_path):
        with open(normal_path, mode='r') as fp:
            data = json.load(fp)
    elif os.path.exists(extra_path):
        with open(extra_path, mode='r') as fp:
            data = json.load(fp)
    else:
        raise FileNotFoundError('Cannot find boot.json "{}" or "{}" ?'.format(
            normal_path, extra_path))
    # load from exist boot.json
    genesis_block = Block.from_binary(binary=a2b_hex(data['genesis_binary']))
    assert genesis_block.hash == a2b_hex(data['genesis_hash'])
    genesis_block.flag = C.BLOCK_GENESIS
    genesis_block.height = 0
    for tx_dct in data['txs']:
        tx = TX.from_binary(binary=a2b_hex(tx_dct['binary']))
        assert tx.hash == a2b_hex(tx_dct['hash'])
        tx.height = 0
        genesis_block.txs.append(tx)
    connections = data['connections']
    network_ver = data['network_ver']
    if isinstance(data['params'], dict):
        # new type boot.json
        params = data['params']
        params['consensus'] = {
            int(k): v
            for k, v in params['consensus'].items()
        }
    elif isinstance(data['params'], str):
        # old type boot.json
        params = original_mpk.unpackb(a2b_hex(data['params']),
                                      raw=True,
                                      encoding='utf8')
    else:
        raise Exception('Unknown type params')
    return genesis_block, params, network_ver, connections
Exemple #17
0
def object_hook(dct):
    if isinstance(dct, dict) and '_bc4py_class_' in dct:
        if dct['_bc4py_class_'] == 'Block':
            block = Block.from_binary(binary=dct['binary'])
            block.height = dct['height']
            block.flag = dct['flag']
            block.txs.extend(object_hook(tx) for tx in dct['txs'])
            for tx in block.txs:
                tx.height = block.height
            return block
        elif dct['_bc4py_class_'] == 'TX':
            tx = TX.from_binary(binary=dct['binary'])
            tx.height = dct['height']
            tx.signature.extend(tuple(sig) for sig in dct['signature'])
            tx.R = dct['R']
            return tx
        else:
            raise Exception('Not found class name "{}"'.format(
                dct['_bc4py_class_']))
    else:
        return dct
Exemple #18
0
    def init(self, genesis_block: Block, batch_size=None):
        assert self.db, 'Why database connection failed?'
        if batch_size is None:
            batch_size = self.cashe_limit
        # GenesisBlockか確認
        t = time.time()
        try:
            if genesis_block.hash != self.db.read_block_hash(0):
                raise BlockBuilderError("Don't match genesis hash [{}!={}]".format(
                    hexlify(genesis_block.hash).decode(), hexlify(self.db.read_block_hash(0).decode())))
            elif genesis_block != self.db.read_block(genesis_block.hash):
                raise BlockBuilderError("Don't match genesis binary [{}!={}]".format(
                    hexlify(genesis_block.b).decode(), hexlify(self.db.read_block(genesis_block.hash).b).decode()))
        except Exception:
            # GenesisBlockしか無いのでDummyBlockを入れる処理
            self.root_block = Block()
            self.root_block.hash = b'\xff' * 32
            self.chain[genesis_block.hash] = genesis_block
            self.best_chain = [genesis_block]
            self.best_block = genesis_block
            logging.info("Set dummy block. GenesisBlock={}".format(genesis_block))
            user_account.init()
            return

        # 0HeightよりBlockを取得して確認
        before_block = genesis_block
        batch_blocks = list()
        for height, blockhash in self.db.read_block_hash_iter(start_height=1):
            block = self.db.read_block(blockhash)
            if block.previous_hash != before_block.hash:
                raise BlockBuilderError("PreviousHash != BlockHash [{}!={}]"
                                        .format(block, before_block))
            elif block.height != height:
                raise BlockBuilderError("BlockHeight != DBHeight [{}!={}]"
                                        .format(block.height, height))
            elif height != before_block.height+1:
                raise BlockBuilderError("DBHeight != BeforeHeight+1 [{}!={}+1]"
                                        .format(height, before_block.height))
            for tx in block.txs:
                if tx.height != height:
                    raise BlockBuilderError("TXHeight != BlockHeight [{}!{}]"
                                            .format(tx.height, height))
                # inputs
                for txhash, txindex in tx.inputs:
                    input_tx = self.db.read_tx(txhash)
                    address, coin_id, amount = input_tx.outputs[txindex]
                    _coin_id, _amount, f_used = self.db.read_address_idx(address, txhash, txindex)
                    usedindex = self.db.read_usedindex(txhash)
                    if coin_id != _coin_id or amount != _amount:
                        raise BlockBuilderError("Inputs, coin_id != _coin_id or amount != _amount [{}!{}] [{}!={}]"
                                                .format(coin_id, _coin_id, amount, _amount))
                    elif txindex not in usedindex:
                        raise BlockBuilderError("Already used but unused. [{} not in {}]".format(txindex, usedindex))
                    elif not f_used:
                        raise BlockBuilderError("Already used but unused flag. [{}:{}]".format(input_tx, txindex))
                # outputs
                for index, (address, coin_id, amount) in enumerate(tx.outputs):
                    _coin_id, _amount, f_used = self.db.read_address_idx(address, tx.hash, index)
                    if coin_id != _coin_id or amount != _amount:
                        raise BlockBuilderError("Outputs, coin_id != _coin_id or amount != _amount [{}!{}] [{}!={}]"
                                                .format(coin_id, _coin_id, amount, _amount))
            # Block確認終了
            before_block = block
            batch_blocks.append(block)
            if len(batch_blocks) >= batch_size:
                user_account.new_batch_apply(batch_blocks)
                batch_blocks.clear()
                logging.debug("UserAccount batched at {} height.".format(block.height))
        # import from starter.dat
        self.root_block = before_block
        memorized_blocks, self.best_block = self.load_starter(before_block)
        # Memory化されたChainを直接復元
        for block in memorized_blocks:
            batch_blocks.append(block)
            self.chain[block.hash] = block
            for tx in block.txs:
                if tx.hash not in tx_builder.chained_tx:
                    tx_builder.chained_tx[tx.hash] = tx
                if tx.hash in tx_builder.unconfirmed:
                    del tx_builder.unconfirmed[tx.hash]
        self.best_chain = list(reversed(memorized_blocks))
        # UserAccount update
        user_account.new_batch_apply(batch_blocks)
        user_account.init()
        logging.info("Init finished, last block is {} {}Sec"
                     .format(before_block, round(time.time()-t, 3)))
Exemple #19
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")
Exemple #20
0
async def submitblock(*args, **kwargs):
    """
    Attempts to submit new block to network.
    See https://en.bitcoin.it/wiki/BIP_0022 for full specification.

    Arguments
        1. "hexdata"        (string, required) the hex-encoded block data to submit
        2. "dummy"          (optional) dummy value, for compatibility with BIP22. This value is ignored.

    Result:
        null if success
        string if failed
    """
    if len(args) == 0:
        raise ValueError('no argument found')
    block_hex_or_obj = args[0]
    if isinstance(block_hex_or_obj, str):
        block_bin = a2b_hex(block_hex_or_obj)
        # Block
        mined_block = Block.from_binary(binary=block_bin[:80])
        if mined_block.previous_hash != chain_builder.best_block.hash:
            return 'PreviousHash don\'t match'
        previous_block = chain_builder.get_block(mined_block.previous_hash)
        mined_block.height = previous_block.height + 1
        mined_block.flag = int(kwargs['password'])
        # tx length
        storage_flag = int.from_bytes(block_bin[80:81], 'little')
        if storage_flag < 0xfd:
            tx_len = storage_flag
            pos = 81
        elif storage_flag == 0xfd:
            tx_len = int.from_bytes(block_bin[81:83], 'little')
            pos = 83
        elif storage_flag == 0xfe:
            tx_len = int.from_bytes(block_bin[81:85], 'little')
            pos = 85
        else:  # == 0xff
            tx_len = int.from_bytes(block_bin[81:89], 'little')
            pos = 89
        log.debug("RpcSubmit block: pos={}, tx_len={}".format(pos, tx_len))
        # correct txs
        while len(block_bin) > pos:
            tx = TX()
            tx.b = block_bin
            tx.deserialize(first_pos=pos, f_raise=False)
            if tx.version != __chain_version__:
                return 'tx_ver do not match [{}!={}]'.format(tx.version, __chain_version__)
            pos += len(tx.b)
            mined_block.txs.append(tx_builder.get_tx(txhash=tx.hash, default=tx))
        # check format
        if tx_len != len(mined_block.txs):
            return 'Do not match txlen [{}!={}]'.format(tx_len, len(mined_block.txs))
        if pos != len(block_bin):
            return 'Do not match pos [{}!={}]'.format(pos, len(block_bin))
    elif isinstance(block_hex_or_obj, Block):
        mined_block = block_hex_or_obj
        previous_block = chain_builder.get_block(mined_block.previous_hash)
        mined_block.height = previous_block.height + 1
        mined_block.flag = int(kwargs['password'])
    else:
        return 'Unknown input? -> {}'.format(block_hex_or_obj)
    mined_block.update_pow()
    if mined_block.pow_check():
        confirmed_generating_block(mined_block)
        return None  # accepted
    else:
        return 'not satisfied work'
Exemple #21
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")
Exemple #22
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")
Exemple #23
0
def create_genesis_block(mining_supply,
                         block_span,
                         hrp='pycon',
                         digit_number=8,
                         minimum_price=100,
                         consensus=None,
                         genesis_msg="blockchain for python",
                         premine=None):
    """
    Height0のGenesisBlockを作成する
    :param mining_supply: PoW/POS合わせた全採掘量、プリマインを除く
    :param block_span: Blockの採掘間隔(Sec)
    :param hrp: human readable part
    :param digit_number: コインの分解能
    :param minimum_price: 最小gas_price
    :param consensus: 採掘アルゴ {consensus: ratio(0~100), ..}
    :param genesis_msg: GenesisMessage
    :param premine: プリマイン [(address, coin_id, amount), ...]
    """

    # default: Yescript9割, Stake1割の分配
    consensus = consensus or {C.BLOCK_X16S_POW: 100}
    if sum(consensus.values()) != 100:
        raise BlockChainError('sum of consensus values is 100 [!={}]'.format(sum(consensus.values())))
    elif not isinstance(sum(consensus.values()), int):
        raise BlockChainError('value is int only')
    elif not (0 < min(consensus.values()) <= 100):
        raise BlockChainError('out of range {}'.format(min(consensus.values())))
    elif not (0 < max(consensus.values()) <= 100):
        raise BlockChainError('out of range {}'.format(min(consensus.values())))
    all_consensus = {
        C.BLOCK_COIN_POS, C.BLOCK_CAP_POS, C.BLOCK_FLK_POS, C.BLOCK_YES_POW, C.BLOCK_X11_POW, C.BLOCK_HMQ_POW,
        C.BLOCK_LTC_POW, C.BLOCK_X16S_POW
    }
    if len(set(consensus.keys()) - all_consensus) > 0:
        raise BlockChainError('Not found all_consensus number {}'.format(set(consensus.keys()) - all_consensus))
    elif len(set(consensus.keys()) & all_consensus) == 0:
        raise BlockChainError('No usable consensus found {}'.format(set(consensus.keys()) & all_consensus))
    elif not (0 < len(hrp) < 5):
        raise BlockChainError('hrp is too long hrp={}'.format(hrp))
    elif 'dummy' in hrp or '1' in hrp:
        raise BlockChainError('Not allowed  include "dummy" and "1" str {}'.format(hrp))

    # params
    assert isinstance(minimum_price, int), 'minimum_price is INT'
    genesis_time = int(time())
    # BLockChainの設定TX
    params = {
        'hrp': hrp,
        'genesis_time': genesis_time,  # GenesisBlockの採掘時間
        'mining_supply': mining_supply,  # 全採掘量
        'block_span': block_span,  # ブロックの採掘間隔
        'digit_number': digit_number,  # 小数点以下の桁数
        'minimum_price': minimum_price,
        'contract_minimum_amount': pow(10, digit_number),
        'consensus': consensus,  # Block承認のアルゴリズム
    }
    V.BLOCK_GENESIS_TIME = genesis_time
    # first tx
    first_tx = TX.from_dict(
        tx={
            'type': C.TX_GENESIS,
            'time': 0,
            'deadline': 10800,
            'gas_price': 0,
            'gas_amount': 0,
            'message_type': C.MSG_PLAIN,
            'message': genesis_msg.encode()
        })
    first_tx.height = 0
    # premine
    premine_txs = list()
    for index, chunk in enumerate(chunked(premine or list(), 255)):
        tx = TX.from_dict(tx={
            'type': C.TX_TRANSFER,
            'time': 0,
            'deadline': 10800,
            'outputs': chunk,
            'gas_price': 0,
            'gas_amount': 0
        })
        tx.height = 0
        premine_txs.append(tx)
    # height0のBlock生成
    genesis_block = Block.from_dict(block={
        'merkleroot': b'\x00' * 32,
        'time': 0,
        'previous_hash': b'\xff' * 32,
        'bits': MAX_BITS,
        'nonce': b'\xff' * 4
    })
    # block params
    genesis_block.height = 0
    genesis_block.flag = C.BLOCK_GENESIS
    # block body
    genesis_block.txs.append(first_tx)
    genesis_block.txs.extend(premine_txs)
    genesis_block.bits2target()
    genesis_block.target2diff()
    genesis_block.update_merkleroot()
    genesis_block.serialize()
    return genesis_block, params
Exemple #24
0
def create_genesis_block(all_supply,
                         block_span,
                         prefix=b'\x98',
                         contract_prefix=b'\x12',
                         digit_number=8,
                         minimum_price=100,
                         consensus=None,
                         premine=None):
    """
    Height0のGenesisBlockを作成する
    :param all_supply: PoW/POS合わせた全採掘量、プリマインを除く
    :param block_span: Blockの採掘間隔(Sec)
    :param prefix: 一般アドレスの頭文字、b'\x98'=N
    :param contract_prefix: コントラクトの頭文字、b'\x98'=C
    :param digit_number: コインの分解能
    :param minimum_price: 最小gas_price
    :param consensus: 採掘アルゴ {consensus: ratio(0~100), ..}
    :param premine: プリマイン [(address, coin_id, amount), ...]
    """

    # default: Yescript9割, Stake1割の分配
    consensus = consensus or {C.BLOCK_YES_POW: 90, C.BLOCK_POS: 10}
    if sum(consensus.values()) != 100:
        raise BlockChainError('sum of consensus values is 100 [!={}]'.format(
            sum(consensus.values())))
    elif not isinstance(sum(consensus.values()), int):
        raise BlockChainError('value is int only.')
    elif not (0 < min(consensus.values()) <= 100):
        raise BlockChainError('out of range {}'.format(min(
            consensus.values())))
    elif not (0 < max(consensus.values()) <= 100):
        raise BlockChainError('out of range {}'.format(min(
            consensus.values())))
    all_consensus = {
        C.BLOCK_POS, C.BLOCK_YES_POW, C.BLOCK_X11_POW, C.BLOCK_HMQ_POW,
        C.BLOCK_LTC_POW, C.BLOCK_X16_POW
    }
    if len(set(consensus.keys()) - all_consensus) > 0:
        raise BlockChainError('Not found all_consensus number {}'.format(
            set(consensus.keys()) - all_consensus))
    elif len(set(consensus.keys()) & all_consensus) == 0:
        raise BlockChainError('No usable consensus found {}'.format(
            set(consensus.keys()) & all_consensus))

    # params
    assert isinstance(minimum_price, int), 'minimum_price is INT'
    genesis_time = int(time.time())
    # premine
    premine_txs = list()
    for index, chunk in enumerate(chunked(premine or list(), 256)):
        tx = TX(
            tx={
                'version': __chain_version__,
                'type': C.TX_TRANSFER,
                'time': 0,
                'deadline': 10800,
                'inputs': list(),
                'outputs': chunk,
                'gas_price': 0,
                'gas_amount': 0,
                'message_type': C.MSG_PLAIN,
                'message': 'Premine {}'.format(index).encode()
            })
        tx.height = 0
        premine_txs.append(tx)
    # validator
    V.BLOCK_GENESIS_TIME = int(time.time())
    with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
        ck = create_new_user_keypair(C.ANT_CONTRACT, db.cursor())
        db.commit()
    c_address = convert_address(ck, contract_prefix)
    c_bin = contract2binary(Contract)
    c_cs = {
        ck.encode(): b'\x00\x00\x00\x00',
        b'\x00' + b'\x00\x00\x00\x00': b'\x01'
    }  # TODO: 初期値どうする?
    validator_tx = TX(
        tx={
            'version': __chain_version__,
            'type': C.TX_CREATE_CONTRACT,
            'time': 0,
            'deadline': 10800,
            'inputs': list(),
            'outputs': list(),
            'gas_price': 0,
            'gas_amount': 0,
            'message_type': C.MSG_BYTE,
            'message': bjson.dumps((c_address, c_bin, c_cs), compress=False)
        })
    validator_tx.height = 0
    params = {
        'prefix': prefix,  # CompressedKey prefix
        'contract_prefix': contract_prefix,  # ContractKey prefix
        'validator_address': c_address,
        'genesis_time': genesis_time,  # GenesisBlockの採掘時間
        'all_supply': all_supply,  # 全採掘量
        'block_span': block_span,  # ブロックの採掘間隔
        'digit_number': digit_number,  # 小数点以下の桁数
        'minimum_price': minimum_price,
        'contract_minimum_amount': pow(10, digit_number),
        'consensus': consensus
    }  # Block承認のアルゴリズム
    # BLockChainの設定TX
    setting_tx = TX(
        tx={
            'version': __chain_version__,
            'type': C.TX_GENESIS,
            'time': 0,
            'deadline': 10800,
            'inputs': list(),
            'outputs': list(),
            'gas_price': 0,
            'gas_amount': 0,
            'message_type': C.MSG_BYTE,
            'message': bjson.dumps(params, compress=False)
        })
    setting_tx.height = 0
    # height0のBlock生成
    genesis_block = Block(
        block={
            'merkleroot': b'\x00' * 32,
            'time': 0,
            'previous_hash': b'\xff' * 32,
            'bits': MAX_BITS,
            'nonce': b'\xff' * 4
        })
    # block params
    genesis_block.height = 0
    genesis_block.flag = C.BLOCK_GENESIS
    # block body
    genesis_block.txs.append(setting_tx)
    genesis_block.txs.append(validator_tx)
    genesis_block.txs.extend(premine_txs)
    genesis_block.bits2target()
    genesis_block.target2diff()
    genesis_block.update_merkleroot()
    genesis_block.serialize()
    return genesis_block