Ejemplo n.º 1
0
 def from_dict(obj: Ser) -> 'Transaction':
     inputs = map(lambda ti: TransactionInput.from_dict(ti), obj["inputs"])
     outputs = map(lambda ti: TransactionOutput.from_dict(ti),
                   obj["outputs"])
     return Transaction(list(inputs), list(outputs),
                        Timestamp.from_dict(obj["timestamp"]),
                        Address.from_dict(obj["claimer"]))
Ejemplo n.º 2
0
    def fetch_submissions(self,
                          fetcher: Optional[Fetcher] = None,
                          since: int = Timestamp.now() - 10 * day,
                          limit: int = 1000) -> List[Submission]:
        """Fetches all submissions (up to 1000) since the given UTC UNIX timestamp, using the provided fetcher.
        
        If no argument is passed for 'fetcher' (or it is None), this method will request the newest posts from r/nearprog.
        """
        def fetch(extended_limit: int) -> List:

            # if None is provided, use the default (live) Submission fetcher
            default_fetcher = Fetcher(
                lambda n: map(lambda s: Submission.wrap(s),
                              self.nearprog().new(limit=n)))
            submissions = list(
                (fetcher or default_fetcher).fetch(since, extended_limit))
            earliest = min(map(lambda s: s.timestamp, submissions))

            # if we're limited only by our own self-imposed max # submissions, try again, but request more
            if (earliest > since and len(submissions) == extended_limit):
                return fetch(extended_limit * 2)
            else:
                # return the oldest submissions first (at the head of the list)
                return sorted(submissions, key=lambda x: x.timestamp)[:limit]

        return fetch(limit)
Ejemplo n.º 3
0
 def from_dict(obj: Ser) -> 'HashedBlock':
     block = Block.from_dict(obj["block"])
     mining_entropy = bytes.fromhex(obj["mining_entropy"])
     mining_timestamp = Timestamp.from_dict(obj["mining_timestamp"])
     hb = HashedBlock(block,
                      mining_entropy=mining_entropy,
                      mining_timestamp=mining_timestamp)
     return hb
Ejemplo n.º 4
0
 def __init__(self,
              block: Block,
              mining_entropy: bytes = b"",
              mining_timestamp: Optional[Timestamp] = None) -> None:
     self.block = block
     self.mining_entropy = mining_entropy
     if mining_timestamp is None:
         self.mining_timestamp = Timestamp.now()
     else:
         self.mining_timestamp = mining_timestamp
Ejemplo n.º 5
0
 def genesis() -> 'HashedBlock':
     """
     The genesis is a block with num=0, no parent hash, a difficulty of
     0, no transactions, no mining entropy and a mining time at the Unix
     epoch.
     """
     b = Block(0, None, BlockConfig(0), [])
     return HashedBlock(b,
                        mining_entropy=b"",
                        mining_timestamp=Timestamp(0))
Ejemplo n.º 6
0
    def start_transaction(self, accepted_trade):
        order = self.order_manager.order_repository.find_by_id(accepted_trade.order_id)

        if order:
            transaction = self.transaction_manager.create_from_accepted_trade(accepted_trade)

            start_transaction = StartTransaction(self.order_book.message_repository.next_identity(),
                                                 transaction.transaction_id, order.order_id,
                                                 accepted_trade.recipient_order_id, accepted_trade.price,
                                                 accepted_trade.quantity, Timestamp.now())
            self.send_start_transaction(transaction, start_transaction)
Ejemplo n.º 7
0
def test_fetch_submissions_since():
    """Test that Connection.fetch_submissions() only returns submissions since the given UTC UNIX timestamp."""

    config = get_config()
    connection: Connection = Connection(config)

    # remove 'fetcher' argument to test this method directly with Reddit
    since = Timestamp.now() - 24 * hour
    submissions = connection.fetch_submissions(fetcher=Fetcher(
        Fixture.fetcher),
                                               since=since)

    assert submissions[0].timestamp >= since
Ejemplo n.º 8
0
def test_fetch_submissions_ordering():
    """Test that Connection.fetch_submissions() returns the Submissions sorted oldest -> newest."""

    config = get_config()
    connection: Connection = Connection(config)

    # remove 'fetcher' argument to test this method directly with Reddit
    since = Timestamp.now() - 30 * day
    submissions = connection.fetch_submissions(fetcher=Fetcher(
        Fixture.fetcher),
                                               since=since)

    assert submissions[0].timestamp < submissions[1].timestamp
    assert submissions[1].timestamp < submissions[2].timestamp
Ejemplo n.º 9
0
def test_fetch_submissions_age():
    """Test that Connection.fetch_submissions() returns the oldest-available submissions."""

    config = get_config()
    connection: Connection = Connection(config)

    # remove 'fetcher' argument to test this method directly with Reddit
    old = connection.fetch_submissions(fetcher=Fetcher(Fixture.fetcher),
                                       since=0,
                                       limit=1)
    new = connection.fetch_submissions(fetcher=Fetcher(Fixture.fetcher),
                                       since=Timestamp.now() - week,
                                       limit=1)

    assert old[0].timestamp < new[0].timestamp
Ejemplo n.º 10
0
    def on_counter_trade(self, messages):
        for message in messages:
            counter_trade = CounterTrade.from_network(message.payload)

            if str(counter_trade.recipient_order_id.trader_id) == str(self.pubkey):  # The message is for this node
                order = self.order_manager.order_repository.find_by_id(counter_trade.recipient_order_id)

                if order:
                    try:  # Accept trade
                        order.release_quantity_for_tick(counter_trade.order_id)
                        self.accept_trade(order, counter_trade)
                    except TickWasNotReserved:  # Send cancel
                        declined_trade = Trade.decline(self.order_book.message_repository.next_identity(),
                                                       Timestamp.now(), counter_trade)
                        self._logger.debug("Declined trade made with id: %s for counter trade with id: %s",
                                           str(declined_trade.message_id), str(counter_trade.message_id))
                        self.send_declined_trade(declined_trade)
