Compact gbt solo extra data and store the length, allowing it to be variable, leaving room for a signature
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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
diff --git a/cgminer.c b/cgminer.c
index 8ad5a11..35ea1b0 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -2325,51 +2325,47 @@ static bool gbt_solo_decode(struct pool *pool, json_t *res_val)
pool->height = height;
memset(pool->scriptsig_base, 0, 42);
- pool->scriptsig_base[ofs++] = 49; // Template is 49 bytes
+ ofs++; // Leave room for template length
/* Put block height at start of template. */
- ser_number(pool->scriptsig_base + ofs, height);
- ofs += 9;
+ ofs += ser_number(pool->scriptsig_base + ofs, height); // max 5
/* Followed by flags */
- pool->scriptsig_base[ofs++] = 7; // Flags length should be 7
len = strlen(flags) / 2;
- if (len > 7) {
- applog(LOG_WARNING, "Coinbaseaux flags too long at %d bytes, truncating to 7", len);
- len = 7;
- }
+ pool->scriptsig_base[ofs++] = len;
hex2bin(pool->scriptsig_base + ofs, flags, len);
- ofs += 7;
+ ofs += len;
/* Followed by timestamp */
cgtime(&now);
- pool->scriptsig_base[ofs++] = 0xff; // Encode seconds as u64
- u64 = (uint64_t *)&pool->scriptsig_base[ofs];
- *u64 = now.tv_sec;
- ofs += 8; // sizeof uint64_t
+ pool->scriptsig_base[ofs++] = 0xfe; // Encode seconds as u32
+ u32 = (uint32_t *)&pool->scriptsig_base[ofs];
+ *u32 = htole32(now.tv_sec);
+ ofs += 4; // sizeof uint32_t
pool->scriptsig_base[ofs++] = 0xfe; // Encode usecs as u32
u32 = (uint32_t *)&pool->scriptsig_base[ofs];
- *u32 = now.tv_usec;
+ *u32 = htole32(now.tv_usec);
ofs += 4; // sizeof uint32_t
- memcpy(pool->scriptsig_base + ofs, "\x07\x63\x67\x6d\x69\x6e\x65\x72", 8);
- ofs += 8;
-
- pool->scriptsig_base[ofs++] = 42; // Just because
+ memcpy(pool->scriptsig_base + ofs, "\x09\x63\x67\x6d\x69\x6e\x65\x72\x34\x32", 10);
+ ofs += 10;
/* Followed by extranonce size, fixed at 8 */
pool->scriptsig_base[ofs++] = 8;
pool->nonce2_offset = 41 + ofs;
ofs += 8;
- free(pool->coinbase);
+ pool->scriptsig_base[0] = ofs++; // Template length
+ pool->n1_len = ofs;
+
len = 41 // prefix
- + ofs // 1 + 49
+ + ofs // Template length
+ 4 // txin sequence no
+ 1 // transactions
+ 8 // value
+ 1 + 25 // txout
+ 4; // lock
+ free(pool->coinbase);
pool->coinbase = calloc(len, 1);
if (unlikely(!pool->coinbase))
quit(1, "Failed to calloc coinbase in gbt_solo_decode");
@@ -2382,7 +2378,7 @@ static bool gbt_solo_decode(struct pool *pool, json_t *res_val)
pool->nonce2 = 0;
pool->n2size = 4;
- pool->coinbase_len = 41 + 50 + 4 + 1 + 8 + 1 + 25 + 4; // Fixed size
+ pool->coinbase_len = 41 + ofs + 4 + 1 + 8 + 1 + 25 + 4;
cg_wunlock(&pool->gbt_lock);
snprintf(header, 225, "%s%s%s%s%s%s%s",
@@ -6454,8 +6450,8 @@ static void __setup_gbt_solo(struct pool *pool)
{
cg_wlock(&pool->gbt_lock);
memcpy(pool->coinbase, scriptsig_header_bin, 41);
- pool->coinbase[41 + 50 + 4 + 1 + 8] = 25;
- memcpy(pool->coinbase + 41 + 50 + 4 + 1 + 8 + 1, pool->script_pubkey, 25);
+ pool->coinbase[41 + pool->n1_len + 4 + 1 + 8] = 25;
+ memcpy(pool->coinbase + 41 + pool->n1_len + 4 + 1 + 8 + 1, pool->script_pubkey, 25);
cg_wunlock(&pool->gbt_lock);
}
diff --git a/miner.h b/miner.h
index 607f433..39c6332 100644
--- a/miner.h
+++ b/miner.h
@@ -1232,7 +1232,6 @@ struct pool {
char *nonce1;
unsigned char *nonce1bin;
- size_t n1_len;
uint64_t nonce2;
int n2size;
char *sessionid;
@@ -1274,6 +1273,7 @@ struct pool {
bool gbt_curl_inuse;
/* Shared by both stratum & GBT */
+ size_t n1_len;
unsigned char *coinbase;
int coinbase_len;
int nonce2_offset;
diff --git a/util.c b/util.c
index 1bca10f..05f635c 100644
--- a/util.c
+++ b/util.c
@@ -772,10 +772,10 @@ void address_to_pubkeyhash(unsigned char *pkh, const char *addr)
pkh[24] = 0xac;
}
-/* For encoding nHeight into coinbase, pad out to 9 bytes */
-void ser_number(unsigned char *s, int64_t val)
+/* For encoding nHeight into coinbase, return how many bytes were used */
+int ser_number(unsigned char *s, int32_t val)
{
- int64_t *i64 = (int64_t *)&s[1];
+ int32_t *i32 = (int32_t *)&s[1];
int len;
if (val < 128)
@@ -786,9 +786,9 @@ void ser_number(unsigned char *s, int64_t val)
len = 3;
else
len = 4;
- *i64 = htole64(val);
+ *i32 = htole32(val);
s[0] = len++;
- s[len] = 9 - len;
+ return len;
}
/* For encoding variable length strings */
diff --git a/util.h b/util.h
index 6df1ee9..f78b015 100644
--- a/util.h
+++ b/util.h
@@ -108,7 +108,7 @@ enum dev_reason;
struct cgpu_info;
void b58tobin(unsigned char *b58bin, const char *b58);
void address_to_pubkeyhash(unsigned char *pkh, const char *addr);
-void ser_number(unsigned char *s, int64_t val);
+int ser_number(unsigned char *s, int32_t val);
unsigned char *ser_string(char *s, int *slen);
int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg);
void thr_info_cancel(struct thr_info *thr);