Esempio n. 1
0
def contract_signature_check(extra_tx: TX, v: Validator, include_block: Block):
    signed_cks = get_signed_cks(extra_tx)
    accept_cks = signed_cks & set(v.validators)
    if include_block:
        # check satisfy require?
        if len(accept_cks) < v.require:
            raise BlockChainError('Not satisfied require signature. [signed={}, accepted={}, require={}]'
                                  .format(signed_cks, accept_cks, v.require))
    else:
        # check can marge?
        original_tx = tx_builder.get_tx(txhash=extra_tx.hash)
        if original_tx is None:
            # not accept before
            if 0 < v.require and len(accept_cks) == 0:
                raise BlockChainError('No acceptable signature. signed={}'.format(signed_cks))
        else:
            # need to marge signature
            if original_tx.height is not None:
                raise BlockChainError('Already included tx. height={}'.format(original_tx.height))
            if v.require == 0:
                raise BlockChainError('Don\t need to marge signature.')
            original_cks = get_signed_cks(original_tx)
            accept_new_cks = (signed_cks - original_cks) & set(v.validators)
            if len(accept_new_cks) == 0:
                raise BlockChainError('No new acceptable cks. ({} - {}) & {}'
                                      .format(signed_cks, original_cks, set(v.validators)))
Esempio n. 2
0
def check_tx_time(tx):
    # For unconfirmed tx
    now = int(time.time()) - V.BLOCK_GENESIS_TIME
    if tx.type in (C.TX_VALIDATOR_EDIT, C.TX_CONCLUDE_CONTRACT):
        if not (tx.time - C.ACCEPT_MARGIN_TIME < now <
                tx.deadline + C.ACCEPT_MARGIN_TIME):
            raise BlockChainError(
                'TX time is not correct range. {}<{}<{}'.format(
                    tx.time - C.ACCEPT_MARGIN_TIME, now,
                    tx.deadline + C.ACCEPT_MARGIN_TIME))
    else:
        if tx.time > now + C.ACCEPT_MARGIN_TIME:
            raise BlockChainError('TX time too early. {}>{}+{}'.format(
                tx.time, now, C.ACCEPT_MARGIN_TIME))
        if tx.deadline < now - C.ACCEPT_MARGIN_TIME:
            raise BlockChainError('TX time is too late. [{}<{}-{}]'.format(
                tx.deadline, now, C.ACCEPT_MARGIN_TIME))
    # common check
    if tx.deadline - tx.time < 10800:
        raise BlockChainError(
            'TX acceptable spam is too short. {}-{}<{}'.format(
                tx.deadline, tx.time, 10800))
    if tx.deadline - tx.time > 43200:  # 12hours
        raise BlockChainError(
            'TX acceptable spam is too long. {}-{}<{}'.format(
                tx.deadline, tx.time, 10800))
Esempio n. 3
0
def update_work_hash(block):
    if block.flag == C.BLOCK_GENESIS:
        block.work_hash = b'\xff' * 32
    elif block.flag == C.BLOCK_COIN_POS:
        proof_tx = block.txs[0]
        if proof_tx.pos_amount is None:
            from bc4py.database.builder import tx_builder
            txhash, txindex = proof_tx.inputs[0]
            output_tx = tx_builder.get_tx(txhash)
            if output_tx is None:
                raise BlockChainError('Not found output {} of {}'.format(
                    proof_tx, block))
            address, coin_id, amount = output_tx.outputs[txindex]
            proof_tx.pos_amount = amount
        block.work_hash = get_stake_coin_hash(
            tx=proof_tx, previous_hash=block.previous_hash)
    elif block.flag == C.BLOCK_CAP_POS:
        proof_tx = block.txs[0]
        address, coin_id, amount = proof_tx.outputs[0]
        scope_hash = poc_hash(address=address, nonce=block.nonce)
        index = scope_index(block.previous_hash)
        block.work_hash = poc_work(time=block.time,
                                   scope_hash=scope_hash[index *
                                                         32:index * 32 + 32],
                                   previous_hash=block.previous_hash)
    elif block.flag == C.BLOCK_FLK_POS:
        raise BlockChainError("unimplemented")
    else:
        # POW_???
        hash_fnc = get_workhash_fnc(block.flag)
        block.work_hash = hash_fnc(block.b)
