From 86159a60ecefbd5f5896d4db1d364d9d53fa729e Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 22 Apr 2014 15:12:49 +1000 Subject: [PATCH] Generate coinbase templates, fixing missing fields from gbt parser --- src/bitcoin.c | 4 ++ src/bitcoin.h | 3 +- src/stratifier.c | 115 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/src/bitcoin.c b/src/bitcoin.c index 644c6b24..53c7e7f5 100644 --- a/src/bitcoin.c +++ b/src/bitcoin.c @@ -252,6 +252,9 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) gbt->height = 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); json_object_set_new_nocheck(gbt->json, "transactions", json_integer(gbt->transactions)); if (gbt->transactions) @@ -272,6 +275,7 @@ out: void clear_gbtbase(gbtbase_t *gbt) { + dealloc(gbt->flags); dealloc(gbt->txn_data); json_decref(gbt->json); gbt->json = NULL; diff --git a/src/bitcoin.h b/src/bitcoin.h index dd291dc2..e2585d72 100644 --- a/src/bitcoin.h +++ b/src/bitcoin.h @@ -19,8 +19,9 @@ struct gbtbase { char ntime[12]; char bbversion[12]; char nbit[12]; - int coinbasevalue; + uint64_t coinbasevalue; int height; + char *flags; int transactions; char *txn_data; int merkles; diff --git a/src/stratifier.c b/src/stratifier.c index 4d1e3758..b7d8b1c8 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -17,6 +17,12 @@ #include "libckpool.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 { /* GBT/shared variables */ char target[68]; @@ -27,14 +33,32 @@ struct workbase { char ntime[12]; char bbversion[12]; char nbit[12]; - int coinbasevalue; + uint64_t coinbasevalue; int height; + char *flags; int transactions; char *txn_data; int merkles; 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; @@ -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)); } +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) { *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))); } +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 * since checking should have been done earlier, and creates the base template * for generating work templates. */ @@ -91,8 +194,9 @@ static void update_base(ckpool_t *ckp) json_strcpy(wb.ntime, val, "ntime"); json_strcpy(wb.bbversion, val, "bbversion"); 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_strdup(&wb.flags, val, "flags"); json_intcpy(&wb.transactions, val, "transactions"); if (wb.transactions) 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))); } json_decref(val); + generate_coinbase(ckp, &wb); } 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; 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); return ret; }