Exemple #1
0
def read_txhash2log(txhash, cur):
    d = cur.execute(
        """
        SELECT `type`,`user`,`coin_id`,`amount`,`time` FROM `log` WHERE `hash`=?
    """, (txhash, )).fetchall()
    if len(d) == 0:
        return None
    movement = UserCoins()
    _type = _time = None
    for _type, user, coin_id, amount, _time in d:
        movement.add_coins(user, coin_id, amount)
    return MoveLog(txhash, _type, movement, _time, False)
Exemple #2
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
Exemple #3
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
Exemple #4
0
 def init(self):
     with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
         cur = db.cursor()
         memory_sum = UserCoins()
         for move_log in read_log_iter(cur):
             # logに記録されてもBlockに取り込まれていないならTXは存在せず
             if builder.db.read_tx(move_log.txhash):
                 memory_sum += move_log.movement
             else:
                 logging.warning("It's unknown log {}".format(move_log))
                 # delete_log(move_log.txhash, cur)
         self.db_balance += memory_sum
Exemple #5
0
 def move_balance(self, _from, _to, coins, outer_cur=None):
     assert isinstance(coins, CoinObject),  'coins is CoinObject.'
     with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
         cur = outer_cur or db.cursor()
         try:
             # DataBaseに即書き込む(Memoryに入れない)
             movements = UserCoins()
             movements[_from] -= coins
             movements[_to] += coins
             txhash = insert_log(movements, cur)
             if outer_cur is None:
                 db.commit()
             self.db_balance += movements
             return txhash
         except BaseException:
             db.rollback()
Exemple #6
0
 def init(self, f_delete=False):
     assert f_delete is False, 'Unsafe function!'
     with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
         cur = db.cursor()
         memory_sum = UserCoins()
         for move_log in read_log_iter(cur):
             # logに記録されてもBlockに取り込まれていないならTXは存在せず
             if builder.db.read_tx(move_log.txhash):
                 memory_sum += move_log.movement
             else:
                 logging.debug("It's unknown log {}".format(move_log))
                 if f_delete:
                     delete_log(move_log.txhash, cur)
         if f_delete:
             logging.warning("Delete user's old unconfirmed tx.")
             db.commit()
         self.db_balance += memory_sum
Exemple #7
0
 def affect_new_tx(self, tx, outer_cur=None):
     with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
         cur = outer_cur or db.cursor()
         movement = UserCoins()
         # send_from_applyで登録済み
         if tx.hash in self.memory_movement:
             return
         # memory_movementに追加
         for txhash, txindex in tx.inputs:
             input_tx = tx_builder.get_tx(txhash)
             address, coin_id, amount = input_tx.outputs[txindex]
             user = read_address2user(address, cur)
             if user is not None:
                 movement.add_coins(user, coin_id, -1 * amount)
         for address, coin_id, amount in tx.outputs:
             user = read_address2user(address, cur)
             if user is not None:
                 movement.add_coins(user, coin_id, amount)
         # check
         if len(movement.users) == 0:
             return  # 無関係である
         move_log = MoveLog(tx.hash, tx.type, movement, tx.time, True, tx)
         self.memory_movement[tx.hash] = move_log
         logging.debug("Affect account new tx. {}".format(tx))
