diff --git a/docker/sqkclient/config.ini.sh b/docker/sqkclient/config.ini.sh index 31312e47..0ef6c16b 100644 --- a/docker/sqkclient/config.ini.sh +++ b/docker/sqkclient/config.ini.sh @@ -6,9 +6,9 @@ BTCD_RPC_HOST=$4 BTCD_RPC_PORT=$5 BTCD_RPC_USER=$6 BTCD_RPC_PASS=$7 -SQK_RPC_HOST=$2 -SQK_RPC_PORT=$3 -PRIVATE_KEY=$8 +SQK_RPC_HOST=$8 +SQK_RPC_PORT=$9 +PRIVATE_KEY=${10} #define the template. cat << EOF diff --git a/docker/sqkclient/start-sqkclient.sh b/docker/sqkclient/start-sqkclient.sh index c47a3c2a..cc0a660d 100755 --- a/docker/sqkclient/start-sqkclient.sh +++ b/docker/sqkclient/start-sqkclient.sh @@ -48,9 +48,9 @@ DEBUG=$(set_default "$DEBUG" "debug") NETWORK=$(set_default "$NETWORK" "simnet") CHAIN=$(set_default "$CHAIN" "bitcoin") BACKEND="btcd" -SQK_HOST="" -SQK_PORT="" -PRIVATE_KEY=$(set_default "$PRIVATE_KEY" "myprivatekey") +SQK_HOST="localhost" +SQK_PORT="56789" +PRIVATE_KEY=$(set_default "$PRIVATE_KEY" "cS59SQeg1khCuVHJfXRmGeYxgZqr6Cu5Bgu8o9Z5ABioSD5Fm7dy") # This is a hack that is needed because python-bitcoinlib does not # currently support simnet network. diff --git a/itests/test.py b/itests/test.py index b45d200d..3438f083 100644 --- a/itests/test.py +++ b/itests/test.py @@ -123,6 +123,20 @@ def run(): print("Balance confirmed %s %s" % (balance.total_balance, balance.total_balance)) assert balance.total_balance == 1505000000000 + print("-------------- MakeSqueak --------------") + squeak_resp = alice_stub.MakeSqueak(route_guide_pb2.MakeSqueakRequest( + content='hello squeak.', + )) + print("squeak: %s" % squeak_resp.squeak) + assert squeak_resp.squeak.content == 'hello squeak.' + + print("-------------- GetSqueak --------------") + get_squeak_resp = alice_stub.GetSqueak(route_guide_pb2.GetSqueakRequest( + hash=squeak_resp.squeak.hash, + )) + print("squeak: %s" % get_squeak_resp) + assert get_squeak_resp.content == 'hello squeak.' + if __name__ == '__main__': logging.basicConfig() diff --git a/squeaknode/client/clientsqueaknode.py b/squeaknode/client/clientsqueaknode.py index 0bd7f997..e65882d0 100644 --- a/squeaknode/client/clientsqueaknode.py +++ b/squeaknode/client/clientsqueaknode.py @@ -1,8 +1,12 @@ import logging +from squeak.core.signing import CSigningKey + +from squeaknode.client.squeak_store import SqueakStore from squeaknode.common.blockchain_client import BlockchainClient from squeaknode.common.lightning_client import LightningClient from squeaknode.common.squeak_maker import SqueakMaker +from squeaknode.client.db import SQLiteDBFactory logger = logging.getLogger(__name__) @@ -12,38 +16,36 @@ class SqueakNodeClient(object): """Network node that handles client commands. """ - def __init__(self, blockchain_client: BlockchainClient, lightning_client: LightningClient) -> None: + def __init__( + self, + blockchain_client: BlockchainClient, + lightning_client: LightningClient, + signing_key: CSigningKey, + db_factory: SQLiteDBFactory, + ) -> None: self.blockchain_client = blockchain_client self.lightning_client = lightning_client - - @property - def address(self): - return (self.peer_server.ip, self.peer_server.port) - - @property - def signing_key(self): - pass + self.signing_key = signing_key + self.squeak_store = SqueakStore(db_factory) def get_address(self): pass - def generate_signing_key(self): - pass - def make_squeak(self, content): - key = self.get_signing_key() - if key is None: + if self.signing_key is None: logger.error('Missing signing key.') raise MissingSigningKeyError() - else: - squeak_maker = SqueakMaker(key, self.blockchain) - squeak = squeak_maker.make_squeak(content) - logger.info('Made squeak: {}'.format(squeak)) - self.add_squeak(squeak) - return squeak + squeak_maker = SqueakMaker(self.signing_key, self.blockchain_client) + squeak = squeak_maker.make_squeak(content) + logger.info('Made squeak: {}'.format(squeak)) + self.add_squeak(squeak) + return squeak def add_squeak(self, squeak): - self.squeaks_access.add_squeak(squeak) + self.squeak_store.save_squeak(squeak) + + def get_squeak(self, squeak_hash): + return self.squeak_store.get_squeak(squeak_hash) def listen_squeaks_changed(self, callback): self.squeaks_access.listen_squeaks_changed(callback) diff --git a/squeaknode/client/db.py b/squeaknode/client/db.py index 70668423..9da8b062 100644 --- a/squeaknode/client/db.py +++ b/squeaknode/client/db.py @@ -24,3 +24,33 @@ def initialize_db(db): """Clear existing data and create new tables.""" schema = files('squeaknode.client').joinpath('schema.sql').read_text() db.executescript(schema) + + +class SQLiteDB(): + + def __init__(self, _file): + self._file=_file + + def __enter__(self): + self.conn = sqlite3.connect( + self._file, + detect_types=sqlite3.PARSE_DECLTYPES, + ) + self.conn.row_factory = sqlite3.Row + return self.conn.cursor() + + def __exit__(self, type, value, traceback): + self.conn.commit() + self.conn.close() + + def initialize(self): + initialize_db(self.conn) + + +class SQLiteDBFactory(): + + def __init__(self, _file=":memory:"): + self._file=_file + + def make_conn(self): + return SQLiteDB(_file=self._file) diff --git a/squeaknode/client/main.py b/squeaknode/client/main.py index 0b600807..c5b15218 100644 --- a/squeaknode/client/main.py +++ b/squeaknode/client/main.py @@ -8,6 +8,7 @@ import time from configparser import ConfigParser from squeak.params import SelectParams +from squeak.core.signing import CSigningKey from squeaknode.common.blockchain_client import BlockchainClient from squeaknode.common.lightning_client import LightningClient @@ -15,8 +16,7 @@ from squeaknode.common.btcd_blockchain_client import BTCDBlockchainClient from squeaknode.common.lnd_lightning_client import LNDLightningClient from squeaknode.client.rpc.route_guide_server import RouteGuideServicer from squeaknode.client.clientsqueaknode import SqueakNodeClient -from squeaknode.client.db import get_db -from squeaknode.client.db import close_db +from squeaknode.client.db import SQLiteDBFactory from squeaknode.client.db import initialize_db @@ -37,13 +37,25 @@ def load_lightning_client(config) -> LightningClient: ) -def load_client(blockchain_client, lightning_client): +def load_client(blockchain_client, lightning_client, signing_key, db): return SqueakNodeClient( blockchain_client, lightning_client, + signing_key, + db, ) +def load_signing_key(config): + signing_key_str = config['client']['private_key'] + if signing_key_str: + return CSigningKey(signing_key_str) + + +def load_db_factory(config): + return SQLiteDBFactory('db_file_path') + + def start_rpc_server(node): server = RouteGuideServicer(node) thread = threading.Thread( @@ -107,8 +119,9 @@ def main(): def init_db(config): - db = get_db() - initialize_db(db) + db_factory = load_db_factory(config) + with db_factory.make_conn() as conn: + initialize_db(conn) print("Initialized the database.") @@ -118,8 +131,9 @@ def run_client(config): blockchain_client = load_blockchain_client(config) lightning_client = load_lightning_client(config) - db = get_db() - node = load_client(blockchain_client, lightning_client) + db_factory = load_db_factory(config) + signing_key = load_signing_key(config) + node = load_client(blockchain_client, lightning_client, signing_key, db_factory) # start rpc server rpc_server, rpc_server_thread = start_rpc_server(node) diff --git a/squeaknode/client/rpc/route_guide.proto b/squeaknode/client/rpc/route_guide.proto index a66113e9..273b0b7b 100644 --- a/squeaknode/client/rpc/route_guide.proto +++ b/squeaknode/client/rpc/route_guide.proto @@ -75,6 +75,10 @@ service RouteGuide { */ rpc MakeSqueak (MakeSqueakRequest) returns (MakeSqueakResponse) {} + /** sqk: `getsqueak` + */ + rpc GetSqueak (GetSqueakRequest) returns (GetSqueakResponse) {} + /** sqk: `generatesigningKey` */ rpc GenerateSigningKey (GenerateSigningKeyRequest) returns (GenerateSigningKeyResponse) {} @@ -194,11 +198,21 @@ message MakeSqueakRequest { string content = 1; } +message GetSqueakRequest { + /// Hash of the squeak to get. + bytes hash = 1; +} + message MakeSqueakResponse { /// The squeak. Squeak squeak = 1; } +message GetSqueakResponse { + /// The squeak. + string content = 1; +} + message GenerateSigningKeyRequest {} message GenerateSigningKeyResponse { diff --git a/squeaknode/client/rpc/route_guide_server.py b/squeaknode/client/rpc/route_guide_server.py index 9599e029..529567b7 100644 --- a/squeaknode/client/rpc/route_guide_server.py +++ b/squeaknode/client/rpc/route_guide_server.py @@ -159,6 +159,23 @@ class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer): squeak=squeak_msg, ) + def GetSqueak(self, request, context): + print("Getting squeak....") + squeak_hash = request.hash + squeak_hash = 1 + post = self.node.get_squeak(squeak_hash) + # squeak_msg = route_guide_pb2.Squeak( + # hash=squeak.GetHash(), + # address=str(squeak.GetAddress()), + # content=squeak.GetDecryptedContentStr(), + # block_height=squeak.nBlockHeight, + # timestamp=squeak.nTime, + # ) + content = post['body'] + return route_guide_pb2.GetSqueakResponse( + content=content, + ) + def GenerateSigningKey(self, request, context): address = self.node.generate_signing_key() return route_guide_pb2.GenerateSigningKeyResponse( diff --git a/squeaknode/client/squeak_store.py b/squeaknode/client/squeak_store.py new file mode 100644 index 00000000..06639502 --- /dev/null +++ b/squeaknode/client/squeak_store.py @@ -0,0 +1,51 @@ +import logging + +from squeak.core.signing import CSigningKey + +from squeaknode.client.db import get_db +from squeaknode.client.db import close_db +from squeaknode.client.db import initialize_db +from squeaknode.client.db import SQLiteDBFactory + + +logger = logging.getLogger(__name__) + + +class SqueakStore(object): + """Network node that handles client commands. + """ + + def __init__( + self, + db_factory: SQLiteDBFactory, + ) -> None: + self.db_factory = db_factory + + def save_squeak(self, squeak): + title = squeak.GetHash() + body = squeak.GetDecryptedContentStr() + with self.db_factory.make_conn() as conn: + conn.execute( + "INSERT INTO post (title, body) VALUES (?, ?)", + (title, body), + ) + + def get_squeak(self, squeak_hash): + with self.db_factory.make_conn() as conn: + post = ( + conn + .execute( + "SELECT p.id, title, body, created" + " FROM post p" + " WHERE p.id = ?", + (squeak_hash,), + ) + .fetchone() + ) + return post + + def delete_squeak(self): + pass + + def unlock_squeak(self): + pass