def handle_sendblock(self, payload):
        new_block = payload
        with self.server.node_manager.lock:
            blockchain = self.server.node_manager.blockchain
            block_height = db.get_block_height(blockchain.wallet.address)
            latest_block = db.get_block_data_by_index(
                blockchain.get_wallet_address(), block_height - 1)

            if (latest_block.current_hash
                    == new_block.previous_hash) and (latest_block.index + 1
                                                     == new_block.index):

                # 校验交易是否有效
                is_valid = True
                for idx in range(len(new_block.transactions)):
                    tx = new_block.transactions[-1 - idx]
                    if not blockchain.verify_transaction(tx):
                        is_valid = False
                        break

                if is_valid:
                    db.write_to_db(blockchain.wallet.address, new_block)
                    # 重新挖矿
                    blockchain.current_transactions = []
                    db.clear_unconfirmed_tx_from_disk(
                        blockchain.wallet.address)
            else:
                self.add_to_candidate_blocks(blockchain, new_block)

            blockchain.set_consensus_chain()
示例#2
0
def node_info():
    values = request.get_json()
    required = ['ip', 'port']
    if not all(k in values for k in required):
        return 'Missing values', 400

    ip = values['ip']
    port = values['port']
    block_height = db.get_block_height(blockchain.wallet.address)
    latest_block = db.get_block_data_by_index(blockchain.wallet.address,
                                              block_height - 1)
    block_hash = latest_block.current_hash
    timestamp = latest_block.timestamp

    time_local = time.localtime(timestamp)

    response = {
        'address': ip + ':' + str(port),
        'block_height': block_height,
        'block_hash': block_hash,
        'wallet_address': blockchain.wallet.address,
        # 'balance': blockchain.get_balance(blockchain.wallet.address),
        'timestamp': time.strftime("%Y-%m-%d %H:%M:%S", time_local)
    }
    return jsonify(response), 200
    def set_consensus_chain(self):
        # 通过POW机制选取nonce最大的链作为公共链
        for block_index in list(self.candidate_blocks.keys()):
            if block_index <= db.get_block_height(
                    self.get_wallet_address()) - 1:
                curr_block = db.get_block_data_by_index(
                    self.get_wallet_address(), block_index)
                max_nonce_block = curr_block
                for candidate_block in self.candidate_blocks[block_index]:
                    if (candidate_block.previous_hash
                            == curr_block.previous_hash) and (
                                candidate_block.nonce > max_nonce_block.nonce):
                        max_nonce_block = candidate_block

                # 校验每一笔交易
                valid_flag = True
                for idx in range(len(max_nonce_block.transactions)):
                    tx = max_nonce_block.transactions[-1 - idx]
                    if not self.verify_transaction(tx):
                        valid_flag = False

                if valid_flag and max_nonce_block.current_hash != curr_block.current_hash:
                    print('[Info] consensusing, replace with new block',
                          max_nonce_block.current_hash)
                    db.write_to_db(self.get_wallet_address(), max_nonce_block)
示例#4
0
def tx_info_app():

    block_index = int(request.args.get('block_index'))
    txid = request.args.get('txid')

    block = db.get_block_data_by_index(blockchain.wallet.address, block_index)
    for tx in block.transactions:
        if tx.txid == txid:
            return json.dumps(tx.json_output()), 200

    return 'not exist!', 200
示例#5
0
def block_info():
    height = request.args.get('height')
    block_index = int(height) - 1

    block = db.get_block_data_by_index(blockchain.wallet.address, block_index)

    json_transaction = list()
    for tx in block.transactions:
        txins = tx.txins
        txouts = tx.txouts

        from_addr = list()
        to_addr = list()
        amount = 0
        for txin in txins:
            if txin.prev_tx_out_idx != -1:
                address = Wallet.get_address(txin.pubkey)
                if address not in from_addr:
                    from_addr.append(address)

        for txout in txouts:
            value = txout.value
            script_pub_key = txout.scriptPubKey
            if len(script_pub_key) == 5:
                recv_addr = get_address_from_ripemd160(script_pub_key[2])
                to_addr.append({'receiver': recv_addr, 'value': value})

        new_tx = {
            'txid': tx.txid,
            'senders': from_addr,
            'receivers': to_addr,
            'amount': amount,
            'timestamp': tx.timestamp
        }

        json_transaction.append(new_tx)

    response = {
        'index': block.index,
        'current_hash': block.current_hash,
        'previous_hash': block.previous_hash,
        'timestamp': block.timestamp,
        'merkleroot': block.merkleroot,
        'difficulty': block.difficulty,
        'nonce': block.nonce,
        'transactions': json_transaction
    }

    return jsonify(response), 200
