Skip to content

Commit

Permalink
Bot script (#37)
Browse files Browse the repository at this point in the history
* upgrade pallets for better logging
* bot script tested with 1000 locations and 10'000 participants
* bump version. minor version now matches runtime spec_version
  • Loading branch information
brenzi authored Oct 18, 2020
1 parent f17b6c5 commit 53a1708
Show file tree
Hide file tree
Showing 8 changed files with 1,011 additions and 644 deletions.
1,372 changes: 756 additions & 616 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 5 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,11 @@ members = [
]

#only while debugging
#[patch."https://github.com/encointer/pallet-encointer-ceremonies"]
#pallet-encointer-ceremonies = { path = "../pallet-encointer-ceremonies" }

#[patch."https://github.com/encointer/pallet-encointer-currencies"]
#pallet-encointer-currencies = { path = "../pallet-encointer-currencies" }

#[patch."https://github.com/encointer/pallet-encointer-balances"]
#pallet-encointer-balances = { path = "../pallet-encointer-balances" }

#[patch."https://github.com/encointer/pallet-encointer-scheduler"]
#pallet-encointer-scheduler = { path = "../pallet-encointer-scheduler" }
#[patch."https://github.com/encointer/pallets"]
#pallet-encointer-ceremonies = { path = "../encointer-pallets/ceremonies" }
#pallet-encointer-currencies = { path = "../encointer-pallets/currencies" }
#pallet-encointer-balances = { path = "../encointer-pallets/balances" }
#pallet-encointer-scheduler = { path = "../encointer-pallets/scheduler" }

#[patch."https://github.com/encointer/substrate-fixed"]
#substrate-fixed = { path = "../substrate-fixed" }
10 changes: 5 additions & 5 deletions client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "encointer-client-notee"
version = "0.3.3"
version = "0.3.5"
authors = ["encointer.org <alain@encointer.org>"]
edition = "2018"

Expand All @@ -22,25 +22,25 @@ base58 = "0.1"
[dependencies.encointer-scheduler]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-scheduler"

[dependencies.encointer-ceremonies]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-ceremonies"

[dependencies.encointer-currencies]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-currencies"

[dependencies.encointer-balances]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-balances"

[dependencies.fixed]
Expand Down
204 changes: 204 additions & 0 deletions client/bot-community.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#!/usr/bin/python3
import argparse
import subprocess
import geojson

from math import sqrt, ceil
from random_word import RandomWords
from pyproj import Geod
geoid = Geod(ellps='WGS84')

cli = ["../target/release/encointer-client-notee"]

NUMBER_OF_LOCATIONS = 10
MAX_POPULATION = 12 * NUMBER_OF_LOCATIONS

def move_point(point, az, dist):
""" move a point a certain distance [meters] into a direction (azimuth) in [degrees] """

lng_new, lat_new, return_az = geoid.fwd(point['coordinates'][0], point['coordinates'][1], az, dist)
return geojson.Point([lng_new, lat_new])

def populate_locations(northwest, n, dist=1000):
""" populate approximately n locations on a square grid of a specified distance in meters """
row = [ northwest ]
for li in range(1, round(sqrt(n))):
row.append(move_point(row[-1], 90, dist))
locations = []
for pnt in row:
col = [ pnt ]
for li in range(1, round(sqrt(n))):
col.append(move_point(col[-1], 180, dist))
locations += col
return locations

def next_phase():
subprocess.run(cli + ["next-phase"])

def get_phase():
ret = subprocess.run(cli + ["get-phase"], stdout=subprocess.PIPE)
return ret.stdout.strip().decode("utf-8")

def list_accounts():
ret = subprocess.run(cli + ["list-accounts"], stdout=subprocess.PIPE)
return ret.stdout.decode("utf-8").splitlines()

def new_account():
ret = subprocess.run(cli + ["new-account"], stdout=subprocess.PIPE)
return ret.stdout.decode("utf-8").strip()

def faucet(accounts):
subprocess.run(cli + ["faucet"] + accounts, stdout=subprocess.PIPE)

def balance(accounts, **kwargs):
bal = []
cid_arg = []
if 'cid' in kwargs:
cid_arg = ["--cid", kwargs.get('cid')]
for account in accounts:
ret = subprocess.run(cli + cid_arg + ["balance", account], stdout=subprocess.PIPE)
bal.append(float(ret.stdout.strip().decode("utf-8").split(' ')[-1]))
return bal

def new_currency(specfile):
ret = subprocess.run(cli + ["new-currency", specfile, '//Alice'], stdout=subprocess.PIPE)
return ret.stdout.decode("utf-8").strip()

def await_block():
subprocess.run(cli + ["listen", "-b", "1"], stdout=subprocess.PIPE)

def register_participant(account, cid):
ret = subprocess.run(cli + ["--cid", cid, "register-participant", account], stdout=subprocess.PIPE)
#print(ret.stdout.decode("utf-8"))

def new_claim(account, vote, cid):
ret = subprocess.run(cli + ["--cid", cid, "new-claim", account, str(vote)], stdout=subprocess.PIPE)
return ret.stdout.decode("utf-8").strip()

def sign_claim(account, claim):
ret = subprocess.run(cli + ["sign-claim", account, claim], stdout=subprocess.PIPE)
return ret.stdout.decode("utf-8").strip()

def list_meetups(cid):
ret = subprocess.run(cli + ["--cid", cid, "list-meetups"], stdout=subprocess.PIPE)
#print(ret.stdout.decode("utf-8"))
meetups = []
lines = ret.stdout.decode("utf-8").splitlines()
while len(lines) > 0:
if 'participants are:' in lines.pop(0):
participants = []
while len(lines) > 0:
l = lines.pop(0)
if 'MeetupRegistry' in l:
break
participants.append(l.strip())
meetups.append(participants)
return meetups

def register_attestations(account, attestations):
ret = subprocess.run(cli + ["register-attestations", account] + attestations, stdout=subprocess.PIPE)
#print(ret.stdout.decode("utf-8"))


def generate_currency_spec(name, locations, bootstrappers):
gj = geojson.FeatureCollection(list(map(lambda x : geojson.Feature(geometry=x), locations)))
gj['currency_meta'] = { 'name': name, 'bootstrappers': bootstrappers }
fname = name + '.json'
with open(fname, 'w') as outfile:
geojson.dump(gj, outfile)
return fname

def random_currency_spec(nloc):
point = geojson.utils.generate_random("Point", boundingBox=[-56, 41, -21, 13])
locations = populate_locations(point, NUMBER_OF_LOCATIONS)
print("created " + str(len(locations)) + " random locations around " + str(point))
bootstrappers = []
for bi in range(0,10):
bootstrappers.append(new_account())
print('new bootstrappers:' + ' '.join(bootstrappers))
faucet(bootstrappers)
await_block()
name = 'currencyspec-' + '-'.join(RandomWords().get_random_words(limit=3))
return generate_currency_spec(name, locations, bootstrappers)

def init():
print("initializing community")
specfile = random_currency_spec(16)
print("generated currency spec: ", specfile)
cid = new_currency(specfile)
print("created community with cid: ", cid)
f = open("cid.txt", "w")
f.write(cid)
f.close()

def run():
f = open("cid.txt", "r")
cid = f.read()
print("cid is " + cid)
phase = get_phase()
print("phase is " + phase)
accounts = list_accounts()
print("number of known accounts: " + str(len(accounts)))
if phase == 'REGISTERING':
bal = balance(accounts, cid=cid)
total = sum(bal)
print("****** money supply is " + str(total))
f = open("bot-stats.csv", "a")
f.write(str(len(accounts)) + ", " + str(total) + "\n")
f.close()
if total > 0:
n_newbies = min(ceil(len(accounts) / 4.0), MAX_POPULATION - len(accounts))
print("*** adding " + str(n_newbies) + " newbies")
if n_newbies > 0:
newbies = []
for n in range(0,n_newbies):
newbies.append(new_account())
faucet(newbies)
await_block()
accounts = list_accounts()

print("registering " + str(len(accounts)) + " participants")
for p in accounts:
#print("registering " + p)
register_participant(p, cid)
await_block()
if phase == 'ATTESTING':
meetups = list_meetups(cid)
print("****** Performing " + str(len(meetups)) + " meetups")
for meetup in meetups:
n = len(meetup)
print("Performing meetup with " + str(n) + " participants")
claims = {}
for p in meetup:
claims[p] = new_claim(p, n, cid)
for claimant in meetup:
attestations = []
for attester in meetup:
if claimant == attester:
continue
#print(claimant + " is attested by " + attester)
attestations.append(sign_claim(attester, claims[claimant]))
#print("registering attestations for " + claimant)
register_attestations(claimant, attestations)
await_block()

def benchmark():
print("will grow population forever")
while True:
run()
await_block
next_phase()
await_block

if __name__ == '__main__':
parser = argparse.ArgumentParser(prog='bot-community')
subparsers = parser.add_subparsers(dest='subparser', help='sub-command help')
parser_a = subparsers.add_parser('init', help='a help')
parser_b = subparsers.add_parser('run', help='b help')
parser_c = subparsers.add_parser('benchmark', help='b help')

kwargs = vars(parser.parse_args())
try:
globals()[kwargs.pop('subparser')](**kwargs)
except KeyError:
parser.print_help()
11 changes: 7 additions & 4 deletions client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use std::str::FromStr;

type AccountPublic = <Signature as Verify>::Signer;
const KEYSTORE_PATH: &str = "my_keystore";
const PREFUNDING_AMOUNT: u128 = 1_000_000_000;
const PREFUNDING_AMOUNT: u128 = 100_000_000_000;
const VERSION: &str = env!("CARGO_PKG_VERSION");

fn main() {
Expand Down Expand Up @@ -1071,9 +1071,12 @@ fn get_meetup_time(api: &Api<sr25519::Pair>, cid: CurrencyIdentifier, mindex: Me
},
CeremonyPhaseType::REGISTERING => panic!("ceremony phase must be ASSIGNING or ATTESTING to request meetup location.")
};

Some(attesting_start + ONE_DAY/2
- (mlon * (ONE_DAY as f64) / 360.0) as Moment )
let mtime = (
(attesting_start + ONE_DAY/2) as i64
- (mlon * (ONE_DAY as f64) / 360.0) as i64
) as Moment;
debug!("meetup time at lon {}: {:?}", mlon, mtime);
Some(mtime)
}

