Skip to content

Commit

Permalink
update merge to master from upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
jagdeep sidhu committed Apr 19, 2021
1 parent ef8435a commit b124f65
Show file tree
Hide file tree
Showing 19 changed files with 117 additions and 313 deletions.
62 changes: 39 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,65 @@
# Syscoin Sentinel

An all-powerful toolset for Syscoin.

[![Build Status](https://travis-ci.org/syscoin/sentinel.svg?branch=master)](https://travis-ci.org/syscoin/sentinel)

Sentinel is an autonomous agent for persisting, processing and automating Syscoin governance objects and tasks, and for expanded functions in the upcoming Syscoin 3.0 release

Sentinel is implemented as a Python application that binds to a local version of syscoind instance on each Syscoin Masternode.
> An automated governance helper for Syscoin Masternodes.
This guide covers installing Sentinel onto an existing Masternode in Ubuntu 14.04 / 16.04.
Sentinel is an autonomous agent for persisting, processing and automating Syscoin governance objects and tasks. It is a Python application which runs alongside the Syscoin instance on each Syscoin Masternode.

## Installation
## Table of Contents
- [Install](#install)
- [Dependencies](#dependencies)
- [Usage](#usage)
- [Configuration](#configuration)
- [Troubleshooting](#troubleshooting)
- [Maintainer](#maintainer)
- [Contributing](#contributing)
- [License](#license)

### 1. Install Prerequisites
## Install

Make sure Python version 2.7.x or above is installed:
These instructions cover installing Sentinel on Ubuntu 18.04 / 20.04.

python --version
### Dependencies

Update system packages and ensure virtualenv is installed:
Update system package list and install dependencies:

$ sudo apt-get update
$ sudo apt-get -y install python-virtualenv
$ sudo apt-get -y install git python3 virtualenv

Make sure Python version 3.6.x or above is installed:

python3 --version

Make sure the local Syscoin daemon running is at least version 4.2.0.

$ syscoin-cli getinfo | grep version
$ syscoind --version | head -n1

### 2. Install Sentinel
### Install Sentinel

Clone the Sentinel repo and install Python dependencies.

$ git clone https://github.com/syscoin/sentinel.git && cd sentinel
$ virtualenv ./venv
$ virtualenv -p $(which python3) ./venv
$ ./venv/bin/pip install -r requirements.txt

### 3. Set up Cron
## Usage

Sentinel is "used" as a script called from cron every minute.

### Set up Cron

Set up a crontab entry to call Sentinel every minute:

$ crontab -e

In the crontab editor, add the lines below, replacing '/home/YOURUSERNAME/sentinel' to the path where you cloned sentinel to:
In the crontab editor, add the lines below, replacing '/path/to/sentinel' to the path where you cloned sentinel to:

*/2 * * * * cd /home/YOURUSERNAME/sentinel && ./venv/bin/python bin/sentinel.py >/dev/null 2>&1
* * * * * cd /path/to/sentinel && ./venv/bin/python bin/sentinel.py >/dev/null 2>&1

### 4. Test the Configuration
### Test Configuration

Test the config by runnings all tests from the sentinel folder you cloned into
Test the config by running tests:

$ ./venv/bin/py.test ./test

Expand All @@ -65,9 +77,13 @@ To view debug output, set the `SENTINEL_DEBUG` environment variable to anything

$ SENTINEL_DEBUG=1 ./venv/bin/python bin/sentinel.py

## Maintainer

[@sidhujag](https://github.com/sidhujag)

## Contributing

Please follow the [SyscoinCore guidelines for contributing](https://github.com/syscoin/syscoin/blob/master/CONTRIBUTING.md).
Please follow the [Syscoin guidelines for contributing](https://github.com/syscoin/syscoin/blob/master/CONTRIBUTING.md).

Specifically:

Expand All @@ -83,6 +99,6 @@ Specifically:

Commit messages should be verbose by default, consisting of a short subject line (50 chars max), a blank line and detailed explanatory text as separate paragraph(s); unless the title alone is self-explanatory (like "Corrected typo in main.cpp") then a single title line is sufficient. Commit messages should be helpful to people reading your code in the future, so explain the reasoning for your decisions. Further explanation [here](http://chris.beams.io/posts/git-commit/).

### License
## License

Released under the MIT license, under the same terms as SyscoinCore itself. See [LICENSE](LICENSE) for more info.
Released under the MIT license, under the same terms as Syscoin itself. See [LICENSE](LICENSE) for more info.
24 changes: 10 additions & 14 deletions bin/sentinel.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,6 @@ def prune_expired_proposals(syscoind):
proposal.vote(syscoind, VoteSignals.delete, VoteOutcomes.yes)


# ping syscoind
def sentinel_ping(syscoind):
printdbg("in sentinel_ping")

syscoind.ping()

printdbg("leaving sentinel_ping")


def attempt_superblock_creation(syscoind):
import syscoinlib

Expand Down Expand Up @@ -74,8 +65,7 @@ def attempt_superblock_creation(syscoind):
budget_max = syscoind.get_superblock_budget_allocation(event_block_height)
sb_epoch_time = syscoind.block_height_to_epoch(event_block_height)

maxgovobjdatasize = syscoind.govinfo['maxgovobjdatasize']
sb = syscoinlib.create_superblock(proposals, event_block_height, budget_max, sb_epoch_time, maxgovobjdatasize)
sb = syscoinlib.create_superblock(proposals, event_block_height, budget_max, sb_epoch_time)
if not sb:
printdbg("No superblock created, sorry. Returning.")
return
Expand Down Expand Up @@ -125,6 +115,11 @@ def main():
syscoind = SyscoinDaemon.from_syscoin_conf(config.syscoin_conf)
options = process_args()

# print version and return if "--version" is an argument
if options.version:
print("Syscoin Sentinel v%s" % config.sentinel_version)
return

# check syscoind connectivity
if not is_syscoind_port_open(syscoind):
print("Cannot connect to syscoind. Please ensure syscoind is running and the JSONRPC port is open to Sentinel.")
Expand Down Expand Up @@ -170,9 +165,6 @@ def main():
# load "gobject list" rpc command data, sync objects into internal database
perform_syscoind_object_sync(syscoind)

if syscoind.has_sentinel_ping:
sentinel_ping(syscoind)

# auto vote network objects as valid/invalid
# check_object_validity(syscoind)

Expand Down Expand Up @@ -202,6 +194,10 @@ def process_args():
action='store_true',
help='Bypass scheduler and sync/vote immediately',
dest='bypass')
parser.add_argument('-v', '--version',
action='store_true',
help='Print the version (Syscoin Sentinel vX.X.X) and exit')

args = parser.parse_args()

return args
Expand Down
3 changes: 1 addition & 2 deletions lib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
)
sentinel_config_file = os.environ.get('SENTINEL_CONFIG', default_sentinel_config)
sentinel_cfg = SyscoinConfig.tokenize(sentinel_config_file)
sentinel_version = 1000000
min_syscoind_proto_version_with_sentinel_ping = 70015
sentinel_version = "1.5.0"


def get_syscoin_conf():
Expand Down
7 changes: 1 addition & 6 deletions lib/governance_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ def vote_validity(self, syscoind):
self.vote(syscoind, models.VoteSignals.valid, models.VoteOutcomes.no)

def get_submit_command(self):
import syscoinlib
obj_data = syscoinlib.SHIM_serialise_for_syscoind(self.serialise())
obj_data = self.serialise()

# new objects won't have parent_hash, revision, etc...
cmd = ['gobject_submit', 0, 1, str(int(time.time())), obj_data]
Expand Down Expand Up @@ -66,10 +65,6 @@ def serialise(self):

return binascii.hexlify(simplejson.dumps(self.get_dict(), sort_keys=True).encode('utf-8')).decode('utf-8')

def syscoind_serialise(self):
import syscoinlib
return syscoinlib.SHIM_serialise_for_syscoind(self.serialise())

@classmethod
def serialisable_fields(self):
# Python is so not very elegant...
Expand Down
2 changes: 1 addition & 1 deletion lib/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def main():
sys.exit(1)

if not has_syscoin_conf():
print("SyscoinCore must be installed and configured, including JSONRPC access in syscoin.conf")
print("Syscoin must be installed and configured, including JSONRPC access in syscoin.conf")
sys.exit(1)


Expand Down
15 changes: 4 additions & 11 deletions lib/masternode.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@ def __init__(self, collateral, mnstring):
self.txid = txid
self.vout_index = int(vout_index)

(status, protocol, address, ip_port, lastseen, activeseconds, lastpaid) = self.parse_mn_string(mnstring)
(status, address, ip_port, lastpaid) = self.parse_mn_string(mnstring)
self.status = status
self.protocol = int(protocol)
self.address = address

# TODO: break this out... take ipv6 into account
self.ip_port = ip_port

self.lastseen = int(lastseen)
self.activeseconds = int(activeseconds)
self.lastpaid = int(lastpaid)

@classmethod
Expand All @@ -27,14 +24,10 @@ def parse_collateral_string(self, collateral):

@classmethod
def parse_mn_string(self, mn_full_out):
# trim whitespace
# mn_full_out = mn_full_out.strip()
(status, address, lastpaid, lastpaidblock, ip_port) = mn_full_out.split()

(status, protocol, address, lastseen, activeseconds, lastpaid,
lastpaidblock, ip_port, pingretries) = mn_full_out.split()

# status protocol pubkey IP lastseen activeseconds lastpaid
return (status, protocol, address, ip_port, lastseen, activeseconds, lastpaid)
# status protocol pubkey IP lastpaid
return (status, address, ip_port, lastpaid)

@property
def vin(self):
Expand Down
4 changes: 2 additions & 2 deletions lib/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def vote(self, syscoind, signal, outcome):
self.sync_network_vote(syscoind, signal)

def sync_network_vote(self, syscoind, signal):
printdbg('\tsyncing network vote for object %s with signal %s' % (self.object_hash, signal.name))
printdbg('\tSyncing network vote for object %s with signal %s' % (self.object_hash, signal.name))
vote_info = syscoind.get_my_gobject_votes(self.object_hash)
for vdikt in vote_info:
if vdikt['signal'] != signal.name:
Expand Down Expand Up @@ -698,7 +698,7 @@ def check_db_sane():
for model in db_models():
if not getattr(model, 'table_exists')():
missing_table_models.append(model)
printdbg("[warning]: table for %s (%s) doesn't exist in DB." % (model, model._meta.db_table))
printdbg("[warning]: Table for %s (%s) doesn't exist in DB." % (model, model._meta.db_table))

if missing_table_models:
printdbg("[warning]: Missing database tables. Auto-creating tables.")
Expand Down
2 changes: 1 addition & 1 deletion lib/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class Scheduler(object):
transient_key_scheduled = 'NEXT_SENTINEL_CHECK_AT'
random_interval_max = 300
random_interval_max = 1800

@classmethod
def is_run_time(self):
Expand Down
2 changes: 1 addition & 1 deletion lib/syscoin_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def slurp_config_file(self, filename):
f = io.open(filename)
lines = []
for line in f:
if re.match('^\s*#', line):
if re.match(r'^\s*#', line):
continue
lines.append(line)
f.close()
Expand Down
18 changes: 2 additions & 16 deletions lib/syscoind.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,7 @@ def is_masternode(self):
return not (self.get_current_masternode_vin() is None)

def is_synced(self):
mnsync_status = self.rpc_command('mnsync', 'status')
synced = (mnsync_status['IsBlockchainSynced'] and
mnsync_status['IsMasternodeListSynced'] and
mnsync_status['IsWinnersListSynced'] and
mnsync_status['IsSynced'] and
not mnsync_status['IsFailed'])
return synced
return self.rpc_command('mnsync', 'status')['IsSynced']

def current_block_hash(self):
height = self.rpc_command('getblockcount')
Expand Down Expand Up @@ -146,7 +140,7 @@ def get_my_gobject_votes(self, object_hash):
return self.gobject_votes[object_hash]

def is_govobj_maturity_phase(self):
# 3-day period for govobj maturity
# SYSCOIN 3-day period for govobj maturity
maturity_phase_delta = 4320 # ~(60*24*3)
if config.network == 'testnet':
maturity_phase_delta = 24 # testnet
Expand Down Expand Up @@ -216,11 +210,3 @@ def block_height_to_epoch(self, height):
raise e

return epoch

@property
def has_sentinel_ping(self):
getinfo = self.rpc_command('getnetworkinfo')
return (getinfo['protocolversion'] >= config.min_syscoind_proto_version_with_sentinel_ping)

def ping(self):
self.rpc_command('sentinelping', config.sentinel_version)
Loading

0 comments on commit b124f65

Please sign in to comment.