示例#6
0
def tx_in_block():
    values = request.get_json()

    block_index = int(request.args.get('block_index'))

    block = db.get_block_data_by_index(blockchain.wallet.address, block_index)
    tmp = dict()
    cnt = 0
    for tx in block.transactions:
        tmp[str(cnt)] = {
            'txid': tx.txid,
            'timestamp': time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(tx.timestamp)),
            'vid': tx.vid
        }
        cnt += 1
    
    return json.dumps(tmp), 200
    def find_transaction(self, txid):
        """
        通过交易id找到一笔Tx交易
        :param txid: <str>交易id
        :return:
        """
        # 在区块中寻找(已确认的交易)
        block_height = db.get_block_height(self.wallet.address)

        for index in range(block_height):
            block = db.get_block_data_by_index(self.wallet.address, index)
            # 1.获取区块下的所有的交易
            transactions = block.get_transactions()
            for tx in transactions:
                if tx.txid == txid:
                    return tx

        # 在交易池中寻找(未确认的交易)TODO待确认
        for k in range(len(self.current_transactions)):
            uncomfirmed_tx = self.current_transactions[-1 - k]
            if uncomfirmed_tx.txid == txid:
                return uncomfirmed_tx
        return None
 def get_last_block(self):
     block_height = db.get_block_height(self.wallet.address)
     return db.get_block_data_by_index(self.wallet.address,
                                       block_height - 1)
    def find_spendalbe_outputs(self, from_addr):
        """
        获取from_addr可以用于交易的TxOutput(未使用过的),
        :param from_addr: <str>发送方钱包地址
        :return:
        """
        unspent_txout_list = list()
        spent_txout_list = list()
        balance = 0
        # Step0:遍历交易池中已经发生过的交易(未打包进区块,未确认)
        # 备注:要从最新的交易开始遍历!!!!!
        for i in range(len(self.current_transactions)):
            unconfirmed_tx = self.current_transactions[
                len(self.current_transactions) - 1 - i]
            txid = unconfirmed_tx.txid

            # 遍历当前交易下所有的TxInput
            if not unconfirmed_tx.is_coinbase():
                # print 'txid:', txid
                # 记录当前tx下被from_addr被使用过的上一次交易的输出,即记录txid和out_idx
                for txin in unconfirmed_tx.txins:
                    if txin.can_unlock_txoutput_with(from_addr):
                        spent_txid = txin.prev_txid
                        spent_tx_out_idx = txin.prev_tx_out_idx
                        spent_txout_list.append((spent_txid, spent_tx_out_idx))

            # 遍历交易下所有的未使用过的TxOutput
            for out_idx in range(len(unconfirmed_tx.txouts)):
                txout = unconfirmed_tx.txouts[out_idx]
                if not (txid, out_idx) in spent_txout_list:
                    if txout.can_be_unlocked_with(from_addr):
                        unspent_txout_list.append((txid, out_idx, txout))
        # --------------------------------------------------

        # Step1:获取from_addr下可以未使用过的TxOutput(打包在区块,已确认)
        block_height = db.get_block_height(self.wallet.address)

        for i in range(block_height):
            block = db.get_block_data_by_index(self.wallet.address,
                                               block_height - 1 - i)
            # 1.获取区块下的所有的交易
            transactions = block.get_transactions()
            # 备注:要从最新的交易开始遍历!!!!!
            for k in range(len(transactions)):
                tx = transactions[len(transactions) - 1 - k]
                if not self.verify_transaction(tx):  # 校验交易是否有效
                    print('[Info] invalid tx', tx.txid, 'block index:', i)
                    continue
                txid = tx.txid  # 当前交易的id

                # 2.遍历某个交易下所有的TxInput
                if not tx.is_coinbase():
                    # 记录当前tx下被from_addr被使用过的上一次交易的输出,即记录txid和out_idx
                    for txin in tx.txins:
                        if txin.can_unlock_txoutput_with(from_addr):
                            spent_txid = txin.prev_txid
                            spent_tx_out_idx = txin.prev_tx_out_idx
                            spent_txout_list.append(
                                (spent_txid, spent_tx_out_idx))

                # 3.遍历某个交易下所有的未使用过的TxOutput
                for out_idx in range(len(tx.txouts)):
                    txout = tx.txouts[out_idx]
                    if not (txid, out_idx) in spent_txout_list:
                        if txout.can_be_unlocked_with(from_addr):
                            unspent_txout_list.append((txid, out_idx, txout))

        # Step2:计算这些未使用过的TxOutput输出之和
        for txid, out_idx, txout in unspent_txout_list:
            balance += txout.value
        return balance, unspent_txout_list