Esempio n. 4
0
def create_conclude_tx(c_address, start_tx, send_pairs=None, c_storage=None):
    assert isinstance(start_tx, TX)
    assert send_pairs is None or isinstance(send_pairs, list)
    assert c_storage is None or isinstance(c_storage, dict)
    message = bjson.dumps((c_address, start_tx.hash, c_storage),
                          compress=False)
    v = get_validator_object(c_address=c_address)
    send_pairs = send_pairs or list()
    tx = TX(
        tx={
            'type': C.TX_CONCLUDE_CONTRACT,
            'time': start_tx.time,
            'deadline': start_tx.deadline,
            'gas_price': start_tx.gas_price,
            'gas_amount': 0,
            'outputs': [tuple(s) for s in send_pairs],
            'message_type': C.MSG_BYTE,
            'message': message
        })
    extra_gas = C.SIGNATURE_GAS * v.require
    tx.gas_amount = tx.size + extra_gas
    # fill unspents
    fill_contract_inputs_outputs(tx=tx,
                                 c_address=c_address,
                                 additional_gas=extra_gas)
    # replace dummy address
    replace_redeem_dummy_address(tx=tx, replace_by=c_address)
    tx.serialize()
    if v.index == -1:
        raise BlockChainError(
            'Not init validator address. {}'.format(c_address))
    if setup_contract_signature(tx, v.validators) == 0:
        raise BlockChainError('Cannot sign, you are not validator.')
    return tx
Esempio n. 5
0
def ask_node(cmd, data=None, f_continue_asking=False):
    check_connection()
    count = 10
    pc = V.PC_OBJ
    user_list = pc.p2p.user.copy()
    random.shuffle(user_list)
    while 0 < count:
        try:
            if len(user_list) == 0:
                raise BlockChainError('Asked all nodes, no node to ask.')
            user = user_list.pop()
            if user in bad_node:
                count -= 1
                continue
            elif user not in good_node:
                set_good_node()
                if len(good_node) == 0:
                    raise BlockChainError('No good node found.')
                else:
                    logging.debug("Get good node {}".format(len(good_node)))
                    continue
            dummy, r = pc.send_direct_cmd(cmd=cmd, data=data, user=user)
            if f_continue_asking and isinstance(r, str):
                if count > 0:
                    logging.warning(
                        "Failed DirectCmd:{} to {} by \"{}\"".format(
                            cmd, user.name, r))
                    count -= 1
                    continue
                else:
                    raise BlockChainError('Node return error "{}"'.format(r))
        except TimeoutError:
            continue
        return r
    raise BlockChainError('Too many retry ask_node.')
Esempio n. 6
0
def amount_check(tx, payfee_coin_id):
    # Inputs
    input_coins = Balance()
    for txhash, txindex in tx.inputs:
        input_tx = tx_builder.get_tx(txhash)
        if input_tx is None:
            raise BlockChainError('Not found input tx {}'.format(txhash.hex()))
        address, coin_id, amount = input_tx.outputs[txindex]
        input_coins[coin_id] += amount

    # Outputs
    output_coins = Balance()
    for address, coin_id, amount in tx.outputs:
        if amount <= 0:
            raise BlockChainError('Input amount is more than 0')
        output_coins[coin_id] += amount

    # Fee
    fee_coins = Balance(coin_id=payfee_coin_id,
                        amount=tx.gas_price * tx.gas_amount)

    # Check all plus amount
    remain_amount = input_coins - output_coins - fee_coins
    if not remain_amount.is_empty():
        raise BlockChainError(
            '77 Don\'t match input/output. {}={}-{}-{}'.format(
                remain_amount, input_coins, output_coins, fee_coins))
Esempio n. 7
0
def amount_check(tx, payfee_coin_id):
    # Inputs
    input_coins = CoinObject()
    for txhash, txindex in tx.inputs:
        input_tx = tx_builder.get_tx(txhash)
        if input_tx is None:
            raise BlockChainError('Not found input tx {}'.format(
                hexlify(txhash).decode()))
        address, coin_id, amount = input_tx.outputs[txindex]
        input_coins[coin_id] += amount

    # Outputs
    output_coins = CoinObject()
    for address, coin_id, amount in tx.outputs:
        if amount <= 0:
            raise BlockChainError('Input amount is more than 0')
        output_coins[coin_id] += amount

    # Fee
    fee_coins = CoinObject(coin_id=payfee_coin_id,
                           amount=tx.gas_price * tx.gas_amount)

    # Check all plus amount
    remain_amount = input_coins - output_coins - fee_coins
    if not remain_amount.is_all_plus_amount():
        raise BlockChainError(
            'There are minus amount coins. {}={}-{}-{}'.format(
                remain_amount, input_coins, output_coins, fee_coins))
