mirror of
https://github.com/hoytech/strfry.git
synced 2025-06-17 08:48:51 +00:00
NIP-40 expiration timestamp
This commit is contained in:
@ -21,6 +21,7 @@ table Event {
|
|||||||
kind: uint64;
|
kind: uint64;
|
||||||
tagsGeneral: [TagGeneral];
|
tagsGeneral: [TagGeneral];
|
||||||
tagsFixed32: [TagFixed32];
|
tagsFixed32: [TagFixed32];
|
||||||
|
expiration: uint64;
|
||||||
}
|
}
|
||||||
|
|
||||||
table Empty {}
|
table Empty {}
|
||||||
|
@ -46,6 +46,9 @@ tables:
|
|||||||
multi: true
|
multi: true
|
||||||
deletion: # eventId, pubkey
|
deletion: # eventId, pubkey
|
||||||
multi: true
|
multi: true
|
||||||
|
expiration:
|
||||||
|
integer: true
|
||||||
|
multi: true
|
||||||
|
|
||||||
indexPrelude: |
|
indexPrelude: |
|
||||||
auto *flat = v.flat_nested();
|
auto *flat = v.flat_nested();
|
||||||
@ -70,6 +73,10 @@ tables:
|
|||||||
if (flat->kind() == 5 && tagName == 'e') deletion.push_back(std::string(tagVal) + std::string(sv(flat->pubkey())));
|
if (flat->kind() == 5 && tagName == 'e') deletion.push_back(std::string(tagVal) + std::string(sv(flat->pubkey())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flat->expiration() != 0) {
|
||||||
|
expiration.push_back(flat->expiration());
|
||||||
|
}
|
||||||
|
|
||||||
CompressionDictionary:
|
CompressionDictionary:
|
||||||
fields:
|
fields:
|
||||||
- name: dict
|
- name: dict
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "RelayServer.h"
|
#include "RelayServer.h"
|
||||||
#include "render.h"
|
|
||||||
|
|
||||||
#include "app_git_version.h"
|
#include "app_git_version.h"
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "DBScan.h"
|
#include "DBScan.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "render.h"
|
|
||||||
|
|
||||||
|
|
||||||
static const char USAGE[] =
|
static const char USAGE[] =
|
||||||
|
@ -19,13 +19,14 @@ std::string nostrJsonToFlat(const tao::json::value &v) {
|
|||||||
std::vector<flatbuffers::Offset<NostrIndex::TagGeneral>> tagsGeneral;
|
std::vector<flatbuffers::Offset<NostrIndex::TagGeneral>> tagsGeneral;
|
||||||
std::vector<flatbuffers::Offset<NostrIndex::TagFixed32>> tagsFixed32;
|
std::vector<flatbuffers::Offset<NostrIndex::TagFixed32>> tagsFixed32;
|
||||||
|
|
||||||
|
uint64_t expiration = 0;
|
||||||
|
|
||||||
if (v.at("tags").get_array().size() > cfg().events__maxNumTags) throw herr("too many tags: ", v.at("tags").get_array().size());
|
if (v.at("tags").get_array().size() > cfg().events__maxNumTags) throw herr("too many tags: ", v.at("tags").get_array().size());
|
||||||
for (auto &tagArr : v.at("tags").get_array()) {
|
for (auto &tagArr : v.at("tags").get_array()) {
|
||||||
auto &tag = tagArr.get_array();
|
auto &tag = tagArr.get_array();
|
||||||
if (tag.size() < 2) throw herr("too few fields in tag");
|
if (tag.size() < 2) throw herr("too few fields in tag");
|
||||||
|
|
||||||
auto tagName = tag.at(0).get_string();
|
auto tagName = tag.at(0).get_string();
|
||||||
if (tagName.size() != 1) continue; // only single-char tags need indexing
|
|
||||||
|
|
||||||
auto tagVal = tag.at(1).get_string();
|
auto tagVal = tag.at(1).get_string();
|
||||||
|
|
||||||
@ -37,8 +38,14 @@ std::string nostrJsonToFlat(const tao::json::value &v) {
|
|||||||
(uint8_t)tagName[0],
|
(uint8_t)tagName[0],
|
||||||
(NostrIndex::Fixed32Bytes*)tagVal.data()
|
(NostrIndex::Fixed32Bytes*)tagVal.data()
|
||||||
));
|
));
|
||||||
} else {
|
} else if (tagName == "expiration") {
|
||||||
if (tagVal.size() < 1 || tagVal.size() > cfg().events__maxTagValSize) throw herr("tag val too small/large: ", tagVal.size());
|
if (expiration == 0) {
|
||||||
|
expiration = parseUint64(tagVal);
|
||||||
|
if (expiration == 0) expiration = 1; // special value to indicate expiration of 0 was set
|
||||||
|
}
|
||||||
|
} else if (tagName.size() == 1) {
|
||||||
|
if (tagVal.size() == 0) throw herr("tag val empty");
|
||||||
|
if (tagVal.size() > cfg().events__maxTagValSize) throw herr("tag val too large: ", tagVal.size());
|
||||||
|
|
||||||
if (tagVal.size() <= MAX_INDEXED_TAG_VAL_SIZE) {
|
if (tagVal.size() <= MAX_INDEXED_TAG_VAL_SIZE) {
|
||||||
tagsGeneral.emplace_back(NostrIndex::CreateTagGeneral(builder,
|
tagsGeneral.emplace_back(NostrIndex::CreateTagGeneral(builder,
|
||||||
@ -57,7 +64,8 @@ std::string nostrJsonToFlat(const tao::json::value &v) {
|
|||||||
created_at,
|
created_at,
|
||||||
kind,
|
kind,
|
||||||
builder.CreateVector<flatbuffers::Offset<NostrIndex::TagGeneral>>(tagsGeneral),
|
builder.CreateVector<flatbuffers::Offset<NostrIndex::TagGeneral>>(tagsGeneral),
|
||||||
builder.CreateVector<flatbuffers::Offset<NostrIndex::TagFixed32>>(tagsFixed32)
|
builder.CreateVector<flatbuffers::Offset<NostrIndex::TagFixed32>>(tagsFixed32),
|
||||||
|
expiration
|
||||||
);
|
);
|
||||||
|
|
||||||
builder.Finish(eventPtr);
|
builder.Finish(eventPtr);
|
||||||
@ -122,6 +130,8 @@ void verifyEventTimestamp(const NostrIndex::Event *flat) {
|
|||||||
|
|
||||||
if (ts < earliest) throw herr("created_at too early");
|
if (ts < earliest) throw herr("created_at too early");
|
||||||
if (ts > latest || ts > MAX_TIMESTAMP) throw herr("created_at too late");
|
if (ts > latest || ts > MAX_TIMESTAMP) throw herr("created_at too late");
|
||||||
|
|
||||||
|
if (flat->expiration() != 0 && flat->expiration() <= now) throw herr("event expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
void parseAndVerifyEvent(const tao::json::value &origJson, secp256k1_context *secpCtx, bool verifyMsg, bool verifyTime, std::string &flatStr, std::string &jsonStr) {
|
void parseAndVerifyEvent(const tao::json::value &origJson, secp256k1_context *secpCtx, bool verifyMsg, bool verifyTime, std::string &flatStr, std::string &jsonStr) {
|
||||||
|
2
src/gc.h
2
src/gc.h
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "golpe.h"
|
#include "golpe.h"
|
||||||
|
|
||||||
#include "render.h"
|
|
||||||
|
|
||||||
|
|
||||||
inline void quadrableGarbageCollect(quadrable::Quadrable &qdb, int logLevel = 0) {
|
inline void quadrableGarbageCollect(quadrable::Quadrable &qdb, int logLevel = 0) {
|
||||||
quadrable::Quadrable::GarbageCollector<flat_hash_set<uint64_t>> gc(qdb);
|
quadrable::Quadrable::GarbageCollector<flat_hash_set<uint64_t>> gc(qdb);
|
||||||
|
@ -12,7 +12,10 @@ quadrable::Quadrable getQdbInstance(lmdb::txn &txn);
|
|||||||
quadrable::Quadrable getQdbInstance();
|
quadrable::Quadrable getQdbInstance();
|
||||||
|
|
||||||
|
|
||||||
std::string renderIP(std::string_view ipBytes);
|
|
||||||
|
|
||||||
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
|
||||||
|
|
||||||
|
std::string renderIP(std::string_view ipBytes);
|
||||||
|
std::string renderSize(uint64_t si);
|
||||||
|
std::string renderPercent(double p);
|
||||||
|
uint64_t parseUint64(const std::string &s);
|
||||||
|
60
src/misc.cpp
60
src/misc.cpp
@ -1,7 +1,12 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "golpe.h"
|
#include "golpe.h"
|
||||||
|
|
||||||
|
|
||||||
std::string renderIP(std::string_view ipBytes) {
|
std::string renderIP(std::string_view ipBytes) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
@ -15,3 +20,58 @@ std::string renderIP(std::string_view ipBytes) {
|
|||||||
|
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string renderSize(uint64_t si) {
|
||||||
|
if (si < 1024) return std::to_string(si) + "b";
|
||||||
|
|
||||||
|
double s = si;
|
||||||
|
char buf[128];
|
||||||
|
char unit;
|
||||||
|
|
||||||
|
do {
|
||||||
|
s /= 1024;
|
||||||
|
if (s < 1024) {
|
||||||
|
unit = 'K';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s /= 1024;
|
||||||
|
if (s < 1024) {
|
||||||
|
unit = 'M';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s /= 1024;
|
||||||
|
if (s < 1024) {
|
||||||
|
unit = 'G';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s /= 1024;
|
||||||
|
unit = 'T';
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
::snprintf(buf, sizeof(buf), "%.2f%c", s, unit);
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::string renderPercent(double p) {
|
||||||
|
char buf[128];
|
||||||
|
::snprintf(buf, sizeof(buf), "%.1f%%", p * 100);
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t parseUint64(const std::string &s) {
|
||||||
|
auto digitChar = [](char c){
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!std::all_of(s.begin(), s.end(), digitChar)) throw herr("non-digit character");
|
||||||
|
|
||||||
|
return std::stoull(s);
|
||||||
|
}
|
||||||
|
44
src/render.h
44
src/render.h
@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
inline std::string renderSize(uint64_t si) {
|
|
||||||
if (si < 1024) return std::to_string(si) + "b";
|
|
||||||
|
|
||||||
double s = si;
|
|
||||||
char buf[128];
|
|
||||||
char unit;
|
|
||||||
|
|
||||||
do {
|
|
||||||
s /= 1024;
|
|
||||||
if (s < 1024) {
|
|
||||||
unit = 'K';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s /= 1024;
|
|
||||||
if (s < 1024) {
|
|
||||||
unit = 'M';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s /= 1024;
|
|
||||||
if (s < 1024) {
|
|
||||||
unit = 'G';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s /= 1024;
|
|
||||||
unit = 'T';
|
|
||||||
} while(0);
|
|
||||||
|
|
||||||
::snprintf(buf, sizeof(buf), "%.2f%c", s, unit);
|
|
||||||
return std::string(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string renderPercent(double p) {
|
|
||||||
char buf[128];
|
|
||||||
::snprintf(buf, sizeof(buf), "%.1f%%", p * 100);
|
|
||||||
return std::string(buf);
|
|
||||||
}
|
|
Reference in New Issue
Block a user