Exemple #1
0
def send_transaction():
    log_ip(request, inspect.stack()[0][3])
    data = request.json
    transaction = Transaction.from_json(data["transaction"]).object()
    sig = data["signature"]
    transaction.add_sign(sig)

    logger.debug(transaction)
    logger.info("Wallet: Attempting to Send Transaction")
    try:
        r = requests.post(
            "http://0.0.0.0:" + str(consts.MINER_SERVER_PORT) +
            "/newtransaction",
            data=compress(transaction.to_json()),
            timeout=(5, 1),
        )
        if r.status_code == 400:
            response.status = 400
            logger.error(
                "Wallet: Could not Send Transaction. Invalid transaction: " +
                r.text)
            return "Invalid Transaction: " + r.text
    except Exception as e:
        response.status = 400
        logger.error("Wallet: Could not Send Transaction. Try Again." + str(e))
        return "Internal error, try again"
    else:
        logger.info("Wallet: Transaction Sent, Wait for it to be Mined")
    return "Done"
Exemple #2
0
def create_transaction(receiver_public_keys: List[str],
                       amounts: List[int],
                       sender_public_key,
                       message="") -> Transaction:
    vout = {}
    vin = {}
    current_amount = 0
    total_amount = sum(amounts)
    i = 0
    for so, utxo_list in BLOCKCHAIN.active_chain.utxo.utxo.items():
        tx_out = utxo_list[0]
        if current_amount >= total_amount:
            break
        if tx_out.address == sender_public_key:
            current_amount += tx_out.amount
            vin[i] = TxIn(payout=SingleOutput.from_json(so),
                          pub_key=sender_public_key,
                          sig="")
            i += 1

    for i, address in enumerate(receiver_public_keys):
        vout[i] = TxOut(amount=amounts[i], address=address)
    change = (current_amount - total_amount)
    if change > 0:
        vout[i + 1] = TxOut(amount=change, address=sender_public_key)

    tx = Transaction(version=consts.MINER_VERSION,
                     locktime=0,
                     timestamp=int(time.time()),
                     vin=vin,
                     vout=vout,
                     message=message)
    return tx
Exemple #3
0
def process_new_transaction(request_data: bytes) -> str:
    global BLOCKCHAIN
    transaction_json = decompress(request_data)
    if transaction_json:
        try:
            tx = Transaction.from_json(transaction_json).object()
            # Add transaction to Mempool
            if tx not in BLOCKCHAIN.mempool:
                if BLOCKCHAIN.active_chain.is_transaction_valid(tx):
                    logger.debug(
                        "Valid Transaction received, Adding to Mempool")
                    BLOCKCHAIN.mempool.add(tx)
                    # Broadcast block to other peers
                    send_to_all_peers("/newtransaction", request_data)
                else:
                    return "Transaction Already received"
            else:
                logger.debug(
                    "The transation is not valid, not added to Mempool")
                return "Not Valid Transaction"
        except Exception as e:
            logger.error("Server: New Transaction: Invalid tx received: " +
                         str(e))
            raise e
            return "Not Valid Transaction"
    return "Done"
Exemple #4
0
 def __mine(self, mempool: Set[Transaction], chain: Chain,
            payout_addr: str) -> Block:
     c_pool = list(copy.deepcopy(mempool))
     mlist, fees = self.__calculate_best_transactions(c_pool)
     # logger.debug(f"Miner: Will mine {len(mlist)} transactions and get {fees} scoins in fees")
     coinbase_tx_in = {
         0:
         TxIn(payout=None,
              sig="Receiving some Money",
              pub_key="Does it matter?")
     }
     coinbase_tx_out = {
         0: TxOut(amount=chain.current_block_reward(), address=payout_addr),
         1: TxOut(amount=fees, address=payout_addr),
     }
     coinbase_tx = Transaction(
         is_coinbase=True,
         version=consts.MINER_VERSION,
         fees=0,
         timestamp=int(time.time()),
         locktime=-1,
         vin=coinbase_tx_in,
         vout=coinbase_tx_out,
     )
     mlist.insert(0, coinbase_tx)
     block_header = BlockHeader(
         version=consts.MINER_VERSION,
         height=chain.length,
         prev_block_hash=dhash(chain.header_list[-1]),
         merkle_root=merkle_hash(mlist),
         timestamp=int(time.time()),
         target_difficulty=chain.target_difficulty,
         nonce=0,
     )
     DONE = False
     for n in range(2**64):
         block_header.nonce = n
         bhash = dhash(block_header)
         if chain.is_proper_difficulty(bhash):
             block = Block(header=block_header, transactions=mlist)
             requests.post("http://0.0.0.0:" +
                           str(consts.MINER_SERVER_PORT) + "/newblock",
                           data=compress(block.to_json()))
             logger.info(
                 f"Miner: Mined Block with {len(mlist)} transactions, Got {fees} in fees and {chain.current_block_reward()} as reward"
             )
             DONE = True
             break
     if not DONE:
         logger.error(
             "Miner: Exhausted all 2 ** 64 values without finding proper hash"
         )
