usawa

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | Submodules | LICENSE

commit f3f2c3c7b5f5f770b785b7bdbd29a1c022c63594
parent 7a5464f4646437451fadc1b15c96b7452c1985a3
Author: lash <dev@holbrook.no>
Date:   Tue,  9 Dec 2025 22:20:50 +0000

Add store implementation for entry

Diffstat:
Mdummy/svcontas/entry.py | 36+++++++++++++++++++++++++-----------
Mdummy/svcontas/error.py | 4++++
Mdummy/svcontas/store.py | 37+++++++++++++++++++++++++++++++------
Mdummy/tests/entry.py | 2+-
Mdummy/tests/ledger.py | 2--
Adummy/tests/store.py | 43+++++++++++++++++++++++++++++++++++++++++++
6 files changed, 104 insertions(+), 20 deletions(-)

diff --git a/dummy/svcontas/entry.py b/dummy/svcontas/entry.py @@ -9,7 +9,7 @@ import rencode from .constant import DEFAULTPARENT, NSPREFIX from .crypto import DemoWallet -from .error import ACLError +from .error import ACLError, VerifyError from .xml import nsmap logg = logging.getLogger('svcontas.entry') @@ -172,15 +172,27 @@ class Entry: return (z, r, b,) - def wrap(self, wallet): - (digest, sig, data) = self.sign(wallet) - pubkey = wallet.pubkey() + def wrap(self, wallet=None): + digest = None + sig = None + data = None + if wallet != None: + (digest, sig, data) = self.sign(wallet) + hdr = [] + sigs = [] + for k in self.sigs: + hdr.append([ + KeyStoreFormat.LITERAL.value, + bytes.fromhex(k) + ]) + sigs.append(self.sigs[k]) + + if len(sigs) == 0: + raise VerifyError() + d = [ - [ - KeyStoreFormat.LITERAL.value, - pubkey, - ], - sig, + hdr, + sigs, data, ] return rencode.dumps(d) @@ -189,7 +201,8 @@ class Entry: @staticmethod def unwrap(data, acl=None): v = rencode.loads(data) - pubkey_bytes = v[0][1] + # TODO: demo only takes into account single signature + pubkey_bytes = v[0][0][1] if acl != None: label = None try: @@ -199,7 +212,8 @@ class Entry: if not acl.may(label, 0x01): raise ACLError() wallet = DemoWallet(publickey=pubkey_bytes) - sig = v[1] + # TODO: demo only takes into account single signature + sig = v[1][0] entry = Entry.deserialize(v[2]) (z, b) = entry.sum() wallet.verify(z, sig) diff --git a/dummy/svcontas/error.py b/dummy/svcontas/error.py @@ -1,2 +1,6 @@ class ACLError(Exception): pass + + +class VerifyError(Exception): + pass diff --git a/dummy/svcontas/store.py b/dummy/svcontas/store.py @@ -8,25 +8,31 @@ from .entry import Entry PFX_LEDGER = b'\x01' -PFX_ENTRY = b'\x02' +PFX_LEDGER_LOCK = b'\x02' +PFX_ENTRY = b'\x04' def pfx_ledger_topic(topic): r = PFX_LEDGER + topic return r +def pfx_ledger_lock(topic): + r = PFX_LEDGER_LOCK + topic + return r + def pfx_ledger(ledger): - if not isintance(ledger, Ledger): + if not isinstance(ledger, Ledger): raise ValueError('invalid ledger') return pfx_ledger_topic(topic) def pfx_entry(ledger, entry): - if not isintance(entry, Entry): + if not isinstance(entry, Entry): raise ValueError('invalid entry') - if not isintance(ledger, Ledger): + if not isinstance(ledger, Ledger): raise ValueError('invalid ledger') + return PFX_LEDGER + ledger.topic + entry.serial.to_bytes(8, byteorder='big') class LedgerStore(Interface): @@ -52,5 +58,24 @@ class LedgerStore(Interface): self.ledger.serial = serial - def put(self): - pass + def lock(self): + k = pfx_ledger_lock(self.ledger.topic) + v = None + # TODO: needs to be an atomic routine + try: + v = self.__o.get(k) + except KeyError: + raise PermissionError() + self.__o.put(k, 0x01, exist_ok) + # atomic until here + + + def unlock(self): + k = pfx_ledger_lock(self.ledger.topic) + v = self.__o.delete(k) + + + def add_entry(self, entry): + k = pfx_entry(self.ledger, entry) + v = entry.wrap() + self.__o.put(k, v) diff --git a/dummy/tests/entry.py b/dummy/tests/entry.py @@ -48,7 +48,7 @@ class TestEntry(unittest.TestCase): src = EntryPart('income', 'foo', 1337, src=True) o = Entry(src, dst, 'USD', 42, datetime.datetime.strptime('2025-11-11', '%Y-%m-%d'), parent=self.parent, ref=self.ref, description=self.description, tx_datereg=self.dtreg) wallet = DemoWallet() - data = o.wrap(wallet) + data = o.wrap(wallet=wallet) r = Entry.unwrap(data) diff --git a/dummy/tests/ledger.py b/dummy/tests/ledger.py @@ -59,8 +59,6 @@ class TestLedger(unittest.TestCase): v.sign(wallet) o.add_entry(v) - print(o.to_string()) - if __name__ == '__main__': unittest.main() diff --git a/dummy/tests/store.py b/dummy/tests/store.py @@ -0,0 +1,43 @@ +import logging +import datetime +import unittest +import os +import copy + +import lxml.etree +from whee.mem import MemStore + +from svcontas import Ledger, UnitIndex, EntryPart, Entry, DemoWallet +from svcontas.store import LedgerStore + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() + +testdir = os.path.realpath(os.path.dirname(__file__)) + + +class TestStore(unittest.TestCase): + + def setUp(self): + self.store = MemStore() + self.parent = bytes.fromhex('0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6') + self.ref = '1bda7dfa-b8fd-400d-8b42-1d2861ad7f70' + self.description = "foo bar baz" + self.dtreg = datetime.datetime.now() + + + def test_store_entry(self): + uidx = UnitIndex('FOO') + ledger = Ledger(uidx) + store = LedgerStore(self.store, ledger) + dst = EntryPart('asset', 'foo', 1337) + src = EntryPart('income', 'foo', 1337, src=True) + o = Entry(src, dst, 'USD', 42, datetime.datetime.strptime('2025-11-11', '%Y-%m-%d'), parent=self.parent, ref=self.ref, description=self.description, tx_datereg=self.dtreg) + wallet = DemoWallet() + #data = o.wrap(wallet) + o.sign(wallet) + store.add_entry(o) + + +if __name__ == '__main__': + unittest.main()