Esempio n. 8
0
def start_tx2index(start_hash=None, start_tx=None):
    if start_hash:
        start_tx = tx_builder.get_tx(txhash=start_hash)
    block = builder.get_block(blockhash=builder.get_block_hash(height=start_tx.height))
    if block is None:
        raise BlockChainError('Not found block of start_tx included? {}'.format(start_tx))
    if start_tx not in block.txs:
        raise BlockChainError('Not found start_tx in block? {}'.format(block))
    return start_tx.height * 0xffffffff + block.txs.index(start_tx)
Esempio n. 9
0
def check_block(block: Block):
    # 挿入前にBlockの正当性チェック
    if len(block.txs) == 0:
        raise BlockChainError('Block don\'t have any txs')
    elif block.size > C.SIZE_BLOCK_LIMIT:
        raise BlockChainError('Block size is too large [{}b>{}b]'.format(block.size, 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))
    log.debug("check block success {}".format(block))
Esempio n. 10
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))
Esempio n. 11
0
def check_output_format(outputs):
    for o in outputs:
        if not isinstance(o, tuple):
            raise BlockChainError('Outputs is tuple.')
        elif len(o) != 3:
            raise BlockChainError('Output is three element.')
        address, coin_id, amount = o
        if not isinstance(address, str) or len(address) != 40:
            raise BlockChainError('output address is 40 string. {}'.format(address))
        elif not isinstance(coin_id, int) or coin_id < 0:
            raise BlockChainError('output coin_id is 0< int. {}'.format(coin_id))
        elif not isinstance(amount, int) or not(amount > 0):
            raise BlockChainError('output amount is 0<= int. {}'.format(amount))
Esempio n. 12
0
def check_tx_time(tx):
    # For unconfirmed tx
    now = int(time.time()) - V.BLOCK_GENESIS_TIME
    if tx.time > now + C.ACCEPT_MARGIN_TIME:
        raise BlockChainError('TX time too early. {}>{}+{}'.format(
            tx.time, now, C.ACCEPT_MARGIN_TIME))
    elif tx.deadline - tx.time < 10800:
        raise BlockChainError(
            'TX acceptable spam is too short. {}-{}<{}'.format(
                tx.deadline, tx.time, 10800))
    elif tx.deadline < now - C.ACCEPT_MARGIN_TIME:
        raise BlockChainError('TX time is too late. [{}<{}-{}]'.format(
            tx.deadline, now, C.ACCEPT_MARGIN_TIME))
Esempio n. 13
0
def check_tx_create_contract(tx: TX, include_block: Block):
    if len(tx.inputs) == 0 or len(tx.outputs) == 0:
        raise BlockChainError('No inputs or outputs.')
    elif tx.message_type != C.MSG_BYTE:
        raise BlockChainError('create contract tx is bytes msg.')
    elif V.BLOCK_CONTRACT_PREFIX is None:
        raise BlockChainError('Not set contract prefix ?')
    elif V.BLOCK_CONTRACT_PREFIX == V.BLOCK_PREFIX:
        raise BlockChainError('normal prefix same with contract prefix.')
    # GAS量チェック
    estimate_gas = tx.getsize() + C.CONTRACT_CREATE_FEE
    if estimate_gas > tx.gas_amount:
        raise BlockChainError('Insufficient gas [{}>{}]'.format(
            estimate_gas, tx.gas_amount))
    # Contractをデコードできるか
    c_address, c_bin, c_cs = bjson.loads(tx.message)
    binary2contract(c_bin)
    # ContractStorageの初期値チェック
    if c_cs:
        for k, v in c_cs.items():
            if not isinstance(k, bytes) or not isinstance(v, bytes):
                raise BlockChainError('cs format is wrong. {}'.format(c_cs))
    if not is_address(c_address, V.BLOCK_CONTRACT_PREFIX):
        raise BlockChainError('Is not contract address. {}'.format(c_address))
    # 既に登録されていないかチェック
    cs = get_contract_storage(c_address, include_block)
    if cs.version != 0:
        raise BlockChainError('Already created contract. {}'.format(tx))
