Esempio n. 1
0
def create_contract_transfer_tx(c_address,
                                cur,
                                c_method,
                                c_args=None,
                                send_pairs=None,
                                sender=C.ANT_UNKNOWN,
                                gas_price=None,
                                retention=10800):
    assert isinstance(c_method, str)
    if sender in (C.ANT_OUTSIDE, C.ANT_RESERVED):
        raise BlockChainError('Not allowed inner account.')
    if c_args is None:
        c_args = tuple()
    else:
        c_args = tuple(c_args)
    redeem_address = create_new_user_keypair(read_user2name(sender, cur), cur)
    msg_body = bjson.dumps((c_address, c_method, redeem_address, c_args),
                           compress=False)
    send_pairs = send_pairs_format_check(c_address=c_address,
                                         send_pairs=send_pairs)
    tx = send_many(sender=sender,
                   send_pairs=send_pairs,
                   cur=cur,
                   fee_coin_id=0,
                   gas_price=gas_price,
                   msg_type=C.MSG_BYTE,
                   msg_body=msg_body,
                   retention=retention)
    return tx
Esempio n. 2
0
def create_contract_update_tx(c_address,
                              cur,
                              c_bin=None,
                              c_extra_imports=None,
                              c_settings=None,
                              send_pairs=None,
                              sender=C.ANT_UNKNOWN,
                              gas_price=None,
                              retention=10800):
    assert c_bin or c_extra_imports or c_settings
    if sender in (C.ANT_OUTSIDE, C.ANT_RESERVED):
        raise BlockChainError('Not allowed inner account.')
    c_method = contract.M_UPDATE
    c_args = (c_bin, c_extra_imports, c_settings)
    redeem_address = create_new_user_keypair(read_user2name(sender, cur), cur)
    msg_body = bjson.dumps((c_address, c_method, redeem_address, c_args),
                           compress=False)
    send_pairs = send_pairs_format_check(c_address=c_address,
                                         send_pairs=send_pairs)
    tx = send_many(sender=sender,
                   send_pairs=send_pairs,
                   cur=cur,
                   fee_coin_id=0,
                   gas_price=gas_price,
                   msg_type=C.MSG_BYTE,
                   msg_body=msg_body,
                   retention=retention)
    return tx
Esempio n. 3
0
def replace_redeem_dummy_address(tx, cur):
    new_redeem_address = set()
    for index, (address, coin_id, amount) in enumerate(tx.outputs):
        if address != DUMMY_REDEEM_ADDRESS:
            continue
        new_address = create_new_user_keypair(C.ANT_NAME_UNKNOWN, cur)
        tx.outputs[index] = (new_address, coin_id, amount)
        new_redeem_address.add(new_address)
    tx.serialize()
    return new_redeem_address
Esempio n. 4
0
def start_contract_tx(c_address,
                      c_method,
                      cur,
                      c_args=None,
                      outputs=None,
                      sender=C.ANT_UNKNOWN,
                      gas_price=None,
                      additional_gas_amount=None,
                      retention=10800):
    # TXを作成
    now = int(time.time()) - V.BLOCK_GENESIS_TIME
    c_redeem = create_new_user_keypair(C.ANT_NAME_UNKNOWN, cur)
    message = bjson.dumps((c_address, c_method, c_args or tuple(), c_redeem),
                          compress=False)
    tx = TX(
        tx={
            'version': __chain_version__,
            'type': C.TX_START_CONTRACT,
            'time': now,
            'deadline': now + retention,
            'inputs': list(),
            'outputs': outputs or list(),
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 1,
            'message_type': C.MSG_BYTE,
            'message': message
        })
    check_output_format(tx.outputs)
    tx.gas_amount = tx.getsize() + 96
    tx.serialize()
    # fill unspents
    fee_coin_id = 0
    input_address = fill_inputs_outputs(
        tx, cur, fee_coin_id, additional_gas_amount
        or V.CONTRACT_MINIMUM_AMOUNT)
    fee_coins = CoinObject(fee_coin_id, tx.gas_price * tx.gas_amount)
    movements = UserCoins()
    movements[sender] -= fee_coins
    movements[C.ANT_OUTSIDE] += fee_coins
    # account check
    send_coins = CoinObject()
    check_enough_amount(sender, send_coins, fee_coins)
    if sender in (C.ANT_OUTSIDE, C.ANT_RESERVED):
        raise BlockChainError('Not allowed inner account.')
    # replace dummy address
    replace_redeem_dummy_address(tx, cur)
    # setup signature
    tx.serialize()
    setup_signature(tx, input_address)
    movements[sender] -= fee_coins
    movements[C.ANT_OUTSIDE] += fee_coins
    insert_log(movements, cur, tx.type, tx.time, tx.hash)
    return tx
