Ejemplo n.º 1
0
def form_transaction(sender, recipient, amount, utxo_obj, wif):
    outputs = []
    inputs = []
    spendable_utxo = utxo_obj.get_outputs_to_spend(sender,
                                                   int(amount) + tx_fee)
    if len(spendable_utxo) == 0:
        raise Exception(
            "Address " + sender +
            " has not enough spendable outputs, can't form transaction")
    utxo_sum = 0
    for v in spendable_utxo:
        utxo_sum += v.output.nVal
    outputs.append(Output(int(amount), recipient))
    if utxo_sum - int(amount) - tx_fee > 0:
        outputs.append(Output(utxo_sum - int(amount) - tx_fee, sender))

    inputs_outpoint_dict = {}  #  {spendable_output : input}
    for outs in spendable_utxo:
        inputs_outpoint_dict[outs] = Input(outs.txid, int(outs.vout, 16), "",
                                           0xffffffff)

    # forming scriptSig for all inputs
    scripts = {}  # {spendable_output : scriptSig}
    for spendable_output in inputs_outpoint_dict.keys():
        scripts[spendable_output] = get_signed_scriptSig(
            spendable_output, inputs_outpoint_dict.copy(), outputs, wif)

    for k in scripts.keys():
        inputs.append(Input(k.txid, int(k.vout, 16), scripts[k], 0xffffffff))
    return Transaction(1, inputs, outputs, 0)
Ejemplo n.º 2
0
def form_coinbase(miner_address, wif, g_miner_reward):
    outputs = [Output(g_miner_reward, miner_address)]
    inputs = []
    scriptSig = script.get_scriptSig(
        wif, "tanya works better")  # it can contain any data i like :)
    inputs.append(Input(coinbase_txid, 0xffffffff, scriptSig, 0xffffffff))
    return CoinbaseTransaction(1, inputs, outputs, 0)
Ejemplo n.º 3
0
    def from_dict(cls, config, mongo, txn):
        try:
            relationship = Relationship(**txn.get('relationship', ''))
        except:
            relationship = txn.get('relationship', '')

        return cls(config=config,
                   mongo=mongo,
                   transaction_signature=txn.get('id'),
                   rid=txn.get('rid', ''),
                   relationship=relationship,
                   public_key=txn.get('public_key'),
                   dh_public_key=txn.get('dh_public_key', ''),
                   fee=float(txn.get('fee')),
                   requester_rid=txn.get('requester_rid', ''),
                   requested_rid=txn.get('requested_rid', ''),
                   txn_hash=txn.get('hash', ''),
                   inputs=[
                       Input.from_dict(input_txn)
                       for input_txn in txn.get('inputs', '')
                   ],
                   outputs=[
                       Output.from_dict(output_txn)
                       for output_txn in txn.get('outputs', '')
                   ],
                   coinbase=txn.get('coinbase', ''),
                   signatures=txn.get('signatures', ''))
Ejemplo n.º 4
0
    def add_new_block(self, miner_address):
        """
        the function adds new block to the chain
        and rewards the miner
        :param miner_address: the miner address
        to reward
        """
        number = len(self.chain)

        # handle genesis block
        if number == 0:
            prev = '0' * 32
        else:
            prev = self.chain[-1].hash_code

        # transaction that rewards the miner
        # the input proof is arbitrary
        transaction_input = Input(str(len(self.chain)), -1,
                                  (miner_address, ''))
        transaction_output = Output(REWORD, miner_address)
        new_transaction = Transaction([transaction_input],
                                      [transaction_output])
        self.add_transaction(new_transaction)

        # create the block
        block = Block.new_block(number, prev, self.transactions_pool)
        self.logger.info('Mining new block')
        block.mine_block()

        # set the block chain
        self.chain.append(block)
        self.transactions_pool = []
        self.logger.info('The new block was added to the block chain')