Esempio n. 14
0
def validator_tx2index(txhash=None, tx=None):
    if txhash:
        tx = tx_builder.get_tx(txhash=txhash)
    if tx is None:
        raise BlockChainError('Not found ValidatorTX {}'.format(tx))
    if tx.height is None:
        raise BlockChainError('Not confirmed ValidatorTX {}'.format(tx))
    block = chain_builder.get_block(height=tx.height)
    if block is None:
        raise BlockChainError(
            'Not found block of start_tx included? {}'.format(tx))
    if tx not in block.txs:
        raise BlockChainError('Not found start_tx in block? {}'.format(block))
    return tx.height * 0xffffffff + block.txs.index(tx)
Esempio n. 15
0
def create_validator_edit_tx(v_address,
                             cur,
                             new_address=None,
                             flag=F_NOP,
                             sig_diff=0,
                             gas_price=None,
                             retention=10800):
    assert not (flag == F_NOP and sig_diff == 0), 'No edit info'
    if new_address is None and flag != F_NOP:
        raise BlockChainError('No cosigner edit, but flag is not NOP')
    # validator object
    v = get_validator_object(v_address=v_address)
    if v.version == -1:
        if new_address is None or flag != F_ADD or sig_diff != 1:
            raise BlockChainError('Not correct info')
    else:
        next_require = v.require + sig_diff
        next_validator_num = len(v.validators)
        if flag == F_ADD:
            next_validator_num += 1
        elif flag == F_REMOVE:
            next_validator_num -= 1
        if not (0 < next_require <= next_validator_num):
            raise BlockChainError('ReqError, 0 < {} <= {}'.format(
                next_require, next_validator_num))
    # tx create
    message = msgpack.packb((v_address, new_address, flag, sig_diff),
                            use_bin_type=True)
    tx = TX.from_dict(
        tx={
            'type': C.TX_VALIDATOR_EDIT,
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 0,
            'message_type': C.MSG_MSGPACK,
            'message': message
        })
    tx.gas_amount = tx.size
    tx.update_time(retention)
    # fill unspents
    additional_gas = C.VALIDATOR_EDIT_GAS + v.require * C.SIGNATURE_GAS
    input_address = fill_inputs_outputs(tx=tx,
                                        cur=cur,
                                        additional_gas=additional_gas)
    assert len(input_address & set(v.validators)) == 0, 'Not implemented?'
    # replace dummy address
    replace_redeem_dummy_address(tx=tx, cur=cur)
    setup_signature(tx, input_address)
    if v.version > -1 and setup_contract_signature(tx, v.validators) == 0:
        raise BlockChainError('Cannot sign, you are not validator')
    return tx
Esempio n. 16
0
def create_validator_edit_tx(c_address,
                             new_address=None,
                             flag=F_NOP,
                             sig_diff=0,
                             gas_price=None,
                             retention=10800):
    assert not (flag == F_NOP and sig_diff == 0), 'No edit info.'
    if new_address is None and flag != F_NOP:
        raise BlockChainError('No cosigner edit, but flag is not NOP.')
    # validator object
    v = get_validator_object(c_address=c_address)
    if v.version == -1:
        if new_address is None or flag != F_ADD or sig_diff != 1:
            raise BlockChainError('Not correct info.')
    else:
        next_require = v.require + sig_diff
        next_validator_num = len(v.validators)
        if flag == F_ADD:
            next_validator_num += 1
        elif flag == F_REMOVE:
            next_validator_num -= 1
        if not (0 < next_require <= next_validator_num):
            raise BlockChainError('ReqError, 0 < {} <= {}'.format(
                next_require, next_validator_num))
    # tx create
    message = bjson.dumps((c_address, new_address, flag, sig_diff),
                          compress=False)
    tx = TX(
        tx={
            'type': C.TX_VALIDATOR_EDIT,
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 0,
            'message_type': C.MSG_BYTE,
            'message': message
        })
    extra_gas = C.VALIDATOR_EDIT_GAS + C.SIGNATURE_GAS * v.require
    tx.gas_amount = tx.size + extra_gas
    tx.update_time(retention)
    # fill unspents
    fill_contract_inputs_outputs(tx=tx,
                                 c_address=c_address,
                                 additional_gas=extra_gas)
    # replace dummy address
    replace_redeem_dummy_address(tx=tx, replace_by=c_address)
    tx.serialize()
    if len(v.validators) > 0 and setup_contract_signature(tx,
                                                          v.validators) == 0:
        raise BlockChainError('Cannot sign, you are not validator.')
    return tx
