Itest for squeaknodeclient (#3)

* Add itest for squeaknode client, not passing yet

* Got working itest with get wallet balance

* Change name of squeak node client class.
This commit is contained in:
Jonathan Zernik 2020-03-01 00:15:24 -08:00 committed by GitHub
parent 9939f9b75b
commit 6851466aed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 2230 additions and 3 deletions

View file

@ -9,6 +9,9 @@ clean:
test:
tox
itest:
./itests/run_itest.sh
coverage:
tox -e coverage
@ -18,4 +21,4 @@ mypy:
run:
tox -e run
.PHONY: all clean test coverage mypy run
.PHONY: all clean test itest coverage mypy run

56
docker/btcd/Dockerfile Normal file
View file

@ -0,0 +1,56 @@
FROM golang:1.12-alpine as builder
MAINTAINER Olaoluwa Osuntokun <laolu@lightning.network>
# Install build dependencies such as git and glide.
RUN apk add --no-cache git gcc musl-dev
WORKDIR $GOPATH/src/github.com/btcsuite/btcd
# Grab and install the latest version of of btcd and all related dependencies.
RUN git clone https://github.com/btcsuite/btcd.git --branch v0.20.0-beta . \
&& GO111MODULE=on go install -v . ./cmd/...
# Start a new image
FROM alpine as final
# Expose mainnet ports (server, rpc)
EXPOSE 8333 8334
# Expose testnet ports (server, rpc)
EXPOSE 18333 18334
# Expose simnet ports (server, rpc)
EXPOSE 18555 18556
# Expose segnet ports (server, rpc)
EXPOSE 28901 28902
# Copy the compiled binaries from the builder image.
COPY --from=builder /go/bin/addblock /bin/
COPY --from=builder /go/bin/btcctl /bin/
COPY --from=builder /go/bin/btcd /bin/
COPY --from=builder /go/bin/findcheckpoint /bin/
COPY --from=builder /go/bin/gencerts /bin/
COPY "docker/btcd/start-btcctl.sh" .
COPY "docker/btcd/start-btcd.sh" .
RUN apk add --no-cache \
bash \
ca-certificates \
&& mkdir "/rpc" "/root/.btcd" "/root/.btcctl" \
&& touch "/root/.btcd/btcd.conf" \
&& chmod +x start-btcctl.sh \
&& chmod +x start-btcd.sh \
# Manually generate certificate and add all domains, it is needed to connect
# "btcctl" and "lnd" to "btcd" over docker links.
&& "/bin/gencerts" --host="*" --directory="/rpc" --force
# Create a volume to house pregenerated RPC credentials. This will be
# shared with any lnd, btcctl containers so they can securely query btcd's RPC
# server.
# You should NOT do this before certificate generation!
# Otherwise manually generated certificate will be overridden with shared
# mounted volume! For more info read dockerfile "VOLUME" documentation.
VOLUME ["/rpc"]

View file

@ -0,0 +1,59 @@
#!/usr/bin/env bash
# exit from script if error was raised.
set -e
# error function is used within a bash function in order to send the error
# message directly to the stderr output and exit.
error() {
echo "$1" > /dev/stderr
exit 0
}
# return is used within bash function in order to return the value.
return() {
echo "$1"
}
# set_default function gives the ability to move the setting of default
# env variable from docker file to the script thereby giving the ability to the
# user override it durin container start.
set_default() {
# docker initialized env variables with blank string and we can't just
# use -z flag as usually.
BLANK_STRING='""'
VARIABLE="$1"
DEFAULT="$2"
if [[ -z "$VARIABLE" || "$VARIABLE" == "$BLANK_STRING" ]]; then
if [ -z "$DEFAULT" ]; then
error "You should specify default variable"
else
VARIABLE="$DEFAULT"
fi
fi
return "$VARIABLE"
}
# Set default variables if needed.
RPCUSER=$(set_default "$RPCUSER" "devuser")
RPCPASS=$(set_default "$RPCPASS" "devpass")
NETWORK=$(set_default "$NETWORK" "simnet")
PARAMS=""
if [ "$NETWORK" != "mainnet" ]; then
PARAMS=$(echo --$NETWORK)
fi
PARAMS=$(echo $PARAMS \
"--rpccert=/rpc/rpc.cert" \
"--rpcuser=$RPCUSER" \
"--rpcpass=$RPCPASS" \
"--rpcserver=rpcserver" \
)
PARAMS="$PARAMS $@"
exec btcctl $PARAMS

74
docker/btcd/start-btcd.sh Normal file
View file

@ -0,0 +1,74 @@
#!/usr/bin/env bash
# exit from script if error was raised.
set -e
# error function is used within a bash function in order to send the error
# message directly to the stderr output and exit.
error() {
echo "$1" > /dev/stderr
exit 0
}
# return is used within bash function in order to return the value.
return() {
echo "$1"
}
# set_default function gives the ability to move the setting of default
# env variable from docker file to the script thereby giving the ability to the
# user override it durin container start.
set_default() {
# docker initialized env variables with blank string and we can't just
# use -z flag as usually.
BLANK_STRING='""'
VARIABLE="$1"
DEFAULT="$2"
if [[ -z "$VARIABLE" || "$VARIABLE" == "$BLANK_STRING" ]]; then
if [ -z "$DEFAULT" ]; then
error "You should specify default variable"
else
VARIABLE="$DEFAULT"
fi
fi
return "$VARIABLE"
}
# Set default variables if needed.
RPCUSER=$(set_default "$RPCUSER" "devuser")
RPCPASS=$(set_default "$RPCPASS" "devpass")
DEBUG=$(set_default "$DEBUG" "info")
NETWORK=$(set_default "$NETWORK" "simnet")
PARAMS=""
if [ "$NETWORK" != "mainnet" ]; then
PARAMS=$(echo --$NETWORK)
fi
PARAMS=$(echo $PARAMS \
"--debuglevel=$DEBUG" \
"--rpcuser=$RPCUSER" \
"--rpcpass=$RPCPASS" \
"--datadir=/data" \
"--logdir=/data" \
"--rpccert=/rpc/rpc.cert" \
"--rpckey=/rpc/rpc.key" \
"--rpclisten=0.0.0.0" \
"--txindex"
)
# Set the mining flag only if address is non empty.
if [[ -n "$MINING_ADDRESS" ]]; then
PARAMS="$PARAMS --miningaddr=$MINING_ADDRESS"
fi
# Add user parameters to command.
PARAMS="$PARAMS $@"
# Print command and start bitcoin node.
echo "Command: btcd $PARAMS"
exec btcd $PARAMS

108
docker/docker-compose.yml Normal file
View file

@ -0,0 +1,108 @@
version: '3'
services:
btcd:
image: btcd
container_name: btcd
build:
context: ../
dockerfile: docker/btcd/Dockerfile
volumes:
- shared:/rpc
- bitcoin:/data
environment:
- RPCUSER
- RPCPASS
- NETWORK
- DEBUG
- MINING_ADDRESS
ports:
- 8334:8334
- 18334:18334
- 18556:18556
- 28902:28902
entrypoint: ["./start-btcd.sh"]
btcctl:
image: btcd
container_name: btcctl
build:
context: ../
dockerfile: docker/btcd/Dockerfile
volumes:
- shared:/rpc
- bitcoin:/data
environment:
- RPCUSER
- RPCPASS
- NETWORK
- DEBUG
- MINING_ADDRESS
links:
- "btcd:rpcserver"
entrypoint: ["./start-btcctl.sh"]
lnd:
image: lnd
container_name: lnd
build:
context: ../
dockerfile: docker/lnd/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
- RPC_LISTEN="0.0.0.0:10009"
volumes:
- shared:/rpc
- lnd_dir:/root/.lnd
links:
- "btcd:blockchain"
entrypoint: ["./start-lnd.sh"]
sqk:
image: sqk
container_name: sqk
build:
context: ../
dockerfile: docker/sqk/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
- HEADLESS
volumes:
- shared:/rpc
- lnd_dir:/root/.lnd
links:
- "btcd:blockchain"
- "lnd:lnd"
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
entrypoint: ["./start-sqk.sh"]
frontend:
container_name: frontend
build:
context: ../
dockerfile: docker/frontend/Dockerfile
ports:
- 8080:80
volumes:
# btcctl and lnd containers.
shared:
driver: local
# bitcoin volume is needed for maintaining blockchain persistence
# during btcd container recreation.
bitcoin:
driver: local
# lnd_dir volume is needed for sharing tht tls certificate
lnd_dir:
driver: local

View file

@ -0,0 +1,11 @@
FROM mhart/alpine-node:latest AS builder
WORKDIR /app
COPY ./frontend/squeakclient-frontend .
RUN npm install
RUN yarn run build
FROM mhart/alpine-node
RUN yarn global add serve
WORKDIR /app
COPY --from=builder /app/build .
CMD ["serve", "-p", "80", "-s", "."]

40
docker/lnd/Dockerfile Normal file
View file

@ -0,0 +1,40 @@
FROM golang:1.12-alpine as builder
MAINTAINER Olaoluwa Osuntokun <lightning.engineering>
RUN apk update && \
apk upgrade && \
apk add git
# Copy in the local repository to build from.
RUN git clone https://github.com/lightningnetwork/lnd.git --branch v0.9.0-beta
# Force Go to use the cgo based DNS resolver. This is required to ensure DNS
# queries required to connect to linked containers succeed.
ENV GODEBUG netdns=cgo
# Install dependencies and install/build lnd.
RUN apk add --no-cache --update alpine-sdk \
git \
make \
&& cd lnd \
&& make \
&& make install
# Start a new, final image to reduce size.
FROM alpine as final
# Expose lnd ports (server, rpc).
EXPOSE 9735 10009
# Copy the binaries and entrypoint from the builder image.
COPY --from=builder /go/bin/lncli /bin/
COPY --from=builder /go/bin/lnd /bin/
# Add bash.
RUN apk add --no-cache \
bash
# Copy the entrypoint script.
COPY "docker/lnd/start-lnd.sh" .
RUN chmod +x start-lnd.sh

62
docker/lnd/start-lnd.sh Normal file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env bash
# exit from script if error was raised.
set -e
# error function is used within a bash function in order to send the error
# message directly to the stderr output and exit.
error() {
echo "$1" > /dev/stderr
exit 0
}
# return is used within bash function in order to return the value.
return() {
echo "$1"
}
# set_default function gives the ability to move the setting of default
# env variable from docker file to the script thereby giving the ability to the
# user override it durin container start.
set_default() {
# docker initialized env variables with blank string and we can't just
# use -z flag as usually.
BLANK_STRING='""'
VARIABLE="$1"
DEFAULT="$2"
if [[ -z "$VARIABLE" || "$VARIABLE" == "$BLANK_STRING" ]]; then
if [ -z "$DEFAULT" ]; then
error "You should specify default variable"
else
VARIABLE="$DEFAULT"
fi
fi
return "$VARIABLE"
}
# Set default variables if needed.
RPCUSER=$(set_default "$RPCUSER" "devuser")
RPCPASS=$(set_default "$RPCPASS" "devpass")
DEBUG=$(set_default "$DEBUG" "debug")
NETWORK=$(set_default "$NETWORK" "simnet")
CHAIN=$(set_default "$CHAIN" "bitcoin")
BACKEND="btcd"
exec lnd \
--noseedbackup \
--logdir="/data" \
"--$CHAIN.active" \
"--$CHAIN.$NETWORK" \
"--$CHAIN.node"="btcd" \
"--$BACKEND.rpccert"="/rpc/rpc.cert" \
"--$BACKEND.rpchost"="blockchain" \
"--$BACKEND.rpcuser"="$RPCUSER" \
"--$BACKEND.rpcpass"="$RPCPASS" \
--rpclisten=0.0.0.0:10009 \
--debuglevel="$DEBUG" \
--tlsextradomain=lnd \
"$@"

View file

@ -0,0 +1,30 @@
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
python3-pip \
curl \
git
COPY requirements.txt /
RUN pip3 install --upgrade pip
RUN pip3 install -r requirements.txt
# Install the gRPC files for lnd.
RUN git clone https://github.com/googleapis/googleapis.git
RUN curl -o rpc.proto -s https://raw.githubusercontent.com/lightningnetwork/lnd/master/lnrpc/rpc.proto
COPY . /app
RUN cp -r googleapis /app
RUN cp rpc.proto /app/squeaknode/common
WORKDIR /app
RUN python3 -m grpc_tools.protoc --proto_path=googleapis:. --python_out=. --grpc_python_out=. squeaknode/common/rpc.proto
RUN python3 -m grpc_tools.protoc --proto_path=googleapis:. --python_out=. --grpc_python_out=. squeaknode/client/rpc/route_guide.proto
RUN python3 setup.py install
# Copy the entrypoint script.
COPY "docker/sqkclient/start-sqkclient.sh" .
RUN chmod +x start-sqkclient.sh

View file

@ -0,0 +1,81 @@
#!/usr/bin/env bash
# exit from script if error was raised.
set -e
# error function is used within a bash function in order to send the error
# message directly to the stderr output and exit.
error() {
echo "$1" > /dev/stderr
exit 0
}
# return is used within bash function in order to return the value.
return() {
echo "$1"
}
# set_default function gives the ability to move the setting of default
# env variable from docker file to the script thereby giving the ability to the
# user override it durin container start.
set_default() {
# docker initialized env variables with blank string and we can't just
# use -z flag as usually.
BLANK_STRING='""'
VARIABLE="$1"
DEFAULT="$2"
if [[ -z "$VARIABLE" || "$VARIABLE" == "$BLANK_STRING" ]]; then
if [ -z "$DEFAULT" ]; then
error "You should specify default variable"
else
VARIABLE="$DEFAULT"
fi
fi
return "$VARIABLE"
}
# Set default variables if needed.
RPCUSER=$(set_default "$RPCUSER" "devuser")
RPCPASS=$(set_default "$RPCPASS" "devpass")
DEBUG=$(set_default "$DEBUG" "debug")
NETWORK=$(set_default "$NETWORK" "simnet")
CHAIN=$(set_default "$CHAIN" "bitcoin")
BACKEND="btcd"
# This is a hack that is needed because python-bitcoinlib does not
# currently support simnet network.
BTCD_RPC_PORT="18332"
if [[ "$NETWORK" == "mainnet" ]]; then
BTCD_RPC_PORT="8334"
elif [[ "$NETWORK" == "testnet" ]]; then
BTCD_RPC_PORT="18334"
elif [[ "$NETWORK" == "regtest" ]]; then
BTCD_RPC_PORT="18445"
elif [[ "$NETWORK" == "simnet" ]]; then
BTCD_RPC_PORT="18556"
fi
# Add btcd's RPC TLS certificate to system Certificate Authority list. exec runsqueak \
cp /rpc/rpc.cert /usr/share/ca-certificates/btcd.crt
echo btcd.crt >> /etc/ca-certificates.conf
update-ca-certificates
# To make python requests use the system ca-certificates bundle, it
# needs to be told to use it over its own embedded bundle
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
exec runsqueaknodeclient \
"--network"="$NETWORK" \
"--rpcuser"="$RPCUSER" \
"--rpcpass"="$RPCPASS" \
"--$BACKEND.rpchost"="blockchain" \
"--$BACKEND.rpcport"="$BTCD_RPC_PORT" \
"--$BACKEND.rpcuser"="$RPCUSER" \
"--$BACKEND.rpcpass"="$RPCPASS" \
"--lnd.rpchost"="lnd" \
--log-level="$DEBUG" \

29
docker/test/Dockerfile Normal file
View file

@ -0,0 +1,29 @@
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
python3-pip \
curl \
git
COPY requirements.txt /
RUN pip3 install --upgrade pip
RUN pip3 install -r requirements.txt
RUN git clone https://github.com/googleapis/googleapis.git
Run mkdir /app
COPY ./squeaknode/client/rpc/route_guide.proto /app
RUN cp -r googleapis /app
WORKDIR /app
RUN python3 -m grpc_tools.protoc --proto_path=googleapis:. --python_out=. --grpc_python_out=. route_guide.proto
# Copy the entrypoint script.
COPY "itests/test.sh" .
COPY "itests/test.py" .
RUN chmod +x test.sh
CMD ["bash", "test.sh"]

200
itests/docker-compose.yml Normal file
View file

@ -0,0 +1,200 @@
version: '3'
services:
btcd:
image: btcd
container_name: btcd
build:
context: ../
dockerfile: docker/btcd/Dockerfile
volumes:
- shared_test:/rpc
- bitcoin_test:/data
environment:
- RPCUSER
- RPCPASS
- NETWORK
- DEBUG
- MINING_ADDRESS
ports:
- 8334:8334
- 18334:18334
- 18556:18556
- 28902:28902
entrypoint: ["./start-btcd.sh"]
btcctl:
image: btcd
container_name: btcctl
build:
context: ../
dockerfile: docker/btcd/Dockerfile
volumes:
- shared_test:/rpc
- bitcoin_test:/data
environment:
- RPCUSER
- RPCPASS
- NETWORK
- DEBUG
- MINING_ADDRESS
links:
- "btcd:rpcserver"
entrypoint: ["./start-btcctl.sh"]
lnd_alice:
image: lnd
container_name: lnd_alice
build:
context: ../
dockerfile: docker/lnd/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
volumes:
- shared_test:/rpc
- lnd_dir_alice:/root/.lnd
links:
- "btcd:blockchain"
entrypoint: ["./start-lnd.sh"]
lnd_bob:
image: lnd
container_name: lnd_bob
build:
context: ../
dockerfile: docker/lnd/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
volumes:
- shared_test:/rpc
- lnd_dir_bob:/root/.lnd
links:
- "btcd:blockchain"
entrypoint: ["./start-lnd.sh"]
lnd_carol:
image: lnd
container_name: lnd_carol
build:
context: ../
dockerfile: docker/lnd/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
volumes:
- shared_test:/rpc
- lnd_dir_carol:/root/.lnd
links:
- "btcd:blockchain"
entrypoint: ["./start-lnd.sh"]
sqkclient_alice:
image: sqkclient
container_name: sqkclient_alice
build:
context: ../
dockerfile: docker/sqkclient/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
- HEADLESS
volumes:
- shared_test:/rpc
- lnd_dir_alice:/root/.lnd
links:
- "btcd:blockchain"
- "lnd_alice:lnd"
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
entrypoint: ["./start-sqkclient.sh"]
sqkclient_bob:
image: sqkclient
container_name: sqkclient_bob
build:
context: ../
dockerfile: docker/sqkclient/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
- HEADLESS
volumes:
- shared_test:/rpc
- lnd_dir_bob:/root/.lnd
links:
- "btcd:blockchain"
- "lnd_bob:lnd"
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
entrypoint: ["./start-sqkclient.sh"]
sqkclient_carol:
image: sqkclient
container_name: sqkclient_carol
build:
context: ../
dockerfile: docker/sqkclient/Dockerfile
environment:
- RPCUSER
- RPCPASS
- NETWORK
- CHAIN
- DEBUG
- HEADLESS
volumes:
- shared_test:/rpc
- lnd_dir_carol:/root/.lnd
links:
- "btcd:blockchain"
- "lnd_carol:lnd"
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
entrypoint: ["./start-sqkclient.sh"]
test:
image: test
container_name: test
build:
context: ../
dockerfile: docker/test/Dockerfile
links:
- "btcd:blockchain"
- "sqkclient_alice:sqkclient_alice"
- "sqkclient_bob:sqkclient_bob"
- "sqkclient_carol:sqkclient_carol"
command: tail -f /dev/null
volumes:
# btcctl and lnd containers.
shared_test:
driver: local
# bitcoin_test volume is needed for maintaining blockchain persistence
# during btcd container recreation.
bitcoin_test:
driver: local
# lnd_dir volume is needed for sharing tht tls certificate
lnd_dir_alice:
driver: local
lnd_dir_bob:
driver: local
lnd_dir_carol:
driver: local

18
itests/run_itest.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
cd itests
docker-compose down --volumes
docker-compose build
docker-compose up -d
# Initialize the blockchain with miner rewards going to alice.
sleep 10
alice_address=$(docker exec -it lnd_alice lncli --network=simnet newaddress np2wkh | jq .address -r)
MINING_ADDRESS=$alice_address docker-compose up -d btcd
echo "Mining 400 blocks to address: $alice_address ..."
docker-compose run btcctl generate 400
echo "Finished mining blocks."
sleep 10
echo "Running test.sh...."
docker-compose run test ./test.sh

129
itests/test.py Normal file
View file

@ -0,0 +1,129 @@
# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The Python implementation of the gRPC route guide client."""
from __future__ import print_function
import logging
import random
import time
import grpc
import route_guide_pb2
import route_guide_pb2_grpc
def make_route_note(message, latitude, longitude):
return route_guide_pb2.RouteNote(
message=message,
location=route_guide_pb2.Point(latitude=latitude, longitude=longitude))
def guide_get_one_feature(stub, point):
feature = stub.GetFeature(point)
if not feature.location:
print("Server returned incomplete feature")
return
if feature.name:
print("Feature called %s at %s" % (feature.name, feature.location))
else:
print("Found no feature at %s" % feature.location)
def guide_get_feature(stub):
guide_get_one_feature(
stub,
route_guide_pb2.Point(
latitude=409146138,
longitude=-746188906,
),
)
guide_get_one_feature(
stub,
route_guide_pb2.Point(
latitude=0,
longitude=0,
),
)
def guide_list_features(stub):
rectangle = route_guide_pb2.Rectangle(
lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000),
hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000))
print("Looking for features between 40, -75 and 42, -73")
features = stub.ListFeatures(rectangle)
for feature in features:
print("Feature called %s at %s" % (feature.name, feature.location))
def generate_route(feature_list):
for _ in range(0, 10):
random_feature = feature_list[random.randint(0, len(feature_list) - 1)]
print("Visiting point %s" % random_feature.location)
yield random_feature.location
def generate_messages():
messages = [
make_route_note("First message", 0, 0),
make_route_note("Second message", 0, 1),
make_route_note("Third message", 1, 0),
make_route_note("Fourth message", 0, 0),
make_route_note("Fifth message", 1, 0),
]
for msg in messages:
print("Sending %s at %s" % (msg.message, msg.location))
yield msg
def guide_route_chat(stub):
responses = stub.RouteChat(generate_messages())
for response in responses:
print("Received message %s at %s" % (response.message,
response.location))
def run():
# NOTE(gRPC Python Team): .close() is possible on a channel and should be
# used in circumstances in which the with statement does not fit the needs
# of the code.
with grpc.insecure_channel('sqkclient_alice:50051') as alice_channel, \
grpc.insecure_channel('sqkclient_bob:50051') as bob_channel, \
grpc.insecure_channel('sqkclient_carol:50051') as carol_channel:
# Make the stubs
alice_stub = route_guide_pb2_grpc.RouteGuideStub(alice_channel)
bob_stub = route_guide_pb2_grpc.RouteGuideStub(bob_channel)
carol_stub = route_guide_pb2_grpc.RouteGuideStub(carol_channel)
print("-------------- GetFeature --------------")
guide_get_feature(alice_stub)
print("-------------- ListFeatures --------------")
guide_list_features(alice_stub)
print("-------------- RouteChat --------------")
guide_route_chat(alice_stub)
print("-------------- WalletBalance --------------")
balance = alice_stub.WalletBalance(route_guide_pb2.WalletBalanceRequest())
print("Balance: %s" % balance)
print("Balance confirmed %s %s" % (balance.total_balance, balance.total_balance))
assert balance.total_balance == 1505000000000
if __name__ == '__main__':
logging.basicConfig()
run()

