mirror of
https://github.com/jb55/nostril.git
synced 2024-12-24 11:15:51 -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 "sha256.h"
|
||||
#include "random.h"
|
||||
#include "proof.h"
|
||||
|
||||
#define MAX_TAGS 32
|
||||
#define MAX_TAG_ELEMS 16
|
||||
|
@ -24,6 +25,7 @@
|
|||
#define HAS_KIND (1<<2)
|
||||
#define HAS_ENVELOPE (1<<3)
|
||||
#define HAS_ENCRYPT (1<<4)
|
||||
#define HAS_DIFFICULTY (1<<5)
|
||||
|
||||
struct key {
|
||||
secp256k1_keypair pair;
|
||||
|
@ -34,6 +36,7 @@ struct key {
|
|||
struct args {
|
||||
unsigned int flags;
|
||||
int kind;
|
||||
int difficulty;
|
||||
|
||||
unsigned char encrypt_to[32];
|
||||
const char *sec;
|
||||
|
@ -72,6 +75,7 @@ void usage()
|
|||
printf(" --kind <number> set kind\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(" --pow <difficulty> number of leading 0 bits of the id to mine\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -375,6 +379,14 @@ static int parse_args(int argc, const char *argv[], struct args *args)
|
|||
args->flags |= HAS_KIND;
|
||||
} else if (!strcmp(arg, "--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")) {
|
||||
arg = *argv++; argc--;
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
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
|
||||
memcpy(ev.pubkey, key.pubkey, 32);
|
||||
|
||||
if (!generate_event_id(&ev)) {
|
||||
fprintf(stderr, "could not generate event id\n");
|
||||
return 5;
|
||||
if (args.flags & HAS_DIFFICULTY) {
|
||||
if (!mine_event(&ev, args.difficulty)) {
|
||||
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)) {
|
||||
|
|
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