1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#include <ctime>
#include <openssl/evp.h>
#include <iomanip>
#include <sstream>
#include <string>
#include <nlohmann/json.hpp>
#include <sha.h>
#include "nostr.hpp"
using nlohmann::json;
using std::hex;
using std::invalid_argument;
using std::make_shared;
using std::setw;
using std::setfill;
using std::shared_ptr;
using std::string;
using std::stringstream;
using std::time;
namespace nostr
{
string Event::serialize()
{
try
{
this->validate();
}
catch (const invalid_argument& e)
{
throw e;
}
json j = {
{"pubkey", this->pubkey},
{"created_at", this->createdAt},
{"kind", this->kind},
{"tags", this->tags},
{"content", this->content},
{"sig", this->sig}
};
j["id"] = this->generateId(j.dump());
return j.dump();
};
Event Event::fromString(string jstr)
{
json j = json::parse(jstr);
return Event::fromJson(j);
};
Event Event::fromJson(json j)
{
Event event;
event.id = j["id"];
event.pubkey = j["pubkey"];
event.createdAt = j["created_at"];
event.kind = j["kind"];
event.tags = j["tags"];
event.content = j["content"];
event.sig = j["sig"];
return event;
};
void Event::validate()
{
bool hasPubkey = this->pubkey.length() > 0;
if (!hasPubkey)
{
throw std::invalid_argument("Event::validate: The pubkey of the event author is required.");
}
bool hasCreatedAt = this->createdAt > 0;
if (!hasCreatedAt)
{
this->createdAt = time(nullptr);
}
bool hasKind = this->kind >= 0 && this->kind < 40000;
if (!hasKind)
{
throw std::invalid_argument("Event::validate: A valid event kind is required.");
}
bool hasSignature = this->sig.length() > 0;
if (!hasSignature)
{
throw std::invalid_argument("Event::validate: The event must be signed.");
}
};
string Event::generateId(string serializedData) const
{
unsigned char hash[SHA256_DIGEST_LENGTH];
EVP_Digest(serializedData.c_str(), serializedData.length(), hash, NULL, EVP_sha256(), NULL);
stringstream ss;
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
ss << hex << setw(2) << setfill('0') << (int)hash[i];
}
return ss.str();
};
} // namespace nostr
|