Exemple #8
0
def change_mintcoin(mint_id,
                    cur,
                    amount=0,
                    message=None,
                    additional_issue=None,
                    image=None,
                    sender=C.ANT_UNKNOWN):
    mint_old = get_mintcoin(mint_id)
    assert mint_old, 'Not defined MintCoin {}'.format(mint_id)
    mint_new = MintCoinObject(None)
    mint_new.version = mint_old.version + 1
    mint_new.coin_id = mint_id
    mint_new.amount = amount
    mint_new.additional_issue = additional_issue
    mint_address = get_address(mint_old.owner, prefix=V.BLOCK_PREFIX)
    uuid, sk, pk = read_address2keypair(mint_address, cur)
    mint_new.owner = pk
    mint_new.image = image
    mint_new.message = message
    # マージチェック
    mint_new.marge(mint_old)
    # Message内署名
    mint_new.generate_sign(sk)
    mint_new.serialize()
    mint_new.check_param()
    mint_new.check_sign()
    logging.info("New Mintcoin skeleton created coin_id={}".format(
        mint_new.coin_id))
    # movement
    movements = UserCoins()
    minting_coins = CoinObject(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)] if 0 < amount else list(),
            'gas_price':
            V.COIN_MINIMUM_PRICE,
            'gas_amount':
            1,
            'message_type':
            C.MSG_BYTE,
            'message':
            mint_new.binary
        })
    tx.gas_amount = tx.getsize() + 96 + C.MINTCOIN_FEE
    tx.serialize()
    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
    if amount > 0:
        replace_mint_dummy_address(tx, mint_address, 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_new, tx
Exemple #9
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
Exemple #10
0
def send_many(sender,
              send_pairs,
              cur,
              fee_coin_id=0,
              gas_price=None,
              msg_type=C.MSG_NONE,
              msg_body=b'',
              f_balance_check=True,
              retention=10800):
    assert isinstance(sender, int), 'Sender is user id.'
    assert 0 < len(send_pairs), 'Empty send_pairs.'
    # send_pairs check
    movements = UserCoins()
    outputs = list()
    coins = CoinObject()
    for address, coin_id, amount in send_pairs:
        assert isinstance(
            address,
            str) and len(address) == 40, 'Recipient is 40 letter string.'
        assert isinstance(coin_id, int) and isinstance(
            amount, int), 'CoinID, amount is int.'
        coins[coin_id] += amount
        outputs.append((address, coin_id, amount))
    movements[sender] -= coins
    movements[C.ANT_OUTSIDE] += coins
    # tx
    now = int(time.time() - V.BLOCK_GENESIS_TIME)
    tx = TX(
        tx={
            'version': __chain_version__,
            'type': C.TX_TRANSFER,
            'time': now,
            'deadline': now + retention,
            'inputs': list(),
            'outputs': outputs,
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 1,
            'message_type': msg_type,
            'message': msg_body
        })
    tx.gas_amount = tx.size + C.SIGNATURE_GAS
    # fill unspents
    input_address = fill_inputs_outputs(tx, cur, fee_coin_id, additional_gas=0)
    # account check
    fee_coins = CoinObject(coin_id=fee_coin_id,
                           amount=tx.gas_price * tx.gas_amount)
    if f_balance_check:
        # 残高が十分にあるかチェック
        send_coins = CoinObject()
        for address, coin_id, amount in send_pairs:
            send_coins[coin_id] += amount
        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
Exemple #11
0
def change_mintcoin(mint_id,
                    cur,
                    amount=None,
                    description=None,
                    image=None,
                    setting=None,
                    new_address=None,
                    gas_price=None,
                    sender=C.ANT_UNKNOWN,
                    retention=10800):
    assert amount or description or image or setting or new_address
    params = dict()
    if description:
        params['description'] = description
    if image:
        params['image'] = image
    if new_address:
        params['address'] = new_address
    if len(params) == 0:
        params = None
    if not params and not setting and not amount:
        raise BlockChainError('No update found.')
    m_before = get_mintcoin_object(coin_id=mint_id)
    if m_before.version == -1:
        raise BlockChainError('Not init mintcoin. {}'.format(m_before))
    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,
            'gas_price': gas_price or V.COIN_MINIMUM_PRICE,
            'gas_amount': 1,
            'message_type': C.MSG_BYTE,
            'message': msg_body
        })
    if amount:
        tx.outputs.append((MINTCOIN_DUMMY_ADDRESS, 0, amount))
        send_coins = CoinObject(0, amount)
        minting_coins = CoinObject(mint_id, amount)
    else:
        send_coins = CoinObject(0, 0)
        minting_coins = CoinObject(0, 0)
    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(m_before.address)
    fee_coins = CoinObject(coin_id=fee_coin_id,
                           amount=tx.gas_price * tx.gas_amount)
    # check amount
    check_enough_amount(sender=sender,
                        send_coins=send_coins,
                        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=m_before.address,
                               mint_id=mint_id,
                               f_raise=False)
    # setup signature
    tx.serialize()
    setup_signature(tx=tx, input_address=input_address)
    # movement
    movements = UserCoins()
    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 tx
