initial commit

This commit is contained in:
lash 2023-08-31 14:21:43 +01:00
commit 7deffc93a4
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
7 changed files with 187 additions and 0 deletions

58
gas3/__init__.py Normal file
View File

@ -0,0 +1,58 @@
# standard imports
import os
import urllib.parse
import logging
import re
# external imports
from leveldir.uuid import UUIDDir
# local imports
from gas3.base import do_yield
from gas3.register import do_register
import gas3.error
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
data_path = os.environ.get('GAS3_DATA_DIR', 'data')
data_dir = UUIDDir(data_path)
re_yield = re.compile('^/yield')
re_register = re.compile('^/register')
def application(env, start_response):
req = urllib.parse.urlparse(env['REQUEST_URI'])
scode = 200
stext = 'OK'
r = ''
if re.match(re_yield, req.path):
r = do_yield(req, env, data_dir)
elif re.match(re_register, req.path):
try:
r = do_register(req, env, data_dir)
except gas3.error.Used:
scode = 410
stext = 'Code already used'
except gas3.error.InvalidInput as e:
scode = 400
stext = 'Malformed request url'
r = str(e)
except FileNotFoundError:
scode = 403
stext = 'No such code'
except Exception as e:
scode = 500
stext = 'Server error'
r = str(e)
else:
r = ''
l = len(r)
status = str(scode) + ' ' + stext
start_response(status, [('Content-Length', str(l))])
return [r.encode('utf-8')]

19
gas3/base.py Normal file
View File

@ -0,0 +1,19 @@
# standard imports
import uuid
import logging
logg = logging.getLogger(__name__)
def do_yield(req, env, data_dir):
u = uuid.uuid4()
data_dir.add(u, b'\x00')
return str(u)
def check(s, data_dir):
p = data_dir.to_filepath(s)
f = open(p, 'rb')
r = f.read(20)
f.close()
return len(r) == 1

6
gas3/error.py Normal file
View File

@ -0,0 +1,6 @@
class InvalidInput(Exception):
pass
class Used(Exception):
pass

39
gas3/register.py Normal file
View File

@ -0,0 +1,39 @@
# standard imports
import logging
# external imports
from chainlib.eth.address import to_checksum_address
from hexathon import strip_0x
# local imports
from gas3.error import InvalidInput
from gas3.error import Used
from gas3.base import check
logg = logging.getLogger(__name__)
def register_address(a):
pass
def do_register(req, env, data_dir):
i = req.path.find('/', 1)
if i == -1:
raise InvalidInput(env.path)
p = req.path[i+1:]
r = None
r = check(p, data_dir)
if not r:
raise Used('already used: ' + p)
v = env['wsgi.input'].read(42)
if type(v) == bytes:
v = v.decode('utf-8')
try:
v = strip_0x(v)
v = to_checksum_address(v)
except:
raise InvalidInput('invalid address: ' + str(v))
data_dir.add(p, bytes.fromhex(v))
return v

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
leveldir~=0.3.3rc1
chainlib-eth~=0.5.2

4
test_requirements.txt Normal file
View File

@ -0,0 +1,4 @@
eth_tester==0.5.0b3
py-evm==0.3.0a20
rlp==2.0.1
coverage==5.5

59
tests/test_register.py Normal file
View File

@ -0,0 +1,59 @@
# standard imports
import io
import os
import unittest
import tempfile
import shutil
import logging
import urllib.parse
# external imports
from chainlib.eth.unittest.ethtester import EthTesterCase
from hexathon import same as is_same_hex
from leveldir.uuid import UUIDDir
from gas3.base import do_yield
from gas3.base import check
from gas3.register import do_register
import gas3.error
logging.basicConfig(level=logging.DEBUG)
class TestRegister(EthTesterCase):
def setUp(self):
super(TestRegister, self).setUp()
self.data_path = tempfile.mkdtemp()
self.data_dir = UUIDDir(self.data_path)
def test_yield(self):
u = do_yield(None, {}, self.data_dir)
p = check(u, self.data_dir)
self.assertTrue(os.path.exists(p))
def test_register(self):
u = do_yield(None, {}, self.data_dir)
req = urllib.parse.urlparse('http://localhost/register/' + u)
address_file = io.StringIO()
address_file.write(self.accounts[0] + '\n')
address_file.seek(0)
env = {
'wsgi.input': address_file,
}
r = do_register(req, env, self.data_dir)
self.assertEqual(len(r), 40)
with self.assertRaises(gas3.error.Used):
r = do_register(req, env, self.data_dir)
fp = self.data_dir.to_filepath(u)
f = open(fp, 'rb')
r = f.read()
f.close()
self.assertTrue(is_same_hex(r.hex(), self.accounts[0]))
if __name__ == '__main__':
unittest.main()