Ejemplo n.º 5
0
 def do_send(self, args):
     if self.key_pair == 0:
         print("Haven`t key pair")
         return False
     split = args.strip().split(' ')
     if (not args or len(split) != 2):
         print("Please input  [Recipient Address] [Amount]")
         return False
     t_recip, t_amount = split
     if t_recip == '-s':
         self.transactions.append(t_amount)
         return False
     t_amount = int(t_amount)
     try:
     # if True:
         self.update_unspend_pool()
         sum_of_inp, prev_outputs = self.get_outputs(t_amount)
         inputs = [Input(txid=bytearray.fromhex(txid), vout=vout) for txid, vout, o in prev_outputs]
         outputs = [Output(recipient=t_recip, value=t_amount)]
         if sum_of_inp - t_amount > FEE:
             change = sum_of_inp - t_amount - FEE
             outputs.append(Output(self.key_pair.get_address(), value=(change)))
         tx = Transaction(inputs, outputs)
         tx.sign_tx(prev_outputs, self.key_pair)
         s_tx = Serializer.serialize(tx)
         print(s_tx)
         self.transactions.append(s_tx)
     except Exception as identifier:
         print (f'Error:[{identifier}]')
     return False
Ejemplo n.º 6
0
    def __init__(
        self,
        config,
        mongo,
        block_height,
        time='',
        rid='',
        transaction_signature='',
        relationship='',
        public_key='',
        dh_public_key='',
        fee=0.0,
        requester_rid='',
        requested_rid='',
        txn_hash='',
        inputs='',
        outputs='',
        coinbase=False,
        signatures=None,
        extra_blocks=None
    ):
        self.config = config
        self.mongo = mongo
        self.block_height = block_height
        self.time = time
        self.rid = rid
        self.transaction_signature = transaction_signature
        self.relationship = relationship
        self.public_key = public_key
        self.dh_public_key = dh_public_key
        self.fee = fee
        self.requester_rid = requester_rid
        self.requested_rid = requested_rid
        self.hash = txn_hash
        self.outputs = []
        self.extra_blocks = extra_blocks
        for x in outputs:
            self.outputs.append(Output.from_dict(x))
        self.inputs = []
        for x in inputs:
            if 'signature' in x and 'public_key' in x:
                self.inputs.append(ExternalInput.from_dict(self.config, self.mongo, x))
            else:
                self.inputs.append(Input.from_dict(x))
        self.coinbase = coinbase

        if not signatures:
            signatures = []

        self.signatures = []
        for signature in signatures:
            if isinstance(signature, FastGraphSignature):
                self.signatures.append(signature)
            else:
                self.signatures.append(FastGraphSignature(signature))
Ejemplo n.º 7
0
 def deserialize_input(self, serial):
     txid = little_endian(serial[:64])
     serial = serial[64:]
     vout = int(little_endian(serial[:8]), 16)
     serial = serial[8:]
     slen, shift1 = get_script_length(serial)
     serial = serial[shift1:]
     scriptSig = serial[:slen]
     serial = serial[slen:]
     seq = int(little_endian(serial[:8]), 16)
     serial = serial[8:]
     shift = 80 + slen + shift1
     return (shift, Input(txid, vout, scriptSig, seq))
Ejemplo n.º 8
0
    def create_transaction(self, amount, recipient_address):
        """
        the functions creates transaction which
        contains the amount of coins to send
        the recipient address, the function implements
        the transaction in the block chain
        :param amount: the amount to send
        :param recipient_address: the address to send the
        coins to
        :returns: true if there is enough money to the
        transaction and false otherwise
        """
        # updates the balance
        self.update_balance()

        # checks weather there is enough money
        # to the transaction
        if amount > self.balance:
            self.logger.info(self.address + '- not enough money to send')
            return False

        # creates the new transaction
        new_transaction = Transaction([], [])
        sending_amount = 0
        for unspent_output in self.unspent_outputs:
            # creating the proof
            data_to_sign = unspent_output.transaction_id
            data_to_sign += recipient_address
            data_to_sign = self.hash(data_to_sign).hexdigest()
            data_to_sign += str(amount)
            data_to_sign = self.hash(data_to_sign)
            signature = self.sign(data_to_sign)
            proof = (signature, self.public_key)
            new_transaction.add_input(
                Input(unspent_output.transaction_id,
                      unspent_output.output_index, proof))
            sending_amount += unspent_output.output.value
            if sending_amount >= amount:
                break
        new_transaction.add_output(Output(sending_amount, recipient_address))

        # add change if it is needed
        if sending_amount > amount:
            change = sending_amount - amount
            new_transaction.add_output(Output(change, self.address))

        # distributes the transaction
        self.logger.info(self.address + " is sending " + str(amount) +
                         "LPC to " + recipient_address)
        self.distribute_transaction(new_transaction)
        return True
