mirror of
https://github.com/stronk-dev/RewardCaller.git
synced 2025-07-05 13:55:10 +02:00
Rewrite
This commit is contained in:
parent
5b426dc22c
commit
bc2097709d
30
.gitignore
vendored
30
.gitignore
vendored
@ -1,30 +0,0 @@
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
# Support for Project snippet scope
|
||||
.vscode/*.code-snippets
|
||||
|
||||
# Ignore code-workspaces
|
||||
*.code-workspace
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
||||
{
|
||||
"python.formatting.provider": "autopep8"
|
||||
}
|
105
README.md
105
README.md
@ -1,88 +1,31 @@
|
||||
# better call reward
|
||||
## better call reward
|
||||
|
||||
#### Script to call `reward` for Livepeer orchestrator.
|
||||
This script uses a list of configured URL's Orchestrator CLI URL's to get info on the last reward call round and current Livepeer round
|
||||
Then compare these numbers and if they are not the same calls `reward`.
|
||||
|
||||
What this do?
|
||||
This script uses livepeer API to get info on the last reward call round and current round.
|
||||
Then compare these numbers and if they are not the same just call to `reward`.
|
||||
Script in default is checking numbers every 1h. You can change this value by editing `retryTimeReward`
|
||||
Modify the `ORCH_TARGETS` variable in `RewardCall.py` to set your Orchestrator URL's
|
||||
|
||||
My Orchestrator has many missing `reward` calls and this was the main motivation to create this script.
|
||||
### Dependencies
|
||||
|
||||
#### help:
|
||||
Requires python 3 and pip: `sudo pacman -S python python-pip`
|
||||
|
||||
Then install the requests library using pip `python -m pip install requests`
|
||||
|
||||
### Running the script
|
||||
|
||||
Recommended to run `better-call-reward.py` as a systemd service:
|
||||
Move the script to an accessible location, like `/usr/local/bin`
|
||||
`sudo nano /etc/systemd/system/rewardCaller.service`
|
||||
```
|
||||
usage: better-call-reward.py [-h] [-url [URL]] [-delay [DELAY]]
|
||||
[Unit]
|
||||
Description=Reward Caller
|
||||
After=multi-user.target
|
||||
|
||||
Optional app description
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-url [URL] URL for your Orchestrator
|
||||
```
|
||||
|
||||
|
||||
#### example usage:
|
||||
`./better-call-reward.py -url http://localhost:7935`
|
||||
|
||||
`./better-call-reward.py ` - this use default url `http://localhost:7935`
|
||||
|
||||
#### script output on succes:
|
||||
```
|
||||
Orchestrator URL: http://192.168.137.103:7935
|
||||
Connection success
|
||||
---Info---
|
||||
Orchestrator Version: 0.5.31-ec920c67
|
||||
GolangRuntimeVersion: go1.18.1
|
||||
|
||||
Transcoders:
|
||||
[1] Address: 127.0.0.1:54396 Capacity:14
|
||||
|
||||
[ 2022-06-02 10:40:36.105142 ] Orchestrator status: online
|
||||
[ 2022-06-02 10:40:36.105176 ] Last reward round: 2584
|
||||
[ 2022-06-02 10:40:36.105190 ] Current round: 2585
|
||||
[ 2022-06-02 10:40:36.105195 ] Call to reward!
|
||||
[ 2022-06-02 10:42:32.865710 ] <Response [200]>
|
||||
[ 2022-06-02 10:42:32.865755 ] Call reward success.
|
||||
. Next call: 3534s
|
||||
```
|
||||
|
||||
#### example output from O:
|
||||
```
|
||||
I0602 10:40:35.750595 417331 handlers.go:845] Calling reward
|
||||
2022/06/02 10:41:30 http: TLS handshake error from 208.115.199.25:41434: EOF
|
||||
I0602 10:42:31.336083 417331 transactionManager.go:119]
|
||||
******************************Eth Transaction******************************
|
||||
|
||||
Invoking transaction: "rewardWithHint". Inputs: "_newPosPrev: 0x86c5A8231712CC8aaa23409B5ad315f304C09531 _newPosNext: 0x22Ae24C2D1f489906266609d14c4C0387909A38a" Hash: "0x410696c59c24527e9c34323be46470f96694cc870982d674ea1b222ae25c59b5".
|
||||
|
||||
***************************************************************************
|
||||
I0602 10:42:32.508922 417331 handlers.go:855] Call to reward successful
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### some error:
|
||||
```
|
||||
Orchestrator URL: http://192.168.137.103:7935
|
||||
Connection success
|
||||
---Info---
|
||||
Orchestrator Version: 0.5.31-ec920c67
|
||||
GolangRuntimeVersion: go1.18.1
|
||||
|
||||
Transcoders:
|
||||
[1] Address: 127.0.0.1:54396 Capacity:14
|
||||
|
||||
[ 2022-06-02 10:33:26.291112 ] Orchestrator status: online
|
||||
[ 2022-06-02 10:33:26.291156 ] Last reward round: 2584
|
||||
[ 2022-06-02 10:33:26.291175 ] Current round: 2585
|
||||
[ 2022-06-02 10:33:26.291189 ] Call to reward!
|
||||
[ 2022-06-02 10:33:26.292445 ] <Response [404]>
|
||||
[ 2022-06-02 10:33:26.292469 ] Call to reward fail. Error: <Response [404]>
|
||||
```
|
||||
|
||||
Buy me a coffee: <br />
|
||||
LPT (Arbitrum): `0xE32971e1a55152A94Fa55DFb80ACdC4bA55679C3` <br />
|
||||
AETH (Arbitrum): `0xE32971e1a55152A94Fa55DFb80ACdC4bA55679C3` <br />
|
||||
ETH: `0xE32971e1a55152A94Fa55DFb80ACdC4bA55679C3` <br />
|
||||
DOGE: `D8mJBFdSQscQKce2vnPsKr4dC4sFvypBfU` <br />
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/python3 /usr/local/bin/RewardCall.py
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
104
RewardCall.py
Executable file
104
RewardCall.py
Executable file
@ -0,0 +1,104 @@
|
||||
#!/bin/python3
|
||||
import requests
|
||||
import time
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
# EDIT THIS to set your O cliAddr targets which this script should call reward on
|
||||
ORCH_TARGETS = ['http://127.0.0.1:7935']
|
||||
|
||||
|
||||
# Global Constants
|
||||
sleepTimeActive = 60 # Wait time when there is any O which has to call reward this round
|
||||
sleepTimeIdle = 60 * 60 * 4 # Wait time between round checks
|
||||
|
||||
# Logs `info` to the terminal with an attached datetime
|
||||
def log(info):
|
||||
print("[", datetime.now(), "] - ", info)
|
||||
sys.stdout.flush()
|
||||
|
||||
# Gets the last round the orch called reward
|
||||
def getLastRewardRound(url):
|
||||
try:
|
||||
r = requests.get(url + '/orchestratorInfo')
|
||||
except requests.exceptions.RequestException as e:
|
||||
return 0
|
||||
if r.status_code != 200:
|
||||
return 0
|
||||
return r.json()['Transcoder']['LastRewardRound']
|
||||
|
||||
# Return the current active Livepeer round
|
||||
def getCurrentRound(url):
|
||||
try:
|
||||
r = requests.get(url + '/currentRound')
|
||||
except requests.exceptions.RequestException as e:
|
||||
return 0
|
||||
if r.status_code != 200:
|
||||
return 0
|
||||
return int(r.content.hex(), 16)
|
||||
|
||||
class Orchestrator:
|
||||
def __init__(self, uri):
|
||||
self.uri = uri
|
||||
self.rewardRound = 0
|
||||
self.currentRound = 0
|
||||
self.hasReward = False
|
||||
|
||||
latestRound = 0
|
||||
orchestrators = []
|
||||
# Init orch objecs
|
||||
for url in ORCH_TARGETS:
|
||||
log("Adding Orchestrator with URL '" + url + "'")
|
||||
orchestrators.append(Orchestrator(url))
|
||||
# Main loop
|
||||
while True:
|
||||
# Init delay to a long sleep time. Override later if an O requires reward calling
|
||||
delay = sleepTimeIdle
|
||||
for i in range(len(orchestrators)):
|
||||
# Update last round if we have a new one
|
||||
currentRound = getCurrentRound(orchestrators[i].uri)
|
||||
if currentRound == 0:
|
||||
log("Error: can't get current round info on '" + url + "'")
|
||||
orchestrators[i].hasReward = False
|
||||
delay = sleepTimeActive
|
||||
continue
|
||||
if currentRound > latestRound:
|
||||
latestRound = currentRound
|
||||
# Reset hasReward flags for all O's since the latest round has changed
|
||||
for j in range(len(orchestrators)):
|
||||
orchestrators[j].hasReward = False
|
||||
# If we are behind in rounds, notify user
|
||||
if currentRound < latestRound:
|
||||
log("Orchestrator '" + orchestrators[i].uri + "' is behind in block syncing!")
|
||||
# We can continue now if the latest round has not changed
|
||||
if orchestrators[i].hasReward:
|
||||
log("Skipping Orchestrator '" + orchestrators[i].uri + "' since they have called reward this round")
|
||||
continue
|
||||
# Check the last reward round
|
||||
lastRewardRound = getLastRewardRound(orchestrators[i].uri)
|
||||
if lastRewardRound == 0:
|
||||
log("Error: can't get last reward round info on '" + url + "'")
|
||||
orchestrators[i].hasReward = False
|
||||
delay = sleepTimeActive
|
||||
continue
|
||||
log("Latest reward round for Orchestrator '" + orchestrators[i].uri + "' is " + str(lastRewardRound) + " and the latest livepeer round is " + str(latestRound))
|
||||
if lastRewardRound < latestRound:
|
||||
log("Calling reward for '" + orchestrators[i].uri + "'")
|
||||
r = requests.get(orchestrators[i].uri + '/reward')
|
||||
log(r)
|
||||
if r.status_code == 200:
|
||||
log('Call to reward success.')
|
||||
orchestrators[i].hasReward = True
|
||||
else:
|
||||
log('Call to reward fail. Error: ' + str(r))
|
||||
orchestrators[i].hasReward = False
|
||||
delay = sleepTimeActive
|
||||
else:
|
||||
orchestrators[i].hasReward = True
|
||||
log("Orchestrator '" + orchestrators[i].uri + "' has already called reward in round " + str(latestRound))
|
||||
# Sleep a long or short time based on whether all Orchestrators have been handled
|
||||
while delay > 0:
|
||||
log("Next check in " + str(delay) + " seconds...")
|
||||
delay = delay - 30
|
||||
time.sleep(30)
|
@ -1,144 +0,0 @@
|
||||
#!/bin/python3
|
||||
from asyncio import constants
|
||||
from pyclbr import Function
|
||||
import requests
|
||||
import time
|
||||
import sys
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
# set your Orchestrator url
|
||||
URL_DEFAULT = 'http://localhost:7935' # default
|
||||
|
||||
retryTimeOffline = 60 # delay when O is offline, in seconds
|
||||
retryTimeReward = 60 * 60 # time retry call "reward ", in seconds
|
||||
|
||||
|
||||
def parseArgs():
|
||||
# Instantiate the parser
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Script to resolve problem with livepeer "reward" call. ')
|
||||
parser.add_argument('-url', type=str, nargs='?',
|
||||
help='URL for your Orchestrator')
|
||||
# todo: ? add delay params
|
||||
# parser.add_argument('-delay', type=int, nargs='?',
|
||||
# help='delay between next try of call "reward"')
|
||||
# Parse the argument
|
||||
args = parser.parse_args()
|
||||
if args.url is None:
|
||||
url = URL_DEFAULT
|
||||
else:
|
||||
url = args.url
|
||||
print("Orchestrator URL: " + url)
|
||||
return url
|
||||
# end parseArgs()
|
||||
|
||||
|
||||
def statusOrch(url): # /status , check O status and get some info
|
||||
try:
|
||||
r = requests.get(url + '/status')
|
||||
responseStatus = r.status_code
|
||||
except requests.exceptions.RequestException as e: # This is the correct syntax
|
||||
print("Error during connection to '" + url +
|
||||
"'. Please check your Orchestrator url.")
|
||||
exit(0)
|
||||
print("Connection success")
|
||||
print("---Info---")
|
||||
print("Orchestrator Version: " + r.json()['Version'])
|
||||
print("GolangRuntimeVersion: " + r.json()['GolangRuntimeVersion'])
|
||||
print("")
|
||||
|
||||
# transcoders info
|
||||
print("Transcoders:")
|
||||
i = 1
|
||||
for t in r.json()['RegisteredTranscoders']:
|
||||
print("["+str(i) + "] Address: " + t['Address'] +
|
||||
" Capacity:" + str(t['Capacity']))
|
||||
# end statusOrch(url) ----------------------------------------------
|
||||
|
||||
|
||||
def pingOrch(url): # /status
|
||||
try:
|
||||
requests.get(url + '/status')
|
||||
except requests.exceptions.RequestException as e: # This is the correct syntax
|
||||
print("Error during connection to '" + url +
|
||||
"'. Please check your Orchestrator url.")
|
||||
return False
|
||||
return True
|
||||
# end pingOrch() ----------------------------------------------
|
||||
|
||||
|
||||
def getLastRewardRound(url): # /orchestratorInfo
|
||||
try:
|
||||
r = requests.get(url + '/orchestratorInfo')
|
||||
except requests.exceptions.RequestException as e: # This is the correct syntax
|
||||
print("Error: can't get 'Last Reward Round' round info.")
|
||||
return -1
|
||||
|
||||
if r.status_code != 200:
|
||||
print("Can not get last reward round info. Error: " + str(r))
|
||||
return -2
|
||||
return r.json()['Transcoder']['LastRewardRound']
|
||||
# end getLastRewardRound() ----------------------------------------------
|
||||
|
||||
|
||||
def getCurrentRound(url): # /currentRound
|
||||
# get current Round value
|
||||
try:
|
||||
r = requests.get(url + '/currentRound')
|
||||
except requests.exceptions.RequestException as e: # This is the correct syntax
|
||||
print("Error: can't get 'current Round' info.")
|
||||
return -1
|
||||
|
||||
if r.status_code != 200:
|
||||
print("Error: can't get 'current Round' info."+" ERROR: " + str(r))
|
||||
return -2
|
||||
|
||||
currentRound = int(r.content.hex(), 16)
|
||||
return currentRound
|
||||
# end getLastRewardRound() ----------------------------------------------
|
||||
|
||||
|
||||
def log(info):
|
||||
print("[", datetime.now(), "]", info)
|
||||
# end log(info) ----------------------------------------------
|
||||
|
||||
|
||||
url = parseArgs()
|
||||
statusOrch(url)
|
||||
print("")
|
||||
|
||||
while True:
|
||||
lastRewardRound = getLastRewardRound(url)
|
||||
currentRound = getCurrentRound(url)
|
||||
|
||||
log('Orchestrator status: ' + ('online' if pingOrch(url) else 'offline'))
|
||||
if (currentRound < 0 or lastRewardRound < 0):
|
||||
log("Is Orchestrator online ?")
|
||||
delay = retryTimeOffline
|
||||
else:
|
||||
log('Last reward round: ' + str(lastRewardRound))
|
||||
log('Current round: ' + str(currentRound))
|
||||
|
||||
if currentRound != lastRewardRound:
|
||||
log('Call reward!')
|
||||
r = requests.get(url + '/reward') # call reward
|
||||
log(r)
|
||||
if r.status_code == 200:
|
||||
log('Call to reward success.')
|
||||
else:
|
||||
log('Call to reward fail. Error: ' + str(r))
|
||||
|
||||
else:
|
||||
log('Do not call reward. ' + 'Reward for current round ' +
|
||||
str(currentRound) + ' already called.')
|
||||
delay = retryTimeReward
|
||||
|
||||
while delay > 0:
|
||||
print(". Next call: " + str(delay) + "s " + "\r", end="")
|
||||
sys.stdout.flush()
|
||||
delay = delay - 1
|
||||
time.sleep(1)
|
||||
print(" ")
|
||||
sys.stdout.flush()
|
||||
print("----------------------------")
|
Loading…
x
Reference in New Issue
Block a user