示例#1
0
def create_tx_outs(receiver_address, my_address, amount, left_over_amount):
    tx_out = TxOut(receiver_address, amount)
    if left_over_amount == 0:
        return [tx_out]
    else:
        left_over_tx = TxOut(my_address, left_over_amount)
        return [tx_out, left_over_tx]
示例#2
0
    def give(self, address, amt):
        if amt > self.balance():
            print("Insufficient balance")
            return

        myOuts = [
            txOut for txOut in self.chain.pool.txOuts
            if txOut.address.equals(self.pubKey)
        ]

        toGive = amt
        consumed = []

        created = [TxOut(address, amt)]

        for out in myOuts:
            consumed.append(TxIn(out.txHash, out.idx))
            if out.value >= toGive:
                created.append(TxOut(self.pubKey, out.value - toGive))
            toGive -= out.value
            if toGive <= 0:
                break

        tx = Transaction(consumed, created)
        for i in range(len(consumed)):
            tx.sign(self.privKey, i)

        self.pendingTxs.append(tx)

        self.sendToPeers({"type": 'TRANSACTION', "data": tx.toJSON()})
示例#3
0
 def clone(self):
     newPool = UTXOPool()
     for txOut in self.txOuts:
         newTxOut = TxOut(txOut.address, txOut.value)
         newTxOut.txHash = txOut.txHash
         newTxOut.idx = txOut.idx
         newPool.txOuts.append(newTxOut)
     return newPool
示例#4
0
 def create_tx_outs(self, receiver_address, amount, left_over_amount):
     amount = Decimal(amount)
     tx_out_1 = TxOut(receiver_address, amount)
     tx_outs = [tx_out_1]
     if left_over_amount > 0:
         my_address = self.get_public_key()
         left_over_tx_out = TxOut(my_address, left_over_amount)
         tx_outs.append(left_over_tx_out)
     return tx_outs
    def __init__(self):

        self.genesis_transaction = Transaction(
            [TxIn('', 0, '')], [TxOut(get_public_from_wallet(), 50)])
        self._blockchain = [self.get_genesis_block()]
        self.difficulty_bits = 15
        self.unspent_tx_outs = process_transactions([self.genesis_transaction],
                                                    [], 0)
示例#6
0
def build_transaction(to_pubkey,
                      value_to_send,
                      my_pubkey,
                      signing_key,
                      fee=TRANSACTION_FEE):
    """
    This will create a pay-to-public-key transaction, for this function we will assume a constant transaction fee,
    our protocol will assume no minimum fees. We will create a change output to the sender.
    """

    # first grab all the utxo belonging to my_pubkey, sort utxo ascendingly by value and height
    utxos = set(
        sorted(get_utxos_for_addr(my_pubkey),
               key=lambda utxo: (utxo.value, utxo.height)))

    total_to_send = value_to_send + fee
    to_be_spent = []
    current_value = 0

    for utxo in utxos:
        to_be_spent.append(utxo)
        current_value += utxo.value
        if current_value > total_to_send:
            # we have all we need to send
            break

    txout = TxOut(value=value_to_send, pubkey=to_pubkey)

    change_amt = sum(utxo.value for utxo in to_be_spent) - total_to_send
    txout_change = TxOut(value=change_amt, pubkey=my_pubkey)

    # we need to make txin now based on where we want to send the outputs
    txins = []
    current_value = 0
    for utxo in to_be_spent:
        current_value += utxo.value
        if current_value > total_to_send:
            txn = make_txin(signing_key, utxo.outpoint, txout_change)
        else:
            txn = make_txin(signing_key, utxo.outpoint, txout)
        txins.append(txn)

    if change_amt < 0:
        raise ValueError(f'insufficient funds {current_value}')

    return Transaction(txins=txins, txouts=[txout, txout_change])
示例#7
0
 def __init__(self, prevHash, coinbaseRecipient, txs, nonce, difficulty):
     self.prevHash = prevHash
     self.txs = [tx.clone() for tx in txs]
     self.nonce = nonce
     self.timestamp = time.time()
     self.difficulty = difficulty
     coinbase = Transaction(
         [], [TxOut(coinbaseRecipient, blockchain.COINBASE_AMT)])
     self.txs.insert(0, coinbase)
示例#8
0
    def __init__(self, reward, miner_address):
        self.vin_sz = 0
        self.vout_sz = 0
        self.inputs = []
        self.outputs = []
        self.hash = None
        self.timestamp = time.time()

        txout = TxOut(miner_address, reward)
        self.outputs.append(txout)
        self.vout_sz = 1
        self.gen_hash()