Exemple #5
0
def calculate_transaction_fees(tx: Transaction, w: Wallet, bounty: int,
                               fees: int):
    current_amount = 0
    i = 0
    for so, utxo_list in BLOCKCHAIN.active_chain.utxo.utxo.items():
        tx_out = utxo_list[0]
        if utxo_list[2]:
            # check for coinbase TxIn Maturity
            if not (BLOCKCHAIN.active_chain.length -
                    utxo_list[1].height) >= consts.COINBASE_MATURITY:
                continue
        if current_amount >= bounty + fees:
            break
        if tx_out.address == w.public_key:
            current_amount += tx_out.amount
            tx.vin[i] = TxIn(payout=SingleOutput.from_json(so),
                             pub_key=w.public_key,
                             sig="")
            i += 1
    tx.vout[1].amount = current_amount - bounty - fees
    tx.fees = fees
    tx.sign(w)
Exemple #6
0
def send_bounty(bounty: int, receiver_public_key: str, fees: int):
    current_balance = check_balance()
    if current_balance < bounty + fees:
        print("Insuficient balance ")
        print("Current balance : " + str(current_balance))
        print("You need " + str(current_balance - bounty) + "more money")

    else:
        transaction = Transaction(
            version=1,
            locktime=0,
            timestamp=2,
            is_coinbase=False,
            fees=0,
            vin={},
            vout={
                0: TxOut(amount=bounty, address=receiver_public_key),
                1: TxOut(amount=0, address=MY_WALLET.public_key)
            },
        )
        calculate_transaction_fees(transaction, MY_WALLET, bounty, fees)

        logger.debug(transaction)
        logger.info("Wallet: Attempting to Send Transaction")
        try:
            requests.post(
                "http://0.0.0.0:" + str(consts.MINER_SERVER_PORT) +
                "/newtransaction",
                data=compress(transaction.to_json()),
                timeout=(5, 1),
            )
        except Exception as e:
            logger.error("Wallet: Could not Send Transaction. Try Again." +
                         str(e))
        else:
            logger.info("Wallet: Transaction Sent, Wait for it to be Mined")
    def send_amount(self, receiver_address: str, amount: int, message: Optional[str]) -> bool:
        contract_private_key = int(self.current_contract_priv_key)
        contract_wallet = Wallet(pub_key=None, priv_key=contract_private_key)
        data = {
            'bounty': amount,
            'sender_public_key': contract_wallet.public_key,
            'receiver_public_key': receiver_address,
            'message': message
        }
        r = requests.post("http://0.0.0.0:" + str(consts.MINER_SERVER_PORT) + "/makeTransaction", json=data)
        tx_data = r.json()
        logger.debug(f"BlockchainVmInterface: send_amount - Make Transaction returned: {tx_data}")

        transaction = Transaction.from_json(tx_data['send_this']).object()
        signed_string = contract_wallet.sign(tx_data['sign_this'])
        transaction.add_sign(signed_string)

        return self.add_contract_tx_to_mempool(transaction)
    def update_contract_output(self, output: str) -> bool:
        contract_private_key = int(self.current_contract_priv_key)
        contract_wallet = Wallet(pub_key=None, priv_key=contract_private_key)
        contract_address = contract_wallet.public_key
        cc, _, cp = get_cc_co_cp_by_contract_address(contract_address)
        if cp != str(contract_private_key):
            # We should panic
            logger.error(f"Contract private keys do not match for address {contract_address}")
            return False
        if cc == '':
            logger.error(f"Contract code is empty for address {contract_address}")
            return False
        cpub = contract_address

        data = {
            'bounty': 1,
            'sender_public_key': contract_wallet.public_key,
            'receiver_public_key': 'AAAAA' + cpub[5:], # Some random address
            'message': "Updated output of the tx", # Possibly add the prev tx_hash here
            'contract_code': cc
        }
        r = requests.post("http://0.0.0.0:" + str(consts.MINER_SERVER_PORT) + "/makeTransaction", json=data)
        logger.debug(f"BlockchainVmInterface: update_contract_output - Make Transaction returned: {r.text}")
        res = r.json()['send_this']
        tx_data = json.loads(res)

        tx_data['contract_output'] = output
        tx_data['contract_priv_key'] = cp
        tx_data['data'] = "" # Leaving it empty
        tx_data['timestamp'] = int(time.time())
        for num in tx_data['vout']:
            tx_data['vout'][num]["address"] = cpub

        transaction = Transaction.from_json(json.dumps(tx_data)).object()
        tx_vin = transaction.vin
        transaction.vin = {}
        transaction.contract_output = None
        tx_json_to_sign = transaction.to_json()
        signed_string = contract_wallet.sign(tx_json_to_sign)
        transaction.vin = tx_vin
        transaction.contract_output = output
        transaction.add_sign(signed_string)

        return self.add_contract_tx_to_mempool(transaction)