Esempio n. 5
0
def create_contract_tx(c_bin,
                       cur,
                       sender=C.ANT_UNKNOWN,
                       c_cs=None,
                       gas_price=None,
                       retention=10800):
    assert isinstance(c_bin, bytes), 'contract is bytes code.'
    assert isinstance(sender, int), 'Sender is id.'
    if c_cs:
        for k, v in c_cs.items():
            assert isinstance(k, bytes), 'Key is bytes.'
            assert isinstance(v, bytes), 'Value is bytes.'
    # TXを作成
    now = int(time.time()) - V.BLOCK_GENESIS_TIME
    ck = create_new_user_keypair(C.ANT_NAME_CONTRACT, cur)
    c_address = convert_address(ck, V.BLOCK_CONTRACT_PREFIX)
    message = bjson.dumps((c_address, c_bin, c_cs), compress=False)
    tx = TX(
        tx={
            'version': __chain_version__,
            'type': C.TX_CREATE_CONTRACT,
            'time': now,
            'deadline': now + retention,
            'inputs': list(),
            'outputs': list(),
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 1,
            'message_type': C.MSG_BYTE,
            'message': message
        })
    tx.gas_amount = tx.getsize() + C.CONTRACT_CREATE_FEE + 96
    # fill unspents
    fee_coin_id = 0
    input_address = fill_inputs_outputs(tx, cur, fee_coin_id,
                                        C.CONTRACT_CREATE_FEE)
    fee_coins = CoinObject(fee_coin_id, tx.gas_price * tx.gas_amount)
    movements = UserCoins()
    movements[sender] -= fee_coins
    movements[C.ANT_OUTSIDE] += fee_coins
    # account check
    send_coins = CoinObject()
    check_enough_amount(sender, send_coins, fee_coins)
    if sender in (C.ANT_OUTSIDE, C.ANT_RESERVED):
        raise BlockChainError('Not allowed inner account.')
    # replace dummy address
    replace_redeem_dummy_address(tx, cur)
    # setup signature
    tx.serialize()
    setup_signature(tx, input_address)
    movements[sender] -= fee_coins
    movements[C.ANT_OUTSIDE] += fee_coins
    insert_log(movements, cur, tx.type, tx.time, tx.hash)
    return c_address, tx
Esempio n. 6
0
def issue_mintcoin(name,
                   unit,
                   amount,
                   digit,
                   cur,
                   gas_price=None,
                   message='',
                   additional_issue=True,
                   image=None,
                   sender=C.ANT_UNKNOWN):
    mint = MintCoinObject(None)
    new_mint_id = get_new_coin_id()
    mint.version = 0
    mint.coin_id = new_mint_id
    mint.name = name
    mint.unit = unit
    mint.digit = digit
    mint.supply_before = 0
    mint.amount = amount
    mint.additional_issue = additional_issue
    new_mint_address = create_new_user_keypair(C.ANT_NAME_UNKNOWN, cur)
    uuid, sk, pk = read_address2keypair(new_mint_address, cur)
    mint.owner = pk
    mint.image = image
    mint.message = message
    # Message内署名
    mint.generate_sign(sk)
    mint.serialize()
    mint.check_param()
    mint.check_sign()
    logging.info("New Mintcoin skeleton created coin_id={}".format(
        mint.coin_id))
    # movement
    movements = UserCoins()
    minting_coins = CoinObject(new_mint_id, amount)
    movements[sender] += minting_coins
    movements[C.ANT_OUTSIDE] -= minting_coins
    # TXを作成する
    base_coin_id = 0
    now = int(time.time()) - V.BLOCK_GENESIS_TIME
    tx = TX(
        tx={
            'version': __chain_version__,
            'type': C.TX_MINT_COIN,
            'time': now,
            'deadline': now + 10800,
            'inputs': list(),
            'outputs': [(MINTCOIN_DUMMY_ADDRESS, base_coin_id, amount)],
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 1,
            'message_type': C.MSG_BYTE,
            'message': mint.binary
        })
    tx.gas_amount = tx.getsize() + 96 + C.MINTCOIN_FEE
    tx.serialize()
    # fill unspents
    fee_coin_id = 0
    input_address = fill_inputs_outputs(tx, cur, fee_coin_id, C.MINTCOIN_FEE)
    fee_coins = CoinObject(fee_coin_id, tx.gas_price * tx.gas_amount)
    # check amount
    check_enough_amount(sender, CoinObject(base_coin_id, amount), fee_coins)
    # replace dummy address
    replace_redeem_dummy_address(tx, cur)
    # replace dummy mint_id
    replace_mint_dummy_address(tx, new_mint_address, new_mint_id)
    # setup signature
    tx.serialize()
    setup_signature(tx, input_address)
    movements[sender] -= fee_coins
    movements[C.ANT_OUTSIDE] += fee_coins
    insert_log(movements, cur, tx.type, tx.time, tx.hash)
    return mint, tx