fn prove_attendance(
Expand Down
2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ homepage = 'https://encointer.org'
license = "GPL-3.0"
name = 'encointer-node-notee'
repository = 'https://github.com/encointer/encointer-node'
version = '0.3.3'
version = '0.3.5'

[[bin]]
name = 'encointer-node-notee'
Expand Down
11 changes: 6 additions & 5 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,31 @@ homepage = 'https://encointer.org'
license = "GPL-3.0"
name = 'encointer-node-notee-runtime'
repository = 'https://github.com/encointer/encointer-node/'
version = '0.3.3'
# minor revision must always match runtime spec_version
version = '0.3.5'

[dependencies.encointer-scheduler]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-scheduler"

[dependencies.encointer-ceremonies]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-ceremonies"

[dependencies.encointer-currencies]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-currencies"

[dependencies.encointer-balances]
default-features = false
git = "https://github.com/encointer/pallets"
tag = "v0.3.5"
tag = "v0.3.6"
package = "pallet-encointer-balances"

[dependencies.fixed]
Expand Down
29 changes: 27 additions & 2 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,35 @@ pub mod opaque {
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("encointer-node-notee"),
impl_name: create_runtime_str!("encointer-node-notee"),
authoring_version: 2,

/// `authoring_version` is the version of the authorship interface. An authoring node
/// will not attempt to author blocks unless this is equal to its native runtime.
authoring_version: 0,

/// Version of the runtime specification. A full-node will not attempt to use its native
/// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
/// `spec_version` and `authoring_version` are the same between Wasm and native.
spec_version: 5,
impl_version: 5,

/// Version of the implementation of the specification. Nodes are free to ignore this; it
/// serves only as an indication that the code is different; as long as the other two versions
/// are the same then while the actual code may be different, it is nonetheless required to
/// do the same thing.
/// Non-consensus-breaking optimizations are about the only changes that could be made which
/// would result in only the `impl_version` changing.
impl_version: 0,

apis: RUNTIME_API_VERSIONS,

/// All existing dispatches are fully compatible when this number doesn't change. If this
/// number changes, then `spec_version` must change, also.
///
/// This number must change when an existing dispatchable (module ID, dispatch ID) is changed,
/// either through an alteration in its user-level semantics, a parameter added/removed/changed,
/// a dispatchable being removed, a module being removed, or a dispatchable/module changing its
/// index.
///
/// It need *not* change when a new module is added or when a dispatchable is added.
transaction_version: 1,
};

Expand Down

0 comments on commit 53a1708

Please sign in to comment.