kee

Offline IOU signer with QR as transport
git clone https://holbrook.no/src/kee
Info | Log | Files | Refs | README | LICENSE

commit 696fba72d238d361b65997b495c9c29af1bdd582
parent 68bd00eb117a41663ffe75c2e38febfee9ceacd2
Author: lash <dev@holbrook.no>
Date:   Tue, 23 Apr 2024 07:50:10 +0100

Add ledger cache for item accumulation

Diffstat:
Msrc/gtk/kee-entry-item-store.c | 10++++------
Msrc/gtk/kee-entry-item.c | 3++-
Msrc/gtk/kee-entry.c | 40++++++++++++++++++++++------------------
Msrc/ledger.c | 31++++++++++++++++++++++++++++++-
Msrc/ledger.h | 16+++++++++++++---
Msrc/tests/ledger.c | 16++++++++++++++++
Mtestdata_asn1.py | 1+
7 files changed, 88 insertions(+), 29 deletions(-)

diff --git a/src/gtk/kee-entry-item-store.c b/src/gtk/kee-entry-item-store.c @@ -29,12 +29,10 @@ struct _KeeEntryItemStore { static void kee_entry_item_store_iface_init(GListModelInterface *ifc); G_DEFINE_TYPE_WITH_CODE(KeeEntryItemStore, kee_entry_item_store, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_LIST_MODEL, kee_entry_item_store_iface_init)); +static int kee_entry_item_store_scan(KeeEntryItemStore *o); static void kee_entry_item_store_finalize(GObject *o); -static int kee_entry_item_store_seek(KeeEntryItemStore *o, int idx); - - static void kee_entry_item_store_class_init(KeeEntryItemStoreClass *kls) { GObjectClass *oc = G_OBJECT_CLASS(kls); oc->finalize = kee_entry_item_store_finalize; @@ -79,7 +77,7 @@ KeeEntryItemStore* kee_entry_item_store_new(struct db_ctx *db, struct kee_ledger o->ledger = ledger; o->resolver = resolver; - o->last_count = kee_entry_item_store_seek(o, INT_MAX); + o->last_count = kee_entry_item_store_scan(o); g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "max key index is: %d", o->last_count - 1); return o; } @@ -87,7 +85,7 @@ KeeEntryItemStore* kee_entry_item_store_new(struct db_ctx *db, struct kee_ledger /// \todo always scans from 0, inefficient /// \todo enum lookup states -static int kee_entry_item_store_seek(KeeEntryItemStore *o, int idx) { +static int kee_entry_item_store_scan(KeeEntryItemStore *o) { struct kee_ledger_item_t *item; int r; int i; @@ -107,7 +105,7 @@ static int kee_entry_item_store_seek(KeeEntryItemStore *o, int idx) { memcpy(entry_key, last_key, entry_ref_len); i = 0; - while (i <= idx) { + while (i <= INT_MAX) { last_value_length = 2048; r = db_next(o->db, DbKeyLedgerEntry, &last_key, &key_len, &last_value, &last_value_length); if (r) { diff --git a/src/gtk/kee-entry-item.c b/src/gtk/kee-entry-item.c @@ -69,7 +69,8 @@ void kee_entry_item_apply_list_item_widget(KeeEntryItem *o) { GtkWidget *widget; kee_content_resolve(&o->item->content, o->resolver); - widget = gtk_label_new(o->item->content.subject); + sprintf(o->header, "%s\nalice: %i\nbob: %i\n", o->item->content.subject, o->item->alice_credit_delta, o->item->bob_credit_delta); + widget = gtk_label_new(o->header); gtk_box_append(GTK_BOX(o), widget); return; } diff --git a/src/gtk/kee-entry.c b/src/gtk/kee-entry.c @@ -36,16 +36,13 @@ extern const asn1_static_node schema_entry_asn1_tab[]; /// \todo factor out separate struct for listitem struct _KeeEntry { GtkWidget parent; + GtkWidget *entry_list; int state; char header[1024]; struct kee_dn_t bob_dn; char current_id[64]; struct kee_ledger_t ledger; struct Cadiz *resolver; - int alice_credit_balance; - int bob_credit_balance; - int alice_collateral_balance; - int bob_collateral_balance; int is_displaying; struct db_ctx *db; }; @@ -96,6 +93,8 @@ static void kee_entry_init(KeeEntry *o) { o->state = 2; o->resolver = NULL; o->is_displaying = 0; + kee_ledger_init(&o->ledger); + kee_ledger_reset_cache(&o->ledger); } KeeEntry* kee_entry_new(struct db_ctx *db) { @@ -110,6 +109,20 @@ void kee_entry_set_resolver(KeeEntry *o, struct Cadiz *resolver) { o->resolver = resolver; } +static void kee_entry_init_list_widget(KeeEntry *o) { + GtkSingleSelection *sel; + GtkListItemFactory *factory; + KeeEntryItemStore *model; + + factory = gtk_signal_list_item_factory_new(); + g_signal_connect(factory, "setup", G_CALLBACK(kee_entry_handle_item_setup), NULL); + g_signal_connect(factory, "bind", G_CALLBACK(kee_entry_handle_item_bind), NULL); + + model = kee_entry_item_store_new(o->db, &o->ledger, o->resolver); + sel = gtk_single_selection_new(G_LIST_MODEL(model)); + o->entry_list = gtk_list_view_new(GTK_SELECTION_MODEL(sel), GTK_LIST_ITEM_FACTORY(factory)); +} + int kee_entry_deserialize(KeeEntry *o, const char *data, size_t data_len) { int r; size_t key_len; @@ -162,6 +175,8 @@ int kee_entry_deserialize(KeeEntry *o, const char *data, size_t data_len) { o->state = 0; + kee_entry_init_list_widget(o); + return ERR_OK; } @@ -173,31 +188,20 @@ void kee_entry_apply_list_item_widget(KeeEntry *o) { return; } - sprintf(o->header, "%s [%s]\n%s (%s)", o->ledger.content.subject, o->ledger.uoa, o->bob_dn.cn, o->bob_dn.uid); + sprintf(o->header, "%s [%s]\n%s (%s)\nalice: %d\nbob: %d", o->ledger.content.subject, o->ledger.uoa, o->bob_dn.cn, o->bob_dn.uid, o->ledger.cache->alice_credit_balance, o->ledger.cache->bob_credit_balance); widget = gtk_label_new(o->header); gtk_box_append(GTK_BOX(o), widget); o->is_displaying = 0; return; } -int kee_entry_apply_display_widget(KeeEntry *o) { - GtkWidget *widget; - GtkSingleSelection *sel; - GtkListItemFactory *factory; - KeeEntryItemStore *model; +int kee_entry_apply_display_widget(KeeEntry *o) { if (o->is_displaying) { return 1; } o->is_displaying = 1; - factory = gtk_signal_list_item_factory_new(); - g_signal_connect(factory, "setup", G_CALLBACK(kee_entry_handle_item_setup), NULL); - g_signal_connect(factory, "bind", G_CALLBACK(kee_entry_handle_item_bind), NULL); - - model = kee_entry_item_store_new(o->db, &o->ledger, o->resolver); - sel = gtk_single_selection_new(G_LIST_MODEL(model)); - widget = gtk_list_view_new(GTK_SELECTION_MODEL(sel), GTK_LIST_ITEM_FACTORY(factory)); - gtk_box_append(GTK_BOX(o), widget); + gtk_box_append(GTK_BOX(o), o->entry_list); return 0; } diff --git a/src/ledger.c b/src/ledger.c @@ -1,4 +1,5 @@ #include <stddef.h> +#include <string.h> #include <libtasn1.h> #include <gcrypt.h> @@ -189,6 +190,26 @@ static int verify_item(asn1_node item, const char *pubkey_first_data, const char return 0; } +void kee_ledger_item_apply_cache(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item) { + if (ledger->cache == NULL) { + return; + } + + ledger->cache->alice_credit_balance += item->alice_credit_delta; + ledger->cache->bob_credit_balance += item->bob_credit_delta; + ledger->cache->alice_collateral_balance += item->alice_collateral_delta; + ledger->cache->bob_collateral_balance += item->bob_collateral_delta; + ledger->cache->count++; +} + +void kee_ledger_reset_cache(struct kee_ledger_t *ledger) { + if (ledger->cache == NULL) { + ledger->cache = calloc(sizeof(struct kee_ledger_cache_t), 1); + } else { + memset(ledger->cache, 0, sizeof(struct kee_ledger_cache_t)); + } +} + struct kee_ledger_item_t *kee_ledger_parse_item(struct kee_ledger_t *ledger, const char *data, size_t data_len) { int r; int c; @@ -293,6 +314,8 @@ struct kee_ledger_item_t *kee_ledger_parse_item(struct kee_ledger_t *ledger, con return NULL; } + kee_ledger_item_apply_cache(ledger, cur); + return cur; } @@ -307,9 +330,16 @@ void kee_ledger_item_free(struct kee_ledger_item_t *item) { } void kee_ledger_free(struct kee_ledger_t *ledger) { + if (ledger->cache) { + free(ledger->cache); + } kee_ledger_item_free(ledger->last_item); } +void kee_ledger_init(struct kee_ledger_t *ledger) { + memset(ledger, 0, sizeof(struct kee_ledger_t)); +} + int kee_ledger_parse(struct kee_ledger_t *ledger, const char *data, size_t data_len) { int r; char err[1024]; @@ -318,7 +348,6 @@ int kee_ledger_parse(struct kee_ledger_t *ledger, const char *data, size_t data_ int c; char content_key[64]; - memset(ledger, 0, sizeof(struct kee_ledger_t)); memset(&root, 0, sizeof(root)); memset(&item, 0, sizeof(item)); r = asn1_array2tree(schema_entry_asn1_tab, &root, err); diff --git a/src/ledger.h b/src/ledger.h @@ -6,12 +6,11 @@ #include "content.h" #include "cadiz.h" -enum kee_initiator { +enum kee_initiator_e { ALICE, BOB, }; - struct kee_ledger_item_t { struct kee_ledger_item_t *prev_item; int alice_credit_delta; @@ -19,11 +18,19 @@ struct kee_ledger_item_t { int alice_collateral_delta; int bob_collateral_delta; time_t time; - enum kee_initiator initiator; + enum kee_initiator_e initiator; char response; struct kee_content_t content; }; +struct kee_ledger_cache_t { + int count; + int alice_credit_balance; + int bob_credit_balance; + int alice_collateral_balance; + int bob_collateral_balance; +}; + struct kee_ledger_t { const char digest[64]; struct kee_ledger_item_t *last_item; @@ -32,12 +39,15 @@ struct kee_ledger_t { char uoa_decimals; char uoa[64]; struct kee_content_t content; + struct kee_ledger_cache_t *cache; }; struct kee_ledger_item_t *kee_ledger_parse_item(struct kee_ledger_t *ledger, const char *data, size_t data_len); int kee_ledger_parse(struct kee_ledger_t *ledger, const char *data, size_t data_len); +void kee_ledger_init(struct kee_ledger_t *ledger); void kee_ledger_free(struct kee_ledger_t *ledger); void kee_ledger_item_free(struct kee_ledger_item_t *item); void kee_ledger_resolve(struct kee_ledger_t *ledger, Cadiz *cadiz); +void kee_ledger_reset_cache(struct kee_ledger_t *ledger); #endif diff --git a/src/tests/ledger.c b/src/tests/ledger.c @@ -21,6 +21,9 @@ int main() { cadiz.locator = "./testdata_resource"; + kee_ledger_init(&ledger); + kee_ledger_reset_cache(&ledger); + c = hex2bin(test_ledger_data, (unsigned char*)data); r = kee_ledger_parse(&ledger, data, c); if (r) { @@ -41,6 +44,19 @@ int main() { kee_ledger_resolve(&ledger, &cadiz); + if (ledger.cache->alice_credit_balance == 0) { + return 1; + } + if (ledger.cache->bob_credit_balance == 0) { + return 1; + } + if (ledger.cache->alice_collateral_balance == 0) { + return 1; + } + if (ledger.cache->bob_collateral_balance == 0) { + return 1; + } + kee_ledger_free(&ledger); return 0; diff --git a/testdata_asn1.py b/testdata_asn1.py @@ -36,6 +36,7 @@ NOSIG = b'' PFX_LEDGER_HEAD = b'\x01' PFX_LEDGER_ENTRY = b'\x02' PFX_LEDGER_PUBKEY = b'\x03' +PFX_LEDGER_CACHE_SUMS = b'\x80' random.seed(int(time.time_ns()))