3
itests/test.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/bash
python3 test.py

View file

@ -1,2 +1,7 @@
flask==1.1.1
squeaklib
argparse
googleapis-common-protos
grpcio
grpcio-tools
requests

View file

@ -18,4 +18,9 @@ setup(
zip_safe=False,
install_requires=["flask"],
extras_require={"test": ["pytest", "coverage"]},
entry_points={
'console_scripts': [
'runsqueaknodeclient = squeaknode.client.main:main',
],
},
)

View file

@ -0,0 +1,67 @@
import logging
from squeaknode.common.blockchain_client import BlockchainClient
from squeaknode.common.lightning_client import LightningClient
from squeaknode.common.squeak_maker import SqueakMaker
logger = logging.getLogger(__name__)
class SqueakNodeClient(object):
"""Network node that handles client commands.
"""
def __init__(self, blockchain_client: BlockchainClient, lightning_client: LightningClient) -> 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
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:
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
def add_squeak(self, squeak):
self.squeaks_access.add_squeak(squeak)
def listen_squeaks_changed(self, callback):
self.squeaks_access.listen_squeaks_changed(callback)
def add_follow(self, follow):
pass
def listen_follows_changed(self, callback):
pass
def get_wallet_balance(self):
return self.lightning_client.get_wallet_balance()
class ClientNodeError(Exception):
pass
class MissingSigningKeyError(ClientNodeError):
def __str__(self):
return 'Missing signing key.'

