mirror of https://github.com/skygpu/skynet.git
Add .ini example & new account config
Add new smart contract clis config etc Update GPU worker software to match contract updates Do dynamic nodeos genesisadd-txt2txt-models
parent
3607c568de
commit
1d7d11a9c1
|
@ -5,9 +5,9 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||||
RUN apt-get update && apt-get install -y wget
|
RUN apt-get update && apt-get install -y wget
|
||||||
|
|
||||||
# install eosio tools
|
# 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
|
RUN mkdir -p /root/nodeos
|
||||||
WORKDIR /root/nodeos
|
WORKDIR /root/nodeos
|
|
@ -1,3 +1,8 @@
|
||||||
|
[skynet.account]
|
||||||
|
name = xxxxxxxxxxxx
|
||||||
|
permission = active
|
||||||
|
key = EOSXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
[skynet.dgpu]
|
[skynet.dgpu]
|
||||||
hf_home = hf_home
|
hf_home = hf_home
|
||||||
hf_token = hf_XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx
|
hf_token = hf_XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import random
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
@ -88,13 +89,15 @@ def download():
|
||||||
|
|
||||||
@skynet.command()
|
@skynet.command()
|
||||||
@click.option(
|
@click.option(
|
||||||
'--account', '-a', default='telegram1')
|
'--account', '-A', default=None)
|
||||||
@click.option(
|
@click.option(
|
||||||
'--permission', '-p', default='active')
|
'--permission', '-p', default=None)
|
||||||
@click.option(
|
@click.option(
|
||||||
'--key', '-k', default=None)
|
'--key', '-k', default=None)
|
||||||
@click.option(
|
@click.option(
|
||||||
'--node-url', '-n', default='http://skynet.ancap.tech')
|
'--node-url', '-n', default='http://skynet.ancap.tech')
|
||||||
|
@click.option(
|
||||||
|
'--reward', '-r', default='20.0000 GPU')
|
||||||
@click.option('--algo', '-a', default='midj')
|
@click.option('--algo', '-a', default='midj')
|
||||||
@click.option(
|
@click.option(
|
||||||
'--prompt', '-p', default='a red old tractor in a sunny wheat field')
|
'--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('--height', '-h', default=512)
|
||||||
@click.option('--guidance', '-g', default=10)
|
@click.option('--guidance', '-g', default=10)
|
||||||
@click.option('--step', '-s', default=26)
|
@click.option('--step', '-s', default=26)
|
||||||
@click.option('--seed', '-S', default=420)
|
@click.option('--seed', '-S', default=None)
|
||||||
@click.option('--upscaler', '-U', default='x4')
|
@click.option('--upscaler', '-U', default='x4')
|
||||||
def enqueue(
|
def enqueue(
|
||||||
account: str,
|
account: str,
|
||||||
permission: str,
|
permission: str,
|
||||||
key: str | None,
|
key: str | None,
|
||||||
node_url: str,
|
node_url: str,
|
||||||
|
reward: str,
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
|
key, account, permission = load_account_info(
|
||||||
|
key, account, permission)
|
||||||
with open_cleos(node_url, key=key) as cleos:
|
with open_cleos(node_url, key=key) as cleos:
|
||||||
|
if not kwargs['seed']:
|
||||||
|
kwargs['seed'] = random.randint(0, 10e9)
|
||||||
|
|
||||||
req = json.dumps({
|
req = json.dumps({
|
||||||
'method': 'diffuse',
|
'method': 'diffuse',
|
||||||
'params': kwargs
|
'params': kwargs
|
||||||
|
@ -120,11 +129,11 @@ def enqueue(
|
||||||
binary = ''
|
binary = ''
|
||||||
|
|
||||||
ec, out = cleos.push_action(
|
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))
|
print(collect_stdout(out))
|
||||||
|
assert ec == 0
|
||||||
|
|
||||||
|
|
||||||
@skynet.command()
|
@skynet.command()
|
||||||
|
@ -175,10 +184,73 @@ def dequeue(
|
||||||
node_url: str,
|
node_url: str,
|
||||||
request_id: int
|
request_id: int
|
||||||
):
|
):
|
||||||
|
key, account, permission = load_account_info(
|
||||||
|
key, account, permission)
|
||||||
with open_cleos(node_url, key=key) as cleos:
|
with open_cleos(node_url, key=key) as cleos:
|
||||||
ec, out = cleos.push_action(
|
ec, out = cleos.push_action(
|
||||||
'telos.gpu', 'dequeue', [account, request_id], f'{account}@{permission}'
|
'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
|
assert ec == 0
|
||||||
|
|
||||||
@skynet.group()
|
@skynet.group()
|
||||||
|
@ -219,6 +291,10 @@ def dgpu(
|
||||||
algos: list[str]
|
algos: list[str]
|
||||||
):
|
):
|
||||||
from .dgpu import open_dgpu_node
|
from .dgpu import open_dgpu_node
|
||||||
|
|
||||||
|
key, account, permission = load_account_info(
|
||||||
|
key, account, permission)
|
||||||
|
|
||||||
vtestnet = None
|
vtestnet = None
|
||||||
try:
|
try:
|
||||||
dclient = docker.from_env()
|
dclient = docker.from_env()
|
||||||
|
@ -270,6 +346,10 @@ def telegram(
|
||||||
db_user: str,
|
db_user: str,
|
||||||
db_pass: str
|
db_pass: str
|
||||||
):
|
):
|
||||||
|
|
||||||
|
key, account, permission = load_account_info(
|
||||||
|
key, account, permission)
|
||||||
|
|
||||||
_, _, tg_token, cfg = init_env_from_config()
|
_, _, tg_token, cfg = init_env_from_config()
|
||||||
asyncio.run(
|
asyncio.run(
|
||||||
run_skynet_telegram(
|
run_skynet_telegram(
|
||||||
|
|
|
@ -37,3 +37,21 @@ def init_env_from_config(
|
||||||
tg_token = config['skynet.telegram']['token']
|
tg_token = config['skynet.telegram']['token']
|
||||||
|
|
||||||
return hf_home, hf_token, tg_token, config
|
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
|
||||||
|
|
|
@ -16,7 +16,7 @@ import asks
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
from leap.cleos import CLEOS, default_nodeos_image
|
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 (
|
from diffusers import (
|
||||||
StableDiffusionPipeline,
|
StableDiffusionPipeline,
|
||||||
|
@ -102,6 +102,9 @@ async def open_dgpu_node(
|
||||||
logging.info(f'resized it to {image.size}')
|
logging.info(f'resized it to {image.size}')
|
||||||
|
|
||||||
if algo not in models:
|
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...')
|
logging.info(f'{algo} not in loaded models, swapping...')
|
||||||
least_used = list(models.keys())[0]
|
least_used = list(models.keys())[0]
|
||||||
for model in models:
|
for model in models:
|
||||||
|
@ -169,6 +172,7 @@ async def open_dgpu_node(
|
||||||
raise DGPUComputeError('Unsupported compute method')
|
raise DGPUComputeError('Unsupported compute method')
|
||||||
|
|
||||||
async def get_work_requests_last_hour():
|
async def get_work_requests_last_hour():
|
||||||
|
logging.info('get_work_requests_last_hour')
|
||||||
return await cleos.aget_table(
|
return await cleos.aget_table(
|
||||||
'telos.gpu', 'telos.gpu', 'queue',
|
'telos.gpu', 'telos.gpu', 'queue',
|
||||||
index_position=2,
|
index_position=2,
|
||||||
|
@ -177,10 +181,41 @@ async def open_dgpu_node(
|
||||||
)
|
)
|
||||||
|
|
||||||
async def get_status_by_request_id(request_id: int):
|
async def get_status_by_request_id(request_id: int):
|
||||||
|
logging.info('get_status_by_request_id')
|
||||||
return await cleos.aget_table(
|
return await cleos.aget_table(
|
||||||
'telos.gpu', request_id, 'status')
|
'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):
|
def begin_work(request_id: int):
|
||||||
|
logging.info('begin_work')
|
||||||
ec, out = cleos.push_action(
|
ec, out = cleos.push_action(
|
||||||
'telos.gpu',
|
'telos.gpu',
|
||||||
'workbegin',
|
'workbegin',
|
||||||
|
@ -189,7 +224,35 @@ async def open_dgpu_node(
|
||||||
)
|
)
|
||||||
assert ec == 0
|
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():
|
async def find_my_results():
|
||||||
|
logging.info('find_my_results')
|
||||||
return await cleos.aget_table(
|
return await cleos.aget_table(
|
||||||
'telos.gpu', 'telos.gpu', 'results',
|
'telos.gpu', 'telos.gpu', 'results',
|
||||||
index_position=4,
|
index_position=4,
|
||||||
|
@ -200,6 +263,7 @@ async def open_dgpu_node(
|
||||||
|
|
||||||
ipfs_node = None
|
ipfs_node = None
|
||||||
def publish_on_ipfs(img_sha: str, raw_img: bytes):
|
def publish_on_ipfs(img_sha: str, raw_img: bytes):
|
||||||
|
logging.info('publish_on_ipfs')
|
||||||
img = Image.open(io.BytesIO(raw_img))
|
img = Image.open(io.BytesIO(raw_img))
|
||||||
img.save(f'tmp/ipfs-docker-staging/image.png')
|
img.save(f'tmp/ipfs-docker-staging/image.png')
|
||||||
|
|
||||||
|
@ -209,18 +273,30 @@ async def open_dgpu_node(
|
||||||
|
|
||||||
return ipfs_hash
|
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(
|
ec, out = cleos.push_action(
|
||||||
'telos.gpu',
|
'telos.gpu',
|
||||||
'submit',
|
'submit',
|
||||||
[account, request_id, result_hash, ipfs_hash],
|
[account, request_id, request_hash, result_hash, ipfs_hash],
|
||||||
f'{account}@{permission}'
|
f'{account}@{permission}'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(collect_stdout(out))
|
||||||
assert ec == 0
|
assert ec == 0
|
||||||
|
|
||||||
|
config = await get_global_config()
|
||||||
|
|
||||||
with open_ipfs_node() as ipfs_node:
|
with open_ipfs_node() as ipfs_node:
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
|
maybe_withdraw_all()
|
||||||
|
|
||||||
queue = await get_work_requests_last_hour()
|
queue = await get_work_requests_last_hour()
|
||||||
|
|
||||||
for req in queue:
|
for req in queue:
|
||||||
|
@ -232,11 +308,18 @@ async def open_dgpu_node(
|
||||||
|
|
||||||
statuses = await get_status_by_request_id(rid)
|
statuses = await get_status_by_request_id(rid)
|
||||||
|
|
||||||
if len(statuses) < 3:
|
if len(statuses) < config['verification_amount']:
|
||||||
|
|
||||||
# parse request
|
# parse request
|
||||||
body = json.loads(req['body'])
|
body = json.loads(req['body'])
|
||||||
binary = bytes.fromhex(req['binary_data'])
|
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
|
# TODO: validate request
|
||||||
|
|
||||||
|
@ -244,15 +327,20 @@ async def open_dgpu_node(
|
||||||
logging.info(f'working on {body}')
|
logging.info(f'working on {body}')
|
||||||
|
|
||||||
begin_work(rid)
|
begin_work(rid)
|
||||||
|
|
||||||
|
try:
|
||||||
img_sha, raw_img = gpu_compute_one(
|
img_sha, raw_img = gpu_compute_one(
|
||||||
body['method'], body['params'], binext=binary)
|
body['method'], body['params'], binext=binary)
|
||||||
|
|
||||||
ipfs_hash = publish_on_ipfs(img_sha, raw_img)
|
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
|
break
|
||||||
|
|
||||||
|
except BaseException as e:
|
||||||
|
cancel_work(rid, str(e))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.info(f'request {rid} already beign worked on, skip...')
|
logging.info(f'request {rid} already beign worked on, skip...')
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -88,6 +88,10 @@ async def run_skynet_telegram(
|
||||||
bot = AsyncTeleBot(tg_token)
|
bot = AsyncTeleBot(tg_token)
|
||||||
logging.info(f'tg_token: {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(
|
async with open_database_connection(
|
||||||
db_user, db_pass, db_host
|
db_user, db_pass, db_host
|
||||||
) as db_call:
|
) as db_call:
|
||||||
|
@ -139,6 +143,7 @@ async def run_skynet_telegram(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
request_time = datetime.datetime.now().isoformat()
|
||||||
ec, out = cleos.push_action(
|
ec, out = cleos.push_action(
|
||||||
'telos.gpu', 'enqueue', [account, req, ''], f'{account}@{permission}'
|
'telos.gpu', 'enqueue', [account, req, ''], f'{account}@{permission}'
|
||||||
)
|
)
|
||||||
|
@ -150,17 +155,19 @@ async def run_skynet_telegram(
|
||||||
request_id = int(out)
|
request_id = int(out)
|
||||||
logging.info(f'{request_id} enqueued.')
|
logging.info(f'{request_id} enqueued.')
|
||||||
|
|
||||||
|
config = await get_global_config()
|
||||||
|
|
||||||
ipfs_hash = None
|
ipfs_hash = None
|
||||||
sha_hash = None
|
sha_hash = None
|
||||||
for i in range(60):
|
for i in range(60):
|
||||||
results = cleos.get_table(
|
submits = await hyperion.aget_actions(
|
||||||
'telos.gpu', 'telos.gpu', 'results',
|
account=account,
|
||||||
index_position=2,
|
filter='telos.gpu:submit',
|
||||||
key_type='i64',
|
sort='desc',
|
||||||
lower_bound=request_id,
|
after=request_Time
|
||||||
upper_bound=request_id
|
|
||||||
)
|
)
|
||||||
if len(results) > 0:
|
actions = submits['actions']
|
||||||
|
if len(actions) > 0:
|
||||||
ipfs_hash = results[0]['ipfs_hash']
|
ipfs_hash = results[0]['ipfs_hash']
|
||||||
sha_hash = results[0]['result_hash']
|
sha_hash = results[0]['result_hash']
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import json
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from contextlib import contextmanager as cm
|
from contextlib import contextmanager as cm
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
|
@ -46,7 +48,7 @@ def open_nodeos(cleanup: bool = True):
|
||||||
dclient = docker.from_env()
|
dclient = docker.from_env()
|
||||||
vtestnet = get_container(
|
vtestnet = get_container(
|
||||||
dclient,
|
dclient,
|
||||||
'guilledk/py-eosio:leap-skynet-4.0.0',
|
'guilledk/skynet:leap-4.0.1',
|
||||||
name='skynet-nodeos',
|
name='skynet-nodeos',
|
||||||
force_unique=True,
|
force_unique=True,
|
||||||
detach=True,
|
detach=True,
|
||||||
|
@ -61,27 +63,76 @@ def open_nodeos(cleanup: bool = True):
|
||||||
|
|
||||||
cleos.start_keosd()
|
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(
|
cleos.start_nodeos_from_config(
|
||||||
'/root/nodeos/config.ini',
|
nodeos_config_ini,
|
||||||
data_dir='/root/nodeos/data',
|
data_dir='/root/nodeos/data',
|
||||||
genesis='/root/nodeos/genesis/skynet.json',
|
genesis='/root/skynet.json',
|
||||||
state_plugin=True)
|
state_plugin=True)
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
public_dev_key = 'EOS5fLreY5Zq5owBhmNJTgQaLqQ4ufzXSTpStQakEyfxNFuUEgNs1'
|
|
||||||
cleos.setup_wallet('5JnvSc6pewpHHuUHwvbJopsew6AKwiGnexwDRc2Pj2tbdw6iML9')
|
|
||||||
cleos.wait_blocks(1)
|
cleos.wait_blocks(1)
|
||||||
cleos.boot_sequence(token_sym=Symbol('GPU', 4))
|
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):
|
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(
|
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(
|
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(
|
cleos.deploy_contract_from_host(
|
||||||
'telos.gpu',
|
'telos.gpu',
|
||||||
|
@ -90,6 +141,29 @@ def open_nodeos(cleanup: bool = True):
|
||||||
create_account=False
|
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
|
yield cleos
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -3,6 +3,47 @@
|
||||||
"version": "eosio::abi/1.2",
|
"version": "eosio::abi/1.2",
|
||||||
"types": [],
|
"types": [],
|
||||||
"structs": [
|
"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",
|
"name": "dequeue",
|
||||||
"base": "",
|
"base": "",
|
||||||
|
@ -32,6 +73,28 @@
|
||||||
{
|
{
|
||||||
"name": "binary_data",
|
"name": "binary_data",
|
||||||
"type": "bytes"
|
"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",
|
"name": "request_id",
|
||||||
"type": "uint64"
|
"type": "uint64"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "request_hash",
|
||||||
|
"type": "checksum256"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "result_hash",
|
"name": "result_hash",
|
||||||
"type": "checksum256"
|
"type": "checksum256"
|
||||||
|
@ -57,6 +124,20 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "withdraw",
|
||||||
|
"base": "",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "user",
|
||||||
|
"type": "name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "quantity",
|
||||||
|
"type": "asset"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "work_request_struct",
|
"name": "work_request_struct",
|
||||||
"base": "",
|
"base": "",
|
||||||
|
@ -69,6 +150,10 @@
|
||||||
"name": "user",
|
"name": "user",
|
||||||
"type": "name"
|
"type": "name"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "reward",
|
||||||
|
"type": "asset"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -142,6 +227,10 @@
|
||||||
{
|
{
|
||||||
"name": "request_id",
|
"name": "request_id",
|
||||||
"type": "uint64"
|
"type": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "reason",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -165,6 +254,16 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": [
|
||||||
|
{
|
||||||
|
"name": "clean",
|
||||||
|
"type": "clean",
|
||||||
|
"ricardian_contract": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "config",
|
||||||
|
"type": "config",
|
||||||
|
"ricardian_contract": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dequeue",
|
"name": "dequeue",
|
||||||
"type": "dequeue",
|
"type": "dequeue",
|
||||||
|
@ -180,6 +279,11 @@
|
||||||
"type": "submit",
|
"type": "submit",
|
||||||
"ricardian_contract": ""
|
"ricardian_contract": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "withdraw",
|
||||||
|
"type": "withdraw",
|
||||||
|
"ricardian_contract": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "workbegin",
|
"name": "workbegin",
|
||||||
"type": "workbegin",
|
"type": "workbegin",
|
||||||
|
@ -192,6 +296,13 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tables": [
|
"tables": [
|
||||||
|
{
|
||||||
|
"name": "config",
|
||||||
|
"type": "global_configuration_struct",
|
||||||
|
"index_type": "i64",
|
||||||
|
"key_names": [],
|
||||||
|
"key_types": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "queue",
|
"name": "queue",
|
||||||
"type": "work_request_struct",
|
"type": "work_request_struct",
|
||||||
|
@ -212,6 +323,13 @@
|
||||||
"index_type": "i64",
|
"index_type": "i64",
|
||||||
"key_names": [],
|
"key_names": [],
|
||||||
"key_types": []
|
"key_types": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "users",
|
||||||
|
"type": "account",
|
||||||
|
"index_type": "i64",
|
||||||
|
"key_names": [],
|
||||||
|
"key_types": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ricardian_clauses": [],
|
"ricardian_clauses": [],
|
||||||
|
|
Binary file not shown.
|
@ -15,8 +15,7 @@ from leap.sugar import collect_stdout
|
||||||
|
|
||||||
|
|
||||||
def test_enqueue_work(cleos):
|
def test_enqueue_work(cleos):
|
||||||
|
user = 'telegram'
|
||||||
user = cleos.new_account()
|
|
||||||
req = json.dumps({
|
req = json.dumps({
|
||||||
'method': 'diffuse',
|
'method': 'diffuse',
|
||||||
'params': {
|
'params': {
|
||||||
|
@ -33,7 +32,7 @@ def test_enqueue_work(cleos):
|
||||||
binary = ''
|
binary = ''
|
||||||
|
|
||||||
ec, out = cleos.push_action(
|
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
|
assert ec == 0
|
||||||
|
@ -48,44 +47,23 @@ def test_enqueue_work(cleos):
|
||||||
assert req_on_chain['body'] == req
|
assert req_on_chain['body'] == req
|
||||||
assert req_on_chain['binary_data'] == binary
|
assert req_on_chain['binary_data'] == binary
|
||||||
|
|
||||||
ipfs_hash = None
|
|
||||||
sha_hash = None
|
|
||||||
for i in range(1, 4):
|
|
||||||
trio.run(
|
trio.run(
|
||||||
partial(
|
partial(
|
||||||
open_dgpu_node,
|
open_dgpu_node,
|
||||||
f'testworker{i}',
|
f'testworker1',
|
||||||
'active',
|
'active',
|
||||||
cleos,
|
cleos,
|
||||||
initial_algos=['midj']
|
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')
|
queue = cleos.get_table('telos.gpu', 'telos.gpu', 'queue')
|
||||||
|
|
||||||
assert len(queue) == 0
|
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):
|
def test_enqueue_dequeue(cleos):
|
||||||
|
user = 'telegram'
|
||||||
user = cleos.new_account()
|
|
||||||
req = json.dumps({
|
req = json.dumps({
|
||||||
'method': 'diffuse',
|
'method': 'diffuse',
|
||||||
'params': {
|
'params': {
|
||||||
|
@ -102,7 +80,7 @@ def test_enqueue_dequeue(cleos):
|
||||||
binary = ''
|
binary = ''
|
||||||
|
|
||||||
ec, out = cleos.push_action(
|
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
|
assert ec == 0
|
||||||
|
|
Loading…
Reference in New Issue