示例#9
0
 def generate_next_with_transaction(self, wallet, receiver_address, amount):
     if not TxOut.is_valid_address(receiver_address):
         error_payload = {'address': bytes_to_hex(receiver_address)}
         raise BadRequestError('invalid address', payload=error_payload)
     if not isinstance(amount, Decimal):
         error_payload = {'amount': amount}
         raise BadRequestError('invalid amount', payload=error_payload)
     coinbase_tx = Transaction.coinbase(wallet.get_public_key(),
                                        self.get_latest().index + 1)
     tx = wallet.create_transaction(receiver_address, amount,
                                    self.unspent_tx_outs, self.tx_pool)
     block_data = [coinbase_tx, tx]
     return self.generate_raw_next_block(block_data)
class Blockchain(object):

    def __init__(self):

        self._blockchain = [self.get_genesis_block()]
        self.difficulty_bits = 15
        self.unspent_tx_outs = process_transactions([self.genesis_transaction], [], 0)

    @property
    def blocks(self):
        return self._blockchain


    def get_unspent_tx_outs(self):
        return self.unspent_tx_outs

    def set_unspent_tx_outs(self, new_utxo):
        print('replacing unspent_tx_outs with: %s' % new_utxo)
        self.unspent_tx_outs = new_utxo

    @blocks.setter
    def blocks(self, blocks):
        self._blockchain = blocks

    # genesis_transaction = {'tx_ins': [{'signature': '', 'tx_out_id': '', 'tx_out_index': 0}],
    #     'tx_outs': [{
    #         'address': getPublicFromWallet(),
    #         'amount': 50
    #     }]
        # 'id': 'e655f6a5f26dc9b4cac6e46f52336428287759cf81ef5ff10854f69d68f43fa3'
    # }

    genesis_transaction = Transaction([TxIn('', 0, '')], [TxOut(get_public_from_wallet(), 50)])

    @classmethod
    def get_genesis_block(cls):

        # SHA256.new(data=(str(0) + "0"+ str(1465154705) +"my genesis block!!").encode()).hexdigest()

        return Block(0, "0", 1465154705, cls.genesis_transaction, 0, 0,
                     "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7")

    def generate_next_block(self, block_data):

        previous_block = self.get_latest_block()
        next_index = previous_block.index + 1
        next_timestamp = datetime.now().strftime("%s")
        next_hash, next_nonce = self.calculate_hash(next_index, previous_block.hash, next_timestamp, block_data)
        new_block = Block(next_index, previous_block.hash, next_timestamp, block_data,
                     self.difficulty_bits, next_nonce, next_hash)

        if self.add_block(new_block):
            # broadcastLatest();
            return new_block


    # gets the unspent transaction outputs owned by the wallet
    def get_my_utxos(self):
        return find_unspent_tx_outs(get_public_from_wallet(), self.get_unspent_tx_outs())

    def construct_next_block(self):
        coinbase_tx = get_coinbase_transaction(get_public_from_wallet(), self.blocks[-1].index + 1)
        block_data = [coinbase_tx] + get_transaction_pool()
        return self.generate_next_block(block_data)

    def construct_next_block_with_transaction(self, receiver_address, amount):
        if not is_valid_address(receiver_address):
            print('invalid address')
            return
        if not isinstance(amount, int):
            print('invalid amount')
            return

        coinbase_tx = get_coinbase_transaction(get_public_from_wallet(), self.blocks[-1].index + 1)
        tx = create_transaction(receiver_address, amount, get_private_from_wallet(),
                                self.get_unspent_tx_outs(), get_transaction_pool())
        if not tx:
            return False
        block_data = [coinbase_tx, tx]
        return self.generate_next_block(block_data)

    def get_account_balance(self):
        return get_balance(get_public_from_wallet(), self.get_unspent_tx_outs())

    def send_transaction(self, address, amount):
        tx = create_transaction(address, amount, get_private_from_wallet(),
                                self.get_unspent_tx_outs(), get_transaction_pool())
        add_to_transaction_pool(tx, self.get_unspent_tx_outs())
        # broadCastTransactionPool()
        return tx

    def get_latest_block(self):

        try:
            return self._blockchain[-1]
        except IndexError as e:
            return None

    def calculate_hash_for_block(self, block):

        return self.calculate_hash(block.index, block.previous_hash, block.timestamp, block.data, block.nonce)

    def calculate_hash(self, index, previous_hash, timestamp, data, nonce=None):

        if not nonce:
            header = str(index) + previous_hash + str(timestamp) + str(data) + str(self.difficulty_bits)
            return self.proof_of_work(header)
        else:
            hash_object = SHA256.new(data=(str(index) + previous_hash + str(timestamp)
                                           + str(data) + str(self.difficulty_bits) + str(nonce)).encode())
            return hash_object.hexdigest()

    def proof_of_work(self, header):
        """Calculates nonce for the block based on the difficulty bits set"""

        print("Computing nonce for the block...")
        target = 2 ** (256 - self.difficulty_bits)

        for nonce in range(max_nonce):
            hash_result = SHA256.new(data=(str(header) + str(nonce)).encode()).hexdigest()

            if int(hash_result, 16) < target:
                print("Success with nonce %d" % nonce)
                print("Hash is %s" % hash_result)
                return (hash_result, nonce)

        print("Failed after %d (max_nonce) tries" % nonce)
        return nonce

    def add_block(self, new_block):

        if self.is_valid_new_block(new_block, self.get_latest_block()):
            ret_val = process_transactions(new_block.data, self.get_unspent_tx_outs(), new_block.index)
            if ret_val is None:
                print('block is not valid in terms of transactions')
                return False
            else:
                self._blockchain.append(new_block)
                self.set_unspent_tx_outs(ret_val)
                update_transaction_pool(self.get_unspent_tx_outs())
                return True

    def is_valid_new_block(self, new_block, previous_block):

        if previous_block.index + 1 != new_block.index:
            logger.warning('invalid index')
            return False
        if previous_block.hash != new_block.previous_hash:
            logger.warning('invalid previous hash')
            return False
        if self.calculate_hash_for_block(new_block) != new_block.hash:
            logger.info(str(type(new_block.hash)) + ' ' + str(type(self.calculate_hash_for_block(new_block))))
            logger.warning('invalid hash: ' + self.calculate_hash_for_block(new_block) + ' ' + new_block.hash)
            return False

        return True

    def is_valid_chain(self, blockchain_to_validate):

        # if self.calculate_hash_for_block(Block(**blockchain_to_validate[0])) != self.get_genesis_block().hash:
        #     return False

        temp_blocks = [Block(**blockchain_to_validate[0])]
        for currentBlock in blockchain_to_validate[1:]:
            if self.is_valid_new_block(Block(**currentBlock), temp_blocks[-1]):
                temp_blocks.append(Block(**currentBlock))
            else:
                return False
        return True
