New blkmk_init_generation and blkmk_address_to_script functions to create a coinbase transaction if it isn't provided

This commit is contained in:
Luke Dashjr
2012-10-12 16:05:26 +00:00
parent 72cf471375
commit 307b08c267
6 changed files with 203 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ lib_LTLIBRARIES = \
libblkmaker_@LIBBLKMAKER_API_VERSION@_la_SOURCES = \ libblkmaker_@LIBBLKMAKER_API_VERSION@_la_SOURCES = \
base58.c \
blkmaker.c \ blkmaker.c \
blktemplate.c \ blktemplate.c \
hex.c hex.c

129
base58.c Normal file
View File

@@ -0,0 +1,129 @@
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <blkmaker.h>
#include "private.h"
static const int8_t b58digits[] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
-1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
-1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
};
bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz) {
const unsigned char *b58u = (void*)b58;
unsigned char *binu = bin;
size_t outisz = (binsz + 3) / 4;
uint32_t outi[outisz];
uint64_t t;
uint32_t c;
size_t i, j;
uint8_t bytesleft = binsz % 4;
uint32_t zeromask = ~((1 << ((bytesleft) * 8)) - 1);
if (!b58sz)
b58sz = strlen(b58);
memset(outi, 0, outisz * sizeof(*outi));
for (i = 0; i < b58sz; ++i)
{
if (b58u[i] & 0x80)
// High-bit set on invalid digit
return false;
if (b58digits[b58u[i]] == -1)
// Invalid base58 digit
return false;
c = b58digits[b58u[i]];
for (j = outisz; j--; )
{
t = ((uint64_t)outi[j]) * 58 + c;
c = (t & 0x3f00000000) >> 32;
outi[j] = t & 0xffffffff;
}
if (c)
// Output number too big (carry to the next int32)
return false;
if (outi[0] & zeromask)
// Output number too big (last int32 filled too far)
return false;
}
j = 0;
switch (bytesleft) {
case 3:
*(binu++) = (outi[0] & 0xff0000) >> 16;
case 2:
*(binu++) = (outi[0] & 0xff00) >> 8;
case 1:
*(binu++) = (outi[0] & 0xff);
++j;
default:
break;
}
for (; j < outisz; ++j)
{
*((uint32_t*)binu) = htonl(outi[j]);
binu += sizeof(uint32_t);
}
return true;
}
int _blkmk_b58check(void *bin, size_t binsz) {
unsigned char buf[32];
unsigned char *binc = bin;
if (!_blkmk_dblsha256(buf, bin, binsz - 4))
return -2;
if (memcmp(&binc[binsz - 4], buf, 4))
return -1;
return binc[0];
}
size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) {
unsigned char addrbin[25];
unsigned char *cout = out;
int addrver;
size_t rv;
if (!_blkmk_b58tobin(addrbin, sizeof(addrbin), addr, 0))
return 0;
addrver = _blkmk_b58check(addrbin, sizeof(addrbin));
switch (addrver) {
case 0: // Bitcoin pubkey hash
case 111: // Testnet pubkey hash
if (outsz < (rv = 24))
return rv;
cout[ 0] = 0x76; // OP_DUP
cout[ 1] = 0xa9; // OP_HASH160
cout[ 2] = 0x14; // push 20 bytes
memcpy(&cout[3], &addrbin[1], 20);
cout[22] = 0x88; // OP_EQUALVERIFY
cout[23] = 0xac; // OP_CHECKSIG
return rv;
case 5: // Bitcoin script hash
case 196: // Testnet script hash
if (outsz < (rv = 22))
return rv;
cout[ 0] = 0xa9; // OP_HASH160
cout[ 1] = 0x14; // push 20 bytes
memcpy(&cout[2], &addrbin[1], 20);
cout[21] = 0x87; // OP_EQUAL
return rv;
default:
return 0;
}
}

View File