Ejemplo n.º 9
0
 def deserialize_input(s):
     padd = 0
     r_i = Input()
     r_i.txid = (bytearray.fromhex(s[0:64]))[::-1]                               #?txid
     padd += 64
     s = s[64:]
     r_i.vout = int.from_bytes(bytearray.fromhex(s[0:8]), byteorder='little')    #?vout
     padd += 8
     s = s[8:]
     r_i.scriptsigsize, v_int = var_int.varint_to_int(s)                           #?sript sig size
     padd += v_int
     s = s[v_int:]
     r_i.scriptsig = s[0:r_i.scriptsigsize * 2]                                  #? script sig
     padd += r_i.scriptsigsize * 2
     s = s[r_i.scriptsigsize * 2:]
     r_i.sequence = bytearray.fromhex(s[0:8])[::-1]                              #? sequence 
     padd += 8 
     return (r_i, padd)
Ejemplo n.º 10
0
    def gui_handler(self, client_socket: socket.socket):
        self.send_verack_handler(client_socket)

        keep_open = True
        while keep_open:
            command_metadata = client_socket.recv(31)
            command = command_metadata[:12].decode('utf-8')

            if command == TX_COMMAND:
                payload = len(self.txs_handler.UTXO_pool).to_bytes(4, 'little')
                for input_inst in self.txs_handler.UTXO_pool.values():
                    payload += input_inst.serialize()

                client_socket.send(payload)
                tx = utils.receive_tx_data(client_socket)
                self.add_tx(tx)

            elif command == CREATE_BLOCK_COMMAND:
                # number_of_txs = len(self.outstanding_txs_pool).to_bytes(4, 'little')
                # client_socket.send(number_of_txs)

                # payload = b''
                # for tx in self.outstanding_txs_pool:
                #     tx_id, tx_value = tx.data['uniqueID'], tx.data['value']
                #     payload += tx_id.to_bytes(4, 'little')
                #     payload += tx_value.to_bytes(4, 'little')
                # client_socket.send(payload)

                # command_metadata = client_socket.recv(31)
                # command = command_metadata[:12].decode('utf-8')
                # if command != BLOCK_COMMAND:
                #     self.__update_events('Did not receive block command')
                #     client_socket.close()
                #     return

                # metadata_new_block = client_socket.recv(4)
                # number_of_txs_in_block = int.from_bytes(metadata_new_block, 'little')

                # txs = []
                # for _ in range(number_of_txs_in_block):
                #     tx_metadata = client_socket.recv(8)
                #     tx_id = int.from_bytes(tx_metadata[:4], 'little')
                #     tx_value = int.from_bytes(tx_metadata[4:], 'little')
                #     txs.append((tx_id, tx_value))

                # self.add_block(txs)
                self.generate_new_block()

            elif command == CREATE_CONNECTION:
                connection_metadata = client_socket.recv(19)
                connection = connection_metadata[:15].decode('utf-8').strip(), int.from_bytes(connection_metadata[15:], 'little')
                self.send_conexion_handler(connection)
                if connection in self.peers:
                    self.send_getblocks_handler(connection)

            elif command == DEFAULT_DATA_COMMAND:
                addressA = load_pk('publickeyAlice.pem')
                addressB = load_pk('publickeyBob.pem')
                addressC = load_pk('publickeyCharlie.pem')
                scrooge = load_pk('publickeyScrooge.pem')

                transactions = []

                # Create coin transaction
                inputs = []
                outputs = [
                    Output(11, addressA),  # Alice has 10 scrooge coins
                    Output(10, addressB),  # Alice has 10 scrooge coins
                ]
                unsigned = UnsignedTransaction(CREATECOINS_TYPE, inputs, outputs)
                to_sign = unsigned.DataForSigs()
                sigs = {}
                sigs[scrooge.export_key(format='DER')] = sign(to_sign, 'privatekeyScrooge.pem')
                transaction = Transaction(unsigned, sigs)
                self.add_tx(transaction)
                transactions.append(transaction)

                # Create block
                block = utils.create_block(
                    transactions,
                    self.blockchain.head_block_hash,
                )
                time.sleep(1)
                self.add_block(block)
                continue
                transactions = []

                # Pay coins transaction
                inputs = [
                    Input(transaction.txID, 10, addressA),
                    Input(transaction.txID, 10, addressB),  # Both spend their 10 scrooge coins
                ]
                outputs = [
                    Output(5, addressA),  # Alice has 5 scrooge coins
                    Output(15, addressB),  # Bob has 15 scrooge coins
                ]
                unsigned = UnsignedTransaction(PAYCOINS_TYPE, inputs, outputs)
                to_sign = unsigned.DataForSigs()
                sigs = {}
                sigs[addressA.export_key(format='DER')] = sign(to_sign, 'privatekeyAlice.pem')
                sigs[addressB.export_key(format='DER')] = sign(to_sign, 'privatekeyBob.pem')
                transaction = Transaction(unsigned, sigs)
                self.add_tx(transaction)
                transactions.append(transaction)

                # Create block
                block = utils.create_block(
                    transactions,
                    self.blockchain.head_block_hash,
                )
                self.add_block(block)

            elif command == GUICLOSE_COMMAND:
                keep_open = False

        client_socket.close()
