usawa

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

commit b7f02d9064e2615043978e48e109dfef3fd0b2c9
parent d2fc48a40122066dbcd7574eed482204d252b84e
Author: lash <dev@holbrook.no>
Date:   Thu,  6 Nov 2025 00:08:35 +0000

Add xml export

Diffstat:
Mdummy/create.py | 14++++++++++++++
Mdummy/running.xml | 9+++++----
Mdummy/svcontas/__init__.py | 94++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/dummy/create.py b/dummy/create.py @@ -16,6 +16,16 @@ state_serial = 0 state_digest = b'00' * 64 +class DemoWallet: + + def sign(self, v): + r = pk.sign(v) + return r.signature + + def pubkey(self): + return pubk.encode() + + def save_state(): f = open('.state', 'wb') b = state_serial.to_bytes(8, byteorder='big') @@ -58,6 +68,10 @@ if __name__ == '__main__': state_serial += 1 entry = Entry(arg.t, amount, arg.u, state_serial, arg.a, arg.date) + wallet = DemoWallet() ledger.add_entry(entry) + entry.package(wallet) + r = lxml.etree.tostring(entry.to_tree()) + print(r.decode('utf-8')) save_state() diff --git a/dummy/running.xml b/dummy/running.xml @@ -18,8 +18,8 @@ <identity keyid="f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" didtype="web">holbrook.no</identity> <incoming serial="231"> <digest algo="sha512">b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944cb5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c</digest> - <sig keyid="58851ae2166b3f1454193e0a7e821402dd1c1a91">1f74a9c0196a025f27d4e940c4abedfa2d37504f268aea359659cb65b85bd4d7974369507950006964c93391d3d4580ab8064f6d30a62908468ef771be952e95</sig> - <sig keyid="566c38287d3f31c7e50836cae58e426c6bccc52d">117a57c72ed210b91469307a1c2e73fe2d5ee306cd8ccf1a9db4ecb15d38ecbbfc97d62fec4ab8aadb08c531f2d1ede34cb6e4d3987bcba63322a0767e532e13</sig> + <sig type='ed25519' keyid="58851ae2166b3f1454193e0a7e821402dd1c1a91">1f74a9c0196a025f27d4e940c4abedfa2d37504f268aea359659cb65b85bd4d7974369507950006964c93391d3d4580ab8064f6d30a62908468ef771be952e95</sig> + <sig type='ed25519' keyid="566c38287d3f31c7e50836cae58e426c6bccc52d">117a57c72ed210b91469307a1c2e73fe2d5ee306cd8ccf1a9db4ecb15d38ecbbfc97d62fec4ab8aadb08c531f2d1ede34cb6e4d3987bcba63322a0767e532e13</sig> <real unit="BTC"> <asset>6323141</asset> <liability>0</liability> @@ -53,7 +53,7 @@ <digest algo="sha512">777b30c8fc40aea3c717777831a05c9f29c7b6735f1573e9b0b55373c264f6f3777b30c8fc40aea3c717777831a05c9f29c7b6735f1573e9b0b55373c264f6f3</digest> </attachment> </data> - <sig keyid="e242ed3bffccdf271b7fbaf34ed72d089537b42f">0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6/</sig> + <sig type='ed25519' keyid="e242ed3bffccdf271b7fbaf34ed72d089537b42f">0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6/</sig> </entry> <entry type="liability"> <data> @@ -62,10 +62,11 @@ <serial>245</serial> <unit>BTC</unit> <date>2025-11-03</date> + <dateTimeRegistered>2025-11-05T12:24:05Z</dateTimeRegistered> <account>Construction</account> <description>Install AC</description> <amount>1000000</amount> </data> - <sig keyid="f1d2d2f924e986ac86fdf7b36c94bcdf32beec15">cc06808cbbee0510331aa97974132e8dc296aeb795be229d064bae784b0a87a5cf4281d82e8c99271b75db2148f08a026c1a60ed9cabdb8cac6d24242dac4063</sig> + <sig type='ed25519' keyid="f1d2d2f924e986ac86fdf7b36c94bcdf32beec15">cc06808cbbee0510331aa97974132e8dc296aeb795be229d064bae784b0a87a5cf4281d82e8c99271b75db2148f08a026c1a60ed9cabdb8cac6d24242dac4063</sig> </entry> </ledger> diff --git a/dummy/svcontas/__init__.py b/dummy/svcontas/__init__.py @@ -1,12 +1,17 @@ import sys import logging import datetime +import uuid +import hashlib from lxml import etree +import rencode logging.basicConfig(level=logging.DEBUG) logg = logging.getLogger() +DEFAULTPARENT = b'\x00' * 64 + class NoopSigVerifier: @@ -84,8 +89,18 @@ class UnitIndex: class Entry: - def __init__(self, typ, amount, unit, serial, account, tx_date, description=None, parent=None): + # TODO: parent only 0 if serial 0 + def __init__(self, typ, amount, unit, serial, account, tx_date, ref=None, description=None, parent=None): self.typ = typ + if isinstance(parent, str): + parent = bytes.fromhex(parent) + elif parent == None: + parent = DEFAULTPARENT + elif len(parent) != 64: + raise ValueError('invalid parent hash') + if ref == None: + ref = str(uuid.uuid4()) + self.ref = ref self.parent = parent self.amount = amount self.unit = unit @@ -95,6 +110,7 @@ class Entry: self.dtreg = datetime.datetime.now() self.attachment = [] self.sigs = {} + self.description = description def attach(self, mime, algo, digest, description=None, slug=None): @@ -117,6 +133,82 @@ class Entry: return r + def serialize(self): + d = [ + self.parent, + self.serial, + self.ref, + self.dtreg.strftime('%Y%m%d%H%M%S'), + self.dt.strftime('%Y%m%d'), + self.unit, + self.amount, + ] + return rencode.dumps(d) + + + def package(self, wallet): + b = self.serialize() + h = hashlib.new('sha512') + h.update(b) + z = h.digest() + r = wallet.sign(z) + pubk_hx = wallet.pubkey().hex() + self.sigs[pubk_hx] = r + logg.debug('added signature from key {}'.format(pubk_hx)) + return (b, z, r,) + + + def to_tree(self): + tree = etree.Element('entry', type=self.typ) + data = etree.Element('data') + + o = etree.Element('parent') + o.text = self.parent.hex() + data.append(o) + + o = etree.Element('ref') + o.text = self.ref + data.append(o) + + o = etree.Element('serial') + o.text = str(self.serial) + data.append(o) + + o = etree.Element('unit') + o.text = self.unit + data.append(o) + + o = etree.Element('date') + o.text = self.dt.strftime('%Y-%m-%d') + data.append(o) + + o = etree.Element('dateTimeRegistered') + o.text = self.dt.strftime('%Y-%m-%dT%H:%M:%SZ') + data.append(o) + + o = etree.Element('account') + o.text = self.account + data.append(o) + + if self.description: + o = etree.Element('description') + o.text = self.account + data.append(o) + + o = etree.Element('amount') + o.text = self.account + data.append(o) + + tree.append(data) + + for k in self.sigs.keys(): + o = etree.Element('sig', type='ed25519', keyid=k) + o.text = self.sigs[k].hex() + tree.append(o) + + return tree + + class RunningTotal: def __init__(self, sym, unitindex, asset=0, liability=0, income=0, expense=0):