示例#10
0
    def get_balance_by_db(self, from_addr):
        """
        获取from_addr可以用于交易的TxOutput(未使用过的),读取交易池和区块链的本地副本,避免被加锁
        :param from_addr: <str>发送方钱包地址
        :return: <int>
        """
        unspent_txout_list = list()
        spent_txout_list = list()
        balance = 0
        # Step1:遍历交易池中已经发生过的交易(未打包进区块,未确认)
        # 备注:要从最新的交易开始遍历!!!!!
        current_transactions = db.get_all_unconfirmed_tx(self.wallet.address)
        current_transactions = sorted(current_transactions,
                                      key=lambda x: x.timestamp,
                                      reverse=False)
        for i in range(len(current_transactions)):
            unconfirmed_tx = current_transactions[len(current_transactions) -
                                                  1 - i]
            txid = unconfirmed_tx.txid

            # 遍历当前交易下所有的TxInput
            if not unconfirmed_tx.is_coinbase():
                # print 'txid:', txid
                # 记录当前tx下被from_addr被使用过的上一次交易的输出,即记录txid和out_idx
                for txin in unconfirmed_tx.txins:
                    if txin.can_unlock_txoutput_with(from_addr):
                        spent_txid = txin.prev_txid
                        spent_tx_out_idx = txin.prev_tx_out_idx
                        spent_txout_list.append((spent_txid, spent_tx_out_idx))

            # 遍历交易下所有的未使用过的TxOutput
            for out_idx in range(len(unconfirmed_tx.txouts)):
                txout = unconfirmed_tx.txouts[out_idx]
                if not (txid, out_idx) in spent_txout_list:
                    if txout.can_be_unlocked_with(from_addr):
                        unspent_txout_list.append((txid, out_idx, txout))
        # --------------------------------------------------

        # Step2:获取from_addr下可以未使用过的TxOutput(打包在区块,已确认)
        block_height = db.get_block_height(self.wallet.address)

        for i in range(block_height):
            block = db.get_block_data_by_index(self.wallet.address,
                                               block_height - 1 - i)
            # 1.获取区块下的所有的交易
            transactions = block.get_transactions()
            # 备注:要从最新的交易开始遍历!!!!!
            for k in range(len(transactions)):
                tx = transactions[len(transactions) - 1 - k]
                if not self.verify_transaction(tx):  # 校验交易是否有效
                    continue
                txid = tx.txid  # 当前交易的id

                # 2.遍历某个交易下所有的TxInput
                if not tx.is_coinbase():
                    # 记录当前tx下被from_addr被使用过的上一次交易的输出,即记录txid和out_idx
                    for txin in tx.txins:
                        if txin.can_unlock_txoutput_with(from_addr):
                            spent_txid = txin.prev_txid
                            spent_tx_out_idx = txin.prev_tx_out_idx
                            spent_txout_list.append(
                                (spent_txid, spent_tx_out_idx))

                # 3.遍历某个交易下所有的未使用过的TxOutput
                for out_idx in range(len(tx.txouts)):
                    txout = tx.txouts[out_idx]
                    if not (txid, out_idx) in spent_txout_list:
                        if txout.can_be_unlocked_with(from_addr):
                            unspent_txout_list.append((txid, out_idx, txout))

        # Step2:计算这些未使用过的TxOutput输出之和
        for txid, out_idx, txout in unspent_txout_list:
            balance += txout.value
        return balance
