Example #1
0
    def add_transaction(self, txn: SignedTransaction) -> None:
        args = {
            "txn_hash": txn.sha256().raw_sha256,
            "serialized": txn.serialize(),
        }

        c = self._conn.cursor()
        c.execute(ADD_TRANSACTION_SQL, args)
        self._conn.commit()
Example #2
0
 def get_transaction(self, txn_hash: Hash) -> Optional[SignedTransaction]:
     args = {"txn_hash": txn_hash.raw_sha256}
     c = self._conn.cursor()
     c.execute(GET_TRANSACTION_SQL, args)
     res = c.fetchone()
     if res is None:
         return None
     else:
         return SignedTransaction.deserialize(res[0])
Example #3
0
 def add_outstanding_transaction(self, txn: SignedTransaction) -> None:
     if self.transaction_storage.has_transaction(txn.txn_hash()):
         self.l.debug("Already have txn", txn)
         return
     elif self.transaction_is_valid(txn):
         self.l.debug("Store transaction", txn)
         self.transaction_storage.add_transaction(txn)
     else:
         raise InvalidTransactionError("Transaction is invalid")
Example #4
0
 def from_dict(obj: Ser) -> 'Block':
     block_num = obj["block_num"]
     if obj["parent_mined_hash"] is not None:
         parent_hash = Hash.from_dict(obj["parent_mined_hash"])
     else:
         parent_hash = None
     txns = list(
         map(lambda o: SignedTransaction.from_dict(o), obj["transactions"]))
     config = BlockConfig.from_dict(obj["config"])
     return Block(block_num, parent_hash, config, txns)
Example #5
0
    def transaction_is_valid(self, signed: SignedTransaction) -> bool:
        if signed.is_reward():
            return self.reward_is_valid(signed)

        if not signed.signature_is_valid():
            self.l.warn("Transaction signature is invalid (sig {})".format(
                signed.signature))
            return False

        output_sum = Amount(0)
        for output in signed.transaction.outputs:
            output_sum += output.amount

        claimed_prev_outputs: List[TransactionOutput] = []
        claimed_sum = Amount(0)
        for inp in signed.transaction.inputs:
            out = self.get_transaction_output(inp.output_block_hash,
                                              inp.output_transaction_hash,
                                              inp.output_id)

            if out is None:
                self.l.warn("Output was unknown", out)
                return False

            if self.uxto_storage.output_is_claimed(inp.output_transaction_hash,
                                                   inp.output_id):
                self.l.warn("Output already claimed", out)
                return False

            claimed_sum += out.amount

            if out.to_addr != signed.transaction.claimer:
                self.l.warn("Output {} can't be claimed by address {}".format(
                    out, signed.transaction.claimer))
                return False

        if output_sum != claimed_sum:
            self.l.warn("Input/output amount mismatch {} != {}".format(
                output_sum, claimed_sum))
            return False

        return True
Example #6
0
    def post(self) -> None:
        ser = self.request.body.decode('utf-8')
        txn = SignedTransaction.deserialize(ser)

        if self.chain.transaction_is_valid(txn):
            self.l.info("New transaction", txn)
            self.chain.add_outstanding_transaction(txn)
            self.set_status(200)
            self.write(util.generic_ok_response())
        else:
            self.l.warn("Invalid transaction", txn)
            self.set_status(400)
            self.write(util.error_response("Invalid transaction"))
Example #7
0
    def reward_is_valid(self, reward: SignedTransaction) -> bool:
        if not reward.signature_is_valid():
            self.l.warn("Reward signature is invalid (sig {})".format(
                reward.signature))
            return False

        if len(reward.transaction.outputs) != 1:
            self.l.warn("Reward has n_outputs != 1", reward)
            return False

        if len(reward.transaction.inputs) != 0:
            self.l.warn("Reward has inputs", reward)
            return False

        if reward.transaction.outputs[0].amount != REWARD_AMOUNT:
            self.l.warn("Reward has invalid amout", reward)
            return False

        return True
Example #8
0
    def request_transactions(self,
                             peer: Peer) -> Optional[List[SignedTransaction]]:
        obj = self._peer_get(peer, "/outstanding_transactions", {})
        if obj is None:
            self.l.debug("No peer response from peer", peer)
            return None

        if not "transactions" in obj:
            self.l.debug("No transaction response from peer", peer, obj)
            return None

        new_transactions: List[SignedTransaction] = []
        for txn_obj in obj["transactions"]:
            try:
                new_txn = SignedTransaction.from_dict(txn_obj)
            except KeyError as e:
                self.l.debug("Invalid transaction from peer",
                             peer,
                             txn_obj,
                             exc=e)
            else:
                new_transactions.append(new_txn)
        return new_transactions
Example #9
0
 def get_all_transactions(self) -> List[SignedTransaction]:
     c = self._conn.cursor()
     c.execute(GET_ALL_TRANSACTIONS_SQL)
     return list(map(lambda s: SignedTransaction.deserialize(s[0]), c))
Example #10
0
 def make_reward(self) -> SignedTransaction:
     reward = Transaction.reward(REWARD_AMOUNT, self.key_pair.address())
     return SignedTransaction.sign(reward, self.key_pair)