Add .ini example & new account config

Add new smart contract clis config etc
Update GPU worker software to match contract updates
Do dynamic nodeos genesis
add-txt2txt-models
Guillermo Rodriguez 2023-05-27 21:38:04 -03:00
parent 3607c568de
commit 1d7d11a9c1
No known key found for this signature in database
GPG Key ID: EC3AB66D5D83B392
22 changed files with 434 additions and 66 deletions

View File

@ -5,9 +5,9 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y wget
# install eosio tools
RUN wget https://github.com/AntelopeIO/leap/releases/download/v4.0.0/leap_4.0.0-ubuntu22.04_amd64.deb
RUN wget https://github.com/AntelopeIO/leap/releases/download/v4.0.1/leap_4.0.1-ubuntu22.04_amd64.deb
RUN apt-get install -y ./leap_4.0.0-ubuntu22.04_amd64.deb
RUN apt-get install -y ./leap_4.0.1-ubuntu22.04_amd64.deb
RUN mkdir -p /root/nodeos
WORKDIR /root/nodeos

View File

@ -1,3 +1,8 @@
[skynet.account]
name = xxxxxxxxxxxx
permission = active
key = EOSXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[skynet.dgpu]
hf_home = hf_home
hf_token = hf_XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

View File

@ -3,6 +3,7 @@
import os
import json
import logging
import random
from typing import Optional
from functools import partial
@ -88,13 +89,15 @@ def download():
@skynet.command()
@click.option(
'--account', '-a', default='telegram1')
'--account', '-A', default=None)
@click.option(
'--permission', '-p', default='active')
'--permission', '-p', default=None)
@click.option(
'--key', '-k', default=None)
@click.option(
'--node-url', '-n', default='http://skynet.ancap.tech')
@click.option(
'--reward', '-r', default='20.0000 GPU')
@click.option('--algo', '-a', default='midj')
@click.option(
'--prompt', '-p', default='a red old tractor in a sunny wheat field')
@ -103,16 +106,22 @@ def download():
@click.option('--height', '-h', default=512)
@click.option('--guidance', '-g', default=10)
@click.option('--step', '-s', default=26)
@click.option('--seed', '-S', default=420)
@click.option('--seed', '-S', default=None)
@click.option('--upscaler', '-U', default='x4')
def enqueue(
account: str,
permission: str,
key: str | None,
node_url: str,
reward: str,
**kwargs
):
key, account, permission = load_account_info(
key, account, permission)
with open_cleos(node_url, key=key) as cleos:
if not kwargs['seed']:
kwargs['seed'] = random.randint(0, 10e9)
req = json.dumps({
'method': 'diffuse',
'params': kwargs
@ -120,11 +129,11 @@ def enqueue(
binary = ''
ec, out = cleos.push_action(
'telos.gpu', 'enqueue', [account, req, binary], f'{account}@{permission}'
'telos.gpu', 'enqueue', [account, req, binary, reward], f'{account}@{permission}'
)
assert ec == 0
print(collect_stdout(out))
assert ec == 0
@skynet.command()
@ -175,10 +184,73 @@ def dequeue(
node_url: str,
request_id: int
):
key, account, permission = load_account_info(
key, account, permission)
with open_cleos(node_url, key=key) as cleos:
ec, out = cleos.push_action(
'telos.gpu', 'dequeue', [account, request_id], f'{account}@{permission}'
)
print(collect_stdout(out))
assert ec == 0
@skynet.command()
@click.option(
'--account', '-a', default='telegram1')
@click.option(
'--permission', '-p', default='active')
@click.option(
'--key', '-k', default=None)
@click.option(
'--node-url', '-n', default='http://skynet.ancap.tech')
@click.option(
'--verifications', '-v', default=1)
@click.option(
'--token-contract', '-c', default='eosio.token')
@click.option(
'--token-symbol', '-S', default='4,GPU')
def config(
account: str,
permission: str,
key: str | None,
node_url: str,
verifications: int,
token_contract: str,
token_symbol: str
):
key, account, permission = load_account_info(
key, account, permission)
with open_cleos(node_url, key=key) as cleos:
ec, out = cleos.push_action(
'telos.gpu', 'config', [verifications, token_contract, token_symbol], f'{account}@{permission}'
)
print(collect_stdout(out))
assert ec == 0
@skynet.command()
@click.option(
'--account', '-a', default='telegram1')
@click.option(
'--permission', '-p', default='active')
@click.option(
'--key', '-k', default=None)
@click.option(
'--node-url', '-n', default='http://skynet.ancap.tech')
@click.argument('quantity')
def deposit(
account: str,
permission: str,
key: str | None,
node_url: str,
quantity: str
):
key, account, permission = load_account_info(
key, account, permission)
with open_cleos(node_url, key=key) as cleos:
ec, out = cleos.transfer_token(account, 'telos.gpu', quantity)
print(collect_stdout(out))
assert ec == 0
@skynet.group()
@ -219,6 +291,10 @@ def dgpu(
algos: list[str]
):
from .dgpu import open_dgpu_node
key, account, permission = load_account_info(
key, account, permission)
vtestnet = None
try:
dclient = docker.from_env()
@ -270,6 +346,10 @@ def telegram(
db_user: str,
db_pass: str
):
key, account, permission = load_account_info(
key, account, permission)
_, _, tg_token, cfg = init_env_from_config()
asyncio.run(
run_skynet_telegram(

View File

@ -37,3 +37,21 @@ def init_env_from_config(
tg_token = config['skynet.telegram']['token']
return hf_home, hf_token, tg_token, config
def load_account_info(
key, account, permission
file_path=DEFAULT_CONFIG_PATH
):
_, _, _, config = init_env_from_config()
if not key:
key = config['skynet.account']['key']
if not account:
account = config['skynet.account']['name']
if not permission:
permission = config['skynet.account']['permission']
return

View File

@ -16,7 +16,7 @@ import asks
import torch
from leap.cleos import CLEOS, default_nodeos_image
from leap.sugar import get_container
from leap.sugar import get_container, collect_stdout
from diffusers import (
StableDiffusionPipeline,
@ -102,6 +102,9 @@ async def open_dgpu_node(
logging.info(f'resized it to {image.size}')
if algo not in models:
if algo not in ALGOS:
raise DGPUComputeError(f'Unknown algo \"{algo}\"')
logging.info(f'{algo} not in loaded models, swapping...')
least_used = list(models.keys())[0]
for model in models:
@ -169,6 +172,7 @@ async def open_dgpu_node(
raise DGPUComputeError('Unsupported compute method')
async def get_work_requests_last_hour():
logging.info('get_work_requests_last_hour')
return await cleos.aget_table(
'telos.gpu', 'telos.gpu', 'queue',
index_position=2,
@ -177,10 +181,41 @@ async def open_dgpu_node(
)
async def get_status_by_request_id(request_id: int):
logging.info('get_status_by_request_id')
return await cleos.aget_table(
'telos.gpu', request_id, 'status')
async def get_global_config():
logging.info('get_global_config')
return (await cleos.aget_table(
'telos.gpu', 'telos.gpu', 'config'))[0]
def get_worker_balance():
logging.info('get_worker_balance')
rows = cleos.get_table(
'telos.gpu', 'telos.gpu', 'users',
index_position=1,
key_type='name',
lower_bound=account,
upper_bound=account
)
if len(rows) == 1:
return rows[0]['balance']
else:
return None
async def get_user_nonce(user: str):
logging.info('get_user_nonce')
return (await cleos.aget_table(
'telos.gpu', 'telos.gpu', 'users',
index_position=1,
key_type='name',
lower_bound=user,
upper_bound=user
))[0]['nonce']
def begin_work(request_id: int):
logging.info('begin_work')
ec, out = cleos.push_action(
'telos.gpu',
'workbegin',
@ -189,7 +224,35 @@ async def open_dgpu_node(
)
assert ec == 0
def cancel_work(request_id: int, reason: str):
logging.info('cancel_work')
ec, out = cleos.push_action(
'telos.gpu',
'workcancel',
[account, request_id, reason],
f'{account}@{permission}'
)
assert ec == 0
def maybe_withdraw_all():
logging.info('maybe_withdraw_all')
balance = get_worker_balance()
if not balance:
return
balance_amount = float(balance.split(' ')[0])
if balance_amount > 0:
ec, out = cleos.push_action(
'telos.gpu',
'withdraw',
[account, balance],
f'{account}@{permission}'
)
logging.info(collect_stdout(out))
assert ec == 0
async def find_my_results():
logging.info('find_my_results')
return await cleos.aget_table(
'telos.gpu', 'telos.gpu', 'results',
index_position=4,
@ -200,6 +263,7 @@ async def open_dgpu_node(
ipfs_node = None
def publish_on_ipfs(img_sha: str, raw_img: bytes):
logging.info('publish_on_ipfs')
img = Image.open(io.BytesIO(raw_img))
img.save(f'tmp/ipfs-docker-staging/image.png')
@ -209,18 +273,30 @@ async def open_dgpu_node(
return ipfs_hash
def submit_work(request_id: int, result_hash: str, ipfs_hash: str):
def submit_work(
request_id: int,
request_hash: str,
result_hash: str,
ipfs_hash: str
):
logging.info('submit_work')
ec, out = cleos.push_action(
'telos.gpu',
'submit',
[account, request_id, result_hash, ipfs_hash],
[account, request_id, request_hash, result_hash, ipfs_hash],
f'{account}@{permission}'
)
print(collect_stdout(out))
assert ec == 0
config = await get_global_config()
with open_ipfs_node() as ipfs_node:
try:
while True:
maybe_withdraw_all()
queue = await get_work_requests_last_hour()
for req in queue:
@ -232,11 +308,18 @@ async def open_dgpu_node(
statuses = await get_status_by_request_id(rid)
if len(statuses) < 3:
if len(statuses) < config['verification_amount']:
# parse request
body = json.loads(req['body'])
binary = bytes.fromhex(req['binary_data'])
hash_str = (
str(await get_user_nonce(req['user']))
+
req['body']
)
logging.info(f'hashing: {hash_str}')
request_hash = sha256(hash_str.encode('utf-8')).hexdigest()
# TODO: validate request
@ -244,15 +327,20 @@ async def open_dgpu_node(
logging.info(f'working on {body}')
begin_work(rid)
try:
img_sha, raw_img = gpu_compute_one(
body['method'], body['params'], binext=binary)
ipfs_hash = publish_on_ipfs(img_sha, raw_img)
submit_work(rid, img_sha, ipfs_hash)
submit_work(rid, request_hash, img_sha, ipfs_hash)
break
except BaseException as e:
cancel_work(rid, str(e))
else:
logging.info(f'request {rid} already beign worked on, skip...')
continue

View File

@ -88,6 +88,10 @@ async def run_skynet_telegram(
bot = AsyncTeleBot(tg_token)
logging.info(f'tg_token: {tg_token}')
async def get_global_config():
return (await cleos.aget_table(
'telos.gpu', 'telos.gpu', 'config'))[0]
async with open_database_connection(
db_user, db_pass, db_host
) as db_call:
@ -139,6 +143,7 @@ async def run_skynet_telegram(
}
})
request_time = datetime.datetime.now().isoformat()
ec, out = cleos.push_action(
'telos.gpu', 'enqueue', [account, req, ''], f'{account}@{permission}'
)
@ -150,17 +155,19 @@ async def run_skynet_telegram(
request_id = int(out)
logging.info(f'{request_id} enqueued.')
config = await get_global_config()
ipfs_hash = None
sha_hash = None
for i in range(60):
results = cleos.get_table(
'telos.gpu', 'telos.gpu', 'results',
index_position=2,
key_type='i64',
lower_bound=request_id,
upper_bound=request_id
submits = await hyperion.aget_actions(
account=account,
filter='telos.gpu:submit',
sort='desc',
after=request_Time
)
if len(results) > 0:
actions = submits['actions']
if len(actions) > 0:
ipfs_hash = results[0]['ipfs_hash']
sha_hash = results[0]['result_hash']
break

View File

@ -1,8 +1,10 @@
#!/usr/bin/env python3
import json
import time
import logging
from datetime import datetime
from contextlib import contextmanager as cm
import docker
@ -46,7 +48,7 @@ def open_nodeos(cleanup: bool = True):
dclient = docker.from_env()
vtestnet = get_container(
dclient,
'guilledk/py-eosio:leap-skynet-4.0.0',
'guilledk/skynet:leap-4.0.1',
name='skynet-nodeos',
force_unique=True,
detach=True,
@ -61,27 +63,76 @@ def open_nodeos(cleanup: bool = True):
cleos.start_keosd()
priv, pub = cleos.create_key_pair()
logging.info(f'SUDO KEYS: {(priv, pub)}')
cleos.setup_wallet(priv)
genesis = json.dumps({
"initial_timestamp": datetime.now().isoformat(),
"initial_key": pub,
"initial_configuration": {
"max_block_net_usage": 1048576,
"target_block_net_usage_pct": 1000,
"max_transaction_net_usage": 1048575,
"base_per_transaction_net_usage": 12,
"net_usage_leeway": 500,
"context_free_discount_net_usage_num": 20,
"context_free_discount_net_usage_den": 100,
"max_block_cpu_usage": 200000,
"target_block_cpu_usage_pct": 1000,
"max_transaction_cpu_usage": 150000,
"min_transaction_cpu_usage": 100,
"max_transaction_lifetime": 3600,
"deferred_trx_expiration_window": 600,
"max_transaction_delay": 3888000,
"max_inline_action_size": 4096,
"max_inline_action_depth": 4,
"max_authority_depth": 6
}
}, indent=4)
ec, out = cleos.run(
['bash', '-c', f'echo \'{genesis}\' > /root/skynet.json'])
assert ec == 0
place_holder = 'EOS5fLreY5Zq5owBhmNJTgQaLqQ4ufzXSTpStQakEyfxNFuUEgNs1=KEY:5JnvSc6pewpHHuUHwvbJopsew6AKwiGnexwDRc2Pj2tbdw6iML9'
sig_provider = f'{pub}=KEY:{priv}'
nodeos_config_ini = '/root/nodeos/config.ini'
ec, out = cleos.run(
['bash', '-c', f'sed -i -e \'s/{place_holder}/{sig_provider}/g\' {nodeos_config_ini}'])
assert ec == 0
cleos.start_nodeos_from_config(
'/root/nodeos/config.ini',
nodeos_config_ini,
data_dir='/root/nodeos/data',
genesis='/root/nodeos/genesis/skynet.json',
genesis='/root/skynet.json',
state_plugin=True)
time.sleep(0.5)
public_dev_key = 'EOS5fLreY5Zq5owBhmNJTgQaLqQ4ufzXSTpStQakEyfxNFuUEgNs1'
cleos.setup_wallet('5JnvSc6pewpHHuUHwvbJopsew6AKwiGnexwDRc2Pj2tbdw6iML9')
cleos.wait_blocks(1)
cleos.boot_sequence(token_sym=Symbol('GPU', 4))
cleos.new_account('telos.gpu', ram=300000, key=public_dev_key)
priv, pub = cleos.create_key_pair()
cleos.import_key(priv)
logging.info(f'GPU KEYS: {(priv, pub)}')
cleos.new_account('telos.gpu', ram=4200000, key=pub)
for i in range(1, 4):
priv, pub = cleos.create_key_pair()
cleos.import_key(priv)
logging.info(f'testworker{i} KEYS: {(priv, pub)}')
cleos.create_account_staked(
'eosio', f'testworker{i}', key=public_dev_key)
'eosio', f'testworker{i}', key=pub)
priv, pub = cleos.create_key_pair()
cleos.import_key(priv)
logging.info(f'TELEGRAM KEYS: {(priv, pub)}')
cleos.create_account_staked(
'eosio', 'telegram1', ram=500000, key=public_dev_key)
'eosio', 'telegram', ram=500000, key=pub)
cleos.transfer_token(
'eosio', 'telegram', '1000000.0000 GPU', 'Initial testing funds')
cleos.deploy_contract_from_host(
'telos.gpu',
@ -90,6 +141,29 @@ def open_nodeos(cleanup: bool = True):
create_account=False
)
ec, out = cleos.push_action(
'telos.gpu',
'config',
[1, 'eosio.token', '4,GPU'],
f'telos.gpu@active'
)
assert ec == 0
ec, out = cleos.transfer_token(
'telegram', 'telos.gpu', '1000000.0000 GPU', 'Initial testing funds')
assert ec == 0
user_row = cleos.get_table(
'telos.gpu',
'telos.gpu',
'users',
index_position=1,
key_type='name',
lower_bound='telegram',
upper_bound='telegram'
)
assert len(user_row) == 1
yield cleos
finally:

View File

@ -3,6 +3,47 @@
"version": "eosio::abi/1.2",
"types": [],
"structs": [
{
"name": "account",
"base": "",
"fields": [
{
"name": "user",
"type": "name"
},
{
"name": "balance",
"type": "asset"
},
{
"name": "nonce",
"type": "uint64"
}
]
},
{
"name": "clean",
"base": "",
"fields": []
},
{
"name": "config",
"base": "",
"fields": [
{
"name": "verification_amount",
"type": "uint8"
},
{
"name": "token_contract",
"type": "name"
},
{
"name": "token_symbol",
"type": "symbol"
}
]
},
{
"name": "dequeue",
"base": "",
@ -32,6 +73,28 @@
{
"name": "binary_data",
"type": "bytes"
},
{
"name": "reward",
"type": "asset"
}
]
},
{
"name": "global_configuration_struct",
"base": "",
"fields": [
{
"name": "verification_amount",
"type": "uint8"
},
{
"name": "token_contract",
"type": "name"
},
{
"name": "token_symbol",
"type": "symbol"
}
]
},
@ -47,6 +110,10 @@
"name": "request_id",
"type": "uint64"
},
{
"name": "request_hash",
"type": "checksum256"
},
{
"name": "result_hash",
"type": "checksum256"
@ -57,6 +124,20 @@
}
]
},
{
"name": "withdraw",
"base": "",
"fields": [
{
"name": "user",
"type": "name"
},
{
"name": "quantity",
"type": "asset"
}
]
},
{
"name": "work_request_struct",
"base": "",
@ -69,6 +150,10 @@
"name": "user",
"type": "name"
},
{
"name": "reward",
"type": "asset"
},
{
"name": "body",
"type": "string"
@ -142,6 +227,10 @@
{
"name": "request_id",
"type": "uint64"
},
{
"name": "reason",
"type": "string"
}
]
},
@ -165,6 +254,16 @@
}
],
"actions": [
{
"name": "clean",
"type": "clean",
"ricardian_contract": ""
},
{
"name": "config",
"type": "config",
"ricardian_contract": ""
},
{
"name": "dequeue",
"type": "dequeue",
@ -180,6 +279,11 @@
"type": "submit",
"ricardian_contract": ""
},
{
"name": "withdraw",
"type": "withdraw",
"ricardian_contract": ""
},
{
"name": "workbegin",
"type": "workbegin",
@ -192,6 +296,13 @@
}
],
"tables": [
{
"name": "config",
"type": "global_configuration_struct",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "queue",
"type": "work_request_struct",
@ -212,6 +323,13 @@
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "users",
"type": "account",
"index_type": "i64",
"key_names": [],
"key_types": []
}
],
"ricardian_clauses": [],

View File

@ -15,8 +15,7 @@ from leap.sugar import collect_stdout
def test_enqueue_work(cleos):
user = cleos.new_account()
user = 'telegram'
req = json.dumps({
'method': 'diffuse',
'params': {
@ -33,7 +32,7 @@ def test_enqueue_work(cleos):
binary = ''
ec, out = cleos.push_action(
'telos.gpu', 'enqueue', [user, req, binary], f'{user}@active'
'telos.gpu', 'enqueue', [user, req, binary, '20.0000 GPU'], f'{user}@active'
)
assert ec == 0
@ -48,44 +47,23 @@ def test_enqueue_work(cleos):
assert req_on_chain['body'] == req
assert req_on_chain['binary_data'] == binary
ipfs_hash = None
sha_hash = None
for i in range(1, 4):
trio.run(
partial(
open_dgpu_node,
f'testworker{i}',
f'testworker1',
'active',
cleos,
initial_algos=['midj']
)
)
if ipfs_hash == None:
result = cleos.get_table(
'telos.gpu', 'telos.gpu', 'results',
index_position=4,
key_type='name',
lower_bound=f'testworker{i}',
upper_bound=f'testworker{i}'
)
assert len(result) == 1
ipfs_hash = result[0]['ipfs_hash']
sha_hash = result[0]['result_hash']
queue = cleos.get_table('telos.gpu', 'telos.gpu', 'queue')
assert len(queue) == 0
resp = requests.get(f'https://ipfs.io/ipfs/{ipfs_hash}/image.png')
assert resp.status_code == 200
assert sha_hash == sha256(resp.content).hexdigest()
def test_enqueue_dequeue(cleos):
user = cleos.new_account()
user = 'telegram'
req = json.dumps({
'method': 'diffuse',
'params': {
@ -102,7 +80,7 @@ def test_enqueue_dequeue(cleos):
binary = ''
ec, out = cleos.push_action(
'telos.gpu', 'enqueue', [user, req, binary], f'{user}@active'
'telos.gpu', 'enqueue', [user, req, binary, '20.0000 GPU'], f'{user}@active'
)
assert ec == 0