示例#11
0
def block_info():
    block_index = request.args.get('block_index')

    block = db.get_block_data_by_index(blockchain.wallet.address, block_index)

    json_transaction = list()
    for tx in block.transactions:
        if isinstance(tx, Tx_vid):
            new_tx = {
                'txid': tx.txid,
                'timestamp': tx.timestamp,
                'type': 'vid',
                'vid': tx.vid
            }
        elif isinstance(tx, Tx_report):
            new_tx = {
                'txid': tx.txid,
                'timestamp': tx.timestamp,
                'type': 'report',
                'edgeId': tx.edgeId,
                'meanSpeed': tx.meanSpeed,
                'vehicleNum': tx.vehicleNum
            }
        elif isinstance(tx, Tx_easy):
            new_tx = {
                'txid': tx.txid,
                'sender': tx.sender,
                'receiver': tx.receiver,
                'amount': tx.amount,
                'timestamp': tx.timestamp
            }
        elif isinstance(tx, Transaction):
            txins = tx.txins
            txouts = tx.txouts

            from_addr = list()
            to_addr = list()
            amount = 0

            for txin in txins:
                if txin.prev_tx_out_idx != -1:
                    address = Wallet.get_address(txin.pubkey)
                    if address not in from_addr:
                        from_addr.append(address)

            for txout in txouts:
                value = txout.value
                script_pub_key = txout.scriptPubKey
                if len(script_pub_key) == 5:
                    recv_addr = get_address_from_ripemd160(script_pub_key[2])
                    to_addr.append({'receiver': recv_addr, 'value': value})

            new_tx = {
                'txid': tx.txid,
                'senders': from_addr,
                'receivers': to_addr,
                'amount': amount,
                'timestamp': tx.timestamp
            }

        json_transaction.append(new_tx)

    response = {
        'index': block.index,
        'timestamp': block.timestamp,
        'current_hash': block.current_hash,
        'previous_hash': block.previous_hash,
        'merkleroot': block.merkleroot,
        'transactions': json_transaction
    }

    return jsonify(response), 200
示例#12
0
def tx_in_block():
    values = request.get_json()

    block_index = int(request.args.get('block_index'))

    block = db.get_block_data_by_index(blockchain.wallet.address, block_index)
    tmp = dict()
    cnt = 0
    for tx in block.transactions:
        if isinstance(tx, Tx_vid):
            tmp[str(cnt)] = {
                'txid':
                tx.txid,
                'timestamp':
                time.strftime("%Y-%m-%d %H:%M:%S",
                              time.localtime(tx.timestamp)),
                'type':
                'vid',
                'vid':
                tx.vid
            }
            cnt += 1

        elif isinstance(tx, Tx_report):
            tmp[str(cnt)] = {
                'txid':
                tx.txid,
                'timestamp':
                time.strftime("%Y-%m-%d %H:%M:%S",
                              time.localtime(tx.timestamp)),
                'type':
                'report',
                'edgeId':
                tx.edgeId,
                'meanSpeed':
                tx.meanSpeed,
                'vehicleNum':
                tx.vehicleNum
            }
            cnt += 1

        elif isinstance(tx, Tx_easy):
            tmp[str(cnt)] = {
                'txid': tx.txid,
                'sender': tx.sender,
                'receiver': tx.receiver,
                'amount': tx.amount,
                'timestamp': tx.timestamp
            }
            cnt += 1

        elif isinstance(tx, Transaction):
            txins = tx.txins
            txouts = tx.txouts

            from_addr = list()
            to_addr = list()
            amount = 0

            for txin in txins:
                if txin.prev_tx_out_idx != -1:
                    address = Wallet.get_address(txin.pubkey)
                    if address not in from_addr:
                        from_addr.append(address)

            for txout in txouts:
                value = txout.value
                script_pub_key = txout.scriptPubKey
                if len(script_pub_key) == 5:
                    recv_addr = get_address_from_ripemd160(script_pub_key[2])
                    to_addr.append({'receiver': recv_addr, 'value': value})

            tmp[str(cnt)] = {
                'txid': tx.txid,
                'senders': from_addr,
                'receivers': to_addr,
                'amount': amount,
                'timestamp': tx.timestamp
            }

            cnt += 1

    return json.dumps(tmp), 200