Exemple #9
0
def process_new_transaction(request_data: bytes) -> Tuple[bool, str]:
    global BLOCKCHAIN
    transaction_json = decompress(request_data)
    if transaction_json:
        try:
            tx = Transaction.from_json(transaction_json).object()
            # Validations
            for txIn in tx.vin.values():
                if is_valid_contract_address(txIn.pub_key):
                    return False, "Cannot send funds from a contract address"
            if tx.contract_output is not None:
                return False, "Contract Output should be None"
            if tx.contract_code != "":  # This is a contract
                contract_address = tx.get_contract_address()
                # Ensure that there is no other contract on this contract address
                cc, _, _ = get_cc_co_cp_by_contract_address(contract_address)
                if cc != "":
                    return False, "There is already some other contract at this contract address"
            # Add transaction to Mempool
            if tx not in BLOCKCHAIN.mempool:
                ok, msg = BLOCKCHAIN.active_chain.is_transaction_valid(tx)
                if ok:
                    logger.debug(
                        "Valid Transaction received, Adding to Mempool")
                    BLOCKCHAIN.mempool.add(tx)
                    logger.debug(
                        f"Mempool now contains {len(BLOCKCHAIN.mempool)} transaction(s)"
                    )
                    # Broadcast block to other peers
                    send_to_all_peers("/newtransaction", request_data)
                else:
                    logger.debug(
                        "The transation is not valid, not added to Mempool - "
                        + msg)
                    return False, "Not Valid Transaction: " + msg
            else:
                return True, "Transaction Already received"
        except Exception as e:
            logger.error("Server: New Transaction: Invalid tx received: " +
                         str(e))
            return False, "Not Valid Transaction"
    return True, "Done"
Exemple #10
0

def get_peer_url(peer: Dict[str, Any]) -> str:
    return "http://" + str(peer["ip"]) + ":" + str(peer["port"])


if __name__ == "__main__":

    # The singleOutput for first coinbase transaction in genesis block
    so = SingleOutput(txid=dhash(first_block_transaction[0]), vout=0)

    first_transaction = Transaction(
        version=1,
        locktime=0,
        timestamp=3,
        is_coinbase=False,
        fees=4000000000,
        vin={0: TxIn(payout=so, sig="", pub_key=consts.WALLET_PUBLIC)},
        vout={0: TxOut(amount=1000000000, address=consts.WALLET_PUBLIC)}
    )

    sign_copy_of_tx = copy.deepcopy(first_transaction)
    sign_copy_of_tx.vin = {}
    w = Wallet()
    w.public_key = consts.WALLET_PUBLIC
    w.private_key = consts.WALLET_PRIVATE
    sig = w.sign(sign_copy_of_tx.to_json())
    first_transaction.vin[0].sig = sig

    peer_list = fetch_peer_list()
    print(peer_list)
Exemple #11
0
    for i in range(peer_height, ACTIVE_CHAIN.length):
        hash_list.append(dhash(ACTIVE_CHAIN.header_list[i]))
    logger.debug(peer_height)
    return jsonify(hash_list)


# The singleOutput for first coinbase transaction in genesis block
so = SingleOutput(txid=dhash(genesis_block_transaction[0]), vout=0)

first_block_transactions = [
    Transaction(
        version=1,
        locktime=0,
        timestamp=2,
        is_coinbase=True,
        fees=0,
        vin={0: TxIn(payout=None, sig="", pub_key=consts.WALLET_PUBLIC)},
        vout={
            0: TxOut(amount=5000000000, address=consts.WALLET_PUBLIC),
            1: TxOut(amount=4000000000, address=consts.WALLET_PUBLIC),
        },
    ),
    Transaction(
        version=1,
        locktime=0,
        timestamp=3,
        is_coinbase=False,
        fees=4000000000,
        vin={0: TxIn(payout=so, sig="", pub_key=consts.WALLET_PUBLIC)},
        vout={0: TxOut(amount=1000000000, address=consts.WALLET_PUBLIC)},
    ),
]