kee

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

commit 1ef98807249886bf8ea47472edc8f86af3e7fb98
parent b23380b4230de99a61739ac2b118d8d67eb56a58
Author: lash <dev@holbrook.no>
Date:   Mon, 22 Apr 2024 11:28:26 +0100

Add proper list item store model and list view for items

Diffstat:
Asrc/gtk/kee-entry-item-store.c | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/gtk/kee-entry-item-store.h | 17+++++++++++++++++
Asrc/gtk/kee-entry-item.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/gtk/kee-entry-item.h | 30++++++++++++++++++++++++++++++
Msrc/gtk/kee-entry-store.c | 3++-
Msrc/gtk/kee-entry.c | 122+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/ledger.h | 1+
Mtestdata_asn1.py | 3---
8 files changed, 362 insertions(+), 69 deletions(-)

diff --git a/src/gtk/kee-entry-item-store.c b/src/gtk/kee-entry-item-store.c @@ -0,0 +1,162 @@ +#include <stdlib.h> +#include <glib-object.h> +#include <gtk/gtk.h> + +#include "kee-entry-item-store.h" +#include "kee-entry-item.h" +#include "cadiz.h" +#include "db.h" + + +typedef struct { +} KeeEntryItemStorePrivate; + +struct _KeeEntryItemStore { + GObject parent; + const char *current_id; + struct db_ctx *db; + int last_idx; + int last_state; + int last_count; + char *last; + char *last_key; + char *last_digest; + char *last_value; + size_t last_value_length; + struct Cadiz resolver; +}; + + +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 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; +} + +static void kee_entry_item_store_init(KeeEntryItemStore *o) { + o->resolver.key_type = CADIZ_KEY_TYPE_ANY; + o->resolver.locator = malloc(1024); +} + +void kee_entry_item_store_set_resolve(KeeEntryItemStore *o, const char *locator) { + strcpy(o->resolver.locator, locator); +} + +static GType kee_entry_item_store_get_item_type(GListModel *list) { + return KEE_TYPE_ENTRY_ITEM; +} + +static guint kee_entry_item_store_get_n_items(GListModel *list) { + return KEE_ENTRY_ITEM_STORE(list)->last_count; +} + + +static gpointer kee_entry_item_store_get_item(GListModel *list, guint index) { +// int r; + KeeEntryItem *o; + KeeEntryItemStore *store; +// +// //kee_entry_load(o, list->db); + store = KEE_ENTRY_ITEM_STORE(list); + o = kee_entry_item_new(store->db); + kee_entry_item_set_resolver(o, &store->resolver); + kee_entry_item_store_seek(store, index); +// //kee_entry_deserialize(o, store->last_key, 9, store->last_value, store->last_value_length); +// r = kee_entry_deserialize(o, store->last_value, store->last_value_length); +// if (r) { +// return NULL; +// } +// +// //return o; +// kee_entry_apply_list_item_widget(o); +// +// return o; + return o; +} + +static void kee_entry_item_store_iface_init(GListModelInterface *ifc) { + ifc->get_item_type = kee_entry_item_store_get_item_type; + ifc->get_n_items = kee_entry_item_store_get_n_items; + ifc->get_item = kee_entry_item_store_get_item; +} + +KeeEntryItemStore* kee_entry_item_store_new(struct db_ctx *db, const char *current_id) { + KeeEntryItemStore *o; + + o = g_object_new(KEE_TYPE_ENTRY_ITEM_STORE, NULL); + o->db = db; + o->last = calloc(2048, 1); + o->last_digest = o->last + DB_KEY_SIZE_LIMIT; + o->last_value_length = 1024; + o->current_id = current_id; + + o->last_count = kee_entry_item_store_seek(o, INT_MAX); + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "max key index is: %d", o->last_idx - 1); + return o; +} + +/// \todo always scans from 0, inefficient +/// \todo enum lookup states +static int kee_entry_item_store_seek(KeeEntryItemStore *o, int idx) { + int r; + int i; + size_t key_len; + size_t entry_key_len; + char *mem[4096]; + char *last_key; + char *entry_key; + char *last_value; + size_t last_value_length; + char out[1024]; + size_t out_len; + + entry_key_len = 65; + key_len = entry_key_len + 8; + last_key = (char*)mem; + entry_key = last_key + 128; + last_value = entry_key + 128; + *last_key = DbKeyLedgerEntry; + memcpy(last_key+1, o->current_id, key_len - 1); + memcpy(entry_key, last_key, entry_key_len); + + i = 0; + while (i <= idx) { + o->last_idx = i; + last_value_length = 2048; + r = db_next(o->db, DbKeyLedgerEntry, &last_key, &key_len, &last_value, &last_value_length); + if (r) { + break; + } + if (memcmp(last_key, entry_key, entry_key_len)) { + break; + } + out_len = 1024; + //r = kee_entry_deserialize_item(o, last_value, last_value_length, out, &out_len); + //if (r) { + // g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "corrupt entry!"); + //} else { + // g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "adding entry: %s", out); + // i++; + // gtk_string_list_append(list, out); + //} + i++; + //o->alice_credit_balance += o-> + } + db_rewind(o->db); + return i; +} + +void kee_entry_item_store_finalize(GObject *go) { + KeeEntryItemStore *o = KEE_ENTRY_ITEM_STORE(go); + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "freeing entry item store"); + free(o->resolver.locator); + free(o->last); +} diff --git a/src/gtk/kee-entry-item-store.h b/src/gtk/kee-entry-item-store.h @@ -0,0 +1,17 @@ +#ifndef _GTK_KEE_ENTRY_ITEM_STORE_H +#define _GTK_KEE_ENTRY_ITEM_STORE_H + +#include <glib-object.h> +#include "db.h" + +G_BEGIN_DECLS + +#define KEE_TYPE_ENTRY_ITEM_STORE kee_entry_item_store_get_type() +G_DECLARE_FINAL_TYPE(KeeEntryItemStore, kee_entry_item_store, KEE, ENTRY_ITEM_STORE, GObject); + +KeeEntryItemStore* kee_entry_item_store_new(struct db_ctx *db, const char *current_id); +void kee_entry_item_store_set_resolve(KeeEntryItemStore *o, const char *locator); + +G_END_DECLS + +#endif // _GTK_KEE_ENTRY_ITEM_STORE_H diff --git a/src/gtk/kee-entry-item.c b/src/gtk/kee-entry-item.c @@ -0,0 +1,93 @@ +#include <glib-object.h> +#include <gtk/gtk.h> + +#include "kee-entry-item.h" +#include "ledger.h" +#include "db.h" +#include "err.h" + + +typedef struct { +} KeeEntryItemPrivate; + +struct _KeeEntryItemClass { + GtkWidget parent_class; +}; + +struct _KeeEntryItem { + GtkWidget parent; + int state; + char header[1024]; + struct kee_ledger_t ledger; + struct Cadiz *resolver; + int alice_credit_delta; + int bob_credit_delta; + int alice_collateral_delta; + int bob_collateral_delta; + struct db_ctx *db; +}; + +G_DEFINE_TYPE(KeeEntryItem, kee_entry_item, GTK_TYPE_BOX); + +void kee_entry_item_handle_setup(GtkListItemFactory* o, GtkListItem *item) { + GtkWidget *label; + + label = gtk_label_new(NULL); + gtk_list_item_set_child(item, label); +} + +void kee_entry_item_handle_bind(GtkListItemFactory *o, GtkListItem *item) { + GtkWidget *label; + GtkStringObject *s; + + label = gtk_list_item_get_child(item); + s = gtk_list_item_get_item(item); + gtk_label_set_label(GTK_LABEL(label), gtk_string_object_get_string(s)); +} + + +static void kee_entry_item_dispose(GObject *o) { +} + +static void kee_entry_item_finalize(GObject *o) { +} + +static void kee_entry_item_class_init(KeeEntryItemClass *kls) { + GObjectClass *object_class = G_OBJECT_CLASS(kls); + object_class->finalize = kee_entry_item_finalize; + object_class->dispose = kee_entry_item_dispose; +} + +static void kee_entry_item_init(KeeEntryItem *o) { + o->state = 2; + o->resolver = NULL; +} + +void kee_entry_item_set_resolver(KeeEntryItem *o, struct Cadiz *resolver) { + o->resolver = resolver; +} + +static int kee_entry_item_deserialize(KeeEntryItem *o, const char *data, size_t data_len, char *out, size_t *out_len) { + struct kee_ledger_item_t *item; + + item = kee_ledger_parse_item(&o->ledger, data, data_len); + if (item == NULL) { + return ERR_FAIL; + } + kee_content_resolve(&item->content, o->resolver); + + if (item->content.flags & KEE_CONTENT_RESOLVED_SUBJECT) { + strcpy(out, item->content.subject); + } else { + strcpy(out, "(no subject)"); + } + + return ERR_OK; +} + +KeeEntryItem* kee_entry_item_new(struct db_ctx *db) { + KeeEntryItem *o; + o = KEE_ENTRY_ITEM(g_object_new(KEE_TYPE_ENTRY_ITEM, "orientation", GTK_ORIENTATION_VERTICAL, NULL)); + o->db = db; + return o; +} diff --git a/src/gtk/kee-entry-item.h b/src/gtk/kee-entry-item.h @@ -0,0 +1,30 @@ +#ifndef _GTK_KEE_ENTRY_ITEM_H +#define _GTK_KEE_ENTRY_ITEM_H + +#include <glib-object.h> +#include <gtk/gtk.h> + +#include "db.h" +#include "cadiz.h" + +G_BEGIN_DECLS + +enum KEE_ENTRY_ITEM_PROPS { + KEE_P_ENTRY_ITEM_ALICE_CREDIT_DELTA = 1, + KEE_P_ENTRY_ITEM_BOB_CREDIT_DELTA, + KEE_P_ENTRY_ITEM_ALICE_COLLATERAL_DELTA, + KEE_P_ENTRY_ITEM_BOB_COLLATERAL_DELTA, + KEE_N_ENTRY_ITEM_PROPS, +}; + +#define KEE_TYPE_ENTRY_ITEM kee_entry_item_get_type() +G_DECLARE_FINAL_TYPE(KeeEntryItem, kee_entry_item, KEE, ENTRY_ITEM, GtkBox); + +KeeEntryItem* kee_entry_item_new(struct db_ctx *db); +void kee_entry_item_handle_setup(GtkListItemFactory* o, GtkListItem *item); +void kee_entry_item_handle_bind(GtkListItemFactory *o, GtkListItem *item); +void kee_entry_item_set_resolver(KeeEntryItem *o, struct Cadiz *resolver); + +G_END_DECLS + +#endif //_GTK_KEE_ENTRY_ITEM_H diff --git a/src/gtk/kee-entry-store.c b/src/gtk/kee-entry-store.c @@ -1,3 +1,4 @@ +#include <stdlib.h> #include <glib-object.h> #include <gtk/gtk.h> #include <gio/gio.h> @@ -32,6 +33,7 @@ static void kee_entry_store_iface_init(GListModelInterface *ifc); G_DEFINE_TYPE_WITH_CODE(KeeEntryStore, kee_entry_store, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_LIST_MODEL, kee_entry_store_iface_init)); static void kee_entry_store_finalize(GObject *o); + static int kee_entry_store_seek(KeeEntryStore *o, int idx); // \todo add construct pointer for db @@ -55,7 +57,6 @@ static GType kee_entry_store_get_item_type(GListModel *list) { return KEE_TYPE_ENTRY; } - static guint kee_entry_store_get_n_items(GListModel *list) { return KEE_ENTRY_STORE(list)->last_count; } diff --git a/src/gtk/kee-entry.c b/src/gtk/kee-entry.c @@ -9,6 +9,8 @@ #include "cmime.h" #include "kee-entry.h" +#include "kee-entry-item.h" +#include "kee-entry-item-store.h" #include "db.h" #include "err.h" #include "hex.h" @@ -40,6 +42,10 @@ struct _KeeEntry { char current_id[128]; struct kee_ledger_t ledger; struct Cadiz *resolver; + int alice_credit_balance; + int bob_credit_balance; + int alice_collateral_balance; + int bob_collateral_balance; struct db_ctx *db; }; @@ -155,24 +161,6 @@ int kee_entry_deserialize(KeeEntry *o, const char *data, size_t data_len) { return ERR_OK; } -static int kee_entry_deserialize_item(KeeEntry *o, const char *data, size_t data_len, char *out, size_t *out_len) { - struct kee_ledger_item_t *item; - - item = kee_ledger_parse_item(&o->ledger, data, data_len); - if (item == NULL) { - return ERR_FAIL; - } - kee_content_resolve(&item->content, o->resolver); - - if (item->content.flags & KEE_CONTENT_RESOLVED_SUBJECT) { - strcpy(out, item->content.subject); - } else { - strcpy(out, "(no subject)"); - } - - return ERR_OK; -} - void kee_entry_apply_list_item_widget(KeeEntry *o) { GtkWidget *widget; @@ -188,67 +176,71 @@ void kee_entry_apply_list_item_widget(KeeEntry *o) { } static int kee_entry_load_items(KeeEntry *o, GtkStringList *list) { - int r; - size_t key_len; - size_t entry_key_len; - char *mem = malloc(4096); - char *last_key; - char *entry_key; - char *last_value; - size_t last_value_length; - char out[1024]; - size_t out_len; - - entry_key_len = 65; - key_len = entry_key_len + 8; - last_key = (char*)mem; - entry_key = last_key + 128; - last_value = entry_key + 128; - *last_key = DbKeyLedgerEntry; - memcpy(last_key+1, o->current_id, key_len - 1); - memcpy(entry_key, last_key, entry_key_len); - while (1) { - last_value_length = 2048; - r = db_next(o->db, DbKeyLedgerEntry, &last_key, &key_len, &last_value, &last_value_length); - if (r) { - break; - } - if (memcmp(last_key, entry_key, entry_key_len)) { - break; - } - out_len = 1024; - r = kee_entry_deserialize_item(o, last_value, last_value_length, out, &out_len); - if (r) { - g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "corrupt entry!"); - } else { - g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "adding entry: %s", out); - gtk_string_list_append(list, out); - } - } - db_rewind(o->db); - free(mem); +// int r; +// size_t key_len; +// size_t entry_key_len; +// char *mem = malloc(4096); +// char *last_key; +// char *entry_key; +// char *last_value; +// size_t last_value_length; +// char out[1024]; +// size_t out_len; +// +// entry_key_len = 65; +// key_len = entry_key_len + 8; +// last_key = (char*)mem; +// entry_key = last_key + 128; +// last_value = entry_key + 128; +// *last_key = DbKeyLedgerEntry; +// memcpy(last_key+1, o->current_id, key_len - 1); +// memcpy(entry_key, last_key, entry_key_len); +// while (1) { +// last_value_length = 2048; +// r = db_next(o->db, DbKeyLedgerEntry, &last_key, &key_len, &last_value, &last_value_length); +// if (r) { +// break; +// } +// if (memcmp(last_key, entry_key, entry_key_len)) { +// break; +// } +// out_len = 1024; +// r = kee_entry_deserialize_item(o, last_value, last_value_length, out, &out_len); +// if (r) { +// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "corrupt entry!"); +// } else { +// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "adding entry: %s", out); +// gtk_string_list_append(list, out); +// } +// //o->alice_credit_balance += o-> +// } +// db_rewind(o->db); +// free(mem); return ERR_OK; } void kee_entry_apply_display_widget(KeeEntry *o) { GtkWidget *widget; - GtkNoSelection *sel; + GtkSingleSelection *sel; GtkListItemFactory *factory; - GtkStringList *list; + KeeEntryItemStore *model; + //GtkStringList *list; - list = gtk_string_list_new(NULL); - kee_entry_load_items(o, list); + //list = gtk_string_list_new(NULL); + //kee_entry_load_items(o, list); widget = gtk_label_new(o->ledger.content.subject); gtk_box_append(GTK_BOX(o), widget); 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); - - sel = gtk_no_selection_new(G_LIST_MODEL(list)); + g_signal_connect(factory, "setup", G_CALLBACK(kee_entry_item_handle_setup), NULL); + g_signal_connect(factory, "bind", G_CALLBACK(kee_entry_item_handle_bind), NULL); + model = kee_entry_item_store_new(o->db, o->current_id); + kee_entry_item_store_set_resolve(model, "./testdata_resource"); + sel = gtk_single_selection_new(G_LIST_MODEL(model)); widget = gtk_list_view_new(GTK_SELECTION_MODEL(sel), GTK_LIST_ITEM_FACTORY(factory)); + //g_signal_connect(view, "activate", G_CALLBACK(kee_entry_item_handle_select), win); gtk_box_append(GTK_BOX(o), widget); return; } diff --git a/src/ledger.h b/src/ledger.h @@ -11,6 +11,7 @@ enum kee_initiator { BOB, }; + struct kee_ledger_item_t { struct kee_ledger_item_t *prev_item; int alice_credit_delta; diff --git a/testdata_asn1.py b/testdata_asn1.py @@ -155,9 +155,6 @@ class LedgerSigner: self.keypair[keyname] = (pk, pubk) self.pubkey_rindex[pubk] = keyname - #env = lmdb.open(d) - #dbi = env.open_db() - self.__write_key(keyname, outdir, pin) self.names[keyname] = fake.name()