Ejemplo n.º 11
0
def decode_input(payload):
    where_created = payload[:64].decode('utf-8')
    value = int.from_bytes(payload[64:68], 'little')
    owner = ECC.import_key(payload[68:])
    return Input(where_created, value, owner)
Ejemplo n.º 12
0
    def do_payout_for_block(self, block):
        # check if we already paid out

        already_used = self.already_used(block.get_coinbase())
        if already_used:
            return

        existing = self.mongo.db.share_payout.find_one({'index': block.index})
        if existing:
            pending = self.mongo.db.miner_transactions.find_one({'inputs.id': block.get_coinbase().transaction_signature})
            if pending:
                return
            else:
                # rebroadcast
                transaction = Transaction.from_dict(self.config, self.mongo, existing['txn'])
                TU.save(self.config, self.mongo, transaction)
                self.broadcast_transaction(transaction)
                return

        try:
            shares = self.get_share_list_for_height(block.index)
        except:
            return

        total_reward = block.get_coinbase()
        if total_reward.outputs[0].to != self.config.address:
            return
        pool_take = 0.01
        total_pool_take = total_reward.outputs[0].value * pool_take
        total_payout = total_reward.outputs[0].value - total_pool_take

        outputs = []
        for address, x in shares.iteritems():
            exists = self.mongo.db.share_payout.find_one({'index': block.index, 'txn.outputs.to': address})
            if exists:
                raise PartialPayoutException('this index has been partially paid out.')
            
            payout = total_payout * x['payout_share']
            outputs.append(Output(to=address, value=payout))

        try:
            transaction = TransactionFactory(
                self.config,
                self.mongo,
                fee=0.0001,
                public_key=self.config.public_key,
                private_key=self.config.private_key,
                inputs=[Input(total_reward.transaction_signature)],
                outputs=outputs
            )
        except NotEnoughMoneyException as e:
            print "not enough money yet"
            return
        except Exception as e:
            print e

        try:
            transaction.transaction.verify()
        except:
            raise
            print 'faucet transaction failed'

        TU.save(self.config, self.mongo, transaction.transaction)
        self.mongo.db.share_payout.insert({'index': block.index, 'txn': transaction.transaction.to_dict()})

        self.broadcast_transaction(transaction.transaction)