コード例 #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"]))
コード例 #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)
コード例 #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
コード例 #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
コード例 #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))
コード例 #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)
コード例 #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
コード例 #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
コード例 #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
コード例 #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)
コード例 #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)
コード例 #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))
コード例 #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)
コード例 #14
0
 def replace_mining_entropy(self, new_entropy: bytes) -> None:
     self.mining_entropy = new_entropy
     self.mining_timestamp = Timestamp.now()
コード例 #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)
コード例 #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)
コード例 #17
0
 def reward(amount: Amount, claimer: Address) -> 'Transaction':
     out = TransactionOutput(0, amount, claimer)
     return Transaction([], [out], Timestamp.now(), claimer)