Merge pull request #8 from dsbaars/feature/check-ring

Check Ring functionality - auto create channels.txt
This commit is contained in:
Stijn 2021-10-19 23:53:00 +02:00 committed by GitHub
commit f40b891fa8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 157 additions and 5 deletions

View file

@ -1,6 +1,8 @@
# Ringtools # Ringtools
Ringtools is a tool to keep an eye on the by you provided channels, like to monitor a Ring of Fire. Ringtools is a tool to keep an eye on the by you provided channels, like to monitor a Ring of Fire.
-------------------- --------------------
## Installation ## Installation
@ -9,6 +11,8 @@ Ringtools is a tool to keep an eye on the by you provided channels, like to moni
3. Clone this repository `git clone https://github.com/StijnBTC/Ringtools` 3. Clone this repository `git clone https://github.com/StijnBTC/Ringtools`
4. Navigate to the right folder `cd Ringtools` 4. Navigate to the right folder `cd Ringtools`
5. Install the requirements `pip3 install -r requirements.txt` 5. Install the requirements `pip3 install -r requirements.txt`
6. Edit the channel file `sudo nano channels.txt`
7. Replace all channels with the channels from your ring and save (Ctrl+X following Y (Yes)) ## Usage
8. Run Ringtools `python3 ringtools.py -f -l status` (When you're ready, hit Ctrl+C) 1. Put all public keys and telegram usernames, separated with a comma in `pubkeys.txt`
2. Run `checkring` functionality with write to create channels.txt `python3 ringtools.py check --write-channels`
3. Run Ringtools `python3 ringtools.py -f -l status` (When you're ready, hit Ctrl+C)

89
checkring.py Normal file
View file

@ -0,0 +1,89 @@
import os
import grpc
from time import sleep
from output import format_channel_error, format_error, clear_screen, format_channel
from yachalk import chalk
class CheckRing:
def __init__(self, lnd, output, pubkeys_file, write_channels, show_fees, channels_file):
self.lnd = lnd
self.output = output
self.pubkeys_file = pubkeys_file
self.show_fees = show_fees
self.write_channels = write_channels
self.channels_file = channels_file
def read_file(self, file):
if not os.path.isfile(file):
self.handle_error("File does not exist")
else:
with open(self.pubkeys_file) as file:
return file.read().splitlines()
def run(self):
self.once()
def once(self):
pubkeys = self.read_file(self.pubkeys_file)
channelList = []
for idx, pubkeyInfo in enumerate(pubkeys):
# pubkeys format is <pubkey>,<telegram username> to be able to mimic the manual pubkey overview with usernames
pubkey = pubkeyInfo.split(',')
try:
response = self.lnd.get_node_channels(pubkey[0])
print("%s" %
(chalk.yellow(response.node.alias)))
channelTo = pubkeys[(idx+1) % (len(pubkeys))].split(',')[0]
hasChannel = False
channelId = 0
channelInfo = {}
for channel in response.channels:
if (channel.node1_pub == channelTo) or (channel.node2_pub == channelTo):
hasChannel = True
channelId = channel.channel_id
channelInfo = channel
channelList.append(channelId)
if hasChannel:
outputHas = chalk.green('')
else:
outputHas = chalk.red('🙌🏻')
print("%s %s\r\n%s" %
(outputHas, pubkey[1], pubkey[0]))
if hasChannel:
print(chalk.green("Channel is open with ID: %s") % channelId)
if self.show_fees:
response = self.lnd.get_edge(int(channelId))
node1 = self.lnd.get_node(response.node1_pub)
node2 = self.lnd.get_node(response.node2_pub)
disabled = response.node1_policy.disabled or response.node2_policy.disabled
self.print_channel(
channelInfo, node1.alias, node2.alias, disabled)
else:
print(chalk.red("Should open to node with pubkey %s") % channelTo)
except grpc.RpcError as e:
self.output.print_line(format_channel_error(pubkey, repr(e)))
except Exception as error:
self.output.print_line(
format_channel_error(pubkey, repr(error)))
if self.write_channels:
f = open(self.channels_file, "w")
for c in channelList:
f.write(str(c) + "\r\n")
f.close()
def print_channel(self, channel, node1_alias, node2_alias, chan_disabled):
self.output.print_line(format_channel(
channel, node1_alias, node2_alias, chan_disabled, self.show_fees))
def handle_error(self, error):
self.output.print_line(format_error(error))

7
lnd.py
View file

@ -48,6 +48,13 @@ class Lnd:
def get_edge(self, channel_id): def get_edge(self, channel_id):
return self.stub.GetChanInfo(ln.ChanInfoRequest(chan_id=channel_id)) return self.stub.GetChanInfo(ln.ChanInfoRequest(chan_id=channel_id))
@lru_cache(maxsize=None)
def get_node_channels(self, pubkey):
return self.stub.GetNodeInfo(ln.NodeInfoRequest(
pub_key=pubkey, include_channels=True))
@lru_cache(maxsize=None) @lru_cache(maxsize=None)
def get_node_alias(self, pub_key): def get_node_alias(self, pub_key):
return self.stub.GetNodeInfo( return self.stub.GetNodeInfo(

21
pubkeys.txt Normal file
View file

@ -0,0 +1,21 @@
0294e9ad2727d623fb22870e32f167d4d014e2f7adccb0926802f0bd4d17959093,@akkorokamui
028e748c8f24acb985cd428eb072d3d71d1a692acd38a4d22b14fb7e6bf6513f33,@MBTC_1
03a3c59c4081ec3f0f5b889ca16c8193d22d1c4aec94d1e6e3873e95c9c3592763,@Kippers37
02258a9aa9463749bf729511af78b1ea339ecdb36b37a6e18a8c8caa895228bfcb,@PeteDoo
02fa5c81d1d41e8d8001e6169fe454441360cfb876dc6c5b82fb5d20c0da5b9a51,Chefke
02719ddac30c16dd856bb61ec4a52a5984d345da078c1855baeef856976e9f312a,Jobe[Jotne-Nodenor]
03aba668b98dbe9550cd998648878c445118c7eff35471f6583c526ad0f39f68aa,@Frodo7
037305dfd540c28353120b42cabd6debf3a832283a18679a7ef205684223998e85,@WolligSchaap
026776c241841182e8f44648b7972249b3a1ba1291a8e1af5c383b3219864cb027,@SatStekker
021d70a400e9b8b0ebc1a8816da9c3294eba17d01beaafa210e5870233aee13d98,@RDdeBruyn
023d153b512346a3a6026859ecf906d7f6912bc9fa4214ed4439ffafe47ba53cef,@TReader01
02b74b259fbfb180e5fac9369204b27aa889cffcc4c348ce7a2b99b52eb0d11af9,@BentedeBitcoinBoer
031ff1fa0ce00bece0879270798ee06d29a54f54e9a4ac632beeddcc74f000e217,@1665
02c23df35912b9393b92cd16761e22e122651b7960720e94a13c01697bfdd27aa1,@commaCamel (Comma)
027ce2952b775e3cc4700d159d82b53f2559dc1f53faf2ca05c7ef28a26d90ac43,Roy
03706a7c275576f161d916e28704f0fe0a487758168147d3722e90855d18cc4336,@J_A_C_C_O (JACCO)
02b6b8e6b683811f358e9602f8271694951b92dd66ff0841501f2ce9ddcf7bc2fc,@I2Sappig
0334aadd6b72f00168c87385c081a171e1a1a1936435c2952d25dd10d2f17d6c43,@GrunnBliksems
037280da8985d5b1b143adec8277d182b709414fcfd9771aaeb31f57bbe81d5b83,@Knetsooj
035c709aae4bcb860ebf07da75e6454172ce27b0dc2131c7263479696e2f1fe6bd,@kapital8one
0205a19356bbb7482057356aef070285a2ce6141d2448545210e9d575b57eddd37,@dsbaars

View file

@ -5,7 +5,7 @@ from lnd import Lnd
from output import Output from output import Output
from status import Status from status import Status
from utils import is_umbrel from utils import is_umbrel
from checkring import CheckRing
class RingTools: class RingTools:
def __init__(self, arguments): def __init__(self, arguments):
@ -20,6 +20,14 @@ class RingTools:
self.arguments.channels_file, self.arguments.channels_file,
self.arguments.loop, self.arguments.loop,
self.arguments.show_fees).run() self.arguments.show_fees).run()
elif self.arguments.function == "check":
CheckRing(self.lnd,
self.output,
self.arguments.pubkeys_file,
self.arguments.write_channels,
self.arguments.show_fees,
self.arguments.channels_file
).run()
pass pass
@ -34,7 +42,7 @@ def get_argument_parser():
# This is needed for the cert and macaroon of LND # This is needed for the cert and macaroon of LND
parser.add_argument( parser.add_argument(
dest="function", dest="function",
choices=['status'], choices=['status', 'check'],
help="Choose which function of the RingTools you would " help="Choose which function of the RingTools you would "
"like to use", "like to use",
default="help", default="help",
@ -56,10 +64,31 @@ def get_argument_parser():
dest="grpc", dest="grpc",
help="(default localhost:10009) lnd gRPC endpoint", help="(default localhost:10009) lnd gRPC endpoint",
) )
status_group = parser.add_argument_group( status_group = parser.add_argument_group(
"status", "status",
"Get the current status of all channels", "Get the current status of all channels",
) )
check_group = parser.add_argument_group(
"check",
"Check if channels are open with pubkey list",
)
check_group.add_argument(
"-pubkeys-file",
"-pk",
default="./pubkeys.txt",
dest="pubkeys_file",
help="(default ./pubkeys.txt) pubkeys file"
)
check_group.add_argument(
'-w',
'--write-channels',
action="store_true",
dest="write_channels",
help="(default False) Write channels.txt"
)
status_group.add_argument( status_group.add_argument(
"-channels-file", "-channels-file",
"-c", "-c",
@ -67,6 +96,7 @@ def get_argument_parser():
dest="channels_file", dest="channels_file",
help="(default ./channels.txt) channels file" help="(default ./channels.txt) channels file"
) )
status_group.add_argument( status_group.add_argument(
"-l", "-l",
"--loop", "--loop",
@ -81,6 +111,7 @@ def get_argument_parser():
dest="show_fees", dest="show_fees",
help="(default False) Shows fees in status screen" help="(default False) Shows fees in status screen"
) )
return parser return parser