167
squeaknode/client/main.py Normal file
View file

@ -0,0 +1,167 @@
import argparse
import logging
import threading
import time
from squeak.params import SelectParams
from squeaknode.common.blockchain_client import BlockchainClient
from squeaknode.common.lightning_client import LightningClient
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
def load_blockchain_client(rpc_host, rpc_port, rpc_user, rpc_pass) -> BlockchainClient:
return BTCDBlockchainClient(
host=rpc_host,
port=rpc_port,
rpc_user=rpc_user,
rpc_password=rpc_pass,
)
def load_lightning_client(rpc_host, rpc_port, network) -> LightningClient:
return LNDLightningClient(
host=rpc_host,
port=rpc_port,
network=network,
)
def _start_node(blockchain_client, lightning_client):
node = SqueakNodeClient(blockchain_client, lightning_client)
return node
def _start_route_guide_rpc_server(node):
server = RouteGuideServicer(node)
thread = threading.Thread(
target=server.serve,
args=(),
)
thread.daemon = True
thread.start()
return server, thread
def parse_args():
parser = argparse.ArgumentParser(
description="squeaknode runs a node using squeak protocol. ",
)
parser.add_argument(
'--network',
dest='network',
type=str,
default='mainnet',
choices=['mainnet', 'testnet', 'regtest', 'simnet'],
help='The bitcoin network to use',
)
parser.add_argument(
'--rpcport',
dest='rpcport',
type=int,
default=None,
help='RPC server port number',
)
parser.add_argument(
'--rpcuser',
dest='rpcuser',
type=str,
default='',
help='RPC username',
)
parser.add_argument(
'--rpcpass',
dest='rpcpass',
type=str,
default='',
help='RPC password',
)
parser.add_argument(
'--btcd.rpchost',
dest='btcd_rpchost',
type=str,
default='localhost',
help='Blockchain (bitcoin) backend hostname',
)
parser.add_argument(
'--btcd.rpcport',
dest='btcd_rpcport',
type=int,
default=18332,
help='Blockchain (bitcoin) backend port',
)
parser.add_argument(
'--btcd.rpcuser',
dest='btcd_rpcuser',
type=str,
default='',
help='Blockchain (bitcoin) backend username',
)
parser.add_argument(
'--btcd.rpcpass',
dest='btcd_rpcpass',
type=str,
default='',
help='Blockchain (bitcoin) backend password',
)
parser.add_argument(
'--lnd.rpchost',
dest='lnd_rpchost',
type=str,
default='localhost',
help='Lightning network backend hostname',
)
parser.add_argument(
'--lnd.rpcport',
dest='lnd_rpcport',
type=int,
default=10009,
help='Lightning network backend port',
)
parser.add_argument(
'--log-level',
dest='log_level',
type=str,
default='info',
help='Logging level',
)
return parser.parse_args()
def main():
logging.basicConfig(level=logging.ERROR)
args = parse_args()
level = args.log_level.upper()
print("level: " + level, flush=True)
logging.getLogger().setLevel(level)
print('network:', args.network, flush=True)
SelectParams(args.network)
blockchain_client = load_blockchain_client(
args.btcd_rpchost,
args.btcd_rpcport,
args.btcd_rpcuser,
args.btcd_rpcpass,
)
lightning_client = load_lightning_client(
args.lnd_rpchost,
args.lnd_rpcport,
args.network,
)
node = _start_node(blockchain_client, lightning_client)
# start rpc server
route_guide_server, route_guide_server_thread = _start_route_guide_rpc_server(node)
while True:
time.sleep(10)
if __name__ == '__main__':
main()

