2024-10-27 03:55:06 +01:00
|
|
|
|
import ply.lex as lex
|
|
|
|
|
import ply.yacc as yacc
|
|
|
|
|
import enum
|
|
|
|
|
import uuid
|
2024-10-28 00:07:20 +01:00
|
|
|
|
import os
|
|
|
|
|
import logging
|
2024-10-28 01:45:07 +01:00
|
|
|
|
import sys
|
|
|
|
|
import select
|
2024-10-28 00:07:20 +01:00
|
|
|
|
from multiprocessing import Process
|
|
|
|
|
from multiprocessing import Pipe
|
2024-11-19 17:03:58 +01:00
|
|
|
|
import subprocess
|
2024-10-28 00:07:20 +01:00
|
|
|
|
|
|
|
|
|
logg = logging.getLogger()
|
|
|
|
|
logg.setLevel(logging.DEBUG)
|
2024-10-27 03:55:06 +01:00
|
|
|
|
|
|
|
|
|
tokens = (
|
|
|
|
|
'ID',
|
|
|
|
|
'NOID',
|
|
|
|
|
'HEX',
|
|
|
|
|
'LABEL',
|
|
|
|
|
'VALUE',
|
|
|
|
|
'END',
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
t_ID = r'[a-zA-Z0-9]+(-[a-zA-Z0-9]+)+'
|
|
|
|
|
t_NOID = r'\-'
|
|
|
|
|
t_LABEL = r'[a-zA-Z_]+'
|
|
|
|
|
t_VALUE = r'\d+'
|
|
|
|
|
t_END = r'\n'
|
|
|
|
|
t_HEX = r'0x([a-fA-F0-9])+'
|
|
|
|
|
|
|
|
|
|
#def t_VALUE(t):
|
|
|
|
|
# r'\d+'
|
|
|
|
|
# t.value = int(t.value)
|
|
|
|
|
|
|
|
|
|
#def t_HEX(t):
|
|
|
|
|
# r'0x([a-fA-F0-9])+'
|
|
|
|
|
#print(t)
|
|
|
|
|
#try:
|
|
|
|
|
# t.value = bytes.fromhex(t.value)
|
|
|
|
|
#except:
|
|
|
|
|
# return False
|
|
|
|
|
#return t.value
|
|
|
|
|
#t.value = t.value
|
|
|
|
|
# pass
|
|
|
|
|
|
|
|
|
|
t_ignore = ' \t'
|
|
|
|
|
|
|
|
|
|
def t_error(t):
|
|
|
|
|
print("problem: ", t.value[0])
|
|
|
|
|
t.lexer.skip(1)
|
|
|
|
|
|
|
|
|
|
lexer = lex.lex()
|
|
|
|
|
#
|
|
|
|
|
#data = '''
|
|
|
|
|
#FOOBAR uf-2etg 0xa3bdefa momo 123
|
|
|
|
|
#
|
|
|
|
|
#BARBAR
|
|
|
|
|
#BAZ
|
|
|
|
|
#
|
|
|
|
|
#BASFB foo-bar-baz
|
|
|
|
|
#'''
|
|
|
|
|
#
|
|
|
|
|
#lexer.input(data)
|
|
|
|
|
#
|
|
|
|
|
#while True:
|
|
|
|
|
# tok = lexer.token()
|
|
|
|
|
# if not tok:
|
|
|
|
|
# break
|
|
|
|
|
# print(tok)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CmdId(enum.IntEnum):
|
|
|
|
|
KEY_CREATE = 0x1
|
|
|
|
|
VOUCHER_CREATE = 0x10
|
|
|
|
|
VOUCHER_MINT = 0x11
|
|
|
|
|
VOUCHER_TRANSFER = 0x12
|
|
|
|
|
WAIT = 0x20
|
|
|
|
|
NEED = 0x21
|
|
|
|
|
PEEK = 0x80
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Agent:
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return self.__class__.__name__ + ':' #{}'.format(self.__class__.__name__, self.v)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AddressAgent(Agent):
|
|
|
|
|
def __init__(self, v):
|
|
|
|
|
self.v = bytes.fromhex(v[2:])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return Agent.__str__(self) + self.v.hex()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NameAgent(Agent):
|
|
|
|
|
def __init__(self, v):
|
|
|
|
|
self.v = v
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return Agent.__str__(self) + self.v
|
|
|
|
|
|
|
|
|
|
class Cmd:
|
|
|
|
|
|
|
|
|
|
def __init__(self, cmd):
|
|
|
|
|
self.c = CmdId[cmd]
|
|
|
|
|
self.i = None
|
|
|
|
|
self.a = None
|
|
|
|
|
self.f = None
|
|
|
|
|
self.t = None
|
|
|
|
|
self.v = 0
|
|
|
|
|
self.k = None
|
|
|
|
|
self.d = 0
|
|
|
|
|
self.p = 0
|
|
|
|
|
self.s = None
|
|
|
|
|
self.n = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return "[{:02d}]{} i={} v={} a={} f={} t={} k={} d={} p={} s={} n={}".format(self.c, self.c.name, self.i, self.v, self.a, self.f, self.t, self.k, self.d, self.p, self.s, self.n)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def to_store(v):
|
|
|
|
|
return str(v)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def to_agent(v):
|
|
|
|
|
r = None
|
|
|
|
|
try:
|
|
|
|
|
r = AddressAgent(v)
|
|
|
|
|
except ValueError:
|
|
|
|
|
r = NameAgent(v)
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_cmd(p):
|
|
|
|
|
'''cmd : key_create
|
|
|
|
|
| voucher_mint
|
|
|
|
|
| voucher_transfer
|
|
|
|
|
| voucher_create
|
|
|
|
|
| pair
|
|
|
|
|
'''
|
|
|
|
|
p[0] = p[1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_key_create(p):
|
|
|
|
|
'''key_create : change_label LABEL LABEL
|
|
|
|
|
| change_label LABEL LABEL HEX
|
|
|
|
|
'''
|
|
|
|
|
o = p[1]
|
|
|
|
|
o.f = NameAgent(p[2])
|
|
|
|
|
o.t = to_store(p[3])
|
|
|
|
|
if len(p) > 4:
|
|
|
|
|
o.k = p[4]
|
|
|
|
|
p[0] = o
|
2024-11-19 17:03:58 +01:00
|
|
|
|
print("PO",p[0])
|
2024-10-27 03:55:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_voucher_mint(p):
|
|
|
|
|
'''voucher_mint : change_label hv
|
|
|
|
|
| change_label nv
|
|
|
|
|
'''
|
|
|
|
|
o = p[1]
|
|
|
|
|
if o.c.value & 0x10 == 0:
|
|
|
|
|
raise ValueError("not a voucher command")
|
|
|
|
|
o.v = int(p[2][1])
|
|
|
|
|
o.a = to_agent(p[2][0])
|
|
|
|
|
p[0] = o
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_voucher_create(p):
|
|
|
|
|
'''voucher_create : change_label LABEL LABEL VALUE
|
|
|
|
|
| change_label LABEL LABEL VALUE VALUE VALUE
|
|
|
|
|
'''
|
|
|
|
|
o = p[1]
|
|
|
|
|
if o.c.value & 0x10 == 0:
|
|
|
|
|
raise ValueError("not a voucher command")
|
|
|
|
|
o.s = p[2]
|
|
|
|
|
o.n = p[3]
|
|
|
|
|
o.v = int(p[4])
|
|
|
|
|
if len(p) > 5:
|
|
|
|
|
o.d = p[5]
|
|
|
|
|
o.p = p[6]
|
|
|
|
|
p[0] = o
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_voucher_mint_recipient(p):
|
|
|
|
|
'''voucher_mint : change_label hv HEX
|
|
|
|
|
| change_label nv HEX
|
|
|
|
|
| change_label hv LABEL
|
|
|
|
|
| change_label nv LABEL
|
|
|
|
|
'''
|
|
|
|
|
o = p[1]
|
|
|
|
|
if o.c.value & 0x10 == 0:
|
|
|
|
|
raise ValueError("not a voucher command")
|
|
|
|
|
o.v = int(p[2][1])
|
|
|
|
|
o.a = to_agent(p[2][0])
|
|
|
|
|
o.t = to_agent(p[3])
|
|
|
|
|
p[0] = o
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_voucher_transfer(p):
|
|
|
|
|
'''voucher_transfer : change_label hv HEX HEX
|
|
|
|
|
| change_label nv HEX HEX
|
|
|
|
|
| change_label hv LABEL HEX
|
|
|
|
|
| change_label nv LABEL HEX
|
|
|
|
|
'''
|
|
|
|
|
o = p[1]
|
|
|
|
|
if o.c.value & 0x10 == 0:
|
|
|
|
|
raise ValueError("not a voucher command")
|
|
|
|
|
o.v = int(p[2][1])
|
|
|
|
|
o.a = to_agent(p[2][0])
|
|
|
|
|
o.t = to_agent(p[3])
|
|
|
|
|
o.f = to_agent(p[4])
|
|
|
|
|
p[0] = o
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_nv(p):
|
|
|
|
|
'nv : LABEL VALUE'
|
|
|
|
|
p[0] = (p[1], p[2],)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_hv(p):
|
|
|
|
|
'hv : HEX VALUE'
|
|
|
|
|
p[0] = (p[1], p[2],)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_change_label(p):
|
|
|
|
|
'''change_label : pair
|
|
|
|
|
| pairnoid
|
|
|
|
|
'''
|
|
|
|
|
p[0] = p[1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_pair(p):
|
|
|
|
|
'pair : LABEL ID'
|
|
|
|
|
o = Cmd(p[1])
|
|
|
|
|
o.i = p[2]
|
|
|
|
|
p[0] = o
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_pairnoid(p):
|
|
|
|
|
'pairnoid : LABEL NOID'
|
|
|
|
|
o = Cmd(p[1])
|
|
|
|
|
o.i = str(uuid.uuid4())
|
|
|
|
|
p[0] = o
|
|
|
|
|
|
|
|
|
|
|
2024-10-28 00:07:20 +01:00
|
|
|
|
class Router:
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.__routes = {}
|
|
|
|
|
self.__r = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register(self, cmd_id, fn):
|
|
|
|
|
self.__routes[cmd_id] = fn
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sync(self, uid):
|
|
|
|
|
o = self.__r[uid]
|
|
|
|
|
if o[1] == None:
|
|
|
|
|
return None
|
|
|
|
|
r = o[1][0].recv()
|
|
|
|
|
o = (o[0], None,)
|
|
|
|
|
o[0].join()
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __wrap(self, uid, fn, cmd):
|
|
|
|
|
r = fn(cmd)
|
|
|
|
|
self.__r[uid][1][1].send(r)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def exec(self, cmd):
|
2024-10-28 01:45:07 +01:00
|
|
|
|
logg.debug("router exec {}".format(cmd))
|
2024-10-28 00:07:20 +01:00
|
|
|
|
if cmd.c & 0xa0 > 0:
|
|
|
|
|
return self.sync(cmd.i)
|
|
|
|
|
fn = self.__routes[cmd.c]
|
|
|
|
|
pi = Pipe(False)
|
|
|
|
|
po = Process(target=self.__wrap, args=(cmd.i, fn, cmd,))
|
|
|
|
|
self.__r[cmd.i] = (po, pi,)
|
|
|
|
|
po.start()
|
|
|
|
|
|
|
|
|
|
|
2024-10-28 01:45:07 +01:00
|
|
|
|
def finish(self):
|
|
|
|
|
print("syncing")
|
2024-10-28 00:07:20 +01:00
|
|
|
|
for k, v in self.__r.items():
|
2024-10-28 01:45:07 +01:00
|
|
|
|
print("syncing key " + k)
|
2024-10-28 00:07:20 +01:00
|
|
|
|
r = self.sync(k)
|
2024-10-28 01:45:07 +01:00
|
|
|
|
logg.debug("synced " + k + ": " + r)
|
|
|
|
|
print("synced " + k + ": " + r)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __del__(self):
|
|
|
|
|
self.finish()
|
2024-10-28 00:07:20 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def noop_handler(cmd):
|
|
|
|
|
return str(cmd)
|
|
|
|
|
|
2024-11-19 17:03:58 +01:00
|
|
|
|
#NOTE:
|
|
|
|
|
#For testing the handlers,am using my hard-coded private key for the cast commands,replace with your actual private key.
|
|
|
|
|
#I have added random characters to the existing.
|
|
|
|
|
def key_create_handler(cmd):
|
|
|
|
|
mnemonic = cmd.i.replace('-', ' ')
|
|
|
|
|
command = f'cast wallet pk -v "{mnemonic}" 2 | cut -c 16-'
|
|
|
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
raise subprocess.CalledProcessError(result.returncode, command, output=result.stdout, stderr=result.stderr)
|
|
|
|
|
if result.stderr:
|
|
|
|
|
raise ValueError(f"Command failed with error: {result.stderr}")
|
|
|
|
|
else:
|
|
|
|
|
privatekey = result.stdout.strip().split("\n")[1]
|
|
|
|
|
return privatekey
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def voucher_create_handler(cmd):
|
|
|
|
|
name = cmd.n
|
|
|
|
|
symbol = cmd.s
|
|
|
|
|
command = f'ge-publish --private-key 1e1d0c1519479f68d9c8d07352a8e7e7cb9e2c676bce422f84502412cf39S4Ca ' \
|
|
|
|
|
f'--rpc https://alfajores-forno.celo-testnet.org --gas-fee-cap 35000000000 --chainid 44787 ' \
|
|
|
|
|
f'p erc20 --name "{name}" --symbol "{symbol}"'
|
|
|
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
|
|
|
|
|
|
|
|
output = result.stderr.strip().split("\n")
|
|
|
|
|
contract_address = None
|
|
|
|
|
|
|
|
|
|
for word in output[1].split():
|
|
|
|
|
if "contract_address=" in word:
|
|
|
|
|
contract_address = word.split("=")[1]
|
|
|
|
|
|
|
|
|
|
return contract_address
|
|
|
|
|
|
|
|
|
|
def voucher_transfer_handler(cmd):
|
|
|
|
|
value = cmd.v
|
|
|
|
|
command = (
|
|
|
|
|
f'cast send --private-key 1e1d0c1519479f68d9c8d07352a8e7e7cb9e2c676bce422f84502412cfsarw54ba '
|
|
|
|
|
f'--rpc-url https://alfajores-forno.celo-testnet.org/ '
|
|
|
|
|
f'0x93bb5f14464A9b7E5D5487DAB12d100417f23323 '
|
|
|
|
|
f'"transfer(address,uint256)" 0x7c9eCcC1de442911954e36e6092DFb10373090a6 {value}'
|
|
|
|
|
)
|
|
|
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
|
|
|
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
raise subprocess.CalledProcessError(result.returncode, command, output=result.stdout, stderr=result.stderr)
|
|
|
|
|
if result.stderr:
|
|
|
|
|
raise ValueError(f"Command failed with error: {result.stderr}")
|
|
|
|
|
return result.stdout
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def voucher_mint_handler(cmd):
|
|
|
|
|
value = cmd.v
|
|
|
|
|
command = (
|
|
|
|
|
f'cast send --private-key 1e1d0c1519479f68d9c8d07352a8e7e7cb9e2c676bce422f84502412cf39ASCa '
|
|
|
|
|
f'--rpc-url https://alfajores-forno.celo-testnet.org/ '
|
|
|
|
|
f'0x3feCC87C2c102984865B996de340bb2C6AdCF01E '
|
|
|
|
|
f'"mintTo(address,uint256)" 0xEef7Ad2cCCB317E6898F43eA2B5b1BD1E9C13b1A {value}'
|
|
|
|
|
)
|
|
|
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
raise subprocess.CalledProcessError(result.returncode, command, output=result.stdout, stderr=result.stderr)
|
|
|
|
|
if result.stderr:
|
|
|
|
|
raise ValueError(f"Command failed with error: {result.stderr}")
|
|
|
|
|
return result.stdout
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-10-28 00:07:20 +01:00
|
|
|
|
|
|
|
|
|
def foo_handler(cmd):
|
|
|
|
|
return os.popen('eth-info -p https://celo.grassecon.net').read()
|
|
|
|
|
|
|
|
|
|
|
2024-10-27 03:55:06 +01:00
|
|
|
|
parser = yacc.yacc()
|
|
|
|
|
|
2024-10-28 01:45:07 +01:00
|
|
|
|
running = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FileGet:
|
|
|
|
|
def __init__(self, o, fp):
|
|
|
|
|
self.__running = True
|
|
|
|
|
self.__o = o
|
|
|
|
|
self.__f = open(fp, 'r')
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
while self.__running:
|
|
|
|
|
v = ifc.get()
|
|
|
|
|
if v == None:
|
|
|
|
|
break
|
|
|
|
|
v = v.strip('\n')
|
|
|
|
|
if len(v) == 0:
|
|
|
|
|
break
|
|
|
|
|
r = parser.parse(v)
|
|
|
|
|
self.__o.exec(r)
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
return self.__f.readline()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WaitGet:
|
|
|
|
|
def __init__(self, o, *r):
|
|
|
|
|
self.__running = True
|
|
|
|
|
self.__o = o
|
|
|
|
|
self.__f = r
|
|
|
|
|
|
|
|
|
|
# TODO: router copy results in missing keys to sync when closing down
|
|
|
|
|
def __process(self, f):
|
|
|
|
|
while self.__running:
|
|
|
|
|
r = select.select([f], [], [])
|
|
|
|
|
v = r[0][0].recv()
|
|
|
|
|
if v == None:
|
|
|
|
|
break
|
|
|
|
|
v = v.strip('\n')
|
|
|
|
|
if len(v) == 0:
|
|
|
|
|
break
|
|
|
|
|
r = parser.parse(v)
|
|
|
|
|
self.__o.exec(r)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
(fo, fi,) = Pipe()
|
|
|
|
|
p = Process(target=self.__process, args=(fo,))
|
|
|
|
|
p.start()
|
|
|
|
|
while self.__running:
|
|
|
|
|
v = input("> ")
|
|
|
|
|
if v == "":
|
|
|
|
|
fi.send(None)
|
|
|
|
|
break
|
|
|
|
|
fi.send(v)
|
|
|
|
|
p.join()
|
|
|
|
|
logg.debug('waitget run end')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
ifc = None
|
2024-10-28 00:07:20 +01:00
|
|
|
|
o = Router()
|
2024-11-19 17:03:58 +01:00
|
|
|
|
o.register(CmdId.KEY_CREATE,key_create_handler)
|
|
|
|
|
o.register(CmdId.VOUCHER_MINT, voucher_mint_handler)
|
|
|
|
|
o.register(CmdId.VOUCHER_CREATE, voucher_create_handler)
|
|
|
|
|
o.register(CmdId.VOUCHER_TRANSFER, voucher_transfer_handler)
|
2024-10-28 01:45:07 +01:00
|
|
|
|
|
|
|
|
|
if len(sys.argv) > 1:
|
|
|
|
|
ifc = FileGet(o, sys.argv[1])
|
|
|
|
|
else:
|
|
|
|
|
ifc = WaitGet(o, sys.stdin)
|
|
|
|
|
|
|
|
|
|
ifc.run()
|
|
|
|
|
o.finish()
|