@@ -1,5 +1,6 @@
#include <limits.h> #include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@@ -8,6 +9,8 @@
#include <blkmaker.h> #include <blkmaker.h>
#include <blktemplate.h> #include <blktemplate.h>
#include "private.h"
static inline static inline
void my_htole32(unsigned char *buf, uint32_t n) { void my_htole32(unsigned char *buf, uint32_t n) {
buf[0] = (n >> 0) % 256; buf[0] = (n >> 0) % 256;
@@ -16,6 +19,12 @@ void my_htole32(unsigned char *buf, uint32_t n) {
buf[3] = (n >> 24) % 256; buf[3] = (n >> 24) % 256;
} }
static inline
void my_htole64(unsigned char *buf, uint64_t n) {
for (int i = 0; i < 8; ++i)
buf[i] = (n >> (8*i)) & 0xff;
}
bool (*blkmk_sha256_impl)(void *, const void *, size_t) = NULL; bool (*blkmk_sha256_impl)(void *, const void *, size_t) = NULL;
@@ -25,6 +34,46 @@ bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz) {
#define dblsha256 _blkmk_dblsha256 #define dblsha256 _blkmk_dblsha256
uint64_t blkmk_init_generation(blktemplate_t *tmpl, void *script, size_t scriptsz) {
if (tmpl->cbtxn)
return 0;
// Skip "no extranonce" scriptSig, since it would be too short (min 2 bytes)
++tmpl->next_dataid;
size_t datasz = 60 + scriptsz;
unsigned char *data = malloc(datasz);
if (!data)
return 0;
memcpy(&data[0],
"\x01\0\0\0" // txn ver
"\x01" // input count
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" // prevout
"\xff\xff\xff\xff" // index (-1)
"\0" // scriptSig length (0; extranonce will bring up to 4)
"\xff\xff\xff\xff" // sequence
"\x01" // output count
, 47);
my_htole64(&data[47], tmpl->cbvalue);
data[55] = scriptsz;
memcpy(&data[56], script, scriptsz);
memset(&data[56 + scriptsz], 0, 4); // lock time
struct blktxn_t *txn = calloc(1, sizeof(*tmpl->cbtxn));
if (!tmpl->cbtxn)
{
free(data);
return 0;
}
txn->data = data;
txn->datasz = datasz;
tmpl->cbtxn = txn;
return tmpl->cbvalue;
}
static static
bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigned char *cbtxndata, size_t cbtxndatasz) { bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigned char *cbtxndata, size_t cbtxndatasz) {
size_t hashcount = tmpl->txncount + 1; size_t hashcount = tmpl->txncount + 1;

View File

@@ -2,6 +2,7 @@
#define BLKMAKER_H #define BLKMAKER_H
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <blktemplate.h> #include <blktemplate.h>
@@ -10,6 +11,7 @@
extern bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz); extern bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz);
extern uint64_t blkmk_init_generation(blktemplate_t *, void *script, size_t scriptsz);
extern ssize_t blkmk_append_coinbase_safe(blktemplate_t *, const void *append, size_t appendsz); extern ssize_t blkmk_append_coinbase_safe(blktemplate_t *, const void *append, size_t appendsz);
extern bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, size_t *offs); extern bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, size_t *offs);
extern size_t blkmk_get_data(blktemplate_t *, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire, unsigned int *out_dataid); extern size_t blkmk_get_data(blktemplate_t *, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire, unsigned int *out_dataid);
@@ -17,4 +19,6 @@ extern blktime_diff_t blkmk_time_left(const blktemplate_t *, time_t nowtime);
extern unsigned long blkmk_work_left(const blktemplate_t *); extern unsigned long blkmk_work_left(const blktemplate_t *);
#define BLKMK_UNLIMITED_WORK_COUNT ULONG_MAX #define BLKMK_UNLIMITED_WORK_COUNT ULONG_MAX
extern size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr);
#endif #endif

View File

@@ -9,8 +9,22 @@
#include <blkmaker.h> #include <blkmaker.h>
#include <blkmaker_jansson.h> #include <blkmaker_jansson.h>
#include "private.h"
#include "testinput.c" #include "testinput.c"
void testb58() {
char bufx[26] = {'\xff'};
char *buf = &bufx[1];
if (!_blkmk_b58tobin(buf, 25, "1Baf75Ferj6A7AoN565gCQj9kGWbDMHfN9", 0))
exit(1);
if (bufx[0] != '\xff')
exit(2);
char cbuf[51];
_blkmk_bin2hex(cbuf, buf, 25);
printf("Base58 raw data: %s\n", cbuf);
printf("Base58 check: %d\n", _blkmk_b58check(buf, 25));
}
static static
void send_json(json_t *req) { void send_json(json_t *req) {
char *s = json_dumps(req, JSON_INDENT(2)); char *s = json_dumps(req, JSON_INDENT(2));
@@ -32,6 +46,8 @@ int main(int argc, char**argv) {
blkmk_sha256_impl = my_sha256; blkmk_sha256_impl = my_sha256;
testb58();
tmpl = blktmpl_create(); tmpl = blktmpl_create();
assert(tmpl); assert(tmpl);
req = blktmpl_request_jansson(blktmpl_addcaps(tmpl), NULL); req = blktmpl_request_jansson(blktmpl_addcaps(tmpl), NULL);

View File

@@ -11,4 +11,8 @@ extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz);
extern void _blkmk_bin2hex(char *out, const void *data, size_t datasz); extern void _blkmk_bin2hex(char *out, const void *data, size_t datasz);
extern bool _blkmk_hex2bin(void *o, const char *x, size_t len); extern bool _blkmk_hex2bin(void *o, const char *x, size_t len);
// base58.c
extern bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz);
extern int _blkmk_b58check(void *bin, size_t binsz);
#endif #endif