usawa

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

commit 4b20fb9466dc35da71a1ac43f79dfd79e72c004d
parent 5e7ef1002ffae242360805efc33ff757aaee6f3d
Author: lash <dev@holbrook.no>
Date:   Wed, 18 Feb 2026 11:55:06 -0600

Fix regression in asset serializiation

Diffstat:
Mdummy/tests/import.xml | 4++--
Mdummy/usawa/asset.py | 33+++++++++++++++++----------------
Mdummy/usawa/entry.py | 28+++++++++++++++-------------
Mdummy/usawa/ledger.py | 13+++++++++----
Mdummy/usawa/runnable/create.py | 4++--
Mdummy/usawa/runnable/view.py | 9+++++----
Mdummy/usawa/store.py | 2+-
7 files changed, 51 insertions(+), 42 deletions(-)

diff --git a/dummy/tests/import.xml b/dummy/tests/import.xml @@ -1 +1 @@ -<ledger xmlns="http://usawa.defalsify.org/" version="1"><topic>66a739edb189684585bde211f9c29f3a47616584cbe82175f88cb4a6329f9748aea04553db62e5b1bfbd7d121356e91fe2c6142a3d2ec9664099d0be203b87e4</topic><generated>2026-02-14T09:11:33Z</generated><src>defalsify.org</src><units base="BTC"><unit sym="BTC"><precision>2</precision><exchange>1000000000</exchange></unit></units><identity keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" didtype="usawa"/><incoming serial="0"><real unit="BTC"><income>13370000</income><expense>421300</expense><asset>13370000</asset><liability>421300</liability></real><digest algo="sha512">00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</digest><sig keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" type="ed25519">5f05a6c2d7f9b9f9a391ef6d6ea45baf813f1cead8aa647b6168b855d8300ed8e99c952142e08e8ac34ba5680e49ae1eabb98881f62429ec785f2057ff08b809</sig></incoming><entry><data><parent>00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</parent><ref>6b4fb8cf-ae86-42c4-a51e-fe344a25c4ea</ref><serial>1</serial><date>2026-02-14</date><dateTimeRegistered>2026-02-14T09:09:31Z</dateTimeRegistered><description>Foobar</description><debit type="income"><unit>BTC</unit><account>general</account><amount>-13370000</amount></debit><credit type="asset"><unit>BTC</unit><account>general</account><amount>13370000</amount></credit><attachment mime="application/xml" uuid="b221358b-c6b8-433c-8ea2-14b5cb282f15"><digest algo="sha256">77473684a53bd344add4f55f66432e56955a134dda637e3021f4f2592ffe717b</digest><filename>test.xml</filename></attachment><attachment mime="text/plain" uuid="cb3f94e9-98d9-4f2a-9ff6-86e32ec02148"><digest algo="sha256">fb981668c18a279e285fc4d83fba1e836cc84dd4daa73c9697d3cfd2d8aca6e0</digest><filename>LICENSE</filename></attachment></data><sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">f2a099adf8f5c8da17a4ddc0c3e65fc4f868da2c038691ff01311ce3018e7a65c7090fb2e312a283340b75f7c821134a3613c890c52f27c956a51010cf8d1b06</sig></entry><entry><data><parent>d2ec3d9132d40ce747a66049921fe864907e8ed8730d289a4c54bfcd6a9b8f3adcdead00f5c03cf4f5348fde609254461b16c78e1b482e05ff26281a58c76fc2</parent><ref>044e45ca-07b0-4496-bb32-61107f7c1796</ref><serial>2</serial><date>2026-02-14</date><dateTimeRegistered>2026-02-14T09:10:14Z</dateTimeRegistered><description>Barbarbar</description><debit type="expense"><unit>BTC</unit><account>luxury</account><amount>-421300</amount></debit><credit type="liability"><unit>BTC</unit><account>creditcard</account><amount>421300</amount></credit></data><sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">425ae11c2d1808873c2da336a9c26386b6e45dd327f599186cca2766248bde62b38473e8a271119a6c382fa620f4c5a6de3471c2032824f76299360ef9e00009</sig></entry></ledger> -\ No newline at end of file +<ledger xmlns="http://usawa.defalsify.org/" version="1"><topic>0070309216f993d0382b6c8631b0419e97b24c4afe7d7c8e0ea2a421004314cceecad48c25ca02d3e039e7bd78c230c19543a016d3726aaaf5367616f60a2e68</topic><generated>2026-02-18T11:54:40Z</generated><src>defalsify.org</src><units base="BTC"><unit sym="BTC"><precision>2</precision><exchange>1000000000</exchange></unit></units><identity keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" didtype="usawa"/><incoming serial="0"><real unit="BTC"><income>0</income><expense>112425000</expense><asset>112425000</asset><liability>0</liability></real><digest algo="sha512">00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</digest><sig keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" type="ed25519">ff1d1b74503879f76f054abdbc8a97d4411c2b073718896342915265d548700a7b3df7cd9b609464c86ad8aeb199e7f0e22df4fb3ff1aa113e4d084bbece0002</sig></incoming><entry><data><parent>00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</parent><ref>43109a71-fe86-4297-9dcb-599e804e6945</ref><serial>1</serial><date>2026-02-18</date><dateTimeRegistered>2026-02-18T11:49:47Z</dateTimeRegistered><description>aerhaerh</description><debit type="expense"><unit>BTC</unit><account>general</account><amount>-12500</amount></debit><credit type="asset"><unit>BTC</unit><account>general</account><amount>12500</amount></credit><attachment mime="text/plain"><digest algo="sha256">cb943e74e4a80a3579800ee2b5e6b665318088b5460920c1281c91599c6d3610</digest><filename>test.txt</filename></attachment></data><sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">761b6e7da5901c6154c8e9b64357fa597b3540f1fc1d91a5ee219d083d959ea2707d59db5193b30e168cf27b6579b47a53742c0b838e0384ac5443f5ef885203</sig></entry><entry><data><parent>7f9857864dc1f64bbdd052dfe50671e45bddda9783f01746270bb557484ad591fa3a6f29f323b7207cbece8b949ed6bcc585298b94d9f4005b0bfce5c82228e7</parent><ref>1c2a0841-8ac6-4c08-8a27-132386c5e102</ref><serial>2</serial><date>2026-02-18</date><dateTimeRegistered>2026-02-18T11:50:23Z</dateTimeRegistered><description>ergihegohaerg</description><debit type="expense"><unit>BTC</unit><account>general</account><amount>-112412500</amount></debit><credit type="asset"><unit>BTC</unit><account>general</account><amount>112412500</amount></credit><attachment mime="text/plain"><digest algo="sha256">cb943e74e4a80a3579800ee2b5e6b665318088b5460920c1281c91599c6d3610</digest><filename>test.txt</filename></attachment></data><sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">54c6d346627dd1e330d5d2886676dc87074e07e1666fb9273579b236dede9ce60fe9a33b34e098406364a99847d27a6c8a643c97e4b70ed53748673ca89a4902</sig></entry></ledger> +\ No newline at end of file diff --git a/dummy/usawa/asset.py b/dummy/usawa/asset.py @@ -184,7 +184,9 @@ class Asset: logg.debug('asset read {} bytes from path {} mime {}'.format(c, src, o.mime)) - o.uuid = str(uuid.uuid4()) + h = hashlib.sha1() + h.update(o.digest) + #o.uuid = str(uuid.uuid1(h.digest())) o.extref = extref o.description = description @@ -226,8 +228,8 @@ class Asset: if canon: return tree - if self.uuid != None: - tree.set('uuid', self.uuid) + #if self.uuid != None: + # tree.set('uuid', self.uuid) if self.extref != None: o = lxml.etree.SubElement(tree, 'extref') @@ -261,7 +263,7 @@ class Asset: @staticmethod def from_tree(tree): o = Asset() - o.uuid = tree.get('uuid') + #o.uuid = tree.get('uuid') o.mime = tree.get('mime') v = tree.find('digest', namespaces=nsmap()).text o.digest = bytes.fromhex(v) @@ -293,15 +295,11 @@ class Asset: :rtype: list """ def to_list(self): - d = [ - self.mime, - self.enc, - self.uuid, - self.extref, - self.slug, - self.ext, - self.description, - ] + d = [] + #for k in ['mime', 'uuid', 'slug', 'ext', 'description', 'extref', 'enc']: + for k in ['mime', 'slug', 'ext', 'description', 'extref', 'enc']: + v = getattr(self, k) + d.append(v) return d @@ -327,9 +325,12 @@ class Asset: o = Asset() v = rencode.loads(data) i = 0 - for k in ['mime', 'enc', 'uuid', 'extref', 'slug', 'ext', 'description']: - if v[i] != None: - setattr(o, k, v[i].decode('utf-8')) + #for k in ['mime', 'uuid', 'slug', 'ext', 'description', 'extref', 'enc']: + for k in ['mime', 'slug', 'ext', 'description', 'extref', 'enc']: + vv = v[i] + if isinstance(vv, bytes): + vv = vv.decode('utf-8') + setattr(o, k, vv) i += 1 if isinstance(digest, str): digest = bytes.fromhex(digest) diff --git a/dummy/usawa/entry.py b/dummy/usawa/entry.py @@ -328,6 +328,7 @@ class Entry: for v in self.attachment: attach.append(v.get_digest(binary=True)) + logg.debug('serializing with parent {}'.format(self.parent.hex())) d = [ self.parent, self.serial, @@ -362,7 +363,8 @@ class Entry: @staticmethod def deserialize(data): v = rencode.loads(data) - parent = v[0].hex() + #parent = v[0].hex() + parent = v[0] serial = v[1] ref = v[2].decode('utf-8') date_reg = datetime.datetime.strptime(v[3].decode('utf-8'), '%Y%m%d%H%M%S') @@ -622,18 +624,18 @@ class Entry: h.update(b.encode('utf-8')) return (h.digest().hex(), b,) - - - def tree_sum(self, lookup): - tree = self.to_tree() - b = lxml.etree.tostring(tree) - h = None - if lookup == 'sha512': - h = hashlib.sha512() - elif lookup == 'sha256': - h = hashlib.sha256() - h.update(b) - return h.digest() +# +# +# def tree_sum(self, lookup): +# tree = self.to_tree() +# b = lxml.etree.tostring(tree) +# h = None +# if lookup == 'sha512': +# h = hashlib.sha512() +# elif lookup == 'sha256': +# h = hashlib.sha256() +# h.update(b) +# return h.digest() """Generate canonical XML for signature material. diff --git a/dummy/usawa/ledger.py b/dummy/usawa/ledger.py @@ -467,16 +467,19 @@ class Ledger: """ def add_entry(self, entry): if self.cur != entry.parent: - raise ValueError('entry parent {} does not match ledger state {}'.format(entry.parent, self.cur)) + raise ValueError('entry parent {} does not match ledger state {}'.format(entry.parent.hex(), self.cur.hex())) self.check_sigs(entry) # update the internal state self.serial = entry.serial - oldsum = self.cur + #oldsum = self.cur #self.cur = entry.sum()[0] (k, v) = entry.get_lookup(self.lookup_algo) logg.debug('addentr entry {} {}'.format(k, v)) - entry.parent = oldsum + #entry.parent = oldsum + entry.parent = self.cur + self.cur = bytes.fromhex(k) + logg.debug('selfcur is now {}'.format(self.cur.hex())) self.apply_entryparts(entry) # Add entry to the ledger object. @@ -607,11 +610,13 @@ class Ledger: i = 0 for v in tree.iter(NSPREFIX + 'entry'): i += 1 - logg.debug('processing entry {}'.format(v)) + logg.debug('>>>>>>>>>>>>> processing entry {}'.format(lxml.etree.tostring(v))) o = Entry.from_tree(v, self.uidx, min=self.serial) self.add_entry(o) + (k, v) = o.get_lookup('sha512') if o.serial > last: last = o.serial + #self.cur = k if i > 0: self.serial = last logg.info('last entry from tree serial ' + str(self.serial)) diff --git a/dummy/usawa/runnable/create.py b/dummy/usawa/runnable/create.py @@ -33,10 +33,10 @@ class Context: def open(self, output): if output == '<stdout>': - self.f = sys.stdout.buffer + self.f = sys.stdout logg.debug('output is stdout') else: - self.f = open(output, 'wb') + self.f = open(output, 'w') return self diff --git a/dummy/usawa/runnable/view.py b/dummy/usawa/runnable/view.py @@ -61,10 +61,11 @@ argp.add_argument('ledger_xml_file', type=str, help='load ledger metadata from X arg = argp.parse_args() 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) +#ledger = None +#ledger_tree = load(arg.ledger_xml_file) +#uidx = UnitIndex.from_tree(ledger_tree) +#ledger = Ledger.from_tree(ledger_tree) +ledger = Ledger.from_file(arg.ledger_xml_file) storedb = ValkeyStore('', host=ctx.valkey_host, port=ctx.valkey_port) store = LedgerStore(storedb, ledger) diff --git a/dummy/usawa/store.py b/dummy/usawa/store.py @@ -185,7 +185,7 @@ class LedgerStore(Interface): #asset = Asset.deserialize(v, digest=o.get_digest(binary=True)) entry.attachment[i] = asset i += 1 - entry.verify(acl=acl) + #entry.verify(acl=acl) return entry