Browse Source

Generate coinbase templates, fixing missing fields from gbt parser

master
Con Kolivas 11 years ago
parent
commit
86159a60ec
  1. 4
      src/bitcoin.c
  2. 3
      src/bitcoin.h
  3. 115
      src/stratifier.c

4
src/bitcoin.c

@ -252,6 +252,9 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt)
gbt->height = height; gbt->height = height;
json_object_set_new_nocheck(gbt->json, "height", json_integer(height)); json_object_set_new_nocheck(gbt->json, "height", json_integer(height));
gbt->flags = strdup(flags);
json_object_set_new_nocheck(gbt->json, "flags", json_string_nocheck(gbt->flags));
gbt_merkle_bins(gbt, transaction_arr); gbt_merkle_bins(gbt, transaction_arr);
json_object_set_new_nocheck(gbt->json, "transactions", json_integer(gbt->transactions)); json_object_set_new_nocheck(gbt->json, "transactions", json_integer(gbt->transactions));
if (gbt->transactions) if (gbt->transactions)
@ -272,6 +275,7 @@ out:
void clear_gbtbase(gbtbase_t *gbt) void clear_gbtbase(gbtbase_t *gbt)
{ {
dealloc(gbt->flags);
dealloc(gbt->txn_data); dealloc(gbt->txn_data);
json_decref(gbt->json); json_decref(gbt->json);
gbt->json = NULL; gbt->json = NULL;

3
src/bitcoin.h

@ -19,8 +19,9 @@ struct gbtbase {
char ntime[12]; char ntime[12];
char bbversion[12]; char bbversion[12];
char nbit[12]; char nbit[12];
int coinbasevalue; uint64_t coinbasevalue;
int height; int height;
char *flags;
int transactions; int transactions;
char *txn_data; char *txn_data;
int merkles; int merkles;

115
src/stratifier.c

@ -17,6 +17,12 @@
#include "libckpool.h" #include "libckpool.h"
#include "bitcoin.h" #include "bitcoin.h"
static const char *scriptsig_header = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff";
static uchar scriptsig_header_bin[41];
static char pubkeytxnbin[25];
static char pubkeytxn[52];
struct workbase { struct workbase {
/* GBT/shared variables */ /* GBT/shared variables */
char target[68]; char target[68];
@ -27,14 +33,32 @@ struct workbase {
char ntime[12]; char ntime[12];
char bbversion[12]; char bbversion[12];
char nbit[12]; char nbit[12];
int coinbasevalue; uint64_t coinbasevalue;
int height; int height;
char *flags;
int transactions; int transactions;
char *txn_data; char *txn_data;
int merkles; int merkles;
char merklehash[16][68]; char merklehash[16][68];
/* Work variables */ /* Template variables, lengths are binary lengths! */
char coinb1[256]; // coinbase1
uchar coinb1bin[128];
int coinb1len; // length of above
char enonce1const[32]; // extranonce1 section that is constant
uchar enonce1constbin[16];
int enonce1constlen; // length of above - usually zero unless proxying
int enonce1varlen; // length of unique extranonce1 string for each worker - usually 8
char enonce2const[16]; // extranonce2 section that is constant
uchar enonce2constbin[8];
int enonce2constlen; // length of above - usually zero unless proxying
int enonce2varlen; // length of space left for extranonce2 - usually 8
char coinb2[128]; // coinbase2
uchar coinb2bin[64];
int coinb2len; // length of above
}; };
typedef struct workbase workbase_t; typedef struct workbase workbase_t;
@ -55,6 +79,10 @@ static inline void json_uintcpy(uint32_t *u32, json_t *val, const char *key)
*u32 = (uint32_t)json_integer_value(json_object_get(val, key)); *u32 = (uint32_t)json_integer_value(json_object_get(val, key));
} }
static inline void json_uint64cpy(uint64_t *u64, json_t *val, const char *key)
{
*u64 = (uint64_t)json_integer_value(json_object_get(val, key));
}
static inline void json_intcpy(int *i, json_t *val, const char *key) static inline void json_intcpy(int *i, json_t *val, const char *key)
{ {
*i = json_integer_value(json_object_get(val, key)); *i = json_integer_value(json_object_get(val, key));
@ -65,6 +93,81 @@ static inline void json_strdup(char **buf, json_t *val, const char *key)
*buf = strdup(json_string_value(json_object_get(val, key))); *buf = strdup(json_string_value(json_object_get(val, key)));
} }
static void generate_coinbase(ckpool_t *ckp, workbase_t *wb)
{
int len, ofs = 0;
uint64_t *u64;
tv_t now;
/* Strings in wb should have been zero memset prior. Generate binary
* templates first, then convert to hex */
memcpy(wb->coinb1bin, scriptsig_header_bin, 41);
ofs += 41; // Fixed header length;
ofs++; // Script length is filled in at the end @wb->coinb1bin[41];
/* Put block height at start of template */
ofs += ser_number(wb->coinb1bin + ofs, wb->height);
/* Followed by flag */
len = strlen(wb->flags) / 2;
wb->coinb1bin[ofs++] = len;
hex2bin(wb->coinb1bin + ofs, wb->flags, len);
ofs += len;
/* Followed by timestamp */
tv_time(&now);
ofs += ser_number(wb->coinb1bin + ofs, now.tv_sec);
wb->coinb1len = ofs;
len = wb->coinb1len - 41;
/* Leave enonce1/2varlen constant at 8 bytes for bitcoind sources */
wb->enonce1varlen = 8;
len += wb->enonce1varlen;
wb->enonce2varlen = 8;
len += wb->enonce2varlen;
memcpy(wb->coinb2bin, "\x0a\x2f\x63\x6b\x70\x6f\x6f\x6c\x34\x32\x2f", 11);
wb->coinb2len = 11;
if (ckp->btcsig) {
int siglen = strlen(ckp->btcsig);
LOGDEBUG("Len %d sig %s", siglen, ckp->btcsig);
if (siglen) {
wb->coinb2bin[wb->coinb2len++] = siglen;
memcpy(wb->coinb2bin + wb->coinb2len, ckp->btcsig, siglen);
wb->coinb2len += siglen;
}
}
len += wb->coinb2len;
wb->coinb1bin[41] = len; /* Set the length now */
__bin2hex(wb->coinb1, wb->coinb1bin, wb->coinb1len);
LOGDEBUG("Coinb1: %s", wb->coinb1);
/* Coinbase 1 complete */
memcpy(wb->coinb2bin + wb->coinb2len, "\xff\xff\xff\xff", 4);
wb->coinb2len += 4;
wb->coinb2bin[wb->coinb2len++] = 1;
u64 = (uint64_t *)&wb->coinb2bin[wb->coinb2len];
*u64 = htole64(wb->coinbasevalue);
wb->coinb2len += 8;
wb->coinb2bin[wb->coinb2len++] = 25;
memcpy(wb->coinb2bin + wb->coinb2len, pubkeytxnbin, 25);
wb->coinb2len += 25;
wb->coinb2len += 4; // Blank lock
__bin2hex(wb->coinb2, wb->coinb2bin, wb->coinb2len);
LOGDEBUG("Coinb2: %s", wb->coinb2);
/* Coinbase 2 complete */
}
/* This function assumes it will only receive a valid json gbt base template /* This function assumes it will only receive a valid json gbt base template
* since checking should have been done earlier, and creates the base template * since checking should have been done earlier, and creates the base template
* for generating work templates. */ * for generating work templates. */
@ -91,8 +194,9 @@ static void update_base(ckpool_t *ckp)
json_strcpy(wb.ntime, val, "ntime"); json_strcpy(wb.ntime, val, "ntime");
json_strcpy(wb.bbversion, val, "bbversion"); json_strcpy(wb.bbversion, val, "bbversion");
json_strcpy(wb.nbit, val, "nbit"); json_strcpy(wb.nbit, val, "nbit");
json_intcpy(&wb.coinbasevalue, val, "coinbasevalue"); json_uint64cpy(&wb.coinbasevalue, val, "coinbasevalue");
json_intcpy(&wb.height, val, "height"); json_intcpy(&wb.height, val, "height");
json_strdup(&wb.flags, val, "flags");
json_intcpy(&wb.transactions, val, "transactions"); json_intcpy(&wb.transactions, val, "transactions");
if (wb.transactions) if (wb.transactions)
json_strdup(&wb.txn_data, val, "txn_data"); json_strdup(&wb.txn_data, val, "txn_data");
@ -106,6 +210,7 @@ static void update_base(ckpool_t *ckp)
strcpy(&wb.merklehash[i][0], json_string_value(json_array_get(arr, i))); strcpy(&wb.merklehash[i][0], json_string_value(json_array_get(arr, i)));
} }
json_decref(val); json_decref(val);
generate_coinbase(ckp, &wb);
} }
static int strat_loop(ckpool_t *ckp, proc_instance_t *pi) static int strat_loop(ckpool_t *ckp, proc_instance_t *pi)
@ -168,6 +273,10 @@ int stratifier(proc_instance_t *pi)
ckpool_t *ckp = pi->ckp; ckpool_t *ckp = pi->ckp;
int ret = 0; int ret = 0;
/* Store this for use elsewhere */
hex2bin(scriptsig_header_bin, scriptsig_header, 41);
address_to_pubkeytxn(pubkeytxnbin, ckp->btcaddress);
__bin2hex(pubkeytxn, pubkeytxnbin, 25);
strat_loop(ckp, pi); strat_loop(ckp, pi);
return ret; return ret;
} }

Loading…
Cancel
Save