Ejemplo n.º 11
0
    def send_end_transaction(self, transaction):
        # Lookup the remote address of the peer with the pubkey
        self._logger.debug("Sending end transaction (quantity: %s)", transaction.total_quantity)
        candidate = Candidate(self.lookup_ip(transaction.partner_trader_id), False)

        message_id = self.order_book.message_repository.next_identity()

        meta = self.get_meta_message(u"end-transaction")
        message = meta.impl(
            authentication=(self.my_member,),
            distribution=(self.claim_global_time(),),
            destination=(candidate,),
            payload=(
                message_id.trader_id,
                message_id.message_number,
                transaction.transaction_id.trader_id,
                transaction.transaction_id.transaction_number,
                Timestamp.now(),
            )
        )

        self.dispersy.store_update_forward([message], True, False, True)
Ejemplo n.º 12
0
    def on_proposed_trade(self, messages):
        for message in messages:
            proposed_trade = ProposedTrade.from_network(message.payload)

            self._logger.debug("Proposed trade received with id: %s", str(proposed_trade.message_id))

            # Update the known IP address of the sender of this proposed trade
            self.update_ip(proposed_trade.message_id.trader_id,
                           (message.payload.address.ip, message.payload.address.port))

            if str(proposed_trade.recipient_order_id.trader_id) == str(self.pubkey):  # The message is for this node
                order = self.order_manager.order_repository.find_by_id(proposed_trade.recipient_order_id)

                if order and order.is_valid() and order.available_quantity > Quantity(0):  # Order is valid
                    self._logger.debug("Proposed trade received with id: %s for order with id: %s",
                                       str(proposed_trade.message_id), str(order.order_id))

                    if order.available_quantity >= proposed_trade.quantity:  # Enough quantity left
                        self.accept_trade(order, proposed_trade)
                    else:  # Not enough quantity for trade
                        counter_trade = Trade.counter(self.order_book.message_repository.next_identity(),
                                                      order.available_quantity, Timestamp.now(), proposed_trade)
                        order.reserve_quantity_for_tick(proposed_trade.order_id, order.available_quantity)
                        self._logger.debug("Counter trade made with id: %s for proposed trade with id: %s",
                                           str(counter_trade.message_id), str(proposed_trade.message_id))
                        self.send_counter_trade(counter_trade)
                else:  # Order invalid send cancel
                    declined_trade = Trade.decline(self.order_book.message_repository.next_identity(), Timestamp.now(),
                                                   proposed_trade)
                    self._logger.debug("Declined trade made with id: %s for proposed trade with id: %s "
                                       "(valid? %s, available quantity of order: %s, reserved: %s, traded: %s)",
                                       str(declined_trade.message_id), str(proposed_trade.message_id),
                                       order.is_valid(), order.available_quantity, order.reserved_quantity,
                                       order.traded_quantity)
                    self.send_declined_trade(declined_trade)
            else:
                self._logger.warning("Received proposed trade message that was not for this node "
                                     "(my id: %s, message recipient id: %s", str(self.pubkey),
                                     str(proposed_trade.recipient_order_id.trader_id))
Ejemplo n.º 13
0
    def send_continue_transaction(self, transaction):
        assert isinstance(transaction, Transaction), type(transaction)

        # Lookup the remote address of the peer with the pubkey
        candidate = Candidate(self.lookup_ip(transaction.partner_trader_id), False)

        message_id = self.order_book.message_repository.next_identity()

        meta = self.get_meta_message(u"continue-transaction")
        message = meta.impl(
            authentication=(self.my_member,),
            distribution=(self.claim_global_time(),),
            destination=(candidate,),
            payload=(
                message_id.trader_id,
                message_id.message_number,
                transaction.transaction_id.trader_id,
                transaction.transaction_id.transaction_number,
                Timestamp.now(),
            )
        )

        self.dispersy.store_update_forward([message], True, False, True)
Ejemplo n.º 14
0
 def replace_mining_entropy(self, new_entropy: bytes) -> None:
     self.mining_entropy = new_entropy
     self.mining_timestamp = Timestamp.now()
Ejemplo n.º 15
0
    def accept_trade(self, order, proposed_trade):
        accepted_trade = Trade.accept(self.order_book.message_repository.next_identity(), Timestamp.now(),
                                      proposed_trade)

        self._logger.debug("Accepted trade made with id: %s for proposed/counter trade with id: %s (quantity: %s)",
                           str(accepted_trade.message_id), str(proposed_trade.message_id), accepted_trade.quantity)

        self.check_history(accepted_trade)  # Set the message received as true

        self.order_book.insert_trade(accepted_trade)
        order.add_trade(accepted_trade.recipient_order_id, accepted_trade.quantity)
        self.order_book.trade_tick(accepted_trade.order_id, accepted_trade.recipient_order_id, accepted_trade.quantity)

        self.send_accepted_trade(accepted_trade)
        self.start_transaction(accepted_trade)
Ejemplo n.º 16
0
 def fetcher(limit: int) -> Iterator[Submission]:
     # assume 1 submission every ~6 hours on average
     end_time = int(Timestamp.now())
     start_time = int(end_time - limit * 6 * hour)
     timestamps = sorted(random.sample(range(start_time, end_time), limit))
     return iter(Submission(timestamp) for timestamp in timestamps)
Ejemplo n.º 17
0
 def reward(amount: Amount, claimer: Address) -> 'Transaction':
     out = TransactionOutput(0, amount, claimer)
     return Transaction([], [out], Timestamp.now(), claimer)