View file

@ -0,0 +1 @@
__version__ = '0.1.0'

View file

@ -0,0 +1,253 @@
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.routeguide";
option java_outer_classname = "RouteGuideProto";
option objc_class_prefix = "RTG";
package routeguide;
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
//
// A feature with an empty name is returned if there's no feature at the given
// position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
/** sqk: `walletbalance`
WalletBalance returns total unspent outputs(confirmed and unconfirmed), all
confirmed unspent outputs and all unconfirmed unspent outputs under control
of the wallet.
*/
rpc WalletBalance (WalletBalanceRequest) returns (WalletBalanceResponse) {}
/** sqk: `addpeer`
*/
rpc ConnectHost (ConnectHostRequest) returns (ConnectHostResponse) {}
/** sqk: `disconnectpeer`
*/
rpc DisconnectPeer (DisconnectPeerRequest) returns (DisconnectPeerResponse) {}
/** sqk: `listpeers`
ListPeers returns a verbose listing of all currently active peers.
*/
rpc ListPeers (ListPeersRequest) returns (ListPeersResponse) {}
/** sqk: `makesqueak`
*/
rpc MakeSqueak (MakeSqueakRequest) returns (MakeSqueakResponse) {}
/** sqk: `generatesigningKey`
*/
rpc GenerateSigningKey (GenerateSigningKeyRequest) returns (GenerateSigningKeyResponse) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
Point lo = 1;
// The other corner of the rectangle.
Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
string name = 1;
// The point where the feature is detected.
Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
Point location = 1;
// The message to be sent.
string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
int32 point_count = 1;
// The number of known features passed while traversing the route.
int32 feature_count = 2;
// The distance covered in metres.
int32 distance = 3;
// The duration of the traversal in seconds.
int32 elapsed_time = 4;
}
message WalletBalanceRequest {
}
message WalletBalanceResponse {
/// The balance of the wallet
int64 total_balance = 1;
/// The confirmed balance of a wallet(with >= 1 confirmations)
int64 confirmed_balance = 2;
/// The unconfirmed balance of a wallet(with 0 confirmations)
int64 unconfirmed_balance = 3;
}
// message GetPeersRequest {
// }
// message GetPeersResponse {
// /// The balance of the wallet
// int64 total_balance = 1 [json_name = "total_balance"];
// /// The confirmed balance of a wallet(with >= 1 confirmations)
// int64 confirmed_balance = 2 [json_name = "confirmed_balance"];
// /// The unconfirmed balance of a wallet(with 0 confirmations)
// int64 unconfirmed_balance = 3 [json_name = "unconfirmed_balance"];
// }
message ConnectHostRequest {
// The address of the peer to add.
string host = 1;
}
message ConnectHostResponse {
}
message DisconnectPeerRequest {
Addr addr = 1;
}
message DisconnectPeerResponse {
}
message ListPeersRequest {
}
message ListPeersResponse {
/// The list of currently connected peers
repeated Peer peers = 1;
}
message MakeSqueakRequest {
/// Content of the squeak to be made.
string content = 1;
}
message MakeSqueakResponse {
/// The squeak.
Squeak squeak = 1;
}
message GenerateSigningKeyRequest {}
message GenerateSigningKeyResponse {
/// Address of the signing key.
string address = 1;
}
message Addr {
string host = 1;
uint64 port = 2;
}
message Peer {
/// Address
Addr addr = 1;
/// Bytes of data transmitted to this peer
uint64 bytes_sent = 2;
/// Bytes of data transmitted from this peer
uint64 bytes_recv = 3;
/// Satoshis sent to this peer
int64 sat_sent = 4;
/// Satoshis received from this peer
int64 sat_recv = 5;
/// A channel is inbound if the counterparty initiated the connection
bool inbound = 6;
/// Ping time to this peer
int64 ping_time = 7;
}
message Squeak {
/// Hash of the squeak.
bytes hash = 1;
/// Address of the creator.
string address = 2;
/// Content of the squeak.
string content = 3;
/// Block height of the squeak.
uint64 block_height = 4;
/// Timestamp of the squeak.
uint64 timestamp = 5;
}

