commit 93843d782e4979521d213e8c3cd2e482e63e2d4e
parent f5754dc907aa1afa7015fe0e5767a528feb10ec1
Author: lash <dev@holbrook.no>
Date: Mon, 29 Apr 2024 20:41:34 +0100
Add ledger put
Diffstat:
11 files changed, 221 insertions(+), 69 deletions(-)
diff --git a/src/db.c b/src/db.c
@@ -29,97 +29,109 @@ int db_connect(struct db_ctx *ctx, char *conn) {
return ERR_OK;
}
-/**
- * \todo split up and optimize
- */
-int db_put(struct db_ctx *ctx, enum DbKey pfx, char *data, size_t data_len) {
+
+/// \todo atomic tx put
+int db_put(struct db_ctx *ctx, char *key, size_t key_len, char *data, size_t data_len) {
int r;
- char *buf;
- char buf_reverse[33];
- unsigned char *rv;
- char kv;
- struct timespec ts;
- char rts[sizeof(struct timespec)];
- gcry_error_t e;
- gcry_md_hd_t h;
MDB_txn *tx;
MDB_dbi dbi;
MDB_val k;
MDB_val v;
- buf = (char*)malloc(1 + 32 + sizeof(struct timespec)); // length should be lookup in sizes array for each key
-
- r = clock_gettime(CLOCK_REALTIME, &ts);
- if (r) {
- free(buf);
- return ERR_FAIL;
- }
- memcpy(rts, &ts.tv_sec, sizeof(ts.tv_sec));
- memcpy(rts + sizeof(ts.tv_sec), &ts.tv_nsec, sizeof(ts.tv_nsec));
- to_endian(0, sizeof(ts.tv_sec), rts);
- to_endian(0, sizeof(ts.tv_nsec), rts + sizeof(ts.tv_sec));
-
- e = gcry_md_open(&h, GCRY_MD_SHA256, 0);
- if (e) {
- free(buf);
- return ERR_DIGESTFAIL;
- }
- gcry_md_write(h, data, data_len);
- rv = gcry_md_read(h, 0);
- kv = (char)pfx;
- memcpy(buf, &kv, 1);
- memcpy(buf + 1, rts, sizeof(struct timespec));
- memcpy(buf + 1 + sizeof(struct timespec), rv, 32);
-
r = mdb_txn_begin(ctx->env, NULL, 0, &tx);
if (r) {
- free(buf);
return ERR_FAIL;
}
r = mdb_dbi_open(tx, NULL, MDB_CREATE, &dbi);
if (r) {
- free(buf);
return ERR_FAIL;
}
- k.mv_data = buf;
- k.mv_size = 1 + 32 + sizeof(struct timespec);
+ k.mv_data = key;
+ k.mv_size = key_len;
v.mv_data = data;
v.mv_size = data_len;
r = mdb_put(tx, dbi, &k, &v, 0);
if (r) {
- free(buf);
- return ERR_FAIL;
- }
-
- // put reverse lookup
- buf_reverse[0] = (char)DbKeyReverse;
- memcpy(buf_reverse+1, rv, 32);
- k.mv_data = buf_reverse;
- k.mv_size = 33;
- v.mv_data = buf;
- v.mv_size = 1 + 32 + sizeof(struct timespec);
- gcry_md_close(h); // keep the handle open until here because we use its digest value again for the key
-
- r = mdb_put(tx, dbi, &k, &v, 0);
- if (r) {
- free(buf);
return ERR_FAIL;
}
r = mdb_txn_commit(tx);
if (r) {
- free(buf);
return ERR_FAIL;
}
- free(buf);
return ERR_OK;
-
}
+///**
+// * \todo split up and optimize
+// */
+//int db_put(struct db_ctx *ctx, enum DbKey pfx, char *data, size_t data_len) {
+// int r;
+// char *buf;
+// char buf_reverse[33];
+// unsigned char *rv;
+// char kv;
+// struct timespec ts;
+// char rts[sizeof(struct timespec)];
+// gcry_error_t e;
+// gcry_md_hd_t h;
+//
+// buf = (char*)malloc(1 + 32 + sizeof(struct timespec)); // length should be lookup in sizes array for each key
+//
+// r = clock_gettime(CLOCK_REALTIME, &ts);
+// if (r) {
+// free(buf);
+// return ERR_FAIL;
+// }
+// memcpy(rts, &ts.tv_sec, sizeof(ts.tv_sec));
+// memcpy(rts + sizeof(ts.tv_sec), &ts.tv_nsec, sizeof(ts.tv_nsec));
+// to_endian(0, sizeof(ts.tv_sec), rts);
+// to_endian(0, sizeof(ts.tv_nsec), rts + sizeof(ts.tv_sec));
+//
+// e = gcry_md_open(&h, GCRY_MD_SHA256, 0);
+// if (e) {
+// free(buf);
+// return ERR_DIGESTFAIL;
+// }
+// gcry_md_write(h, data, data_len);
+// rv = gcry_md_read(h, 0);
+// kv = (char)pfx;
+// memcpy(buf, &kv, 1);
+// memcpy(buf + 1, rts, sizeof(struct timespec));
+// memcpy(buf + 1 + sizeof(struct timespec), rv, 32);
+//
+//
+//
+// // put reverse lookup
+// buf_reverse[0] = (char)DbKeyReverse;
+// memcpy(buf_reverse+1, rv, 32);
+// k.mv_data = buf_reverse;
+// k.mv_size = 33;
+// v.mv_data = buf;
+// v.mv_size = 1 + 32 + sizeof(struct timespec);
+// gcry_md_close(h); // keep the handle open until here because we use its digest value again for the key
+//
+// r = mdb_put(tx, dbi, &k, &v, 0);
+// if (r) {
+// free(buf);
+// return ERR_FAIL;
+// }
+//
+// r = mdb_txn_commit(tx);
+// if (r) {
+// free(buf);
+// return ERR_FAIL;
+// }
+// free(buf);
+//
+// return ERR_OK;
+//
+//}
+
/**
*
* \todo change cursor to jump to new search match when current (last) prefix does not match lookup prefix.
diff --git a/src/db.h b/src/db.h
@@ -15,6 +15,7 @@
enum DbErr {
ERR_DB_FAIL = 1,
ERR_DB_NOMATCH,
+ ERR_DB_EXISTS,
ERR_DB_INVALID,
};
@@ -54,7 +55,8 @@ struct db_ctx {
};
int db_connect(struct db_ctx *ctx, char *conn);
-int db_put(struct db_ctx *ctx, enum DbKey pfx, char *data, size_t data_len);
+//int db_put(struct db_ctx *ctx, enum DbKey pfx, char *data, size_t data_len);
+int db_put(struct db_ctx *ctx, char *key, size_t key_len, char *data, size_t data_len);
int db_next(struct db_ctx *ctx, enum DbKey pfx, char **key, size_t *key_len, char **value, size_t *value_len);
void db_rewind(struct db_ctx *ctx);
void db_reset(struct db_ctx *ctx);
diff --git a/src/gtk/kee-entry.c b/src/gtk/kee-entry.c
@@ -81,7 +81,6 @@ static void kee_entry_handle_add(GtkButton *butt, KeeEntry *o) {
struct kee_ledger_item_t *item;
GtkEntryBuffer *buf;
char *b;
- size_t c;
struct kee_transport_t trans;
char *out;
size_t out_len;
diff --git a/src/ledger.c b/src/ledger.c
@@ -136,7 +136,7 @@ static int verify_item(struct kee_ledger_t *ledger, asn1_node item, const char *
if (r) {
return 1;
}
- debug_log(DEBUG_DEBUG, "ledger item verified\n");
+ debug_log(DEBUG_DEBUG, "ledger item verified");
}
// c = 0;
@@ -202,9 +202,10 @@ void kee_ledger_item_apply_cache(struct kee_ledger_t *ledger, struct kee_ledger_
}
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_credit_balance += item->bob_credit_delta;
ledger->cache->bob_collateral_balance += item->bob_collateral_delta;
+
ledger->cache->count++;
}
@@ -220,7 +221,7 @@ struct kee_ledger_item_t *kee_ledger_add_item(struct kee_ledger_t *ledger) {
struct kee_ledger_item_t *prev;
prev = ledger->last_item;
- ledger->last_item = malloc(sizeof(struct kee_ledger_item_t));
+ ledger->last_item = calloc(sizeof(struct kee_ledger_item_t), 1);
kee_ledger_item_init(ledger->last_item);
ledger->last_item->prev_item = prev;
@@ -798,6 +799,8 @@ int kee_ledger_parse_open(struct kee_ledger_t *ledger, char *in, size_t in_len)
struct kee_ledger_item_t *item;
char is_bob;
+ kee_ledger_init(ledger);
+
memset(&root, 0, sizeof(root));
memset(&pair, 0, sizeof(root));
r = asn1_array2tree(schema_entry_asn1_tab, &root, err);
@@ -862,3 +865,85 @@ int kee_ledger_parse_open(struct kee_ledger_t *ledger, char *in, size_t in_len)
return ERR_OK;
}
+
+static size_t ledger_db_key(char *out) {
+ int r;
+ char *p;
+ struct timespec ts;
+ unsigned int sec;
+ unsigned int nsec;
+
+ *out = DbKeyLedgerHead;
+ p = out + 1;
+
+ r = clock_gettime(CLOCK_REALTIME, &ts);
+ if (r) {
+ return 0;
+ }
+
+ sec = (unsigned int)ts.tv_sec;
+ nsec = (unsigned int)ts.tv_nsec;
+
+ memcpy(p, &sec, sizeof(sec));
+ memcpy(p + sizeof(sec), &nsec, sizeof(nsec));
+ to_endian(TO_ENDIAN_BIG, sizeof(sec), p);
+ to_endian(TO_ENDIAN_BIG, sizeof(nsec), p + sizeof(sec));
+ return sizeof(sec) + sizeof(nsec) + 1;
+}
+
+int kee_ledger_put(struct kee_ledger_t *ledger, struct db_ctx *db) {
+ int r;
+ size_t c;
+ size_t l;
+ char mem[1024];
+ char *k;
+ char *v;
+
+ k = (char*)mem;
+ v = ((char*)mem)+96;
+
+ k[0] = DbKeyReverse;
+ memcpy(((char*)k)+1, ledger->digest, DIGEST_LENGTH);
+ l = DIGEST_LENGTH + 1;
+ c = 928; // 1024 - 96
+ db_rewind(db);
+ r = db_next(db, DbKeyReverse, &k, &l, &v, &c);
+ if (!r) {
+ k = v;
+ l = c;
+ c = 928;
+ db_rewind(db);
+ r = db_next(db, DbKeyLedgerHead, &k, &l, &v, &c);
+ if (!r) {
+ return ERR_DB_EXISTS;
+ }
+ }
+
+ l = ledger_db_key(k);
+ if (l == 0) {
+ return ERR_FAIL;
+ }
+
+ c = 928;
+ r = kee_ledger_serialize(ledger, v, &c);
+ if (r) {
+ return ERR_DB_FAIL;
+ }
+
+ r = db_put(db, k, l, v, c);
+ if (r) {
+ return ERR_DB_FAIL;
+ }
+
+ memcpy(v, k, l);
+ c = l;
+ l = DIGEST_LENGTH + 1;
+ *k = DbKeyReverse;
+ memcpy(k+1, ledger->digest, DIGEST_LENGTH);
+ r = db_put(db, k, l, v, c);
+ if (r) {
+ return ERR_DB_FAIL;
+ }
+
+ return ERR_OK;
+}
diff --git a/src/ledger.h b/src/ledger.h
@@ -6,6 +6,7 @@
#include "content.h"
#include "cadiz.h"
#include "gpg.h"
+#include "db.h"
enum kee_initiator_e {
ALICE,
@@ -66,5 +67,7 @@ void kee_ledger_item_init(struct kee_ledger_item_t *item);
int kee_ledger_item_serialize(struct kee_ledger_item_t *item, char *out, size_t *out_len, enum kee_item_serialize_mode_e mode);
int kee_ledger_serialize_open(struct kee_ledger_t *ledger, char *out, size_t *out_len);
int kee_ledger_parse_open(struct kee_ledger_t *ledger, char *in, size_t in_len);
+int kee_ledger_put(struct kee_ledger_t *ledger, struct db_ctx *db);
+
#endif
diff --git a/src/term_debug.c b/src/term_debug.c
@@ -2,6 +2,6 @@
#include "debug.h"
-void debugLog(enum debugLevel level, const char *s) {
- fprintf(stderr, "%d: %s\n", level, s);
-}
+//void debug_log(enum debugLevel level, const char *s) {
+// fprintf(stderr, "%d: %s\n", level, s);
+//}
diff --git a/src/tests/debug.c b/src/tests/debug.c
@@ -3,5 +3,5 @@
#include "debug.h"
void debug_log(enum debugLevel level, const char *s) {
- fprintf(stderr, s);
+ fprintf(stderr, "%s\n", s);
}
diff --git a/src/tests/ledger.c b/src/tests/ledger.c
@@ -402,6 +402,28 @@ int test_pair() {
return 0;
}
+int test_put() {
+ int r;
+ struct kee_test_t t;
+
+ r = kee_test_generate(&t);
+ if (r) {
+ return 1;
+ }
+
+ r = kee_test_db(&t);
+ if (r) {
+ return 1;
+ }
+
+ r = kee_ledger_put(&t.ledger, &t.db);
+ if (r) {
+ return 1;
+ }
+
+ return 0;
+}
+
int main() {
int r;
@@ -425,6 +447,10 @@ int main() {
if (r) {
return 1;
}
+ r = test_put();
+ if (r) {
+ return 1;
+ }
return 0;
}
diff --git a/src/tests/testutil.c b/src/tests/testutil.c
@@ -8,7 +8,26 @@
#include "err.h"
#include "content.h"
#include "digest.h"
+#include "db.h"
+int kee_test_db(struct kee_test_t *t) {
+ int r;
+ char *p;
+ char path[64];
+
+ strcpy(path, "/tmp/keetest_db_XXXXXX");
+ p = mkdtemp(path);
+ if (p == NULL) {
+ return 1;
+ }
+
+ r = db_connect(&t->db, p);
+ if (r) {
+ return 1;
+ }
+
+ return 0;
+}
int kee_test_generate(struct kee_test_t *t) {
int r;
@@ -85,6 +104,7 @@ int kee_test_generate(struct kee_test_t *t) {
return 1;
}
+ /// \todo oh dear, they are serialized as platform endian, should be big.
item = kee_ledger_add_item(&t->ledger);
item->alice_credit_delta = 666;
item->bob_credit_delta = -42;
diff --git a/src/tests/testutil.h b/src/tests/testutil.h
@@ -4,6 +4,7 @@
#include <gcrypt.h>
#include "ledger.h"
+#include "db.h"
static const char *content_test = "Subject: foo\n\nsome content\n";
static const char *content_test_item = "Subject: bar\n\nsome other content\n";
@@ -23,6 +24,7 @@ struct kee_test_t {
char ledger_item_bytes[1024];
size_t ledger_item_bytes_len;
size_t item_count;
+ struct db_ctx db;
};
int kee_test_generate(struct kee_test_t *t);
@@ -30,5 +32,6 @@ int kee_test_ledger_data(struct kee_test_t *t);
void kee_test_free(struct kee_test_t *t);
size_t kee_test_get_ledger_data(struct kee_test_t *t, char **out);
size_t kee_test_get_ledger_item_data(struct kee_test_t *t, int idx, char **out);
+int kee_test_db(struct kee_test_t *t);
#endif
diff --git a/testdata_asn1.py b/testdata_asn1.py
@@ -479,6 +479,9 @@ if __name__ == '__main__':
z = v[0]
k = LedgerHead.to_key(v[0])
tx.put(k, v[1])
+ # reverse lookup
+ kr = b'\xff' + v[0]
+ tx.put(kr, k[1:])
for v in r:
k = LedgerEntry.to_key(v[1], z)
@@ -488,4 +491,3 @@ if __name__ == '__main__':
pubk = signer.get_pubkey(k)
name = signer.get_name(k).encode('utf-8')
tx.put(PFX_LEDGER_PUBKEY + pubk, b'CN=' + name)
-