mirror of
https://github.com/jb55/nostril.git
synced 2024-11-27 02:09:07 -05:00
add proof-of-work mining
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
parent
75da4517be
commit
29be8497fc
72
nostril.c
72
nostril.c
|
@ -16,6 +16,7 @@
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
#include "proof.h"
|
||||||
|
|
||||||
#define MAX_TAGS 32
|
#define MAX_TAGS 32
|
||||||
#define MAX_TAG_ELEMS 16
|
#define MAX_TAG_ELEMS 16
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
#define HAS_KIND (1<<2)
|
#define HAS_KIND (1<<2)
|
||||||
#define HAS_ENVELOPE (1<<3)
|
#define HAS_ENVELOPE (1<<3)
|
||||||
#define HAS_ENCRYPT (1<<4)
|
#define HAS_ENCRYPT (1<<4)
|
||||||
|
#define HAS_DIFFICULTY (1<<5)
|
||||||
|
|
||||||
struct key {
|
struct key {
|
||||||
secp256k1_keypair pair;
|
secp256k1_keypair pair;
|
||||||
|
@ -34,6 +36,7 @@ struct key {
|
||||||
struct args {
|
struct args {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int kind;
|
int kind;
|
||||||
|
int difficulty;
|
||||||
|
|
||||||
unsigned char encrypt_to[32];
|
unsigned char encrypt_to[32];
|
||||||
const char *sec;
|
const char *sec;
|
||||||
|
@ -72,6 +75,7 @@ void usage()
|
||||||
printf(" --kind <number> set kind\n");
|
printf(" --kind <number> set kind\n");
|
||||||
printf(" --created-at <unix timestamp> set a specific created-at time\n");
|
printf(" --created-at <unix timestamp> set a specific created-at time\n");
|
||||||
printf(" --sec <hex seckey> set the secret key for signing, otherwise one will be randomly generated\n");
|
printf(" --sec <hex seckey> set the secret key for signing, otherwise one will be randomly generated\n");
|
||||||
|
printf(" --pow <difficulty> number of leading 0 bits of the id to mine\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +379,14 @@ static int parse_args(int argc, const char *argv[], struct args *args)
|
||||||
args->flags |= HAS_KIND;
|
args->flags |= HAS_KIND;
|
||||||
} else if (!strcmp(arg, "--envelope")) {
|
} else if (!strcmp(arg, "--envelope")) {
|
||||||
args->flags |= HAS_ENVELOPE;
|
args->flags |= HAS_ENVELOPE;
|
||||||
|
} else if (!strcmp(arg, "--pow")) {
|
||||||
|
arg = *argv++; argc--;
|
||||||
|
if (!parse_num(arg, &n)) {
|
||||||
|
fprintf(stderr, "could not parse difficulty as number: '%s'\n", arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
args->difficulty = n;
|
||||||
|
args->flags |= HAS_DIFFICULTY;
|
||||||
} else if (!strcmp(arg, "--dm")) {
|
} else if (!strcmp(arg, "--dm")) {
|
||||||
arg = *argv++; argc--;
|
arg = *argv++; argc--;
|
||||||
if (!hex_decode(arg, strlen(arg), args->encrypt_to, 32)) {
|
if (!hex_decode(arg, strlen(arg), args->encrypt_to, 32)) {
|
||||||
|
@ -439,6 +451,53 @@ static int copyx(unsigned char *output, const unsigned char *x32, const unsigned
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ensure_nonce_tag(struct nostr_event *ev, int *index)
|
||||||
|
{
|
||||||
|
struct nostr_tag *tag;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ev->num_tags; i++) {
|
||||||
|
tag = &ev->tags[i];
|
||||||
|
if (tag->num_elems == 2 && !strcmp(tag->strs[0], "nonce")) {
|
||||||
|
*index = i;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*index = ev->num_tags;
|
||||||
|
return nostr_add_tag(ev, "nonce", "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mine_event(struct nostr_event *ev, int difficulty)
|
||||||
|
{
|
||||||
|
char *strnonce = malloc(33);
|
||||||
|
struct nostr_tag *tag;
|
||||||
|
uint64_t nonce;
|
||||||
|
int index, res;
|
||||||
|
|
||||||
|
if (!ensure_nonce_tag(ev, &index))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tag = &ev->tags[index];
|
||||||
|
assert(tag->num_elems == 2);
|
||||||
|
assert(!strcmp(tag->strs[0], "nonce"));
|
||||||
|
tag->strs[1] = strnonce;
|
||||||
|
|
||||||
|
for (nonce = 0;; nonce++) {
|
||||||
|
snprintf(strnonce, 32, "%" PRIu64, nonce);
|
||||||
|
|
||||||
|
if (!generate_event_id(ev))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((res = count_leading_zero_bits(ev->id)) >= difficulty) {
|
||||||
|
fprintf(stderr, "mined %d bits\n", res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int make_encrypted_dm(secp256k1_context *ctx, struct key *key,
|
static int make_encrypted_dm(secp256k1_context *ctx, struct key *key,
|
||||||
struct nostr_event *ev, unsigned char nostr_pubkey[32])
|
struct nostr_event *ev, unsigned char nostr_pubkey[32])
|
||||||
{
|
{
|
||||||
|
@ -572,9 +631,16 @@ int main(int argc, const char *argv[])
|
||||||
// set the event's pubkey
|
// set the event's pubkey
|
||||||
memcpy(ev.pubkey, key.pubkey, 32);
|
memcpy(ev.pubkey, key.pubkey, 32);
|
||||||
|
|
||||||
if (!generate_event_id(&ev)) {
|
if (args.flags & HAS_DIFFICULTY) {
|
||||||
fprintf(stderr, "could not generate event id\n");
|
if (!mine_event(&ev, args.difficulty)) {
|
||||||
return 5;
|
fprintf(stderr, "error when mining id\n");
|
||||||
|
return 22;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!generate_event_id(&ev)) {
|
||||||
|
fprintf(stderr, "could not generate event id\n");
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sign_event(ctx, &key, &ev)) {
|
if (!sign_event(ctx, &key, &ev)) {
|
||||||
|
|
26
proof.h
Normal file
26
proof.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
static inline int zero_bits(unsigned char b)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (b == 0)
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
while (b >>= 1)
|
||||||
|
n++;
|
||||||
|
|
||||||
|
return 7-n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the number of leading zero bits in a hash */
|
||||||
|
static int count_leading_zero_bits(unsigned char *hash)
|
||||||
|
{
|
||||||
|
int bits, total, i;
|
||||||
|
|
||||||
|
for (i = 0, total = 0; i < 32; i++) {
|
||||||
|
bits = zero_bits(hash[i]);
|
||||||
|
total += bits;
|
||||||
|
if (bits != 8)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user