View file

@ -0,0 +1,601 @@
[{
"location": {
"latitude": 407838351,
"longitude": -746143763
},
"name": "Patriots Path, Mendham, NJ 07945, USA"
}, {
"location": {
"latitude": 408122808,
"longitude": -743999179
},
"name": "101 New Jersey 10, Whippany, NJ 07981, USA"
}, {
"location": {
"latitude": 413628156,
"longitude": -749015468
},
"name": "U.S. 6, Shohola, PA 18458, USA"
}, {
"location": {
"latitude": 419999544,
"longitude": -740371136
},
"name": "5 Conners Road, Kingston, NY 12401, USA"
}, {
"location": {
"latitude": 414008389,
"longitude": -743951297
},
"name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
}, {
"location": {
"latitude": 419611318,
"longitude": -746524769
},
"name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
}, {
"location": {
"latitude": 406109563,
"longitude": -742186778
},
"name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
}, {
"location": {
"latitude": 416802456,
"longitude": -742370183
},
"name": "352 South Mountain Road, Wallkill, NY 12589, USA"
}, {
"location": {
"latitude": 412950425,
"longitude": -741077389
},
"name": "Bailey Turn Road, Harriman, NY 10926, USA"
}, {
"location": {
"latitude": 412144655,
"longitude": -743949739
},
"name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
}, {
"location": {
"latitude": 415736605,
"longitude": -742847522
},
"name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
}, {
"location": {
"latitude": 413843930,
"longitude": -740501726
},
"name": "162 Merrill Road, Highland Mills, NY 10930, USA"
}, {
"location": {
"latitude": 410873075,
"longitude": -744459023
},
"name": "Clinton Road, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 412346009,
"longitude": -744026814
},
"name": "16 Old Brook Lane, Warwick, NY 10990, USA"
}, {
"location": {
"latitude": 402948455,
"longitude": -747903913
},
"name": "3 Drake Lane, Pennington, NJ 08534, USA"
}, {
"location": {
"latitude": 406337092,
"longitude": -740122226
},
"name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
}, {
"location": {
"latitude": 406421967,
"longitude": -747727624
},
"name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
}, {
"location": {
"latitude": 416318082,
"longitude": -749677716
},
"name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
}, {
"location": {
"latitude": 415301720,
"longitude": -748416257
},
"name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
}, {
"location": {
"latitude": 402647019,
"longitude": -747071791
},
"name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
}, {
"location": {
"latitude": 412567807,
"longitude": -741058078
},
"name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
}, {
"location": {
"latitude": 416855156,
"longitude": -744420597
},
"name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
}, {
"location": {
"latitude": 404663628,
"longitude": -744820157
},
"name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
}, {
"location": {
"latitude": 407113723,
"longitude": -749746483
},
"name": ""
}, {
"location": {
"latitude": 402133926,
"longitude": -743613249
},
"name": ""
}, {
"location": {
"latitude": 400273442,
"longitude": -741220915
},
"name": ""
}, {
"location": {
"latitude": 411236786,
"longitude": -744070769
},
"name": ""
}, {
"location": {
"latitude": 411633782,
"longitude": -746784970
},
"name": "211-225 Plains Road, Augusta, NJ 07822, USA"
}, {
"location": {
"latitude": 415830701,
"longitude": -742952812
},
"name": ""
}, {
"location": {
"latitude": 413447164,
"longitude": -748712898
},
"name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
}, {
"location": {
"latitude": 405047245,
"longitude": -749800722
},
"name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
}, {
"location": {
"latitude": 418858923,
"longitude": -746156790
},
"name": ""
}, {
"location": {
"latitude": 417951888,
"longitude": -748484944
},
"name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
}, {
"location": {
"latitude": 407033786,
"longitude": -743977337
},
"name": "26 East 3rd Street, New Providence, NJ 07974, USA"
}, {
"location": {
"latitude": 417548014,
"longitude": -740075041
},
"name": ""
}, {
"location": {
"latitude": 410395868,
"longitude": -744972325
},
"name": ""
}, {
"location": {
"latitude": 404615353,
"longitude": -745129803
},
"name": ""
}, {
"location": {
"latitude": 406589790,
"longitude": -743560121
},
"name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
}, {
"location": {
"latitude": 414653148,
"longitude": -740477477
},
"name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
}, {
"location": {
"latitude": 405957808,
"longitude": -743255336
},
"name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
}, {
"location": {
"latitude": 411733589,
"longitude": -741648093
},
"name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
}, {
"location": {
"latitude": 412676291,
"longitude": -742606606
},
"name": "1270 Lakes Road, Monroe, NY 10950, USA"
}, {
"location": {
"latitude": 409224445,
"longitude": -748286738
},
"name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
}, {
"location": {
"latitude": 406523420,
"longitude": -742135517
},
"name": "652 Garden Street, Elizabeth, NJ 07202, USA"
}, {
"location": {
"latitude": 401827388,
"longitude": -740294537
},
"name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
}, {
"location": {
"latitude": 410564152,
"longitude": -743685054
},
"name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 408472324,
"longitude": -740726046
},
"name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
}, {
"location": {
"latitude": 412452168,
"longitude": -740214052
},
"name": "5 White Oak Lane, Stony Point, NY 10980, USA"
}, {
"location": {
"latitude": 409146138,
"longitude": -746188906
},
"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
}, {
"location": {
"latitude": 404701380,
"longitude": -744781745
},
"name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 409642566,
"longitude": -746017679
},
"name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
}, {
"location": {
"latitude": 408031728,
"longitude": -748645385
},
"name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
}, {
"location": {
"latitude": 413700272,
"longitude": -742135189
},
"name": "367 Prospect Road, Chester, NY 10918, USA"
}, {
"location": {
"latitude": 404310607,
"longitude": -740282632
},
"name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
}, {
"location": {
"latitude": 409319800,
"longitude": -746201391
},
"name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
}, {
"location": {
"latitude": 406685311,
"longitude": -742108603
},
"name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
}, {
"location": {
"latitude": 419018117,
"longitude": -749142781
},
"name": "43 Dreher Road, Roscoe, NY 12776, USA"
}, {
"location": {
"latitude": 412856162,
"longitude": -745148837
},
"name": "Swan Street, Pine Island, NY 10969, USA"
}, {
"location": {
"latitude": 416560744,
"longitude": -746721964
},
"name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
}, {
"location": {
"latitude": 405314270,
"longitude": -749836354
},
"name": ""
}, {
"location": {
"latitude": 414219548,
"longitude": -743327440
},
"name": ""
}, {
"location": {
"latitude": 415534177,
"longitude": -742900616
},
"name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
}, {
"location": {
"latitude": 406898530,
"longitude": -749127080
},
"name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
}, {
"location": {
"latitude": 407586880,
"longitude": -741670168
},
"name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
}, {
"location": {
"latitude": 400106455,
"longitude": -742870190
},
"name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
}, {
"location": {
"latitude": 400066188,
"longitude": -746793294
},
"name": ""
}, {
"location": {
"latitude": 418803880,
"longitude": -744102673
},
"name": "40 Mountain Road, Napanoch, NY 12458, USA"
}, {
"location": {
"latitude": 414204288,
"longitude": -747895140
},
"name": ""
}, {
"location": {
"latitude": 414777405,
"longitude": -740615601
},
"name": ""
}, {
"location": {
"latitude": 415464475,
"longitude": -747175374
},
"name": "48 North Road, Forestburgh, NY 12777, USA"
}, {
"location": {
"latitude": 404062378,
"longitude": -746376177
},
"name": ""
}, {
"location": {
"latitude": 405688272,
"longitude": -749285130
},
"name": ""
}, {
"location": {
"latitude": 400342070,
"longitude": -748788996
},
"name": ""
}, {
"location": {
"latitude": 401809022,
"longitude": -744157964
},
"name": ""
}, {
"location": {
"latitude": 404226644,
"longitude": -740517141
},
"name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
}, {
"location": {
"latitude": 410322033,
"longitude": -747871659
},
"name": ""
}, {
"location": {
"latitude": 407100674,
"longitude": -747742727
},
"name": ""
}, {
"location": {
"latitude": 418811433,
"longitude": -741718005
},
"name": "213 Bush Road, Stone Ridge, NY 12484, USA"
}, {
"location": {
"latitude": 415034302,
"longitude": -743850945
},
"name": ""
}, {
"location": {
"latitude": 411349992,
"longitude": -743694161
},
"name": ""
}, {
"location": {
"latitude": 404839914,
"longitude": -744759616
},
"name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 414638017,
"longitude": -745957854
},
"name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
}, {
"location": {
"latitude": 412127800,
"longitude": -740173578
},
"name": ""
}, {
"location": {
"latitude": 401263460,
"longitude": -747964303
},
"name": ""
}, {
"location": {
"latitude": 412843391,
"longitude": -749086026
},
"name": ""
}, {
"location": {
"latitude": 418512773,
"longitude": -743067823
},
"name": ""
}, {
"location": {
"latitude": 404318328,
"longitude": -740835638
},
"name": "42-102 Main Street, Belford, NJ 07718, USA"
}, {
"location": {
"latitude": 419020746,
"longitude": -741172328
},
"name": ""
}, {
"location": {
"latitude": 404080723,
"longitude": -746119569
},
"name": ""
}, {
"location": {
"latitude": 401012643,
"longitude": -744035134
},
"name": ""
}, {
"location": {
"latitude": 404306372,
"longitude": -741079661
},
"name": ""
}, {
"location": {
"latitude": 403966326,
"longitude": -748519297
},
"name": ""
}, {
"location": {
"latitude": 405002031,
"longitude": -748407866
},
"name": ""
}, {
"location": {
"latitude": 409532885,
"longitude": -742200683
},
"name": ""
}, {
"location": {
"latitude": 416851321,
"longitude": -742674555
},
"name": ""
}, {
"location": {
"latitude": 406411633,
"longitude": -741722051
},
"name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
}, {
"location": {
"latitude": 413069058,
"longitude": -744597778
},
"name": "261 Van Sickle Road, Goshen, NY 10924, USA"
}, {
"location": {
"latitude": 418465462,
"longitude": -746859398
},
"name": ""
}, {
"location": {
"latitude": 411733222,
"longitude": -744228360
},
"name": ""
}, {
"location": {
"latitude": 410248224,
"longitude": -747127767
},
"name": "3 Hasta Way, Newton, NJ 07860, USA"
}]

