From a32ae4f299caf135ec762a85d1f91f146bc37253 Mon Sep 17 00:00:00 2001 From: Jonathan Zernik Date: Sun, 19 Jul 2020 04:02:31 -0700 Subject: [PATCH] Include block time in squeak entry response (#93) --- itests/test.py | 19 ++++++++++ proto/squeak_admin.proto | 12 +++++++ .../admin/squeak_admin_server_handler.py | 10 ++++++ .../admin/squeak_admin_server_servicer.py | 27 +++++++++++++- squeakserver/node/squeak_block_verifier.py | 2 +- squeakserver/node/squeak_node.py | 3 ++ squeakserver/server/postgres_db.py | 35 ++++++++++++++----- 7 files changed, 98 insertions(+), 10 deletions(-) diff --git a/itests/test.py b/itests/test.py index 62b2aac3..debec587 100644 --- a/itests/test.py +++ b/itests/test.py @@ -313,6 +313,25 @@ def run(): == "Hello from the profile on the server!" ) + # Make another squeak + admin_stub.MakeSqueak( + squeak_admin_pb2.MakeSqueakRequest( + profile_id=profile_id, content="Hello again!", + ) + ) + + # Wait a few seconds for the squeak to be verified on the server. + time.sleep(5) + + # Get all followed squeak display items + get_followed_squeak_display_response = admin_stub.GetFollowedSqueakDisplays( + squeak_admin_pb2.GetFollowedSqueakDisplaysRequest() + ) + print("Get followed squeak displays response: " + str(get_followed_squeak_display_response)) + assert ( + len(get_followed_squeak_display_response.squeak_display_entries) == 2 + ) + if __name__ == "__main__": logging.basicConfig() diff --git a/proto/squeak_admin.proto b/proto/squeak_admin.proto index 9506aeb6..c44294cb 100644 --- a/proto/squeak_admin.proto +++ b/proto/squeak_admin.proto @@ -32,6 +32,10 @@ service SqueakAdmin { */ rpc GetSqueakDisplay (GetSqueakDisplayRequest) returns (GetSqueakDisplayReply) {} + /** sqkadmin: `getfollowedsqueakdisplays` + */ + rpc GetFollowedSqueakDisplays (GetFollowedSqueakDisplaysRequest) returns (GetFollowedSqueakDisplaysReply) {} + } message GetBalanceRequest { @@ -136,3 +140,11 @@ message SqueakDisplayEntry { /// The author name string author_name = 9; } + +message GetFollowedSqueakDisplaysRequest { +} + +message GetFollowedSqueakDisplaysReply { + /// Multiple squeak display entries + repeated SqueakDisplayEntry squeak_display_entries = 1; +} diff --git a/squeakserver/admin/squeak_admin_server_handler.py b/squeakserver/admin/squeak_admin_server_handler.py index f5e687fa..28fa4c68 100644 --- a/squeakserver/admin/squeak_admin_server_handler.py +++ b/squeakserver/admin/squeak_admin_server_handler.py @@ -50,3 +50,13 @@ class SqueakAdminServerHandler(object): ) ) return squeak_entry_with_profile + + def handle_get_followed_squeak_display_entries(self): + logger.info("Handle get followed squeak display entries.") + squeak_entries_with_profile = self.squeak_node.get_followed_squeak_entries_with_profile() + logger.info( + "Got squeak entries with profile: {}".format( + squeak_entries_with_profile + ) + ) + return squeak_entries_with_profile diff --git a/squeakserver/admin/squeak_admin_server_servicer.py b/squeakserver/admin/squeak_admin_server_servicer.py index c4fd19b5..cfeada77 100644 --- a/squeakserver/admin/squeak_admin_server_servicer.py +++ b/squeakserver/admin/squeak_admin_server_servicer.py @@ -5,6 +5,8 @@ import grpc from proto import squeak_admin_pb2, squeak_admin_pb2_grpc +from squeakserver.server.util import get_hash + logger = logging.getLogger(__name__) @@ -57,14 +59,37 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer): ) squeak_entry = squeak_entry_with_profile.squeak_entry squeak = squeak_entry.squeak + block_header = squeak_entry.block_header + logger.info("Got block_header: {}".format(block_header)) return squeak_admin_pb2.GetSqueakDisplayReply( squeak_display_entry=squeak_admin_pb2.SqueakDisplayEntry( - squeak_hash=squeak_hash.hex(), + squeak_hash=get_hash(squeak).hex(), is_unlocked=True, content_str=squeak.GetDecryptedContentStr(), + block_height=squeak.nBlockHeight, + block_time=block_header.nTime, ) ) + def GetFollowedSqueakDisplays(self, request, context): + squeak_entries_with_profile = self.handler.handle_get_followed_squeak_display_entries() + ret = [] + for entry in squeak_entries_with_profile: + squeak_entry = entry.squeak_entry + squeak = squeak_entry.squeak + block_header = squeak_entry.block_header + squeak_display_entry=squeak_admin_pb2.SqueakDisplayEntry( + squeak_hash=get_hash(squeak).hex(), + is_unlocked=True, + content_str=squeak.GetDecryptedContentStr(), + block_height=squeak.nBlockHeight, + block_time=block_header.nTime, + ) + ret.append(squeak_display_entry) + return squeak_admin_pb2.GetFollowedSqueakDisplaysReply( + squeak_display_entries=ret + ) + def serve(self): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) squeak_admin_pb2_grpc.add_SqueakAdminServicer_to_server(self, server) diff --git a/squeakserver/node/squeak_block_verifier.py b/squeakserver/node/squeak_block_verifier.py index 2d9c2b97..0c94539f 100644 --- a/squeakserver/node/squeak_block_verifier.py +++ b/squeakserver/node/squeak_block_verifier.py @@ -54,7 +54,7 @@ class SqueakBlockVerifier: block_hash_str = squeak.hashBlock.hex() block_header = self.blockchain_client.get_block_header(block_hash_str, False) logger.info("Got block header from blockchain: {}".format(block_header)) - return block_header + return bytes.fromhex(block_header) def _get_block_hash(self, block_height): block_hash = self.blockchain_client.get_block_hash(block_height) diff --git a/squeakserver/node/squeak_node.py b/squeakserver/node/squeak_node.py index b5795aaa..6c876006 100644 --- a/squeakserver/node/squeak_node.py +++ b/squeakserver/node/squeak_node.py @@ -122,3 +122,6 @@ class SqueakNode: def get_squeak_entry_with_profile(self, squeak_hash): return self.postgres_db.get_squeak_entry_with_profile(squeak_hash) + + def get_followed_squeak_entries_with_profile(self): + return self.postgres_db.get_followed_squeak_entries_with_profile() diff --git a/squeakserver/server/postgres_db.py b/squeakserver/server/postgres_db.py index 6e5357bc..8b61ab50 100644 --- a/squeakserver/server/postgres_db.py +++ b/squeakserver/server/postgres_db.py @@ -9,6 +9,8 @@ from squeakserver.core.squeak_entry import SqueakEntry from squeakserver.core.squeak_entry_with_profile import SqueakEntryWithProfile from squeakserver.server.squeak_profile import SqueakProfile from squeakserver.server.util import get_hash +from squeakserver.blockchain.util import parse_block_header + logger = logging.getLogger(__name__) @@ -105,11 +107,22 @@ class PostgresDb: with self.get_cursor() as curs: curs.execute(sql, (squeak_hash_str,)) row = curs.fetchone() - squeak_entry = self._parse_squeak_entry(row) - squeak_profile = self._parse_squeak_profile(row) - return SqueakEntryWithProfile( - squeak_entry=squeak_entry, squeak_profile=squeak_profile, - ) + return self._parse_squeak_entry_with_profile(row) + + def get_followed_squeak_entries_with_profile(self): + """ Get a squeak. """ + sql = """ + SELECT * FROM squeak + JOIN profile + ON squeak.address=profile.address + WHERE squeak.block_header IS NOT NULL + AND profile.following=False + ORDER BY n_block_height DESC, n_time DESC; + """ + with self.get_cursor() as curs: + curs.execute(sql) + rows = curs.fetchall() + return [self._parse_squeak_entry_with_profile(row) for row in rows] def lookup_squeaks(self, addresses, min_block, max_block): """ Lookup squeaks. """ @@ -153,10 +166,8 @@ class PostgresDb: squeak_profile.following, ), ) - logger.info("Inserted new profile") # get the new profile id back row = curs.fetchone() - logger.info("New profile id: {}".format(row["profile_id"])) return row["profile_id"] def get_profile(self, profile_id): @@ -224,7 +235,8 @@ class PostgresDb: vchDecryptionKey=vch_decryption_key, ) block_header_column = row["block_header"] - block_header = bytes(block_header_column) if block_header_column else None + block_header_bytes = bytes(block_header_column) if block_header_column else None + block_header = parse_block_header(block_header_bytes) if block_header_bytes else None return SqueakEntry(squeak=squeak, block_header=block_header) def _parse_squeak_profile(self, row): @@ -238,3 +250,10 @@ class PostgresDb: sharing=row["sharing"], following=row["following"], ) + + def _parse_squeak_entry_with_profile(self, row): + squeak_entry = self._parse_squeak_entry(row) + squeak_profile = self._parse_squeak_profile(row) + return SqueakEntryWithProfile( + squeak_entry=squeak_entry, squeak_profile=squeak_profile, + )