Load squeak display entry without deserializing squeak object (#1052)

* Load squeak display entry without deserializing squeak object

* Use block time column instead of block header in squeak table

* Include block time in squeak display response
This commit is contained in:
Jonathan Zernik 2021-08-24 05:09:00 -07:00 committed by GitHub
parent 2b09900828
commit dd4ddabb5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 85 additions and 57 deletions

View file

@ -91,6 +91,14 @@ def test_make_squeak(admin_stub, signing_profile_id):
assert len(
get_squeak_display_entry.author.profile_image) > 0
# Block time should be within the past hour
block_time = datetime.datetime.fromtimestamp(
get_squeak_display_entry.block_time,
)
one_hour = datetime.timedelta(hours=1)
assert block_time > datetime.datetime.now() - one_hour
assert block_time < datetime.datetime.now() + one_hour
# Get the squeak profile
squeak_profile = get_squeak_profile(admin_stub, signing_profile_id)
squeak_profile_address = squeak_profile.address

View file

@ -1,5 +1,7 @@
import logging
from squeak.core import CSqueak
from proto import squeak_admin_pb2
from squeaknode.admin.profile_image_util import bytes_to_base64_string
from squeaknode.admin.profile_image_util import load_default_profile_image
@ -13,7 +15,6 @@ from squeaknode.core.sent_payment_summary import SentPaymentSummary
from squeaknode.core.squeak_entry_with_profile import SqueakEntryWithProfile
from squeaknode.core.squeak_peer import SqueakPeer
from squeaknode.core.squeak_profile import SqueakProfile
from squeaknode.core.util import get_hash
from squeaknode.network.peer import Peer
logger = logging.getLogger(__name__)
@ -21,36 +22,33 @@ logger = logging.getLogger(__name__)
DEFAULT_PROFILE_IMAGE = load_default_profile_image()
# TODO: Remove this after reply is nullable column
EMPTY_HASH = b'\x00' * 32
def squeak_entry_to_message(squeak_entry_with_profile: SqueakEntryWithProfile) -> squeak_admin_pb2.SqueakDisplayEntry:
squeak_entry = squeak_entry_with_profile.squeak_entry
squeak = squeak_entry.squeak
block_header = squeak_entry.block_header
liked_time_s = squeak_entry.liked_time or 0
is_unlocked = squeak.HasDecryptionKey()
content_str = squeak_entry.content if is_unlocked else None
is_reply = squeak.is_reply
reply_to = squeak.hashReplySqk.hex() if is_reply else None
author_address = str(squeak.GetAddress())
squeak_profile = squeak_entry_with_profile.squeak_profile
is_reply = squeak_entry.reply_to != EMPTY_HASH
reply_to = squeak_entry.reply_to.hex() if squeak_entry.reply_to else None
is_author_known = False
profile_msg = None
if squeak_profile is not None:
is_author_known = True
profile_msg = squeak_profile_to_message(squeak_profile)
return squeak_admin_pb2.SqueakDisplayEntry(
squeak_hash=get_hash(squeak).hex(),
is_unlocked=squeak.HasDecryptionKey(),
content_str=content_str, # type: ignore
block_height=squeak.nBlockHeight,
block_hash=squeak.hashBlock.hex(),
block_time=block_header.nTime,
squeak_hash=squeak_entry.squeak_hash.hex(),
is_unlocked=squeak_entry.is_unlocked,
content_str=squeak_entry.content, # type: ignore
block_height=squeak_entry.block_height,
block_hash=squeak_entry.block_hash.hex(),
block_time=squeak_entry.block_time,
is_reply=is_reply,
reply_to=reply_to,
author_address=author_address,
reply_to=reply_to, # type: ignore
author_address=squeak_entry.address,
is_author_known=is_author_known,
author=profile_msg,
liked_time_s=liked_time_s,
liked_time_s=squeak_entry.liked_time, # type: ignore
)
@ -116,9 +114,7 @@ def sent_payment_to_message(sent_payment: SentPayment) -> squeak_admin_pb2.SentP
)
def squeak_entry_to_detail_message(squeak_entry_with_profile: SqueakEntryWithProfile) -> squeak_admin_pb2.SqueakDetailEntry:
squeak_entry = squeak_entry_with_profile.squeak_entry
squeak = squeak_entry.squeak
def squeak_to_detail_message(squeak: CSqueak) -> squeak_admin_pb2.SqueakDetailEntry:
serialized_squeak = squeak.serialize()
return squeak_admin_pb2.SqueakDetailEntry(
serialized_squeak_hex=serialized_squeak.hex(),

View file

@ -9,10 +9,10 @@ from squeaknode.admin.messages import payment_summary_to_message
from squeaknode.admin.messages import received_payments_to_message
from squeaknode.admin.messages import sent_offer_to_message
from squeaknode.admin.messages import sent_payment_to_message
from squeaknode.admin.messages import squeak_entry_to_detail_message
from squeaknode.admin.messages import squeak_entry_to_message
from squeaknode.admin.messages import squeak_peer_to_message
from squeaknode.admin.messages import squeak_profile_to_message
from squeaknode.admin.messages import squeak_to_detail_message
from squeaknode.admin.profile_image_util import base64_string_to_bytes
from squeaknode.lightning.lnd_lightning_client import LNDLightningClient
from squeaknode.node.squeak_controller import SqueakController
@ -547,17 +547,16 @@ class SqueakAdminServerHandler(object):
squeak_hash = bytes.fromhex(squeak_hash_str)
logger.info(
"Handle get squeak details for hash: {}".format(squeak_hash_str))
squeak_entry_with_profile = (
self.squeak_controller.get_squeak_entry_with_profile(
squeak = (
self.squeak_controller.get_squeak(
squeak_hash
)
)
if squeak_entry_with_profile is None:
if squeak is None:
return squeak_admin_pb2.GetSqueakDetailsReply(
squeak_detail_entry=None
)
detail_message = squeak_entry_to_detail_message(
squeak_entry_with_profile)
detail_message = squeak_to_detail_message(squeak)
return squeak_admin_pb2.GetSqueakDetailsReply(
squeak_detail_entry=detail_message
)

View file

@ -1,12 +1,14 @@
from typing import NamedTuple
from typing import Optional
from bitcoin.core import CBlockHeader
from squeak.core import CSqueak
class SqueakEntry(NamedTuple):
squeak: CSqueak
block_header: CBlockHeader
squeak_hash: bytes
address: str
block_height: int
block_hash: bytes
block_time: int
reply_to: Optional[bytes]
is_unlocked: bool
liked_time: Optional[int] = None
content: Optional[str] = None

View file

@ -0,0 +1,36 @@
"""Add block time column to squeak table
Revision ID: a35d180bf020
Revises: c0316d4931a5
Create Date: 2021-08-24 04:27:45.463418
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = 'a35d180bf020'
down_revision = 'c0316d4931a5'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('squeak', schema=None) as batch_op:
batch_op.add_column(
sa.Column('block_time', sa.Integer(), nullable=False, server_default=sa.text('0')))
batch_op.drop_column('block_header')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('squeak', schema=None) as batch_op:
batch_op.add_column(
sa.Column('block_header', sa.BLOB(), nullable=False, server_default=sa.literal('')))
batch_op.drop_column('block_time')
# ### end Alembic commands ###

View file

@ -69,7 +69,7 @@ class Models:
Column("n_time", Integer, nullable=False),
Column("author_address", String(35), index=True, nullable=False),
Column("secret_key", String(64), nullable=True),
Column("block_header", Binary, nullable=False),
Column("block_time", Integer, nullable=False),
Column("liked_time", TZDateTime,
default=None, nullable=True),
Column("content", String(280), nullable=True),

View file

@ -14,7 +14,6 @@ from sqlalchemy import literal
from sqlalchemy.sql import select
from squeak.core import CSqueak
from squeaknode.bitcoin.util import parse_block_header
from squeaknode.core.lightning_address import LightningAddressHostPort
from squeaknode.core.peer_address import PeerAddress
from squeaknode.core.received_offer import ReceivedOffer
@ -174,7 +173,7 @@ class SqueakDb:
n_time=squeak.nTime,
author_address=str(squeak.GetAddress()),
secret_key=None,
block_header=block_header.serialize(),
block_time=block_header.nTime,
)
with self.get_connection() as connection:
try:
@ -1103,30 +1102,19 @@ class SqueakDb:
def _parse_squeak_entry(self, row) -> SqueakEntry:
secret_key_column = row["secret_key"]
secret_key = (
bytes.fromhex(secret_key_column) if
secret_key_column else b""
)
squeak = CSqueak.deserialize(row["squeak"])
if secret_key:
squeak.SetDecryptionKey(secret_key)
block_header_column = row["block_header"]
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
)
is_locked = bool(secret_key_column)
liked_time = row["liked_time"]
liked_time_s = int(liked_time.timestamp()) if liked_time else None
content = row["content"]
return SqueakEntry(
squeak=squeak,
block_header=block_header,
squeak_hash=bytes.fromhex(row["hash"]),
address=row["author_address"],
block_height=row["n_block_height"],
block_hash=bytes.fromhex(row["hash_block"]),
block_time=row["block_time"],
reply_to=bytes.fromhex(row["hash_reply_sqk"]),
is_unlocked=is_locked,
liked_time=liked_time_s,
content=content,
content=row["content"],
)
def _parse_squeak_profile(self, row) -> SqueakProfile:

View file

@ -75,8 +75,7 @@ class SqueakController:
return inserted_squeak_hash
def unlock_squeak(self, squeak_hash: bytes, secret_key: bytes):
squeak_entry = self.squeak_db.get_squeak_entry(squeak_hash)
squeak = squeak_entry.squeak
squeak = self.squeak_db.get_squeak(squeak_hash)
decrypted_content = self.squeak_core.get_decrypted_content(
squeak,
secret_key,