Esempio n. 7
0
def issue_mintcoin(name,
                   unit,
                   digit,
                   amount,
                   cur,
                   description=None,
                   image=None,
                   additional_issue=True,
                   change_address=True,
                   gas_price=None,
                   sender=C.ANT_UNKNOWN,
                   retention=10800):
    mint_id = get_new_coin_id()
    sender_name = read_user2name(user=sender, cur=cur)
    mint_address = create_new_user_keypair(name=sender_name, cur=cur)
    params = {
        "name": name,
        "unit": unit,
        "digit": digit,
        "address": mint_address,
        "description": description,
        "image": image
    }
    setting = {
        "additional_issue": additional_issue,
        "change_address": change_address
    }
    m_before = get_mintcoin_object(coin_id=mint_id)
    result = check_mintcoin_new_format(m_before=m_before,
                                       new_params=params,
                                       new_setting=setting)
    if isinstance(result, str):
        raise BlockChainError('check_mintcoin_new_format(): {}'.format(result))
    msg_body = bjson.dumps((mint_id, params, setting), compress=False)
    tx = TX(
        tx={
            'type': C.TX_MINT_COIN,
            'inputs': list(),
            'outputs': [(MINTCOIN_DUMMY_ADDRESS, 0, amount)],
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 1,
            'message_type': C.MSG_BYTE,
            'message': msg_body
        })
    tx.update_time(retention)
    additional_gas = C.MINTCOIN_GAS
    tx.gas_amount = tx.size + C.SIGNATURE_GAS + additional_gas
    tx.serialize()
    # fill unspents
    fee_coin_id = 0
    input_address = fill_inputs_outputs(tx=tx,
                                        cur=cur,
                                        fee_coin_id=fee_coin_id,
                                        additional_gas=additional_gas)
    # input_address.add(mint_address)
    fee_coins = Balance(coin_id=fee_coin_id,
                        amount=tx.gas_price * tx.gas_amount)
    # check amount
    check_enough_amount(sender=sender,
                        send_coins=Balance(0, amount),
                        fee_coins=fee_coins)
    # replace dummy address
    replace_redeem_dummy_address(tx=tx, cur=cur)
    # replace dummy mint_id
    replace_mint_dummy_address(tx=tx,
                               mint_address=mint_address,
                               mint_id=mint_id,
                               f_raise=True)
    # setup signature
    tx.serialize()
    setup_signature(tx=tx, input_address=input_address)
    # movement
    movements = Accounting()
    minting_coins = Balance(mint_id, amount)
    movements[sender] += minting_coins
    movements[C.ANT_OUTSIDE] -= minting_coins
    movements[sender] -= fee_coins
    movements[C.ANT_OUTSIDE] += fee_coins
    insert_log(movements, cur, tx.type, tx.time, tx.hash)
    return mint_id, tx
Esempio n. 8
0
def new_key(user=C.ANT_NAME_UNKNOWN):
    with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
        cur = db.cursor()
        ck = create_new_user_keypair(user, cur)
        db.commit()
    return ck
Esempio n. 9
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