mirror of
https://github.com/curly60e/pyblock.git
synced 2026-08-20 13:28:10 +02:00
Add files via upload
This commit is contained in:
parent
5bc8014265
commit
962bb5d079
24 changed files with 11627 additions and 0 deletions
6462
pybitblock/SPV/PyBlock-SPV.py
Normal file
6462
pybitblock/SPV/PyBlock-SPV.py
Normal file
File diff suppressed because it is too large
Load diff
264
pybitblock/SPV/apisnd.py
Normal file
264
pybitblock/SPV/apisnd.py
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
|
||||
import os
|
||||
import qrcode
|
||||
import requests
|
||||
import time as t
|
||||
import sys
|
||||
from nodeconnection import *
|
||||
from pblogo import *
|
||||
from logos import *
|
||||
|
||||
def clear(): # clear the screen
|
||||
os.system('cls' if os.name=='nt' else 'clear')
|
||||
|
||||
def apisender():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
message = input("\nInsert your Message: ")
|
||||
a = sys.getsizeof(message)
|
||||
mini = 6000
|
||||
n = (a * 50)
|
||||
if n <= mini:
|
||||
q = str(mini)
|
||||
elif n >= mini:
|
||||
k = n + mini
|
||||
q = str(k)
|
||||
|
||||
url = 'https://api.blockstream.space/order'
|
||||
sentby = " - PyBLOCK."
|
||||
print("\n\tATENTION: YOU NEED TO PAY \033[1;31;40m" + q + "\033[0;37;40m MilliSats")
|
||||
amountmsat = input("\nInsert the amount in MSats: ")
|
||||
curl = 'curl -F ' "bid={} ".format(amountmsat) + '-F ' + ' "message=' + message + sentby + '" ' + url
|
||||
sh = os.popen(curl)
|
||||
clear()
|
||||
blogo()
|
||||
sh0 = sh.read()
|
||||
while True:
|
||||
if 'Bid too low' in sh0:
|
||||
print("\n\t\033[1;31;40mATENTION: Per byte bid cannot be below 50 millisatoshis per byte.\033[0;37;40m\n")
|
||||
print("Try again...\n")
|
||||
message = input("\nInsert your Message: ")
|
||||
a = sys.getsizeof(message)
|
||||
mini = 6000
|
||||
n = (a * 50)
|
||||
if n <= mini:
|
||||
q = str(mini)
|
||||
elif n >= mini:
|
||||
k = n + mini
|
||||
q = str(k)
|
||||
|
||||
url = 'https://api.blockstream.space/order'
|
||||
sentby = " - PyBLOCK."
|
||||
print("\n\tATENTION: YOU NEED TO PAY \033[1;31;40m" + q + "\033[0;37;40m MilliSats")
|
||||
amountmsat = input("\nInsert the amount in MSats: ")
|
||||
curl = 'curl -F ' "bid={} ".format(amountmsat) + '-F ' + ' "message=' + message + sentby + '" ' + url
|
||||
sh = os.popen(curl)
|
||||
clear()
|
||||
blogo()
|
||||
sh0 = sh.read()
|
||||
elif 'lightning_invoice' in sh0:
|
||||
break
|
||||
|
||||
sh1 = str(sh0)
|
||||
shh = sh1.split(',')
|
||||
invoice = str(shh[6])
|
||||
|
||||
#---------------Token-----------
|
||||
authtoken = str(shh[0])
|
||||
authtoken1 = authtoken.split(':')
|
||||
token = authtoken1[1]
|
||||
#---------------End Token-------
|
||||
|
||||
#---------------Order-----------
|
||||
uuid = str(shh[1])
|
||||
uuid1 = uuid.split(':')
|
||||
order = uuid1[1]
|
||||
#---------------End Order-------
|
||||
|
||||
#---------------Amount----------
|
||||
msat = str(shh[3])
|
||||
msat1 = msat.split(':')
|
||||
amount = msat1[1]
|
||||
#---------------End Amount------
|
||||
|
||||
orderid = str(shh[1])
|
||||
ln1 = invoice.split(':')
|
||||
ln2 = str(ln1[1])
|
||||
cln = ln2.strip('"')
|
||||
print("\n\033[0;37;40mYour Token Authorization: \033[1;31;40m" + token + "\033[0;37;40m")
|
||||
print("\033[0;37;40mYour Order Number: \033[1;31;40m" + order + "\033[0;37;40m")
|
||||
print("\033[0;37;40mAmount in MSats: \033[1;33;40m" + amount + "\033[0;37;40m\n")
|
||||
clear()
|
||||
blogo()
|
||||
node_not = input("Do you want to pay this message with your node? Y/n: ")
|
||||
if node_not in ["Y", "y"]:
|
||||
lndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "ln":""}
|
||||
lndconnectData = pickle.load(open("blndconnect.conf", "rb")) # Load the file 'bclock.conf'
|
||||
lndconnectload = lndconnectData # Copy the variable pathv to 'path'
|
||||
if lndconnectload['ip_port']:
|
||||
print("\nInvoice: " + cln + "\n")
|
||||
payinvoice()
|
||||
elif lndconnectload['ln']:
|
||||
print("\nInvoice: " + cln + "\n")
|
||||
localpayinvoice()
|
||||
elif node_not in ["N", "n"]:
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(cln)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
print("\nLND Invoice: " + cln + "\n")
|
||||
sh.close()
|
||||
continue1 = input("Continue? Y: ")
|
||||
if continue1 == "Y" or continue1 == "y":
|
||||
donate()
|
||||
else:
|
||||
t.sleep(2)
|
||||
|
||||
def apisenderFile():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
url = 'https://api.blockstream.space/order'
|
||||
message = input("\nInsert the path to the File: ")
|
||||
print("ATENTION: Minimum amount for sending a File is 50000 MSats")
|
||||
amountmsat = input("\nInsert the amount in MSats: ")
|
||||
curl = 'curl -F ' "bid={} ".format(amountmsat) + '-F ' + ' "file=@' + message + '" ' + url
|
||||
sh = os.popen(curl)
|
||||
sh0 = sh.read()
|
||||
while True:
|
||||
try:
|
||||
if 'Bid too low' in sh0:
|
||||
print("\n\t\033[1;31;40mATENTION: Per byte bid cannot be below 50 millisatoshis per byte.\033[0;37;40m\n")
|
||||
print("Try again...\n")
|
||||
url = 'https://api.blockstream.space/order'
|
||||
message = input("\nInsert the path to the File: ")
|
||||
print("ATENTION: Minimum amount for sending a File is 50000 MSats")
|
||||
amountmsat = input("\nInsert the amount in MSats: ")
|
||||
curl = 'curl -F ' "bid={} ".format(amountmsat) + '-F ' + ' "file=@' + message + '" ' + url
|
||||
sh = os.popen(curl)
|
||||
sh0 = sh.read()
|
||||
elif 'lightning_invoice' in sh0:
|
||||
break
|
||||
except:
|
||||
break
|
||||
|
||||
sh1 = str(sh0)
|
||||
shh = sh1.split(',')
|
||||
invoice = str(shh[6])
|
||||
|
||||
#---------------Token-----------
|
||||
authtoken = str(shh[0])
|
||||
authtoken1 = authtoken.split(':')
|
||||
token = authtoken1[1]
|
||||
#---------------End Token-------
|
||||
|
||||
#---------------Order-----------
|
||||
uuid = str(shh[1])
|
||||
uuid1 = uuid.split(':')
|
||||
order = uuid1[1]
|
||||
#---------------End Order-------
|
||||
|
||||
#---------------Amount----------
|
||||
msat = str(shh[3])
|
||||
msat1 = msat.split(':')
|
||||
amount = msat1[1]
|
||||
#---------------End Amount------
|
||||
|
||||
orderid = str(shh[1])
|
||||
ln1 = invoice.split(':')
|
||||
ln2 = str(ln1[1])
|
||||
cln = ln2.strip('"')
|
||||
print("\n\033[0;37;40mYour Token Authorization: \033[1;31;40m" + token + "\033[0;37;40m")
|
||||
print("\033[0;37;40mYour Order Number: \033[1;31;40m" + order + "\033[0;37;40m")
|
||||
print("\033[0;37;40mAmount in MSats: \033[1;33;40m" + amount + "\033[0;37;40m")
|
||||
clear()
|
||||
blogo()
|
||||
try:
|
||||
node_not = input("Do you want to pay this message with your node? Y/n: ")
|
||||
if node_not in ["Y", "y"]:
|
||||
lndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "ln":""}
|
||||
lndconnectData = pickle.load(open("blndconnect.conf", "rb")) # Load the file 'bclock.conf'
|
||||
lndconnectload = lndconnectData # Copy the variable pathv to 'path'
|
||||
if lndconnectload['ip_port']:
|
||||
print("\nInvoice: " + cln + "\n")
|
||||
payinvoice()
|
||||
elif lndconnectload['ln']:
|
||||
print("\nInvoice: " + cln + "\n")
|
||||
localpayinvoice()
|
||||
elif node_not in ["N", "n"]:
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(cln)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
print("\nLND Invoice: " + cln)
|
||||
sh.close()
|
||||
continue1 = input("Continue? Y: ")
|
||||
if continue1 == "Y" or continue1 == "y":
|
||||
donate()
|
||||
else:
|
||||
t.sleep(2)
|
||||
except:
|
||||
pass
|
||||
|
||||
def devAddr():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
print("\n\t\t\033[1;33;44mGive us some love and \033[1;31;44mDONATE\033[1;33;44m us! We will appreciate it. This will be a boost to continue this beautiful project! \033[0;37;40m")
|
||||
url = 'https://api.tippin.me/v1/public/addinvoice/royalfield370'
|
||||
response = requests.get(url)
|
||||
responseB = str(response.text)
|
||||
responseC = responseB
|
||||
lnreq = responseC.split(',')
|
||||
lnbc1 = lnreq[1]
|
||||
lnbc1S = str(lnbc1)
|
||||
lnbc1R = lnbc1S.split(':')
|
||||
lnbc1W = lnbc1R[1]
|
||||
ln = str(lnbc1W)
|
||||
ln1 = ln.strip('"')
|
||||
clear()
|
||||
blogo()
|
||||
try:
|
||||
node_not = input("Do you want to pay this tip with your node? Y/n: ")
|
||||
if node_not in ["Y", "y"]:
|
||||
lndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "ln":""}
|
||||
lndconnectData = pickle.load(open("blndconnect.conf", "rb")) # Load the file 'bclock.conf'
|
||||
lndconnectload = lndconnectData # Copy the variable pathv to 'path'
|
||||
if lndconnectload['ip_port']:
|
||||
print("\nInvoice: " + ln1 + "\n")
|
||||
payinvoice()
|
||||
elif lndconnectload['ln']:
|
||||
print("\nInvoice: " + ln1 + "\n")
|
||||
localpayinvoice()
|
||||
elif node_not in ["N", "n"]:
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(ln1)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
print("LND Invoice: " + ln1)
|
||||
response.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
def donate():
|
||||
print("""\t\t
|
||||
\033[1;31;40mPyBLOCK\033[0;37;40m Menu
|
||||
|
||||
\033[1;32;40mA.\033[0;37;40m Donate
|
||||
<<< Back Control + C
|
||||
\n\n""")
|
||||
menuB = (input("\033[1;32;40mSelect option: \033[0;37;40m"))
|
||||
if menuB in ["A", "a"]:
|
||||
devAddr()
|
||||
BIN
pybitblock/SPV/bitcoin.pdf
Normal file
BIN
pybitblock/SPV/bitcoin.pdf
Normal file
Binary file not shown.
153
pybitblock/SPV/clockscript.py
Normal file
153
pybitblock/SPV/clockscript.py
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
import pickle
|
||||
import os
|
||||
import sys
|
||||
import base64, codecs, json, requests
|
||||
from cfonts import render, say
|
||||
|
||||
|
||||
def clear(): # clear the screen
|
||||
os.system('cls' if os.name=='nt' else 'clear')
|
||||
|
||||
def rectangle(n):
|
||||
x = n - 3
|
||||
y = n - x
|
||||
[
|
||||
print(''.join(i))
|
||||
for i in
|
||||
(
|
||||
''*x
|
||||
if i in (0,y-1)
|
||||
else
|
||||
(
|
||||
f'{""*n}{"|"*n}{""*n}'
|
||||
if i >= (n+1)/2 and i <= (1*n)/2
|
||||
else
|
||||
f'\u001b[38;5;27m{"■"*(x-1)}'
|
||||
)
|
||||
for i in range(y)
|
||||
)
|
||||
]
|
||||
|
||||
def blogo():
|
||||
|
||||
if os.path.isfile('config/pyblocksettings.conf') or os.path.isfile('config/pyblocksettings.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
settingsv = pickle.load(open("config/pyblocksettings.conf", "rb")) # Load the file 'bclock.conf'
|
||||
settings = settingsv # Copy the variable pathv to 'path'
|
||||
else:
|
||||
settings = {"gradient":"", "design":"block", "colorA":"green", "colorB":"yellow"}
|
||||
pickle.dump(settings, open("config/pyblocksettings.conf", "wb"))
|
||||
|
||||
if settings["gradient"] == "grd":
|
||||
output = render('PyBLOCK', gradient=[settings['colorA'], settings['colorB']], align='center', font=settings['design'])
|
||||
else:
|
||||
output = render('PyBLOCK', colors=[settings['colorA'], settings['colorB']], align='center', font=settings['design'])
|
||||
|
||||
print(output)
|
||||
|
||||
def artist(): # here we convert the result of the command 'getblockcount' on a random art design
|
||||
while True:
|
||||
try:
|
||||
clear()
|
||||
design()
|
||||
except:
|
||||
break
|
||||
|
||||
def design():
|
||||
while True:
|
||||
if os.path.isfile('config/pyblocksettingsClock.conf') or os.path.isfile('config/pyblocksettingsClock.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
settingsv = pickle.load(open("config/pyblocksettingsClock.conf", "rb")) # Load the file 'bclock.conf'
|
||||
settingsClock = settingsv # Copy the variable pathv to 'path'
|
||||
else:
|
||||
settingsClock = {"gradient":"", "design":"block", "colorA":"green", "colorB":"yellow"}
|
||||
pickle.dump(settingsClock, open("config/pyblocksettingsClock.conf", "wb"))
|
||||
bitcoinclient = path['bitcoincli'] + " getblockcount"
|
||||
block = os.popen(str(bitcoinclient)).read() # 'getblockcount' convert to string
|
||||
b = block
|
||||
a = b
|
||||
blogo()
|
||||
output = render(str(b), colors=[settingsClock['colorA'], settingsClock['colorB']], align='center')
|
||||
print("\x1b[?25l" + output)
|
||||
bitcoinclient = path['bitcoincli'] + " getbestblockhash"
|
||||
bb = os.popen(str(bitcoinclient)).read()
|
||||
ll = bb
|
||||
bitcoinclientgetblock = path['bitcoincli'] + " getblock " + ll
|
||||
qq = os.popen(bitcoinclientgetblock).read()
|
||||
yy = json.loads(qq)
|
||||
mm = yy
|
||||
outputsize = render(str(mm['size']) + " bytes", colors=[settingsClock['colorA'], settingsClock['colorB']], align='center', font='tiny')
|
||||
print("\x1b[?25l" + outputsize)
|
||||
outputtxs = render(str(mm['nTx']) + " txs", colors=[settingsClock['colorA'], settingsClock['colorB']], align='center', font='tiny')
|
||||
print("\x1b[?25l" + outputtxs)
|
||||
sh = int(mm['nTx']) / 4
|
||||
shq = int(sh)
|
||||
ss = str(rectangle(shq))
|
||||
print(ss.replace("None",""))
|
||||
while True:
|
||||
x = a
|
||||
bitcoinclient = path['bitcoincli'] + " getblockcount"
|
||||
block = os.popen(str(bitcoinclient)).read() # 'getblockcount' convert to string
|
||||
b = block
|
||||
if b > a:
|
||||
clear()
|
||||
blogo()
|
||||
output = render(str(b), colors=[settingsClock['colorA'], settingsClock['colorB']], align='center')
|
||||
print("\a\x1b[?25l" + output)
|
||||
bitcoinclient = path['bitcoincli'] + " getbestblockhash"
|
||||
bb = os.popen(str(bitcoinclient)).read()
|
||||
ll = bb
|
||||
bitcoinclientgetblock = path['bitcoincli'] + " getblock " + ll
|
||||
qq = os.popen(bitcoinclientgetblock).read()
|
||||
yy = json.loads(qq)
|
||||
mm = yy
|
||||
outputsize = render(str(mm['size']) + " bytes", colors=[settingsClock['colorA'], settingsClock['colorB']], align='center', font='tiny')
|
||||
print("\x1b[?25l" + outputsize)
|
||||
outputtxs = render(str(mm['nTx']) + " txs", colors=[settingsClock['colorA'], settingsClock['colorB']], align='center', font='tiny')
|
||||
print("\x1b[?25l" + outputtxs)
|
||||
sh = int(mm['nTx']) / 4
|
||||
shq = int(sh)
|
||||
ss = str(rectangle(shq))
|
||||
print(ss.replace("None",""))
|
||||
t.sleep(10)
|
||||
txs = str(mm['nTx'])
|
||||
if txs == "1":
|
||||
try:
|
||||
p = subprocess.Popen(['curl', 'https://poptart.spinda.net'])
|
||||
p.wait(5)
|
||||
except subprocess.TimeoutExpired:
|
||||
p.kill()
|
||||
print("\033[0;37;40m\x1b[?25l")
|
||||
clear()
|
||||
close()
|
||||
a = b
|
||||
output = render(str(b), colors=[settingsClock['colorA'], settingsClock['colorB']], align='center')
|
||||
print("\x1b[?25l" + output)
|
||||
|
||||
|
||||
|
||||
settings = {"gradient":"", "design":"block", "colorA":"green", "colorB":"yellow"}
|
||||
settingsClock = {"gradient":"", "colorA":"green", "colorB":"yellow"}
|
||||
while True: # Loop
|
||||
try:
|
||||
clear()
|
||||
path = {"ip_port":"", "rpcuser":"", "rpcpass":"", "bitcoincli":""}
|
||||
|
||||
if os.path.isfile('config/bclock.conf') or os.path.isfile('config/blnclock.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
pathv = pickle.load(open("config/bclock.conf", "rb")) # Load the file 'bclock.conf'
|
||||
path = pathv # Copy the variable pathv to 'path'
|
||||
else:
|
||||
blogo()
|
||||
print("Welcome to \033[1;31;40mPyBLOCK\033[0;37;40m\n\n")
|
||||
print("\n\tIf you are going to use your local node leave IP:PORT/USER/PASSWORD in blank.\n")
|
||||
path['ip_port'] = "http://{}".format(input("Insert IP:PORT to access your remote Bitcoin-Cli node: "))
|
||||
path['rpcuser'] = input("RPC User: ")
|
||||
path['rpcpass'] = input("RPC Password: ")
|
||||
print("\n\tLocal Bitcoin Core Node connection.\n")
|
||||
path['bitcoincli']= input("Insert the Path to Bitcoin-Cli: ")
|
||||
pickle.dump(path, open("config/bclock.conf", "wb"))
|
||||
|
||||
artist()
|
||||
|
||||
|
||||
except:
|
||||
print("\n")
|
||||
sys.exit(101)
|
||||
89
pybitblock/SPV/clockscriptREMOTE.py
Normal file
89
pybitblock/SPV/clockscriptREMOTE.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import base64, codecs, json, requests
|
||||
import pickle
|
||||
import os
|
||||
import sys
|
||||
import simplejson as json
|
||||
from cfonts import render, say
|
||||
|
||||
ndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "ln":""}
|
||||
settingsClock = {"gradient":"", "design":"", "colorA":"", "colorB":""}
|
||||
|
||||
def blogo():
|
||||
|
||||
if os.path.isfile('pyblocksettings.conf') or os.path.isfile('pyblocksettings.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
settingsv = pickle.load(open("pyblocksettings.conf", "rb")) # Load the file 'bclock.conf'
|
||||
settings = settingsv # Copy the variable pathv to 'path'
|
||||
else:
|
||||
settings = {"gradient":"", "design":"block", "colorA":"green", "colorB":"yellow"}
|
||||
pickle.dump(settings, open("pyblocksettings.conf", "wb"))
|
||||
|
||||
if settings["gradient"] == "grd":
|
||||
output = render('PyBLOCK', gradient=[settings['colorA'], settings['colorB']], align='center', font=settings['design'])
|
||||
else:
|
||||
output = render('PyBLOCK', colors=[settings['colorA'], settings['colorB']], align='center', font=settings['design'])
|
||||
|
||||
print(output)
|
||||
|
||||
def clear(): # clear the screen
|
||||
os.system('cls' if os.name=='nt' else 'clear')
|
||||
|
||||
if os.path.isfile('blndconnect.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
lndconnectData= pickle.load(open("blndconnect.conf", "rb")) # Load the file 'bclock.conf'
|
||||
lndconnectload = lndconnectData # Copy the variable pathv to 'path'
|
||||
else:
|
||||
clear()
|
||||
blogo()
|
||||
print("\n\tIf you are going to use your local node leave IP:PORT/CERT/MACAROONS in blank.\n")
|
||||
lndconnectload["ip_port"] = input("Insert IP:PORT to your node: ") # path to the bitcoin-cli
|
||||
lndconnectload["tls"] = input("Insert the path to tls.cert file: ")
|
||||
lndconnectload["macaroon"] = input("Insert the path to admin.macaroon: ")
|
||||
print("\n\tLocal Lightning Node connection.\n")
|
||||
lndconnectload["ln"] = input("Insert the path to lncli: ")
|
||||
pickle.dump(lndconnectload, open("blndconnect.conf", "wb")) # Save the file 'bclock.conf'
|
||||
|
||||
def rpc(method, params=[]):
|
||||
payload = json.dumps({
|
||||
"jsonrpc": "2.0",
|
||||
"id": "minebet",
|
||||
"method": method,
|
||||
"params": params
|
||||
})
|
||||
path = {"ip_port":"", "rpcuser":"", "rpcpass":"", "bitcoincli":""}
|
||||
if os.path.isfile('bclock.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
pathv = pickle.load(open("bclock.conf", "rb")) # Load the file 'bclock.conf'
|
||||
path = pathv # Copy the variable pathv to 'path'
|
||||
return requests.post(path['ip_port'], auth=(path['rpcuser'], path['rpcpass']), data=payload).json()['result']
|
||||
|
||||
|
||||
def remotegetblock():
|
||||
if os.path.isfile('pyblocksettingsClock.conf') or os.path.isfile('pyblocksettingsClock.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
settingsv = pickle.load(open("pyblocksettingsClock.conf", "rb")) # Load the file 'bclock.conf'
|
||||
settingsClock = settingsv # Copy the variable pathv to 'path'
|
||||
else:
|
||||
settingsClock = {"gradient":"", "design":"block", "colorA":"green", "colorB":"yellow"}
|
||||
pickle.dump(settingsClock, open("pyblocksettingsClock.conf", "wb"))
|
||||
b = rpc('getblockcount')
|
||||
c = str(b)
|
||||
a = c
|
||||
output = render(str(c), colors=[settingsClock['colorA'], settingsClock['colorB']], align='center')
|
||||
print("\x1b[?25l" + output)
|
||||
while True:
|
||||
x = a
|
||||
b = rpc('getblockcount')
|
||||
c = str(b)
|
||||
if c > a:
|
||||
clear()
|
||||
blogo()
|
||||
output = render(str(c), colors=[settingsClock['colorA'], settingsClock['colorB']], align='center')
|
||||
print("\a\x1b[?25l" + output)
|
||||
a = c
|
||||
|
||||
while True:
|
||||
try:
|
||||
clear()
|
||||
blogo()
|
||||
remotegetblock()
|
||||
tmp()
|
||||
except:
|
||||
print("\n")
|
||||
sys.exit(101)
|
||||
30
pybitblock/SPV/clone.py
Normal file
30
pybitblock/SPV/clone.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import time as t
|
||||
|
||||
|
||||
def gitclone():
|
||||
url = "https://github.com/curly60e/satellite"
|
||||
os.system("git clone " + url)
|
||||
os.system("mkdir satellite/api/examples/.gnupg")
|
||||
os.system("gpg --full-generate-key --homedir satellite/api/examples/.gnupg")
|
||||
|
||||
def satnode():
|
||||
try:
|
||||
os.system("python3 satellite/api/examples/demo-rx.py &")
|
||||
t.sleep(5)
|
||||
os.system("python3 satellite/api/examples/api_data_reader.py --demo --plaintext ")
|
||||
except:
|
||||
os.system("ps -ef | grep api_data_reader.py | grep -v grep | awk '{print $2}' | xargs kill -9")
|
||||
os.system("ps -ef | grep demo-rx.py | grep -v grep | awk '{print $2}' | xargs kill -9")
|
||||
|
||||
def matrixsc():
|
||||
if os.path.isdir('$HOME/pyblock/terminal_matrix'):
|
||||
print("OK Pass")
|
||||
else:
|
||||
url = "https://github.com/curly60e/terminal_matrix.git"
|
||||
os.system("git clone " + url)
|
||||
BIN
pybitblock/SPV/config/bclock.conf
Normal file
BIN
pybitblock/SPV/config/bclock.conf
Normal file
Binary file not shown.
BIN
pybitblock/SPV/config/init.conf
Normal file
BIN
pybitblock/SPV/config/init.conf
Normal file
Binary file not shown.
BIN
pybitblock/SPV/config/pyblocksettings.conf
Normal file
BIN
pybitblock/SPV/config/pyblocksettings.conf
Normal file
Binary file not shown.
BIN
pybitblock/SPV/config/pyblocksettingsClock.conf
Normal file
BIN
pybitblock/SPV/config/pyblocksettingsClock.conf
Normal file
Binary file not shown.
BIN
pybitblock/SPV/config/selection.conf
Normal file
BIN
pybitblock/SPV/config/selection.conf
Normal file
Binary file not shown.
BIN
pybitblock/SPV/config/slushAPI.conf
Normal file
BIN
pybitblock/SPV/config/slushAPI.conf
Normal file
Binary file not shown.
11
pybitblock/SPV/console.py
Normal file
11
pybitblock/SPV/console.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import os
|
||||
import typer
|
||||
|
||||
|
||||
def main():
|
||||
scriptpath = os.path.join(os.path.dirname(__file__), 'PyBlock.py')
|
||||
os.system(f"python3 {scriptpath}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
typer.run(main)
|
||||
149
pybitblock/SPV/donation.py
Normal file
149
pybitblock/SPV/donation.py
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
|
||||
|
||||
import requests
|
||||
import qrcode
|
||||
import pickle
|
||||
from nodeconnection import *
|
||||
|
||||
def donationAddr():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
url = 'bc1qjzaz34nv2ev55vfdu9m5qh0zq0fwcn6c7pkcrv'
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(url)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
qr.clear()
|
||||
print("Bitcoin Address Bech32: " + url)
|
||||
|
||||
def donationPayNym():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
url = 'PM8TJhNTTq3YVocXuPtLjKx7pKkdUxqwTerWJ2j2a7dNitgyMmBPN6gK61yE17N2vgvQvKYokXktt6D6GZFTmocvDJhaUJfHt7ehEMmthjsT3NQHseFM'
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(url)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
qr.clear()
|
||||
print("PayNym: " + url)
|
||||
|
||||
#Dev LN
|
||||
def donationLN():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
amt = input("Amount: ")
|
||||
curl = 'curl -X POST https://lnbits.com/api/v1/payments -d ' + "'{" + """"out": false, "amount": {}, "memo": "Donation" """.format(amt) + "}'" + """ -H "X-Api-Key: 1d646820055e4e2da218e801eaacfc94 " -H "Content-type: application/json" """
|
||||
sh = os.popen(curl).read()
|
||||
clear()
|
||||
blogo()
|
||||
n = str(sh)
|
||||
d = json.loads(n)
|
||||
q = d['payment_request']
|
||||
c = q.lower()
|
||||
while True:
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(c)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
qr.clear()
|
||||
print("Lightning Invoice: " + c)
|
||||
dn = str(d['checking_id'])
|
||||
t.sleep(10)
|
||||
checkcurl = 'curl -X GET https://lnbits.com/api/v1/payments/' + dn + """ -H "X-Api-Key: 1d646820055e4e2da218e801eaacfc94" -H "Content-type: application/json" """
|
||||
rsh = os.popen(checkcurl).read()
|
||||
clear()
|
||||
blogo()
|
||||
nn = str(rsh)
|
||||
dd = json.loads(nn)
|
||||
db = dd['paid']
|
||||
if db is not True:
|
||||
continue
|
||||
|
||||
clear()
|
||||
blogo()
|
||||
tick()
|
||||
bitLN['pd'] = "PAID"
|
||||
|
||||
#Tester Address
|
||||
def donationAddrTst():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
url = 'bc1qwtzwu2evtchkvnf3ey6520yprsyv7vrjvhula5'
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(url)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
qr.clear()
|
||||
print("Bitcoin Address Bech32: " + url)
|
||||
|
||||
#Tester LN
|
||||
def donationLNTst():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
url = 'https://api.tippin.me/v1/public/addinvoice/__B__T__C__'
|
||||
response = requests.get(url)
|
||||
responseB = str(response.text)
|
||||
responseC = responseB
|
||||
lnreq = responseC.split(',')
|
||||
lnbc1 = lnreq[1]
|
||||
lnbc1S = str(lnbc1)
|
||||
lnbc1R = lnbc1S.split(':')
|
||||
lnbc1W = lnbc1R[1]
|
||||
ln = str(lnbc1W)
|
||||
ln1 = ln.strip('"')
|
||||
node_not = input("Do you want to pay this tip with your node? Y/n: ")
|
||||
if node_not in ["Y", "y"]:
|
||||
lndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "ln":""}
|
||||
lndconnectData = pickle.load(open("blndconnect.conf", "rb")) # Load the file 'bclock.conf'
|
||||
lndconnectload = lndconnectData # Copy the variable pathv to 'path'
|
||||
if lndconnectload['ip_port']:
|
||||
print("\nInvoice: " + ln1 + "\n")
|
||||
payinvoice()
|
||||
elif lndconnectload['ln']:
|
||||
print("\nInvoice: " + ln1 + "\n")
|
||||
localpayinvoice()
|
||||
elif node_not in ["N", "n"]:
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(ln1)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
print("LND Invoice: " + ln1)
|
||||
qr.clear()
|
||||
response.close()
|
||||
|
||||
def decodeQR():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
url = input("Insert your Bitcoin Address to show the QRCode: ")
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(url)
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
qr.clear()
|
||||
print("Bitcoin Address: " + url)
|
||||
24
pybitblock/SPV/feed.py
Normal file
24
pybitblock/SPV/feed.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import time as t
|
||||
|
||||
|
||||
def readFile():
|
||||
try:
|
||||
print ("\n\033[1;34;40mWaiting for new data...\n")
|
||||
downloadsFolder = 'downloads/'
|
||||
while True:
|
||||
if not os.listdir(downloadsFolder):
|
||||
continue
|
||||
else:
|
||||
print("\t\t\n\033[1;33;40mNew message from Space just arrived...\033[0;37;40m\n")
|
||||
os.system("cat downloads/*")
|
||||
os.system("rm downloads/*")
|
||||
|
||||
except:
|
||||
os.system("ps -ef | grep api_data_reader.py | grep -v grep | awk '{print $2}' | xargs kill -9")
|
||||
os.system("ps -ef | grep demo-rx.py | grep -v grep | awk '{print $2}' | xargs kill -9")
|
||||
108
pybitblock/SPV/lnd.py
Normal file
108
pybitblock/SPV/lnd.py
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import base64
|
||||
import os
|
||||
from os.path import expanduser
|
||||
import codecs
|
||||
import grpc
|
||||
import sys
|
||||
|
||||
from grpc_generated import router_pb2_grpc as lnrouterrpc, router_pb2 as lnrouter, rpc_pb2_grpc as lnrpc, rpc_pb2 as ln
|
||||
|
||||
MESSAGE_SIZE_MB = 50 * 1024 * 1024
|
||||
|
||||
|
||||
def debug(message):
|
||||
sys.stderr.write(message + "\n")
|
||||
|
||||
|
||||
class Lnd:
|
||||
def __init__(self, lnd_dir, server):
|
||||
os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA'
|
||||
lnd_dir = expanduser(lnd_dir)
|
||||
combined_credentials = self.get_credentials(lnd_dir)
|
||||
channel_options = [
|
||||
('grpc.max_message_length', MESSAGE_SIZE_MB),
|
||||
('grpc.max_receive_message_length', MESSAGE_SIZE_MB)
|
||||
]
|
||||
grpc_channel = grpc.secure_channel(server, combined_credentials, channel_options)
|
||||
self.stub = lnrpc.LightningStub(grpc_channel)
|
||||
self.router_stub = lnrouterrpc.RouterStub(grpc_channel)
|
||||
self.graph = None
|
||||
self.info = None
|
||||
self.channels = None
|
||||
|
||||
@staticmethod
|
||||
def get_credentials(lnd_dir):
|
||||
tls_certificate = open(lnd_dir + '/tls.cert', 'rb').read()
|
||||
ssl_credentials = grpc.ssl_channel_credentials(tls_certificate)
|
||||
macaroon = codecs.encode(open(lnd_dir + '/data/chain/bitcoin/mainnet/admin.macaroon', 'rb').read(), 'hex')
|
||||
auth_credentials = grpc.metadata_call_credentials(lambda _, callback: callback([('macaroon', macaroon)], None))
|
||||
combined_credentials = grpc.composite_channel_credentials(ssl_credentials, auth_credentials)
|
||||
return combined_credentials
|
||||
|
||||
def get_info(self):
|
||||
if self.info is None:
|
||||
self.info = self.stub.GetInfo(ln.GetInfoRequest())
|
||||
return self.info
|
||||
|
||||
def get_graph(self):
|
||||
if self.graph is None:
|
||||
self.graph = self.stub.DescribeGraph(ln.ChannelGraphRequest(include_unannounced=True))
|
||||
return self.graph
|
||||
|
||||
def get_own_pubkey(self):
|
||||
return self.get_info().identity_pubkey
|
||||
|
||||
def get_edges(self):
|
||||
return self.get_graph().edges
|
||||
|
||||
def generate_invoice(self, memo, amount):
|
||||
invoice_request = ln.Invoice(
|
||||
memo=memo,
|
||||
value=amount,
|
||||
)
|
||||
add_invoice_response = self.stub.AddInvoice(invoice_request)
|
||||
return self.decode_payment_request(add_invoice_response.payment_request)
|
||||
|
||||
def decode_payment_request(self, payment_request):
|
||||
request = ln.PayReqString(
|
||||
pay_req=payment_request,
|
||||
)
|
||||
return self.stub.DecodePayReq(request)
|
||||
|
||||
def get_channels(self):
|
||||
if self.channels is None:
|
||||
request = ln.ListChannelsRequest(
|
||||
active_only=True,
|
||||
)
|
||||
self.channels = self.stub.ListChannels(request).channels
|
||||
return self.channels
|
||||
|
||||
def get_route(self, pub_key, amount, ignored_edges, ignored_nodes, first_hop_channel_id):
|
||||
if pub_key:
|
||||
last_hop_pubkey = base64.b16decode(pub_key, True)
|
||||
else:
|
||||
last_hop_pubkey = None
|
||||
request = ln.QueryRoutesRequest(
|
||||
pub_key=self.get_own_pubkey(),
|
||||
last_hop_pubkey=last_hop_pubkey,
|
||||
amt=amount,
|
||||
ignored_edges=ignored_edges,
|
||||
ignored_nodes=ignored_nodes,
|
||||
use_mission_control=True,
|
||||
outgoing_chan_id=first_hop_channel_id,
|
||||
)
|
||||
try:
|
||||
response = self.stub.QueryRoutes(request)
|
||||
return response.routes
|
||||
except:
|
||||
return None
|
||||
|
||||
def send_payment(self, payment_request, route):
|
||||
request = lnrouter.SendToRouteRequest(route=route)
|
||||
request.payment_hash = self.hex_string_to_bytes(payment_request.payment_hash)
|
||||
return self.router_stub.SendToRoute(request)
|
||||
|
||||
@staticmethod
|
||||
def hex_string_to_bytes(hex_string):
|
||||
decode_hex = codecs.getdecoder("hex_codec")
|
||||
return decode_hex(hex_string)[0]
|
||||
153
pybitblock/SPV/logic.py
Normal file
153
pybitblock/SPV/logic.py
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
import sys
|
||||
|
||||
from routes import Routes
|
||||
|
||||
DEFAULT_BASE_FEE_SAT_MSAT = 1000
|
||||
DEFAULT_FEE_RATE_MSAT = 0.001
|
||||
|
||||
|
||||
def debug(message):
|
||||
sys.stderr.write(message + "\n")
|
||||
|
||||
|
||||
def debugnobreak(message):
|
||||
sys.stderr.write(message)
|
||||
|
||||
|
||||
class Logic:
|
||||
def __init__(self, lnd, first_hop_channel, last_hop_channel, amount, channel_ratio, excluded, max_fee_factor):
|
||||
self.lnd = lnd
|
||||
self.first_hop_channel = first_hop_channel
|
||||
self.last_hop_channel = last_hop_channel
|
||||
self.amount = amount
|
||||
self.channel_ratio = channel_ratio
|
||||
self.excluded = []
|
||||
if excluded:
|
||||
self.excluded = excluded
|
||||
self.max_fee_factor = max_fee_factor
|
||||
|
||||
def rebalance(self):
|
||||
if self.last_hop_channel:
|
||||
debug(("Sending {:,} satoshis to rebalance to channel with ID %d"
|
||||
% self.last_hop_channel.chan_id).format(self.amount))
|
||||
else:
|
||||
debug("Sending {:,} satoshis.".format(self.amount))
|
||||
if self.channel_ratio != 0.5:
|
||||
debug("Channel ratio used is %d%%" % int(self.channel_ratio * 100))
|
||||
if self.first_hop_channel:
|
||||
debug("Forced first channel has ID %d" % self.first_hop_channel.chan_id)
|
||||
|
||||
payment_request = self.generate_invoice()
|
||||
routes = Routes(self.lnd, payment_request, self.first_hop_channel, self.last_hop_channel)
|
||||
|
||||
self.initialize_ignored_channels(routes)
|
||||
|
||||
tried_routes = []
|
||||
while routes.has_next():
|
||||
route = routes.get_next()
|
||||
|
||||
success = self.try_route(payment_request, route, routes, tried_routes)
|
||||
if success:
|
||||
return True
|
||||
debug("Could not find any suitable route")
|
||||
return False
|
||||
|
||||
def try_route(self, payment_request, route, routes, tried_routes):
|
||||
if self.route_is_invalid(route, routes):
|
||||
return False
|
||||
|
||||
tried_routes.append(route)
|
||||
debug("")
|
||||
debug("Trying route #%d" % len(tried_routes))
|
||||
debug(Routes.print_route(route))
|
||||
|
||||
response = self.lnd.send_payment(payment_request, route)
|
||||
is_successful = response.failure.code == 0
|
||||
if is_successful:
|
||||
debug("")
|
||||
debug("")
|
||||
debug("")
|
||||
debug("Success! Paid fees: %s sat (%s msat)" % (route.total_fees, route.total_fees_msat))
|
||||
debug("Successful route:")
|
||||
debug(Routes.print_route(route))
|
||||
debug("")
|
||||
debug("")
|
||||
debug("")
|
||||
return True
|
||||
else:
|
||||
self.handle_error(response, route, routes)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def handle_error(response, route, routes):
|
||||
code = response.failure.code
|
||||
failure_source_pubkey = Logic.get_failure_source_pubkey(response, route)
|
||||
if code == 15:
|
||||
debugnobreak("Temporary channel failure, ")
|
||||
routes.ignore_edge_on_route(failure_source_pubkey, route)
|
||||
elif code == 18:
|
||||
debugnobreak("Unknown next peer, ")
|
||||
routes.ignore_edge_on_route(failure_source_pubkey, route)
|
||||
elif code == 12:
|
||||
debugnobreak("Fee insufficient, ")
|
||||
routes.ignore_edge_on_route(failure_source_pubkey, route)
|
||||
else:
|
||||
debug(repr(response))
|
||||
debug("Unknown error code %s" % repr(code))
|
||||
|
||||
@staticmethod
|
||||
def get_failure_source_pubkey(response, route):
|
||||
if response.failure.failure_source_index == 0:
|
||||
failure_source_pubkey = route.hops[-1].pub_key
|
||||
else:
|
||||
failure_source_pubkey = route.hops[response.failure.failure_source_index - 1].pub_key
|
||||
return failure_source_pubkey
|
||||
|
||||
def route_is_invalid(self, route, routes):
|
||||
first_hop = route.hops[0]
|
||||
if self.low_local_ratio_after_sending(first_hop, route.total_amt):
|
||||
debugnobreak("Low local ratio after sending, ")
|
||||
routes.ignore_first_hop(self.get_channel_for_channel_id(first_hop.chan_id))
|
||||
return True
|
||||
if self.fees_too_high(route):
|
||||
routes.ignore_node_with_highest_fee(route)
|
||||
return True
|
||||
return False
|
||||
|
||||
def low_local_ratio_after_sending(self, first_hop, total_amount):
|
||||
if self.first_hop_channel:
|
||||
# Just use the computed/specified amount to drain the first hop, ignoring fees
|
||||
return False
|
||||
channel_id = first_hop.chan_id
|
||||
channel = self.get_channel_for_channel_id(channel_id)
|
||||
|
||||
remote = channel.remote_balance + total_amount
|
||||
local = channel.local_balance - total_amount
|
||||
ratio = float(local) / (remote + local)
|
||||
return ratio < self.channel_ratio
|
||||
|
||||
def fees_too_high(self, route):
|
||||
hops_with_fees = len(route.hops) - 1
|
||||
lnd_fees = hops_with_fees * (DEFAULT_BASE_FEE_SAT_MSAT + (self.amount * DEFAULT_FEE_RATE_MSAT))
|
||||
limit = self.max_fee_factor * lnd_fees
|
||||
return route.total_fees_msat > limit
|
||||
|
||||
def generate_invoice(self):
|
||||
if self.last_hop_channel:
|
||||
memo = "Rebalance of channel with ID %d" % self.last_hop_channel.chan_id
|
||||
else:
|
||||
memo = "Rebalance of channel with ID %d" % self.first_hop_channel.chan_id
|
||||
return self.lnd.generate_invoice(memo, self.amount)
|
||||
|
||||
def get_channel_for_channel_id(self, channel_id):
|
||||
for channel in self.lnd.get_channels():
|
||||
if channel.chan_id == channel_id:
|
||||
return channel
|
||||
|
||||
def initialize_ignored_channels(self, routes):
|
||||
for channel in self.lnd.get_channels():
|
||||
if self.low_local_ratio_after_sending(channel, self.amount):
|
||||
routes.ignore_first_hop(channel, show_message=False)
|
||||
if channel.chan_id in self.excluded:
|
||||
debugnobreak("Channel is excluded, ")
|
||||
routes.ignore_first_hop(channel)
|
||||
112
pybitblock/SPV/logos.py
Normal file
112
pybitblock/SPV/logos.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
|
||||
|
||||
def logoA():
|
||||
print("""\n\n\033[1;33;40m
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*****@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@****************************#@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@***************************************@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@***********************************************@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@*****************************************************@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@***********************************************************@@@@@@@@@@
|
||||
@@@@@@@@@****************************** *****************************@@@@@@@@
|
||||
@@@@@@@******************************* *** ***********************@@@@@@
|
||||
@@@@@@********************** .**** **** *************************@@@@@
|
||||
@@@@*********************** ,* **************************@@@@
|
||||
@@@**************************** ***************************@@
|
||||
@@****************************** *. **********************#@
|
||||
@@***************************** ******** *********************@
|
||||
@****************************** *********** **********************
|
||||
@***************************** *********** **********************
|
||||
@***************************** ***********************
|
||||
***************************** **************************
|
||||
@*************************** ******** *************************
|
||||
@*************************** ***********. ***********************
|
||||
@********************* *** ************* ***********************
|
||||
@@******************* ************ **********************@
|
||||
@@******************** **********************@@
|
||||
@@@************************** ,***********************@@
|
||||
@@@@#*********************** *** *. **************************@@@@
|
||||
@@@@@@********************* **** ***********************************@@@@@
|
||||
@@@@@@@**************************** **********************************@@@@@@
|
||||
@@@@@@@@@***************************************************************@@@@@@@@
|
||||
@@@@@@@@@@@**********************************************************,@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@*****************************************************@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@***********************************************@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@***************************************@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@#***************************@@@@@@@@@@@@@@@@@@@@@@@@@@\033[0;37;40m
|
||||
""")
|
||||
|
||||
def logoB():
|
||||
print("""\n\n\033[1;33;40m
|
||||
/////
|
||||
////////////////////////////%
|
||||
///////////////////////////////////////
|
||||
///////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
////////////////////////////// /////////////////////////////
|
||||
/////////////////////////////// /// ///////////////////////
|
||||
////////////////////// .//// //// /////////////////////////
|
||||
/////////////////////// */ //////////////////////////
|
||||
//////////////////////////// *//////////////////////////
|
||||
////////////////////////////// /. //////////////////////
|
||||
///////////////////////////// //////// /////////////////////
|
||||
////////////////////////////// //////////* //////////////////////
|
||||
///////////////////////////// /////////// //////////////////////
|
||||
///////////////////////////// ///////////////////////
|
||||
///////////////////////////// */////////////////////////
|
||||
/////////////////////////// //////// /////////////////////////
|
||||
/////////////////////////// ///////////, ///////////////////////
|
||||
///////////////////// /// ///////////// ///////////////////////
|
||||
/////////////////// //////////// //////////////////////
|
||||
//////////////////// //////////////////////
|
||||
////////////////////////// *///////////////////////
|
||||
%/////////////////////// /// /. //////////////////////////
|
||||
///////////////////// //// ///////////////////////////////////
|
||||
//////////////////////////// //////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////*
|
||||
/////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////
|
||||
///////////////////////////////////////
|
||||
%///////////////////////////
|
||||
/////\033[0;37;40m
|
||||
""")
|
||||
|
||||
def logoC():
|
||||
print("""\n\n\033[1;33;40m
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@
|
||||
@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@
|
||||
@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&& &&&&&&&&&&&&&&&&&&&&&&&@@@@@@
|
||||
@@@@@@&&&&&&&&&&&&&&&&&&&&&& *&&&& &&&& &&&&&&&&&&&&&&&&&&&&&&&&&@@@@@
|
||||
@@@@&&&&&&&&&&&&&&&&&&&&&&& #& &&&&&&&&&&&&&&&&&&&&&&&&&&@@@@
|
||||
@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&. %&&&&&&&&&&&&&&&&&&&&&&&&&&@@
|
||||
@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &, &&&&&&&&&&&&&&&&&&&&&&@@
|
||||
@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&. &&&&&&&& &&&&&&&&&&&&&&&&&&&&&@
|
||||
@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&% &&&&&&&&&&&&&&&&&&&&&&
|
||||
@&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&
|
||||
@&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&
|
||||
&&&&&&&&&&&&&&&&&&&&&&&&&&&&& %&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
@&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
@&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&/ &&&&&&&&&&&&&&&&&&&&&&&
|
||||
@&&&&&&&&&&&&&&&&&&&&& &&& &&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&
|
||||
@@&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&@
|
||||
@@&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&@@
|
||||
@@@&&&&&&&&&&&&&&&&&&&&&&&&&& %&&&&&&&&&&&&&&&&&&&&&&&@@
|
||||
@@@@@&&&&&&&&&&&&&&&&&&&&&&& &&& &, &&&&&&&&&&&&&&&&&&&&&&&&&&@@@@
|
||||
@@@@@@&&&&&&&&&&&&&&&&&&&&& &&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@
|
||||
@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@
|
||||
@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@
|
||||
@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@\033[0;37;40m
|
||||
""")
|
||||
1425
pybitblock/SPV/nodeconnection.py
Normal file
1425
pybitblock/SPV/nodeconnection.py
Normal file
File diff suppressed because it is too large
Load diff
69
pybitblock/SPV/pblogo.py
Normal file
69
pybitblock/SPV/pblogo.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
|
||||
import os
|
||||
import pickle
|
||||
from cfonts import render, say
|
||||
|
||||
def blogo():
|
||||
|
||||
if os.path.isfile('config/pyblocksettinconfig/gs.conf') or os.path.isfile('config/pyblocksettings.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
settingsv = pickle.load(open("config/pyblocksettings.conf", "rb")) # Load the file 'bclock.conf'
|
||||
settings = settingsv # Copy the variable pathv to 'path'
|
||||
else:
|
||||
settings = {"gradient":"", "design":"block", "colorA":"green", "colorB":"yellow"}
|
||||
pickle.dump(settings, open("config/pyblocksettings.conf", "wb"))
|
||||
|
||||
if settings["gradient"] == "grd":
|
||||
output = render('PyBLOCK', gradient=[settings['colorA'], settings['colorB']], align='left', font=settings['design'])
|
||||
else:
|
||||
output = render('PyBLOCK', colors=[settings['colorA'], settings['colorB']], align='left', font=settings['design'])
|
||||
|
||||
print(output)
|
||||
|
||||
def tick():
|
||||
print("""\033[1;32;40m
|
||||
|
||||
|
||||
|
||||
|
||||
@
|
||||
@
|
||||
@
|
||||
@@
|
||||
@@
|
||||
@@@
|
||||
@@@ @@.
|
||||
@@@@@@@
|
||||
@@@@@@@@
|
||||
@@@@
|
||||
@@@@
|
||||
@ @@@@
|
||||
@@@@@@@@
|
||||
@@@@@@@@
|
||||
@@@
|
||||
@@@
|
||||
@@
|
||||
@@
|
||||
@
|
||||
@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
\033[0;37;40m""")
|
||||
|
||||
def canceled():
|
||||
print("""
|
||||
) ( (
|
||||
( ( ( /( ( )\ ) )\ )
|
||||
)\ )\ )\()) )\ ( (()/( ( (()/(
|
||||
(((_)((((_)( ((_)\ (((_) )\ /(_)) )\ /(_))
|
||||
)\___ )\ _ )\ _((_) )\___ ((_) (_)) ((_)(_))_
|
||||
((/ __|(_)_\(_)| \| |((/ __|| __|| | | __|| \
|
||||
| (__ / _ \ | .` | | (__ | _| | |__ | _| | |) |
|
||||
\___|/_/ \_\ |_|\_| \___||___||____||___||___/
|
||||
|
||||
""")
|
||||
2180
pybitblock/SPV/ppi.py
Normal file
2180
pybitblock/SPV/ppi.py
Normal file
File diff suppressed because it is too large
Load diff
256
pybitblock/SPV/rebalance.py
Normal file
256
pybitblock/SPV/rebalance.py
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import math
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
from lnd import Lnd
|
||||
from logic import Logic
|
||||
|
||||
MAX_CHANNEL_CAPACITY = 16777215
|
||||
MAX_SATOSHIS_PER_TRANSACTION = 4294967
|
||||
|
||||
|
||||
def main():
|
||||
argument_parser = get_argument_parser()
|
||||
arguments = argument_parser.parse_args()
|
||||
lnd = Lnd(arguments.lnddir, arguments.grpc)
|
||||
first_hop_channel_id = vars(arguments)['from']
|
||||
to_channel = arguments.to
|
||||
|
||||
if arguments.ratio < 1 or arguments.ratio > 50:
|
||||
print("--ratio must be between 1 and 50")
|
||||
sys.exit(1)
|
||||
channel_ratio = float(arguments.ratio) / 100
|
||||
|
||||
if arguments.incoming is not None and not arguments.list_candidates:
|
||||
print("--outgoing and --incoming only work in conjunction with --list-candidates")
|
||||
sys.exit(1)
|
||||
|
||||
if arguments.list_candidates:
|
||||
incoming = arguments.incoming is None or arguments.incoming
|
||||
if incoming:
|
||||
list_incoming_candidates(lnd, channel_ratio)
|
||||
else:
|
||||
list_outgoing_candidates(lnd, channel_ratio)
|
||||
sys.exit(0)
|
||||
|
||||
if to_channel is None and first_hop_channel_id is None:
|
||||
argument_parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
percentage = arguments.percentage
|
||||
if percentage:
|
||||
if percentage < 1 or percentage > 100:
|
||||
print("--percentage must be between 1 and 100")
|
||||
argument_parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
# the 'to' argument might be an index, or a channel ID
|
||||
if to_channel and to_channel < 10000:
|
||||
# here we are in the "channel index" case
|
||||
index = int(to_channel) - 1
|
||||
candidates = get_incoming_rebalance_candidates(lnd, channel_ratio)
|
||||
candidate = candidates[index]
|
||||
last_hop_channel = candidate
|
||||
else:
|
||||
# else the channel argument should be the channel ID
|
||||
last_hop_channel = get_channel_for_channel_id(lnd, to_channel)
|
||||
|
||||
first_hop_channel = get_channel_for_channel_id(lnd, first_hop_channel_id)
|
||||
|
||||
amount = get_amount(arguments, first_hop_channel, last_hop_channel)
|
||||
|
||||
if amount == 0:
|
||||
print("Amount is 0, nothing to do")
|
||||
sys.exit(0)
|
||||
|
||||
max_fee_factor = arguments.max_fee_factor
|
||||
excluded = arguments.exclude
|
||||
return Logic(lnd, first_hop_channel, last_hop_channel, amount, channel_ratio, excluded,
|
||||
max_fee_factor).rebalance()
|
||||
|
||||
|
||||
def get_amount(arguments, first_hop_channel, last_hop_channel):
|
||||
if last_hop_channel:
|
||||
amount = get_rebalance_amount(last_hop_channel)
|
||||
else:
|
||||
amount = get_rebalance_amount(first_hop_channel)
|
||||
|
||||
if arguments.percentage:
|
||||
amount = int(round(amount * arguments.percentage / 100))
|
||||
|
||||
if last_hop_channel and first_hop_channel:
|
||||
rebalance_amount_from_channel = get_rebalance_amount(first_hop_channel)
|
||||
amount = min(amount, rebalance_amount_from_channel)
|
||||
|
||||
if arguments.amount:
|
||||
amount = min(amount, int(arguments.amount))
|
||||
|
||||
amount = min(amount, MAX_SATOSHIS_PER_TRANSACTION)
|
||||
|
||||
return amount
|
||||
|
||||
|
||||
def get_channel_for_channel_id(lnd, channel_id):
|
||||
for channel in lnd.get_channels():
|
||||
if channel.chan_id == channel_id:
|
||||
return channel
|
||||
return None
|
||||
|
||||
|
||||
def get_argument_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--lnddir",
|
||||
default="~/.lnd",
|
||||
dest="lnddir",
|
||||
help="(default ~/.lnd) lnd directory")
|
||||
parser.add_argument("--grpc",
|
||||
default="localhost:10009",
|
||||
dest="grpc",
|
||||
help="(default localhost:10009) lnd gRPC endpoint")
|
||||
parser.add_argument("-r", "--ratio",
|
||||
type=int,
|
||||
default=50,
|
||||
help="(default: 50) ratio for channel imbalance between 1 and 50, "
|
||||
"eg. 45 to only show channels (-l) with less than 45%% of the "
|
||||
"funds on the local (-i) or remote (-o) side")
|
||||
list_group = parser.add_argument_group("list candidates", "Show the unbalanced channels.")
|
||||
list_group.add_argument("-l", "--list-candidates", action="store_true",
|
||||
help="list candidate channels for rebalance")
|
||||
|
||||
direction_group = list_group.add_mutually_exclusive_group()
|
||||
direction_group.add_argument("-o", "--outgoing",
|
||||
action="store_const",
|
||||
const=False,
|
||||
dest="incoming",
|
||||
help="lists channels with less than x%% of the funds on the remote side (see --ratio)")
|
||||
direction_group.add_argument("-i", "--incoming",
|
||||
action="store_const",
|
||||
const=True,
|
||||
dest="incoming",
|
||||
help="(default) lists channels with less than x%% of the funds on the local side "
|
||||
"(see --ratio)")
|
||||
|
||||
rebalance_group = parser.add_argument_group("rebalance",
|
||||
"Rebalance a channel. You need to specify at least"
|
||||
" the 'from' channel (-f) or the 'to' channel (-t).")
|
||||
rebalance_group.add_argument("-f", "--from",
|
||||
metavar="CHANNEL",
|
||||
type=int,
|
||||
help="channel ID of the outgoing channel "
|
||||
"(funds will be taken from this channel)")
|
||||
rebalance_group.add_argument("-t", "--to",
|
||||
metavar="CHANNEL",
|
||||
type=int,
|
||||
help="channel ID of the incoming channel "
|
||||
"(funds will be sent to this channel). "
|
||||
"You may also use the index as shown in the incoming candidate list (-l -i).")
|
||||
amount_group = rebalance_group.add_mutually_exclusive_group()
|
||||
amount_group.add_argument("-a", "--amount",
|
||||
type=int,
|
||||
help="Amount of the rebalance, in satoshis. If not specified, "
|
||||
"the amount computed for a perfect rebalance will be used"
|
||||
" (up to the maximum of 4,294,967 satoshis)")
|
||||
amount_group.add_argument("-p", "--percentage",
|
||||
type=int,
|
||||
help="Set the amount to send to a percentage of the amount required to rebalance. "
|
||||
"As an example, if this is set to 50, the amount will half of the default. "
|
||||
"See --amount.")
|
||||
rebalance_group.add_argument("-e", "--exclude",
|
||||
type=int,
|
||||
action="append",
|
||||
help="Exclude the given channel ID as the outgoing channel (no funds will be taken "
|
||||
"out of excluded channels)")
|
||||
rebalance_group.add_argument("--max-fee-factor",
|
||||
type=float,
|
||||
default=10,
|
||||
help="(default: 10) Reject routes that cost more than x times the lnd default "
|
||||
"(base: 1 sat, rate: 1 millionth sat) per hop on average")
|
||||
return parser
|
||||
|
||||
|
||||
def list_incoming_candidates(lnd, channel_ratio):
|
||||
candidates = get_incoming_rebalance_candidates(lnd, channel_ratio)
|
||||
list_candidates(candidates)
|
||||
|
||||
|
||||
def list_outgoing_candidates(lnd, channel_ratio):
|
||||
candidates = get_outgoing_rebalance_candidates(lnd, channel_ratio)
|
||||
list_candidates(candidates)
|
||||
|
||||
|
||||
def list_candidates(candidates):
|
||||
index = 0
|
||||
for candidate in candidates:
|
||||
index += 1
|
||||
rebalance_amount_int = get_rebalance_amount(candidate)
|
||||
rebalance_amount = "{:,}".format(rebalance_amount_int)
|
||||
if rebalance_amount_int > MAX_SATOSHIS_PER_TRANSACTION:
|
||||
rebalance_amount += " (max per transaction: {:,})".format(MAX_SATOSHIS_PER_TRANSACTION)
|
||||
|
||||
print("(%2d) Channel ID: " % index + str(candidate.chan_id))
|
||||
print("Pubkey: " + candidate.remote_pubkey)
|
||||
print("Local ratio: {:.3f}".format(get_local_ratio(candidate)))
|
||||
print("Capacity: {:,}".format(candidate.capacity))
|
||||
print("Remote balance: {:,}".format(candidate.remote_balance))
|
||||
print("Local balance: {:,}".format(candidate.local_balance))
|
||||
print("Amount for 50-50: " + rebalance_amount)
|
||||
print(get_capacity_and_ratio_bar(candidate))
|
||||
print("")
|
||||
|
||||
|
||||
def get_rebalance_amount(channel):
|
||||
return abs(int(math.ceil(float(get_remote_surplus(channel)) / 2)))
|
||||
|
||||
|
||||
def get_incoming_rebalance_candidates(lnd, channel_ratio):
|
||||
low_local = list(filter(lambda c: get_local_ratio(c) < channel_ratio, lnd.get_channels()))
|
||||
low_local = list(filter(lambda c: get_rebalance_amount(c) > 0, low_local))
|
||||
return sorted(low_local, key=get_remote_surplus, reverse=False)
|
||||
|
||||
|
||||
def get_outgoing_rebalance_candidates(lnd, channel_ratio):
|
||||
high_local = list(filter(lambda c: get_local_ratio(c) > 1 - channel_ratio, lnd.get_channels()))
|
||||
high_local = list(filter(lambda c: get_rebalance_amount(c) > 0, high_local))
|
||||
return sorted(high_local, key=get_remote_surplus, reverse=True)
|
||||
|
||||
|
||||
def get_local_ratio(channel):
|
||||
remote = channel.remote_balance
|
||||
local = channel.local_balance
|
||||
return float(local) / (remote + local)
|
||||
|
||||
|
||||
def get_remote_surplus(channel):
|
||||
return channel.remote_balance - channel.local_balance
|
||||
|
||||
|
||||
def get_capacity_and_ratio_bar(candidate):
|
||||
columns = get_columns()
|
||||
columns_scaled_to_capacity = int(round(columns * float(candidate.capacity) / MAX_CHANNEL_CAPACITY))
|
||||
|
||||
bar_width = columns_scaled_to_capacity - 2
|
||||
result = "|"
|
||||
ratio = get_local_ratio(candidate)
|
||||
length = int(round(ratio * bar_width))
|
||||
for x in range(0, length):
|
||||
result += "="
|
||||
for x in range(length, bar_width):
|
||||
result += " "
|
||||
return result + "|"
|
||||
|
||||
|
||||
def get_columns():
|
||||
if platform.system() == 'Linux' and sys.__stdin__.isatty():
|
||||
return int(os.popen('stty size', 'r').read().split()[1])
|
||||
else:
|
||||
return 80
|
||||
|
||||
|
||||
success = main()
|
||||
if success:
|
||||
sys.exit(0)
|
||||
sys.exit(1)
|
||||
115
pybitblock/SPV/routes.py
Normal file
115
pybitblock/SPV/routes.py
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import base64
|
||||
import sys
|
||||
|
||||
MAX_ROUTES_TO_REQUEST = 100
|
||||
|
||||
|
||||
def debug(message):
|
||||
sys.stderr.write(message + "\n")
|
||||
|
||||
|
||||
def debugnobreak(message):
|
||||
sys.stderr.write(message)
|
||||
|
||||
|
||||
class Routes:
|
||||
def __init__(self, lnd, payment_request, first_hop_channel, last_hop_channel):
|
||||
self.lnd = lnd
|
||||
self.payment_request = payment_request
|
||||
self.first_hop_channel = first_hop_channel
|
||||
self.last_hop_channel = last_hop_channel
|
||||
self.all_routes = []
|
||||
self.returned_routes = []
|
||||
self.ignored_edges = []
|
||||
self.ignored_nodes = []
|
||||
self.num_requested_routes = 0
|
||||
|
||||
def has_next(self):
|
||||
self.update_routes()
|
||||
return self.returned_routes < self.all_routes
|
||||
|
||||
def get_next(self):
|
||||
self.update_routes()
|
||||
for route in self.all_routes:
|
||||
if route not in self.returned_routes:
|
||||
self.returned_routes.append(route)
|
||||
return route
|
||||
return None
|
||||
|
||||
def update_routes(self):
|
||||
while True:
|
||||
if self.returned_routes < self.all_routes:
|
||||
return
|
||||
if self.num_requested_routes >= MAX_ROUTES_TO_REQUEST:
|
||||
return
|
||||
self.request_route()
|
||||
|
||||
def request_route(self):
|
||||
amount = self.get_amount()
|
||||
if self.last_hop_channel:
|
||||
last_hop_pubkey = self.last_hop_channel.remote_pubkey
|
||||
else:
|
||||
last_hop_pubkey = None
|
||||
if self.first_hop_channel:
|
||||
first_hop_channel_id = self.first_hop_channel.chan_id
|
||||
else:
|
||||
first_hop_channel_id = None
|
||||
routes = self.lnd.get_route(last_hop_pubkey, amount, self.ignored_edges,
|
||||
self.ignored_nodes, first_hop_channel_id)
|
||||
if routes is None:
|
||||
self.num_requested_routes = MAX_ROUTES_TO_REQUEST
|
||||
else:
|
||||
self.num_requested_routes += 1
|
||||
for route in routes:
|
||||
self.add_route(route)
|
||||
|
||||
def add_route(self, route):
|
||||
if route is None:
|
||||
return
|
||||
if route not in self.all_routes:
|
||||
self.all_routes.append(route)
|
||||
|
||||
@staticmethod
|
||||
def print_route(route):
|
||||
route_str = " -> ".join(str(h.chan_id) for h in route.hops)
|
||||
return route_str
|
||||
|
||||
def get_amount(self):
|
||||
return self.payment_request.num_satoshis
|
||||
|
||||
def ignore_first_hop(self, channel, show_message=True):
|
||||
own_key = self.lnd.get_own_pubkey()
|
||||
other_key = channel.remote_pubkey
|
||||
self.ignore_edge_from_to(channel.chan_id, own_key, other_key, show_message)
|
||||
|
||||
def ignore_edge_on_route(self, failure_source_pubkey, route):
|
||||
ignore_next = False
|
||||
for hop in route.hops:
|
||||
if ignore_next:
|
||||
self.ignore_edge_from_to(hop.chan_id, failure_source_pubkey, hop.pub_key)
|
||||
return
|
||||
if hop.pub_key == failure_source_pubkey:
|
||||
ignore_next = True
|
||||
|
||||
def ignore_node_with_highest_fee(self, route):
|
||||
max_fee_msat = 0
|
||||
max_fee_hop = None
|
||||
for hop in route.hops:
|
||||
if hop.fee_msat > max_fee_msat:
|
||||
max_fee_msat = hop.fee_msat
|
||||
max_fee_hop = hop
|
||||
|
||||
pub_key = max_fee_hop.pub_key
|
||||
debugnobreak("High fees (%s msat), " % max_fee_msat)
|
||||
self.ignore_node(pub_key)
|
||||
|
||||
def ignore_edge_from_to(self, chan_id, from_pubkey, to_pubkey, show_message=True):
|
||||
if show_message:
|
||||
debug("ignoring channel %s (from %s to %s)" % (chan_id, from_pubkey, to_pubkey))
|
||||
direction_reverse = from_pubkey > to_pubkey
|
||||
edge = {"channel_id": chan_id, "direction_reverse": direction_reverse}
|
||||
self.ignored_edges.append(edge)
|
||||
|
||||
def ignore_node(self, pub_key):
|
||||
debug("ignoring node %s" % pub_key)
|
||||
self.ignored_nodes.append(base64.b16decode(pub_key, True))
|
||||
27
pybitblock/SPV/sysinf.py
Normal file
27
pybitblock/SPV/sysinf.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
|
||||
import os
|
||||
import psutil
|
||||
import time as t
|
||||
from pblogo import *
|
||||
|
||||
|
||||
def clear(): # clear the screen
|
||||
os.system('cls' if os.name=='nt' else 'clear')
|
||||
|
||||
def sysinfoDetail(): #Cpu and memory usage
|
||||
# gives a single float value
|
||||
while True:
|
||||
try:
|
||||
clear()
|
||||
blogo()
|
||||
print(" \033[0;37;40m----------------------------")
|
||||
print(" \033[3;33;40mCPU Usage: \033[1;32;40m" + str(psutil.cpu_percent()) + "\033[0;37;40m%")
|
||||
print(" \033[3;33;40mMemory Usage: \033[1;32;40m" "{}\033[0;37;40m%".format(int(psutil.virtual_memory().percent)))
|
||||
print(" \033[3;33;40mMemory Available: \033[1;32;40m" "{} \033[0;37;40mMB".format(int(psutil.virtual_memory().available / 1024 / 1024)))
|
||||
print(" \033[3;33;40mDisk Usage: \033[1;32;40m" "{}%\033[0;37;40m%".format(psutil.disk_usage('/').percent))
|
||||
print(" \033[0;37;40m----------------------------")
|
||||
t.sleep(1)
|
||||
except:
|
||||
break
|
||||
Loading…
Add table
Add a link
Reference in a new issue