commit a8ee942152ad43bebd79f8ce596c9ebdbaf4b994
parent 67c546dc16456db2462c72dd7f9f85eb7ecdc67a
Author: lash <dev@holbrook.no>
Date: Wed, 11 Feb 2026 13:46:04 +0000
Add first part of socket command handler
Diffstat:
8 files changed, 196 insertions(+), 27 deletions(-)
diff --git a/dummy/tests/handler.py b/dummy/tests/handler.py
@@ -0,0 +1,33 @@
+import logging
+import datetime
+import unittest
+import os
+import copy
+
+import lxml.etree
+from whee.mem import MemStore
+
+from usawa.store import LedgerStore
+from usawa.service import Handler
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+testdir = os.path.realpath(os.path.dirname(__file__))
+
+
+class TestHandler(unittest.TestCase):
+
+ def setUp(self):
+ self.store = MemStore()
+ self.handler = Handler()
+
+
+ def test_handler(self):
+ b = b'\x00\x00\x00\x00'
+ r = self.handler.scan(b)
+ self.assertEqual(r, 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/dummy/usawa/context.py b/dummy/usawa/context.py
@@ -0,0 +1,2 @@
+class Context:
+ pass
diff --git a/dummy/usawa/crypto.py b/dummy/usawa/crypto.py
@@ -306,7 +306,7 @@ class ACL:
def have(self, who):
if isinstance(who, bytes):
who = who.hex()
- return self.rev[who]
+ return self.rev.get(who) != None
"""Check if key is valid for the given purpose.
diff --git a/dummy/usawa/ledger.py b/dummy/usawa/ledger.py
@@ -280,12 +280,14 @@ class Ledger:
"""
def set_wallet(self, v):
self.wallet = v
+ pubkey = self.wallet.pubkey()
if self.acl == None:
self.acl = ACL.from_wallet(self.wallet)
+ elif not self.acl.have(pubkey):
+ self.acl.add(pubkey)
- v = self.wallet.pubkey()
try:
- self.sigs[v]
+ self.sigs[pubkey]
return
except KeyError:
pass
@@ -560,6 +562,7 @@ class Ledger:
ledger.apply_entries(tree)
logg.debug('loaded ledger tree last serial {}'.format(ledger.serial))
+
return ledger.check()
diff --git a/dummy/usawa/runnable/server.py b/dummy/usawa/runnable/server.py
@@ -1,34 +1,44 @@
-import socket
import logging
+import argparse
+#import threading
+
+from usawa import Ledger, Entry, EntryPart, DemoWallet, ACL, UnitIndex, load
+from usawa.context import Context
+from usawa.store import LedgerStore
+from usawa.service import Handler, SocketServer
+from whee.valkey import ValkeyStore
+
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
+READ_SIZE = 2048
+LISTEN_COUNT = 5
+
def parse(v):
logg.debug('parsing {}'.format(v.hex()))
+
def main():
- scks = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- scks.bind(('', 32327,))
- scks.listen(1)
- while True:
- logg.debug('waiting for connection')
- (sckc, address) = scks.accept()
- logg.info('connect: {}'.format(address))
- c = 0
- data = bytearray()
- while True:
- b = sckc.recv(2048)
- if len(b) == 0:
- logg.info('connection broken: {}'.format(address))
- break
- for v in b:
- if v == 0x0a:
- logg.debug('command boundary reached')
- parse(bytes(data))
- data.append(v)
- logg.debug('read {}: {}'.format(len(b), b.hex()))
+ argp = argparse.ArgumentParser()
+ argp.add_argument('-k', action='append', type=str, default=[], help='Add public key to list of valid signers')
+ argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from XML file')
+ arg = argp.parse_args()
+
+ acl = ACL()
+ for k in arg.k:
+ acl.add(k)
+
+ ledger = None
+ ledger_tree = load(arg.ledger_xml_file)
+ uidx = UnitIndex.from_tree(ledger_tree)
+ ledger = Ledger.from_tree(ledger_tree, acl=acl)
+ db = ValkeyStore('')
+ store = LedgerStore(db, ledger)
+
+ srv = SocketServer(store)
+ #srv.start()
if __name__ == '__main__':
diff --git a/dummy/usawa/runnable/view.py b/dummy/usawa/runnable/view.py
@@ -56,10 +56,10 @@ ctx = Context.from_args(arg)
ledger = None
ledger_tree = load(arg.ledger_xml_file)
uidx = UnitIndex.from_tree(ledger_tree)
-ledger = Ledger.from_tree(ledger_tree) #, uidx)
+ledger = Ledger.from_tree(ledger_tree)
-db = ValkeyStore('')
-store = LedgerStore(db, ledger)
+storedb = ValkeyStore('')
+store = LedgerStore(storedb, ledger)
pk = store.get_key()
wallet = DemoWallet(privatekey=pk)
store.load()
diff --git a/dummy/usawa/service.py b/dummy/usawa/service.py
@@ -0,0 +1,112 @@
+import logging
+import socket
+
+logg = logging.getLogger('handler')
+
+
+class Handler:
+
+ def __init__(self):
+ self.cmd = None
+ self.buf = b''
+ self.c = 0
+ self.l = 0
+ self.state = 0
+
+
+ def scan(self, v):
+ self.buf = v
+ if len(v) == 0:
+ return -1
+ if self.cmd == None:
+ r = self.handle_cmd()
+ if r > 0:
+ return r
+ if self.handle_len() > 0:
+ return False
+ if self.handle_collect() > 0:
+ return False
+ if self.cmd == 0:
+ return self.handle_getlastserial()
+ raise ValueError()
+
+
+ def handle_cmd(self):
+ self.cmd = self.buf[0]
+ self.c = 1
+ self.l = -1
+ self.state = 1
+ return self.handle_len()
+
+
+ def __remainder(self):
+ v = self.buf[self.c:]
+ return (len(v), v,)
+
+
+ def handle_len(self):
+ (l, v) = self.__remainder()
+ if l == 0:
+ return 0
+ if l < 3:
+ return 3 - l
+ self.l = int.from_bytes(v, byteorder='big')
+ self.c += 3
+ return 0
+
+
+ def handle_collect(self):
+ (l, v) = self.__remainder()
+ self.c += l
+ c = self.c - 3
+ if c >= l:
+ self.r = True
+ self.c = l + 3
+ c = l
+ logg.debug('have cmd {} len {} arg {}'.format(self.cmd, self.l, self.buf[3:self.c].hex()))
+ return l - c
+
+
+ def handle_getlastserial(self):
+ logg.debug('would get last serial')
+ self.state = 0
+ return 0
+
+
+class SocketServer:
+
+ def __init__(self, store):
+ self.scks = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.store = store
+
+
+ def start(self):
+ scks.bind(('', 32327,))
+ scks.listen(LISTEN_COUNT)
+ while True:
+ logg.debug('waiting for connection')
+ (sckc, address) = scks.accept()
+ logg.info('connect: {}'.format(address))
+ #th = threading.Thread(target=self.receive, args=(sckc, address))
+ #th.start()
+ self.receive(sckc, address)
+
+
+ def receive(self, sckc, address):
+ c = 0
+ data = bytearray()
+ handler = Handler()
+ while True:
+ b = sckc.recv(READ_SIZE)
+ if len(b) == 0:
+ logg.info('connection broken: {}'.format(address))
+ break
+ for v in b:
+ if v == 0x0a:
+ logg.debug('command boundary reached')
+ parse(bytes(data))
+ data.append(v)
+ logg.debug('read {}: {}'.format(len(b), b.hex()))
+
+
+
diff --git a/dummy/usawa/store.py b/dummy/usawa/store.py
@@ -169,6 +169,7 @@ class LedgerStore(Interface):
if update_ledger:
self.ledger.add_entry(entry)
+
"""Restore an entry from data from the store.
The entry is referenced by its serial number within the store's ledger. It can either be specified as an integer, or an entry object with the serial number property set accordingly.
@@ -244,3 +245,11 @@ class LedgerStore(Interface):
pubkey = self.__o.get(k)
k = pfx_key(pubkey=pubkey)
return self.__o.get(k)
+
+
+ def put(self, k, v):
+ return self.__o.put(k, v)
+
+
+ def get(self, k):
+ return self.__o.get(k)