Exemple #12
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 = CoinObject(coin_id=fee_coin_id,
                           amount=tx.gas_price * tx.gas_amount)
    # check amount
    check_enough_amount(sender=sender,
                        send_coins=CoinObject(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 = UserCoins()
    minting_coins = CoinObject(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
Exemple #13
0
 def __init__(self):
     self.db_balance = UserCoins()
     # {txhash: (_type, movement, _time),..}
     self.memory_movement = dict()
Exemple #14
0
class UserAccount:
    def __init__(self):
        self.db_balance = UserCoins()
        # {txhash: (_type, movement, _time),..}
        self.memory_movement = dict()

    def init(self, f_delete=False):
        assert f_delete is False, 'Unsafe function!'
        with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
            cur = db.cursor()
            memory_sum = UserCoins()
            for move_log in read_log_iter(cur):
                # logに記録されてもBlockに取り込まれていないならTXは存在せず
                if builder.db.read_tx(move_log.txhash):
                    memory_sum += move_log.movement
                else:
                    logging.debug("It's unknown log {}".format(move_log))
                    if f_delete:
                        delete_log(move_log.txhash, cur)
            if f_delete:
                logging.warning("Delete user's old unconfirmed tx.")
                db.commit()
            self.db_balance += memory_sum

    def get_balance(self, confirm=6):
        assert confirm < builder.cashe_limit - builder.batch_size, 'Too few cashe size.'
        assert builder.best_block, 'Not DataBase init.'
        # DataBase
        balance = self.db_balance.copy()
        with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
            cur = db.cursor()
            # Memory
            limit_height = builder.best_block.height - confirm
            for block in builder.best_chain:
                for tx in block.txs:
                    move_log = read_txhash2log(tx.hash, cur)
                    if move_log is None:
                        if tx.hash in self.memory_movement:
                            move_log = self.memory_movement[tx.hash]
                    if move_log:
                        for user, coins in move_log.movement.items():
                            for coin_id, amount in coins:
                                if limit_height < block.height:
                                    if amount < 0:
                                        balance.add_coins(user, coin_id, amount)
                                else:
                                    balance.add_coins(user, coin_id, amount)
            # Unconfirmed
            for tx in list(tx_builder.unconfirmed.values()):
                move_log = read_txhash2log(tx.hash, cur)
                if move_log is None:
                    if tx.hash in self.memory_movement:
                        move_log = self.memory_movement[tx.hash]
                if move_log:
                    for user, coins in move_log.movement.items():
                        for coin_id, amount in coins:
                            if amount < 0:
                                balance.add_coins(user, coin_id, amount)
        return balance

    def move_balance(self, _from, _to, coins, outer_cur=None):
        assert isinstance(coins, CoinObject),  'coins is CoinObject.'
        with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
            cur = outer_cur or db.cursor()
            try:
                # DataBaseに即書き込む(Memoryに入れない)
                movements = UserCoins()
                movements[_from] -= coins
                movements[_to] += coins
                txhash = insert_log(movements, cur)
                if outer_cur is None:
                    db.commit()
                self.db_balance += movements
                return txhash
            except BaseException:
                db.rollback()

    def get_movement_iter(self, start=0, f_dict=False):
        count = 0
        with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
            cur = db.cursor()
            # Unconfirmed
            for tx in sorted(tx_builder.unconfirmed.values(), key=lambda x: x.time, reverse=True):
                move_log = read_txhash2log(tx.hash, cur)
                if move_log is None:
                    if tx.hash in self.memory_movement:
                        move_log = self.memory_movement[tx.hash]
                else:
                    if tx.hash in self.memory_movement:
                        move_log.pointer = self.memory_movement[tx.hash].pointer
                if move_log:
                    if count >= start:
                        if f_dict:
                            yield move_log.get_dict_data(cur)
                        else:
                            yield move_log.get_tuple_data()
                    count += 1
            # Memory
            for block in reversed(builder.best_chain):
                for tx in block.txs:
                    move_log = read_txhash2log(tx.hash, cur)
                    if move_log is None:
                        if tx.hash in self.memory_movement:
                            move_log = self.memory_movement[tx.hash]
                    else:
                        if tx.hash in self.memory_movement:
                            move_log.pointer = self.memory_movement[tx.hash].pointer
                    if move_log:
                        if count >= start:
                            if f_dict:
                                yield move_log.get_dict_data(cur)
                            else:
                                yield move_log.get_tuple_data()
                        count += 1
            # DataBase
            for move_log in read_log_iter(cur, start - count):
                # TRANSFERなど はDBとMemoryの両方に存在する
                if move_log.txhash in self.memory_movement:
                    continue
                elif f_dict:
                    yield move_log.get_dict_data(cur)
                else:
                    yield move_log.get_tuple_data()

    def new_batch_apply(self, batched_blocks):
        with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
            cur = db.cursor()
            for block in batched_blocks:
                for tx in block.txs:
                    move_log = read_txhash2log(tx.hash, cur)
                    if move_log:
                        # User操作の記録
                        self.db_balance += move_log.movement
                        if tx.hash in self.memory_movement:
                            del self.memory_movement[tx.hash]
                        # logging.debug("Already recoded log {}".format(tx))
                    elif tx.hash in self.memory_movement:
                        # db_balanceに追加
                        _type, movement, _time = self.memory_movement[tx.hash].get_tuple_data()
                        self.db_balance += movement
                        # memory_movementから削除
                        del self.memory_movement[tx.hash]
                        # insert_log
                        insert_log(movement, cur, _type, _time, tx.hash)
            db.commit()

    def affect_new_tx(self, tx, outer_cur=None):
        with closing(create_db(V.DB_ACCOUNT_PATH)) as db:
            cur = outer_cur or db.cursor()
            movement = UserCoins()
            # send_from_applyで登録済み
            if tx.hash in self.memory_movement:
                return
            # memory_movementに追加
            for txhash, txindex in tx.inputs:
                input_tx = tx_builder.get_tx(txhash)
                address, coin_id, amount = input_tx.outputs[txindex]
                user = read_address2user(address, cur)
                if user is not None:
                    movement.add_coins(user, coin_id, -1 * amount)
            for address, coin_id, amount in tx.outputs:
                user = read_address2user(address, cur)
                if user is not None:
                    movement.add_coins(user, coin_id, amount)
            # check
            if len(movement.users) == 0:
                return  # 無関係である
            move_log = MoveLog(tx.hash, tx.type, movement, tx.time, True, tx)
            self.memory_movement[tx.hash] = move_log
            logging.debug("Affect account new tx. {}".format(tx))