示例#11
0
def buildTxOuts(senderLegacyAddress, receiverLegacyAddress, initialBalance,
                amount, fee):
    return [TxOut(utils.addressToScriptPubKey(receiverLegacyAddress), amount), \
            TxOut(utils.addressToScriptPubKey(senderLegacyAddress), initialBalance - amount - fee)]
示例#12
0
    def fromJSON(j):
        blockchain = Blockchain()
        jsonChain = json.loads(j)

        # copy over blocks
        newBlocks = []
        for block in jsonChain['blocks']:
            newBlockTxs = []

            for tx in block['txs']:
                newBlockTxIns = []
                newBlockTxOuts = []

                for txIn in tx['txIns']:
                    newBlockTxIn = TxIn(txIn['prevTxHash'],
                                        txIn['prevTxOutIndex'])
                    newBlockTxIn.signature = eval(txIn['signature'])
                    newBlockTxIns.append(newBlockTxIn)
                for txOut in tx['txOuts']:
                    if txOut['address'] == None:
                        newPubKey = None
                    else:
                        newPubKey = PubKey.wrap(txOut['address'])
                    newBlockTxOut = TxOut(newPubKey, txOut['value'])
                    newBlockTxOut.txHash = txOut['txHash']
                    newBlockTxOut.idx = txOut['idx']
                    newBlockTxOuts.append(newBlockTxOut)

                newBlockTx = Transaction(newBlockTxIns, newBlockTxOuts)
                newBlockTx.timestamp = tx['timestamp']
                newBlockTxs.append(newBlockTx)

            coinbaseRecipientDict = block['txs'][0]['txOuts'][0]['address']
            if coinbaseRecipientDict == None:
                coinbaseRecipient = None
            else:
                coinbaseRecipient = PubKey.wrap(coinbaseRecipientDict)

            prevHash = newBlocks[-1].hash() if len(newBlocks) else None
            newBlock = Block(prevHash, coinbaseRecipient, newBlockTxs,
                             block['nonce'], block['difficulty'])

            # remove duplicate coinbase transaction
            newBlock.txs.pop(0)
            newBlock.timestamp = block['timestamp']
            newBlocks.append(newBlock)
        blockchain.blocks = newBlocks

        # copy over pool
        newPoolTxOuts = []
        for txOut in jsonChain['pool']['txOuts']:
            if txOut['address'] == None:
                newPubKey = None
            else:
                newPubKey = PubKey.wrap(txOut['address'])
            newPoolTxOut = TxOut(newPubKey, txOut['value'])
            newPoolTxOut.txHash = txOut['txHash']
            newPoolTxOut.idx = txOut['idx']
            newPoolTxOuts.append(newPoolTxOut)
        blockchain.pool.txOuts = newPoolTxOuts

        # don't need to remove duplicate genesis block because everything was replaced
        return blockchain