Esempio n. 17
0
def check_hash_locked(tx):
    if len(tx.R) == 0:
        raise BlockChainError('R of Hash-locked is None type')
    if len(tx.R) > 64:
        raise BlockChainError('R is too large {}bytes'.format(len(tx.R)))
    size = len(tx.message)
    if size == 20:
        if RIPEMD160.new(tx.R).digest() != tx.message:
            raise BlockChainError('Hash-locked check RIPEMD160 failed')
    elif size == 32:
        if SHA256.new(tx.R).digest() != tx.message:
            raise BlockChainError('Hash-locked check SHA256 failed')
    else:
        raise BlockChainError(
            'H of Hash-locked is not correct size {}'.format(size))
Esempio n. 18
0
def signature_check(tx):
    need_cks = set()
    for txhash, txindex in tx.inputs:
        input_tx = tx_builder.get_tx(txhash)
        if input_tx is None:
            raise BlockChainError('Not found input tx {}'.format(hexlify(txhash).decode()))
        address, coin_id, amount = input_tx.outputs[txindex]
        if is_address(address, V.BLOCK_PREFIX):
            need_cks.add(address)  # 通常のアドレスのみ
        else:
            raise BlockChainError('Not common address {} {}.'.format(address, tx))

    signed_cks = get_signed_cks(tx)
    if need_cks != signed_cks:
        raise BlockChainError('Signature verification failed. [{}={}]'.format(need_cks, signed_cks))
Esempio n. 19
0
async def sign_raw_tx(request):
    post = await utils.content_type_json_check(request)
    try:
        binary = a2b_hex(post['hex'])
        other_pairs = dict()
        for sk in post.get('pairs', list()):
            sk = a2b_hex(sk)
            keypair: PyKeyPair = PyKeyPair.from_secret_key(sk)
            r, s = keypair.get_single_sign(binary)
            pk = keypair.get_public_key()
            ck = get_address(pk=pk, hrp=V.BECH32_HRP, ver=C.ADDR_NORMAL_VER)
            other_pairs[ck] = (pk, r, s)
        tx = TX.from_binary(binary=binary)
        for txhash, txindex in tx.inputs:
            input_tx = tx_builder.get_tx(txhash)
            address, coin_id, amount = input_tx.outputs[txindex]
            try:
                tx.signature.append(
                    sign_message_by_address(raw=tx.b, address=address))
            except BlockChainError:
                if address not in other_pairs:
                    raise BlockChainError(
                        'Not found secret key "{}"'.format(address))
                tx.signature.append(other_pairs[address])
        data = tx.getinfo()
        return utils.json_res({
            'hash': data['hash'],
            'signature': data['signature'],
            'hex': tx.b.hex()
        })
    except Exception:
        return utils.error_res()
Esempio n. 20
0
async def change_mint_tx(request):
    start = time()
    post = await utils.content_type_json_check(request)
    with create_db(V.DB_ACCOUNT_PATH, f_strict=True) as db:
        cur = db.cursor()
        try:
            user_name = post.get('from', C.account2name[C.ANT_UNKNOWN])
            sender = read_name2userid(user_name, cur)
            tx = change_mintcoin(mint_id=post['mint_id'],
                                 cur=cur,
                                 amount=post.get('amount'),
                                 description=post.get('description'),
                                 image=post.get('image'),
                                 setting=post.get('setting'),
                                 new_address=post.get('new_address'),
                                 sender=sender)
            if not send_newtx(new_tx=tx, outer_cur=cur):
                raise BlockChainError('Failed to send new tx')
            db.commit()
            return utils.json_res({
                'hash': tx.hash.hex(),
                'gas_amount': tx.gas_amount,
                'gas_price': tx.gas_price,
                'fee': tx.gas_amount * tx.gas_price,
                'time': round(time() - start, 3)
            })
        except Exception:
            return utils.error_res()