View file

@ -0,0 +1,36 @@
# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Common resources used in the gRPC route guide example."""
import json
from squeaknode.client.rpc import route_guide_pb2
def read_route_guide_database():
"""Reads the route guide database.
Returns:
The full contents of the route guide database as a sequence of
route_guide_pb2.Features.
"""
feature_list = []
with open("squeaknode/client/rpc/route_guide_db.json") as route_guide_db_file:
for item in json.load(route_guide_db_file):
feature = route_guide_pb2.Feature(
name=item["name"],
location=route_guide_pb2.Point(
latitude=item["location"]["latitude"],
longitude=item["location"]["longitude"]))
feature_list.append(feature)
return feature_list

View file

@ -0,0 +1,174 @@
# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The Python implementation of the gRPC route guide server."""
import math
import time
from concurrent import futures
import grpc
from squeaknode.client.rpc import route_guide_pb2
from squeaknode.client.rpc import route_guide_pb2_grpc
from squeaknode.client.rpc import route_guide_resources
def get_feature(feature_db, point):
"""Returns Feature at given location or None."""
for feature in feature_db:
if feature.location == point:
return feature
return None
def get_distance(start, end):
"""Distance between two points."""
coord_factor = 10000000.0
lat_1 = start.latitude / coord_factor
lat_2 = end.latitude / coord_factor
lon_1 = start.longitude / coord_factor
lon_2 = end.longitude / coord_factor
lat_rad_1 = math.radians(lat_1)
lat_rad_2 = math.radians(lat_2)
delta_lat_rad = math.radians(lat_2 - lat_1)
delta_lon_rad = math.radians(lon_2 - lon_1)
# Formula is based on http://mathforum.org/library/drmath/view/51879.html
a = (pow(math.sin(delta_lat_rad / 2), 2) +
(math.cos(lat_rad_1) * math.cos(lat_rad_2) * pow(
math.sin(delta_lon_rad / 2), 2)))
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
R = 6371000
# metres
return R * c
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
"""Provides methods that implement functionality of route guide server."""
def __init__(self, node):
self.db = route_guide_resources.read_route_guide_database()
self.node = node
def GetFeature(self, request, context):
feature = get_feature(self.db, request)
if feature is None:
return route_guide_pb2.Feature(name="", location=request)
else:
return feature
def ListFeatures(self, request, context):
left = min(request.lo.longitude, request.hi.longitude)
right = max(request.lo.longitude, request.hi.longitude)
top = max(request.lo.latitude, request.hi.latitude)
bottom = min(request.lo.latitude, request.hi.latitude)
for feature in self.db:
if (feature.location.longitude >= left and
feature.location.longitude <= right and
feature.location.latitude >= bottom and
feature.location.latitude <= top):
yield feature
def RecordRoute(self, request_iterator, context):
point_count = 0
feature_count = 0
distance = 0.0
prev_point = None
start_time = time.time()
for point in request_iterator:
point_count += 1
if get_feature(self.db, point):
feature_count += 1
if prev_point:
distance += get_distance(prev_point, point)
prev_point = point
elapsed_time = time.time() - start_time
return route_guide_pb2.RouteSummary(
point_count=point_count,
feature_count=feature_count,
distance=int(distance),
elapsed_time=int(elapsed_time))
def RouteChat(self, request_iterator, context):
prev_notes = []
for new_note in request_iterator:
for prev_note in prev_notes:
if prev_note.location == new_note.location:
yield prev_note
prev_notes.append(new_note)
def WalletBalance(self, request, context):
response = self.node.get_wallet_balance()
return route_guide_pb2.WalletBalanceResponse(
total_balance=response.total_balance,
confirmed_balance=response.confirmed_balance,
unconfirmed_balance=response.unconfirmed_balance,
)
def ConnectHost(self, request, context):
host = request.host
self.node.connect_host(host)
return route_guide_pb2.ConnectHostResponse()
def DisconnectPeer(self, request, context):
addr = request.addr
host = addr.host
port = addr.port
address = (host, port)
self.node.disconnect_peer(address)
return route_guide_pb2.DisconnectPeerResponse()
def ListPeers(self, request, context):
peers = self.node.get_peers()
peer_msgs = [
route_guide_pb2.Peer(
addr=route_guide_pb2.Addr(
host=peer.address[0],
port=peer.address[1],
),
)
for peer in peers
]
return route_guide_pb2.ListPeersResponse(
peers=peer_msgs,
)
def MakeSqueak(self, request, context):
content = request.content
squeak = self.node.make_squeak(content)
squeak_msg = route_guide_pb2.Squeak(
hash=squeak.GetHash(),
address=str(squeak.GetAddress()),
content=squeak.GetDecryptedContentStr(),
block_height=squeak.nBlockHeight,
timestamp=squeak.nTime,
)
return route_guide_pb2.MakeSqueakResponse(
squeak=squeak_msg,
)
def GenerateSigningKey(self, request, context):
address = self.node.generate_signing_key()
return route_guide_pb2.GenerateSigningKeyResponse(
address=str(address),
)
def serve(self):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
self, server)
server.add_insecure_port('0.0.0.0:50051')
server.start()
server.wait_for_termination()

View file

@ -0,0 +1,15 @@
[DEFAULT]
network =
[lnd]
rpc_host =
rpc_port =
[btcd]
rpc_host =
rpc_port =
rpc_user=
rpc_pass =
[squeakserver]
host =

View file

@ -4,8 +4,8 @@ import os
import grpc
import squeakclient.rpc_pb2 as ln
import squeakclient.rpc_pb2_grpc as lnrpc
import squeaknode.common.rpc_pb2 as ln
import squeaknode.common.rpc_pb2_grpc as lnrpc
from squeaknode.common.lightning_client import LightningClient