commit 4ca60c282d2f913eb1eabae2d5fc1f0fdbda7f88
parent 6ea284af227c41e6a25705c49348fb6ba18efe59
Author: lash <dev@holbrook.no>
Date: Sat, 14 Feb 2026 11:54:44 +0000
Update texinfo docs, add enc to asset serialize
Diffstat:
16 files changed, 332 insertions(+), 173 deletions(-)
diff --git a/dummy/doc/accounts.texi b/dummy/doc/accounts.texi
@@ -1,8 +1,10 @@
+@anchor{accounts}
@chapter Accounts
Accounts are made up of two parts, @emph{type} and @emph{path}.
@anchor{account_type}
+@section Types
There are four account types:
@itemize
@@ -12,7 +14,26 @@ There are four account types:
@item @strong{liability}, representing value owed in the ledger.
@end itemize
+@anchor{account_value}
+@subsection Values
+
+Values for each type are intepreted according as follows:
+
+A @emph{positive} value for @strong{income} or @strong{asset} means an @emph{increase} in value.
+A @emph{positive} value for @strong{expense} or @strong{liability} means a @emph{decrease} in value.
+
+Consider the following examples:
+
+@itemize
+@item Taking out credit card debt (a @emph{liability}) could be a @emph{positive debit value} for @strong{liability} (transaction leads to more liability) and a @emph{positive credit value} for @strong{asset} (the borrowed value the liability yields, e.g. in cash).
+@item Paying back credit card debt (a @emph{liability}) could be a @emph{negative debit value} for @strong{asset} (àsset has less value), and a @emph{negative credit value} for @strong{liability} (transaction leads to less liability).
+@item Crediting an @emph{issued invoice} that has already been paid could be a @emph{negative debit value} for @strong{income}, and a @emph{positive debit value} for @strong{liability} (i.e. the pending refund).
+@end itemize
+
+
@anchor{account_path}
+@section Path
+
Under each type, a path-like identifier may be freely chosen to subdivide the context under each type. This context can in turn be used to obtain granular balances and totals.
For example, @code{rents/Apartment A} could subdivide an @code{income} account type to separate it from @code{rents/Apartment B}
diff --git a/dummy/doc/appendix.texi b/dummy/doc/appendix.texi
@@ -2,8 +2,6 @@
@appendix XML schema
@example
-<?xml version="1.0" ?>
-
<xs:schema xmlns:xs = "http://www.w3.org/2001/XMLSchema"
targetNamespace = "http://usawa.defalsify.org/"
xmlns = "http://usawa.defalsify.org/"
@@ -12,15 +10,17 @@
<xs:element name="ledger">
<xs:complexType>
<xs:sequence>
- <xs:element name="uuid" type="xs:string" minOccurs="0" maxOccurs="1" />
- <xs:element name="topic" type="xs:string" /> <xs:element name="generated" type="xs:dateTime" /> <xs:element name="src" type="xs:string" minOccurs="1" maxOccurs="1" />
- <xs:element name="units" type="Units" minOccurs="1" maxOccurs="1" />
+ <xs:element name="topic" type="xs:string" />
+ <xs:element name="generated" type="xs:dateTime" />
+ <xs:element name="src" type="xs:string" />
+ <xs:element name="units" type="Units" />
<xs:element name="resolver" type="Resolver" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="identity" type="Identity" minOccurs="1" maxOccurs="unbounded" />
<xs:element name="incoming" type="Incoming" minOccurs="0" maxOccurs="1" />
<xs:element name="entry" type="Entry" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="version" type="xs:integer" />
+ <xs:attribute name="uuid" type="xs:string" />
</xs:complexType>
</xs:element>
@@ -101,13 +101,20 @@
</xs:sequence>
</xs:complexType>
- <xs:complexType name="Identity">
+ <xs:complexType name="Permission">
<xs:simpleContent>
<xs:extension base="xs:string">
- <xs:attribute name="keyid" type="xs:string" />
- <xs:attribute name="didtype" type="xs:string" />
+ <xs:attribute name="flag" type="xs:positiveInteger" />
</xs:extension>
</xs:simpleContent>
+
+ </xs:complexType>
+ <xs:complexType name="Identity">
+ <xs:sequence>
+ <xs:element name="trust" type="Permission" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="keyid" type="xs:string" />
+ <xs:attribute name="didtype" type="xs:string" />
</xs:complexType>
<xs:complexType name="Resolver">
@@ -124,13 +131,12 @@
<xs:element name="data" type="EntryData" />
<xs:element name="sig" type="Signature" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
- <!-- TODO: attribute enum -->
+ <xs:attribute name="uuid" type="xs:string" />
</xs:complexType>
<xs:complexType name="EntryData">
<xs:sequence>
<xs:element name="parent" type="xs:string" />
- <xs:element name="uuid" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="ref" type="xs:string" />
<xs:element name="serial" type="xs:positiveInteger" />
<xs:element name="date" type="xs:date" />
@@ -152,12 +158,15 @@
<xs:complexType name="Attachment">
<xs:sequence>
- <xs:element name="uuid" type="xs:string" minOccurs="0" maxOccurs="1" />
- <xs:element name="slug" type="xs:string" />
- <xs:element name="description" type="xs:string" />
- <xs:element name="lookup" type="Lookup" />
+ <xs:element name="digest" type="Digest" />
+ <xs:element name="extref" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="filename" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="lookup" type="Lookup" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="sig" type="Signature" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="mime" type="xs:string" />
+ <xs:attribute name="uuid" type="xs:string" />
</xs:complexType>
<xs:simpleType name="accountType" final="restriction">
@@ -188,178 +197,75 @@ The third displays header for the ledger state after last entry added. It lists
@example
<?xml version="1.0"?>
<ledger xmlns="http://usawa.defalsify.org/" version="1">
- <topic xmlns:ns="http://usawa.defalsify.org/">24448167713e4f7d7e09fd06716b17ffcbd8bd10aa2ebbaac0a0902292993a86244acb9683c7dc45500daf1193a760b87de6fadd0f7b30c1a7b63ac06c555ca8</topic>
- <generated xmlns:ns="http://usawa.defalsify.org/">2026-01-20T09:30:34Z</generated>
- <src xmlns:ns="http://usawa.defalsify.org/">defalsify.org</src>
- <units xmlns:ns="http://usawa.defalsify.org/" base="BTC">
- <unit sym="BTC">
- <precision>2</precision>
- <exchange>1000000000</exchange>
- </unit>
- </units>
- <identity xmlns:ns="http://usawa.defalsify.org/" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" didtype="usawa"/>
- <incoming xmlns:ns="http://usawa.defalsify.org/" serial="0">
- <real unit="BTC">
- <asset>0</asset>
- <liability>0</liability>
- </real>
- <digest algo="sha512">00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</digest>
- </incoming>
- <entry>
- <data>
- <parent>00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</parent>
- <ref>2ae1dae8-8071-4a40-983d-e25f80634d6b</ref>
- <serial>1</serial>
- <date>2026-01-20</date>
- <dateTimeRegistered>2026-01-20T09:29:28Z</dateTimeRegistered>
- <description>awergaergh</description>
- <debit type="expense">
- <unit>BTC</unit>
- <account>general</account>
- <amount>-2346300</amount>
- </debit>
- <credit type="asset">
- <unit>BTC</unit>
- <account>general</account>
- <amount>2346300</amount>
- </credit>
- </data>
- <sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">0a0bec86152bd411dff6d7569778305f30bf52dd03c060992d8bfd1f3432fe27cf3acd17d8019a0e5e3fe0c038664c478b1576fed027f3902bb32b56b05fd708</sig>
- </entry>
- <entry>
- <data>
- <parent>50740013c78726ddd4fd199bbe21ad3eb3c50dcfd3540e12c5b52151a9b9f3a41346a22a2d1928dfc5749faac332a8c15ff2f545e8ff92b07aa037c39b1ba93e</parent>
- <ref>182536c7-f2ce-4976-af2a-6b0d2cf10e0c</ref>
- <serial>2</serial>
- <date>2026-01-20</date>
- <dateTimeRegistered>2026-01-20T09:29:40Z</dateTimeRegistered>
- <description>wergagh</description>
- <debit type="expense">
- <unit>BTC</unit>
- <account>general</account>
- <amount>-1251613262700</amount>
- </debit>
- <credit type="asset">
- <unit>BTC</unit>
- <account>general</account>
- <amount>1251613262700</amount>
- </credit>
- </data>
- <sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">603bf1bf05951f1c78e3ba9ab430e914f73f03b6570c15cb241695393e57eb178029ba1ff0f86afa5f29ea10ea49418825e387feb8d03f79280593e4598b1b0d</sig>
- </entry>
-</ledger>
-@end example
-
-
-@section Ledger after last entry
-
-@example
-<?xml version="1.0"?>
-<ledger xmlns="http://usawa.defalsify.org/" version="1">
- <topic xmlns:ns="http://usawa.defalsify.org/">24448167713e4f7d7e09fd06716b17ffcbd8bd10aa2ebbaac0a0902292993a86244acb9683c7dc45500daf1193a760b87de6fadd0f7b30c1a7b63ac06c555ca8</topic>
- <generated xmlns:ns="http://usawa.defalsify.org/">2026-01-20T09:30:34Z</generated>
- <src xmlns:ns="http://usawa.defalsify.org/">defalsify.org</src>
- <units xmlns:ns="http://usawa.defalsify.org/" base="BTC">
+ <topic>66a739edb189684585bde211f9c29f3a47616584cbe82175f88cb4a6329f9748aea04553db62e5b1bfbd7d121356e91fe2c6142a3d2ec9664099d0be203b87e4</topic>
+ <generated>2026-02-14T09:55:37Z</generated>
+ <src>defalsify.org</src>
+ <units base="BTC">
<unit sym="BTC">
<precision>2</precision>
<exchange>1000000000</exchange>
</unit>
</units>
- <identity xmlns:ns="http://usawa.defalsify.org/" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" didtype="usawa"/>
- <incoming xmlns:ns="http://usawa.defalsify.org/" serial="0">
+ <identity keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" didtype="usawa"/>
+ <incoming serial="0">
<real unit="BTC">
- <asset>0</asset>
- <liability>0</liability>
+ <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>2ae1dae8-8071-4a40-983d-e25f80634d6b</ref>
+ <ref>6b4fb8cf-ae86-42c4-a51e-fe344a25c4ea</ref>
<serial>1</serial>
- <date>2026-01-20</date>
- <dateTimeRegistered>2026-01-20T09:29:28Z</dateTimeRegistered>
- <description>awergaergh</description>
- <debit type="expense">
- <unit>BTC</unit>
- <account>general</account>
- <amount>-2346300</amount>
- </debit>
- <credit type="asset">
- <unit>BTC</unit>
- <account>general</account>
- <amount>2346300</amount>
- </credit>
- </data>
- <sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">0a0bec86152bd411dff6d7569778305f30bf52dd03c060992d8bfd1f3432fe27cf3acd17d8019a0e5e3fe0c038664c478b1576fed027f3902bb32b56b05fd708</sig>
- </entry>
- <entry>
- <data>
- <parent>50740013c78726ddd4fd199bbe21ad3eb3c50dcfd3540e12c5b52151a9b9f3a41346a22a2d1928dfc5749faac332a8c15ff2f545e8ff92b07aa037c39b1ba93e</parent>
- <ref>182536c7-f2ce-4976-af2a-6b0d2cf10e0c</ref>
- <serial>2</serial>
- <date>2026-01-20</date>
- <dateTimeRegistered>2026-01-20T09:29:40Z</dateTimeRegistered>
- <description>wergagh</description>
- <debit type="expense">
+ <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>-1251613262700</amount>
+ <amount>-13370000</amount>
</debit>
<credit type="asset">
<unit>BTC</unit>
<account>general</account>
- <amount>1251613262700</amount>
+ <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">603bf1bf05951f1c78e3ba9ab430e914f73f03b6570c15cb241695393e57eb178029ba1ff0f86afa5f29ea10ea49418825e387feb8d03f79280593e4598b1b0d</sig>
+ <sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">f2a099adf8f5c8da17a4ddc0c3e65fc4f868da2c038691ff01311ce3018e7a65c7090fb2e312a283340b75f7c821134a3613c890c52f27c956a51010cf8d1b06</sig>
</entry>
-</ledger>
-@end example
-
-@section Ledger after last entry
-
-@example
-<?xml version="1.0"?>
-<ledger xmlns="http://usawa.defalsify.org/" version="1">
- <topic xmlns:ns="http://usawa.defalsify.org/">24448167713e4f7d7e09fd06716b17ffcbd8bd10aa2ebbaac0a0902292993a86244acb9683c7dc45500daf1193a760b87de6fadd0f7b30c1a7b63ac06c555ca8</topic>
- <generated xmlns:ns="http://usawa.defalsify.org/">2026-01-20T09:32:09Z</generated>
- <src xmlns:ns="http://usawa.defalsify.org/">defalsify.org</src>
- <units xmlns:ns="http://usawa.defalsify.org/" base="BTC">
- <unit sym="BTC">
- <precision>2</precision>
- <exchange>1000000000</exchange>
- </unit>
- </units>
- <identity xmlns:ns="http://usawa.defalsify.org/" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc" didtype="usawa"/>
- <incoming xmlns:ns="http://usawa.defalsify.org/" serial="1">
- <real unit="BTC">
- <asset>2346300</asset>
- <liability>0</liability>
- </real>
- <digest algo="sha512">50740013c78726ddd4fd199bbe21ad3eb3c50dcfd3540e12c5b52151a9b9f3a41346a22a2d1928dfc5749faac332a8c15ff2f545e8ff92b07aa037c39b1ba93e</digest>
- </incoming>
<entry>
<data>
- <parent>50740013c78726ddd4fd199bbe21ad3eb3c50dcfd3540e12c5b52151a9b9f3a41346a22a2d1928dfc5749faac332a8c15ff2f545e8ff92b07aa037c39b1ba93e</parent>
- <ref>182536c7-f2ce-4976-af2a-6b0d2cf10e0c</ref>
+ <parent>d2ec3d9132d40ce747a66049921fe864907e8ed8730d289a4c54bfcd6a9b8f3adcdead00f5c03cf4f5348fde609254461b16c78e1b482e05ff26281a58c76fc2</parent>
+ <ref>044e45ca-07b0-4496-bb32-61107f7c1796</ref>
<serial>2</serial>
- <date>2026-01-20</date>
- <dateTimeRegistered>2026-01-20T09:29:40Z</dateTimeRegistered>
- <description>wergagh</description>
+ <date>2026-02-14</date>
+ <dateTimeRegistered>2026-02-14T09:10:14Z</dateTimeRegistered>
+ <description>Barbarbar</description>
<debit type="expense">
<unit>BTC</unit>
- <account>general</account>
- <amount>-1251613262700</amount>
+ <account>luxury</account>
+ <amount>-421300</amount>
</debit>
- <credit type="asset">
+ <credit type="liability">
<unit>BTC</unit>
- <account>general</account>
- <amount>1251613262700</amount>
+ <account>creditcard</account>
+ <amount>421300</amount>
</credit>
</data>
- <sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">603bf1bf05951f1c78e3ba9ab430e914f73f03b6570c15cb241695393e57eb178029ba1ff0f86afa5f29ea10ea49418825e387feb8d03f79280593e4598b1b0d</sig>
+ <sig type="ed25519" keyid="3b54648d60bb8a5b9e84fa0057f79b3a5996e511682e80176dc948dcbff5a4fc">425ae11c2d1808873c2da336a9c26386b6e45dd327f599186cca2766248bde62b38473e8a271119a6c382fa620f4c5a6de3471c2032824f76299360ef9e00009</sig>
</entry>
</ledger>
@end example
diff --git a/dummy/doc/assets.texi b/dummy/doc/assets.texi
@@ -11,9 +11,12 @@ Attachments are not limited to any specific type of content, but are usually a @
The attachment is defined by the following data:
@itemize
-@item A @strong{slug}, specifically a filesystem-safe string appropriate for use as a filename stem. (i.e. the substring @emph{"picture"} from @file{/foo/bar/picture.png})
+@item A @strong{slug} and @strong{extension}, together defining a filesystem-safe string appropriate for use as a file name. (i.e. the substrings @emph{"picture"} and @emph{"png"} from @file{/foo/bar/picture.png} respectively)
@item A (preferably succint) @strong{description} of what the asset represents.
-@item One or more @strong{lookup} elements, specifying the @emph{lookup key} and the @xref{method} used to generate the lookup key.
+@item An optional @emph{external reference}, intended to override the external reference in the @code{entry} element (e.g. if different parties refer to the same transaction with different identifiers).
+@item Zero or more @strong{lookup} elements, specifying the @emph{lookup key} and the @xref{method} used to generate the lookup key.
+@item A @strong{mime type} string.
+@item A @strong{uuid} string.
@end itemize
@@ -22,7 +25,6 @@ The attachment is defined by the following data:
The method may or may not be verifiable from the content.
-
At a minimum, any implementation should accommodate the following methods:
@itemize
@@ -31,3 +33,12 @@ At a minimum, any implementation should accommodate the following methods:
@end itemize
Any implementation is free to define any method it wishes, but should refrain from using well-known method strings like the above.
+
+If the lookup element is missing from an asset, any matching resolvers should be attempted in turn.
+
+
+@subsubsection Metadata
+
+The lookup method @emph{should} provide the @strong{mime type} of the contents (e.g. @code{Content-Type} header over @strong{http}).
+
+It @emph{can} also provide @strong{file name} (e.g. @code{Content-Disposition} header over @strong{http}), aswell as other metadata defined in the @strong{Attachment} schema.
diff --git a/dummy/doc/identity.texi b/dummy/doc/identity.texi
@@ -5,4 +5,4 @@ Ledger headers and entry chains may be signed be more than one private key.
Each entry signature element is bundled with a @code{keyid} attribute. @code{identity} elements matching the @code{keyid} may be defined in the ledger header, mapping them to a @emph{did URI}@footnote{DID v1.0: @url{https://www.w3.org/TR/did-1.0/}}.
-The default @emph{did method} is @code{usawa}, which refers to a resolution using the usawa store mechanism directly. @ref{store_identity, Identity entries in the store chapter} for details.
+The default @emph{did method} is @code{usawa}, which refers to a resolution using the usawa store mechanism directly. @xref{store_identity, Identity entries in the store chapter} for details.
diff --git a/dummy/doc/index.texi b/dummy/doc/index.texi
@@ -25,7 +25,7 @@ Documentation released 2026 under CC-BY-SA
@include accounts.texi
@include unit.texi
@include identity.texi
-@include time.texi
+@include entry.texi
@include store.texi
@include resolver.texi
@include assets.texi
diff --git a/dummy/doc/internals.texi b/dummy/doc/internals.texi
@@ -1,15 +1,64 @@
@chapter Internals
-@section Serializations
+@section Serialization for signature
+
+Object XML representations are used to generate signature material. The XML is canonicalized using the @url{https://www.w3.org/TR/xml-c14n2/,C14N 2.0 standard}, and all unnecessary whitespace is removed.
+
+Signatures are calculated and embedded on three elements individually, while at the same time having a hierarchical relation. Some data is omitted from the full XML representation.
+
+The following describes any transformation applied to the XML. Also, any @code{sig} elements are removed before .
+
+
+@anchor{serialize_attachment}
+@subsection Attachment
+
+Before canonicalization, the entry attachment element is reduced to contents that can be recreated with only the actual file data available:
+
+@itemize
+@item The @code{mime} attribute.
+@item The @code{digest} element.
+@end itemize
+
+
+@subsection Entry
+
+Contains zero or more @strong{Attachment} elements, as specified @ref{serialize_attachment,above}.
+
+Otherwise, used in its entirety.
+
@subsection Ledger
-The serialization of ledger is used to generate signature material used in the XML state header.
+Before signing, the last known entry is applied to the ledger state, and all entry elements are removed.
+
+The @code{digest} sub-element and @code{serial} attribute of the @code{ledger/incoming} element is set accordingly. @xref{ledger_trunc_header,Truncated header}.
+
+Thus, the XML used to calculate the ledger state signature material is the @code{ledger} element @emph{without} any @code{entry} elements.
+
+
+@section Serialization for cache store
+
+This serialization is used as compact representation of the data in the cache store.
Serialization uses the rencode format, and all individual elements are elements in a list.
-The list elements are generated as follows:
+The lookup key descriptions below are enumerated. Each element in the list should be concatenated in order, without intermediate data.
+
+Any optional and undefined elements @emph{must} contain a @emph{null value} in the serialization.
+
+@xref{store,Cache store} for more details.
+
+@subsection Ledger
+
+The lookup key for the ledger cache item is:
+
+@enumerate
+@item @code{0x01}
+@item The literal bytes of the @emph{ledger topic}
+@end enumerate
+
+The list elements for the value are generated as follows:
@enumerate
@item @strong{topic}, literal bytes.
@@ -22,6 +71,75 @@ The list elements are generated as follows:
@end enumerate
+@anchor{serialize_entry}
+@subsection Entry
+
+The lookup key for the entry cache item is:
+
+@enumerate
+@item @code{0x04}
+@item The literal bytes of the @emph{ledger topic}.
+@item The entry @strong{serial}, LEB128s encoded.
+@end enumerate
+
+The list elements for the value are generated as follows:
+
+@enumerate
+@item @strong{parent}, literal bytes of the preceding entry digest (or zero-value if it is the first entry).
+@item The @strong{serial} number of the entry.
+@item The @strong{local reference} of the entry, by default a @emph{uuid string}.
+@item The @strong{datetime} the entry was @emph{registered} (i.e. signed into) the ldger.
+@item The @strong{date} or @strong{datetime} of the transaction. @xref{entry_timing,Timing in ledger entries}.
+@item Serializations of the @emph{entry parts} of the @strong{debits}, one or more. @xref{serialize_entry_part,Entry part serialization}.
+@item Serializations of the @emph{entry parts} of the @strong{credits}, one or more. @xref{serialize_entry_part,Entry part serialization}.
+@item The @emph{digest} from each of the @strong{attachments}, zero or more.
+@end enumerate
+
+
+@anchor{serialize_entry_part}
+@subsubsection Entry parts
+
+Entry parts are @strong{debit} and @strong{credit} items.
+
+These are individually @emph{rencode serialized} before embedded in the @ref{serialize_entry,Entry serialization}. They do not have their own lookup key.
+
+The list elements for both have identical structure, and are generated as follows:
+
+@enumerate
+@item The @ref{unit_index,account unit symbol}.
+@item The @ref{account_type,account type}.
+@item The @ref{account_path,account path}.
+@item The @ref{account_value,value of the item}.
+@end enumerate
+
+
+@anchor{serialize_asset}
+@section Entry attachment assets
+
+The lookup key for the entry cache item is:
+
+@enumerate
+@item @code{0x10}
+@item The literal bytes of the @emph{asset digest}.
+@end enumerate
+
+The list elements for the value are generated as follows:
+
+@enumerate
+@item The @strong{mime type} string (required).
+@item The @strong{mime encoding / charset} string (required, if it has been defined).
+@item The @strong{uuid}.
+@item The @strong{external reference}.
+@item The @strong{slug} (the filename stem).
+@item The @strong{file extension}.
+@item The @strong{description}.
+@end enumerate
+
+All elements are optional unless otherwise marked.
+
+The file data is never stored in the cache store. File content for a @emph{digest} should be retrieved consulting @ref{resolver,resolvers} and @ref{method,lookup methods}.
+
+
@subsection Unit Index
A collection of units of account, defining their value precision level aswell as exchange rates.
diff --git a/dummy/doc/intro.texi b/dummy/doc/intro.texi
@@ -41,3 +41,21 @@ It leaves it up the implementer to create protocols and procedures to make sure
@subsection No bundled dissemination.
There is no node software specific to nor any protocol proposal for @strong{usawa} that defines how to make the state of the ledger known to all relevant parties at any one time.
+
+
+@section Cryptography
+
+Signatures and encryption use the @url{https://nacl.cr.yp.to/,NaCl} library. For the python implementation specifically, @url{https://pypi.org/project/PyNaCl/,PyNaCl} is used.
+
+The signature algorithm is the @strong{ed25519} implementation of the @url{eddsa,https://www.rfc-editor.org/rfc/rfc8032} recommendation.
+
+
+@section State of this document
+
+This is the documentation for version @code{0.1.0}.
+
+For each release (i.e. in git, a semver tag), the document @emph{should} cover the current state of the implementation.
+
+It @emph{may} cover features not yet implemented.
+
+The @emph{inline code documentation} should be kept up to date before each merge to the @emph{master} branch. It should be consulted when in doubt about state of features.
diff --git a/dummy/doc/server.texi b/dummy/doc/server.texi
@@ -1,7 +1,7 @@
@anchor{service}
@chapter Service
-usawa provides a socket daemon service to allow multiple clients operate on the same entry store concurrently.
+usawa provides a socket daemon service to allow multiple clients operate on the same cache store concurrently.
It is currently implemented as a @emph{Unix socket} and a @emph{TCP socket}.
diff --git a/dummy/doc/store.texi b/dummy/doc/store.texi
@@ -1,2 +1,31 @@
@anchor{store}
+@chapter Cache store
+
+Entries, assets and keys are kept in a cache store.
+
+It is a key-value store, the first byte expressing what type of data it holds.
+
+Data stored is serialized using the @url{https://github.com/aresch/rencode,rencode} format.
+
+The prefixes are:
+
+@table @code
+@item 0x00
+Key information, currently in this early development only contains private key, unencrypted.
+@item 0x01
+Reserved for Ledger metadata, currently unimplemented, as ledger state also can be loaded from XML.
+@item 0x02
+Reserved for Ledger lock, currently inimplemented, to be used in aiding atomic inserts if needed.
+@item 0x04
+Entry data, everything needed to reconstruct a full entry element.
+@item 0x10
+Asset (entry attachment) data, everything needed to reconstruct a full entry element @emph{except} the actual asset data (@ref{method, Lookup methods}).
+@end table
+
+The CLI tools provided use the @emph{valkey} store, thus expecting a valkey server to be running on an available host.
+
+
@anchor{store_identity}
+@section Keys and store identities
+
+(todo)
diff --git a/dummy/doc/xml.texi b/dummy/doc/xml.texi
@@ -2,7 +2,7 @@
The canonical ledger data format is XML.
-The XML schema is designed to allow embedding of all data necessary to verify integrity signatures, including exchange rates between units of account.
+The XML schema is designed to allow embedding of all data necessary to verify integrity signatures, including exchange rates between units of account. It also contains additional elements that are not part of the signature, but enriches the context of the ledger and its composite parts.
Order of elements are important in the XML document. The schema is cited in @ref{xml_schema, appendix A}.
@@ -26,6 +26,7 @@ It includes:
@end itemize
+@anchor{ledger_trunc_header}
@subsection Truncated header
An important feature of the header is to allow only a portion of the ledger's entries to appear in the document.
diff --git a/dummy/setup.cfg b/dummy/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = usawa
-version = 0.0.2
+version = 0.1.0
description = Signed, immutable accounting.
author = Louis Holbrook
author_email = dev@holbrook.no
diff --git a/dummy/usawa/asset.py b/dummy/usawa/asset.py
@@ -219,6 +219,7 @@ class Asset:
:returns: XML tree representing the asset.
:rtype: lxml.etree.Element
:todo: implement sigs
+ :todo: implement lookup
"""
def to_tree(self, canon=False):
tree = self.canon()
@@ -255,6 +256,7 @@ class Asset:
:rtype: lxml.etree.Element
:todo: add to docs cannot directly import from tree generated from to_tree, must go way by string export
:todo: implement sigs
+ :todo: implement lookup
"""
@staticmethod
def from_tree(tree):
@@ -293,6 +295,7 @@ class Asset:
def to_list(self):
d = [
self.mime,
+ self.enc,
self.uuid,
self.extref,
self.slug,
@@ -324,7 +327,7 @@ class Asset:
o = Asset()
v = rencode.loads(data)
i = 0
- for k in ['mime', 'uuid', 'extref', 'slug', 'ext', 'description']:
+ for k in ['mime', 'enc', 'uuid', 'extref', 'slug', 'ext', 'description']:
if v[i] != None:
setattr(o, k, v[i].decode('utf-8'))
i += 1
diff --git a/dummy/usawa/crypto.py b/dummy/usawa/crypto.py
@@ -363,7 +363,7 @@ class ACL:
return r
- """Generate the unit index part of a Wallet in wire format.
+ """Generate the wire format for the ACL.
:return: rencoded object
:rtype: bytes
diff --git a/dummy/usawa/data/schema.xsd b/dummy/usawa/data/schema.xsd
@@ -136,6 +136,7 @@
<xs:sequence>
<xs:element name="parent" type="xs:string" />
<xs:element name="ref" type="xs:string" />
+ <xs:element name="extref" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="serial" type="xs:positiveInteger" />
<xs:element name="date" type="xs:date" />
<xs:element name="dateTimeRegistered" type="xs:dateTime" />
@@ -160,6 +161,7 @@
<xs:element name="extref" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="filename" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="lookup" type="Lookup" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="sig" type="Signature" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="mime" type="xs:string" />
diff --git a/dummy/usawa/entry.py b/dummy/usawa/entry.py
@@ -100,6 +100,50 @@ class EntryPart:
return tree
+ """Generate the simple data structure used for rencode serialization.
+
+ :returns: data structure
+ :rtype: list
+ """
+ def to_list(self):
+ d = [
+ self.unit,
+ self.typ,
+ self.account,
+ self.amount,
+ ]
+ return d
+
+
+ """Generate the serialization format used to calculate the digest for the entry part.
+
+ :returns: String representation of the entry, in rencode format.
+ :rtype: str
+ """
+ def serialize(self):
+ b = self.to_list()
+ return rencode.dumps(b)
+
+ """Create an entry part object from serialized data.
+
+ :param data: rencoded entry part object, as produced by the serialize() method.
+ :type data: str
+ :param debit: If true, a debit part will be created. Otherwise, a credit object is created.
+ :type debit: boolean
+ :returns: Entry part object.
+ :rtype: usawa.EntryPart
+ """
+ @staticmethod
+ def deserialize(data, debit=False):
+ v = rencode.loads(data)
+ unit = v[0].decode('utf-8')
+ typ = v[1].decode('utf-8')
+ account = v[2].decode('utf-8')
+ amount = v[3]
+ o = EntryPart(unit, typ, account, amount, debit=debit)
+ return o
+
+
def __str__(self):
pfx = 'credit'
if self.isdebit:
@@ -258,16 +302,17 @@ class Entry:
:returns: data structure
:rtype: list
+ :todo: Add time component to entry.
"""
def to_list(self):
debit = []
credit = []
attach = []
for v in self.debit:
- debit.append((v.unit, v.typ, v.account, v.amount,))
+ debit.append(v.serialize())
for v in self.credit:
- credit.append((v.unit, v.typ, v.account, v.amount,))
+ credit.append(v.serialize())
for v in self.attachment:
attach.append(v.get_digest(binary=True))
@@ -318,11 +363,13 @@ class Entry:
attach_data = v[8]
o = Entry(serial, date, ref=ref, description=description, parent=parent, tx_datereg=date_reg)
for v in src_data:
- src = EntryPart(v[0].decode('utf-8'), v[1].decode('utf-8'), v[2].decode('utf-8'), v[3], debit=True)
+ #src = EntryPart(v[0].decode('utf-8'), v[1].decode('utf-8'), v[2].decode('utf-8'), v[3], debit=True)
+ src = EntryPart.deserialize(v, debit=True)
o.add_part(src, debit=True)
for v in dst_data:
- dst = EntryPart(v[0].decode('utf-8'), v[1].decode('utf-8'), v[2].decode('utf-8'), v[3])
+ #dst = EntryPart(v[0].decode('utf-8'), v[1].decode('utf-8'), v[2].decode('utf-8'), v[3])
+ dst = EntryPart.deserialize(v)
o.add_part(dst)
for v in attach_data:
diff --git a/dummy/usawa/store.py b/dummy/usawa/store.py
@@ -233,11 +233,14 @@ class LedgerStore(Interface):
:param wallet: The wallet object to store keys for.
:type wallet: usawa.Wallet implementation
+ :param acl: Access control list data to retrieve the allowance and label for the key.
+ :type acl: usawa.ACL
:param default: If True, this key will be set as default key.
:type default: bool
:todo: Currently the signing key is stored literally. It needs encryption!
+ :todo: Implement the ACL lookup
"""
- def add_key(self, wallet, default=False):
+ def add_key(self, wallet, acl=None, default=False):
k = pfx_key()
try:
self.__o.get(k)