Esempio n. 21
0
async def issue_mint_tx(request):
    start = time()
    post = await utils.content_type_json_check(request)
    with create_db(V.DB_ACCOUNT_PATH, f_strict=True) as db:
        cur = db.cursor()
        try:
            user_name = post.get('from', C.account2name[C.ANT_UNKNOWN])
            sender = read_name2userid(user_name, cur)
            mint_id, tx = issue_mintcoin(
                name=post['name'],
                unit=post['unit'],
                digit=post.get('digit', 8),
                amount=post['amount'],
                cur=cur,
                description=post.get('description', None),
                image=post.get('image', None),
                additional_issue=post.get('additional_issue', True),
                sender=sender)
            if not send_newtx(new_tx=tx, outer_cur=cur):
                raise BlockChainError('Failed to send new tx')
            db.commit()
            return utils.json_res({
                'hash': tx.hash.hex(),
                'gas_amount': tx.gas_amount,
                'gas_price': tx.gas_price,
                'fee': tx.gas_amount * tx.gas_price,
                'time': round(time() - start, 3),
                'mint_id': mint_id
            })
        except Exception:
            return utils.error_res()
Esempio n. 22
0
 def update_time(self, retention=10800):
     if retention < 10800:
         raise BlockChainError('Retention time is too short')
     now = int(time())
     self.time = now - V.BLOCK_GENESIS_TIME
     self.deadline = now - V.BLOCK_GENESIS_TIME + retention
     self.serialize()
Esempio n. 23
0
 def deserialize(self, first_pos=0, f_raise=True):
     self.version, self.type, self.time, self.deadline, self.gas_price, self.gas_amount,\
         self.message_type, input_len, outputs_len, msg_len = struct_tx_header.unpack_from(self.b, first_pos)
     # inputs
     pos = first_pos + struct_tx_header.size
     self.inputs = list()
     for i in range(input_len):
         self.inputs.append(struct_inputs.unpack_from(self.b, pos))
         pos += struct_inputs.size
     # outputs
     self.outputs = list()
     for i in range(outputs_len):
         b_address, coin_id, amount = struct_outputs.unpack_from(
             self.b, pos)
         self.outputs.append((bin2addr(b=b_address,
                                       hrp=V.BECH32_HRP), coin_id, amount))
         pos += struct_outputs.size
     # msg
     self.message = self.b[pos:pos + msg_len]
     pos += msg_len
     if len(self.b) != pos - first_pos:
         if f_raise:
             raise BlockChainError('Do not match len [{}!={}'.format(
                 len(self.b), pos))
         else:
             self.b = self.b[first_pos:pos]
     self.hash = sha256d_hash(self.b)
Esempio n. 24
0
async def sign_raw_tx(request):
    post = await web_base.content_type_json_check(request)
    try:
        binary = unhexlify(post['hex'].encode())
        other_pairs = dict()
        for sk in post.get('pairs', list()):
            pk = public_key(sk=sk)
            ck = get_address(pk=pk, prefix=V.BLOCK_PREFIX)
            other_pairs[ck] = (pk, sign(msg=binary, sk=sk, pk=pk))
        tx = TX(binary=binary)
        for txhash, txindex in tx.inputs:
            input_tx = tx_builder.get_tx(txhash)
            address, coin_id, amount = input_tx.outputs[txindex]
            try:
                tx.signature.append(
                    message2signature(raw=tx.b, address=address))
            except BlockChainError:
                if address not in other_pairs:
                    raise BlockChainError(
                        'Not found secret key "{}"'.format(address))
                tx.signature.append(other_pairs[address])
        data = tx.getinfo()
        return web_base.json_res({
            'hash': data['hash'],
            'signature': data['signature'],
            'hex': hexlify(tx.b).decode()
        })
    except BaseException:
        return web_base.error_res()
Esempio n. 25
0
def ask_node(cmd, data=None, f_continue_asking=False):
    check_network_connection()
    failed = 0
    pc = V.PC_OBJ
    user_list = pc.p2p.user.copy()
    random.shuffle(user_list)
    while failed < 10:
        try:
            if len(user_list) == 0:
                break
            if len(good_node) == 0:
                set_good_node()
            user = user_list.pop()
            if user in good_node:
                dummy, r = pc.send_direct_cmd(cmd=cmd, data=data, user=user)
                if isinstance(r, str):
                    failed += 1
                    if f_continue_asking:
                        logging.warning("Failed cmd={} to {} by \"{}\"".format(cmd, user.name, r))
                        continue
                return r
            elif user in bad_node:
                pass
            else:
                set_good_node()
        except TimeoutError:
            pass
    raise BlockChainError('Too many retry ask_node. good={} bad={} failed={} cmd={}'
                          .format(len(good_node), len(bad_node), failed, cmd))
Esempio n. 26
0
def replace_mint_dummy_address(tx, mint_address, mint_id):
    for index, (address, coin_id, amount) in enumerate(tx.outputs):
        if address == MINTCOIN_DUMMY_ADDRESS:
            tx.outputs[index] = (mint_address, mint_id, amount)
            break
    else:
        raise BlockChainError('Cannot replace Mintcoin dummy address.')
Esempio n. 27
0
 def result(self):
     data = self.parent_conn.recv()
     self.lock.release()
     if isinstance(data, tuple):
         return data
     else:
         raise BlockChainError('Unknown status on pipe {}'.format(data))
Esempio n. 28
0
def subtract_fee_from_user_balance(tx: TX):
    """subtract fee from user's sending outputs"""
    subtract_fee = tx.gas_amount * tx.gas_price
    f_subtracted = False
    f_added = False
    for index, (address, coin_id, amount) in enumerate(tx.outputs):
        if coin_id != 0:
            continue
        elif amount < subtract_fee:
            continue
        elif not f_added and address == DUMMY_REDEEM_ADDRESS:
            # add used fee to redeem output
            tx.outputs[index] = (address, coin_id, amount + subtract_fee)
            f_added = True
        elif not f_subtracted and address != DUMMY_REDEEM_ADDRESS:
            # subtract used fee from sending output
            tx.outputs[index] = (address, coin_id, amount - subtract_fee)
            f_subtracted = True
        else:
            continue
    # check
    if f_subtracted is False or f_added is False:
        raise BlockChainError('failed to subtract fee sub={} add={} fee={}'
                              .format(f_subtracted, f_added, subtract_fee))
    return subtract_fee
Esempio n. 29
0
 def update(self, params, setting, txhash):
     if self.version == -1:
         self.name = params['name']
         self.unit = params['unit']
         self.digit = params['digit']
         self.address = params['address']
         self.description = params.get('description')
         self.image = params.get('image')
         if setting is not None:
             self.setting.update(setting)
     else:
         if params is not None:
             if self.setting['change_address'] and 'address' in params:
                 self.address = params['address']
             if self.setting['change_description'] and 'description' in params:
                 self.description = params['description']
             if self.setting['change_image'] and 'image' in params:
                 self.image = params['image']
         if setting is not None:
             for k in setting_template.keys():
                 if k not in setting:
                     continue
                 assert isinstance(self.setting[k], bool) and isinstance(setting[k], bool)
                 if self.setting[k] and setting[k]:  # true => true
                     pass
                 elif self.setting[k]:  # true => false
                     self.setting[k] = False
                 elif setting[k]:  # false => true
                     raise BlockChainError('Not allowed change setting to True. {}'.format(k))
                 else:  # false => false
                     pass
     self.txhash = txhash
     self.version += 1
Esempio n. 30
0
def validator_check(tx, include_block):
    assert tx.type == C.TX_FINISH_CONTRACT, 'validator_check is for FinishTX.'
    validator_cks, required_num = get_validator_info(include_block)
    already_signed_num = tx.inner_params.get('signed_num', 0)

    signed_cks = get_signed_cks(tx)
    valid_num = len(validator_cks & signed_cks)
    if include_block:
        if required_num > valid_num:
            raise BlockChainError(
                'Not satisfied required sign num. [{}>{}&{}]'.format(
                    required_num, len(validator_cks), len(signed_cks)))
    else:
        if already_signed_num >= valid_num:
            raise BlockChainError('Not found any change {}.'.format(tx))
        tx.inner_params['signed_num'] = valid_num