Browse Source

Implement native bech32 segwit address support.

master
Con Kolivas 7 years ago
parent
commit
aab51ae9b4
  1. 83
      src/libckpool.c
  2. 14
      src/stratifier.c

83
src/libckpool.c

@ -1730,9 +1730,54 @@ char *http_base64(const char *src)
return (str);
}
static const int8_t charset_rev[128] = {
-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,
15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
};
/* It's assumed that there is no chance of sending invalid chars to these
* functions as they should have been checked beforehand. */
static void address_to_pubkeytxn(char *pkh, const char *addr)
static void bech32_decode(uint8_t *data, int *data_len, const char *input)
{
int input_len = strlen(input), hrp_len, i;
*data_len = 0;
while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1')
++(*data_len);
hrp_len = input_len - (1 + *data_len);
*(data_len) -= 6;
for (i = hrp_len + 1; i < input_len; i++) {
int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]];
if (i + 6 < input_len)
data[i - (1 + hrp_len)] = v;
}
}
static void convert_bits(char *out, int *outlen, const uint8_t *in,
int inlen)
{
const int outbits = 8, inbits = 5;
uint32_t val = 0, maxv = (((uint32_t)1) << outbits) - 1;
int bits = 0;
while (inlen--) {
val = (val << inbits) | *(in++);
bits += inbits;
while (bits >= outbits) {
bits -= outbits;
out[(*outlen)++] = (val >> bits) & maxv;
}
}
}
static int address_to_pubkeytxn(char *pkh, const char *addr)
{
char b58bin[25] = {};
@ -1743,9 +1788,10 @@ static void address_to_pubkeytxn(char *pkh, const char *addr)
memcpy(&pkh[3], &b58bin[1], 20);
pkh[23] = 0x88;
pkh[24] = 0xac;
return 25;
}
static void address_to_scripttxn(char *psh, const char *addr)
static int address_to_scripttxn(char *psh, const char *addr)
{
char b58bin[25] = {};
@ -1754,22 +1800,33 @@ static void address_to_scripttxn(char *psh, const char *addr)
psh[1] = 0x14;
memcpy(&psh[2], &b58bin[1], 20);
psh[22] = 0x87;
return 23;
}
static int segaddress_to_txn(char *p2h, const char *addr)
{
int data_len, witdata_len = 0;
char *witdata = &p2h[2];
uint8_t data[84];
bech32_decode(data, &data_len, addr);
p2h[0] = data[0];
/* Witness version is > 0 */
if (p2h[0])
p2h[0] += 0x50;
convert_bits(witdata, &witdata_len, data + 1, data_len - 1);
p2h[1] = witdata_len;
return witdata_len + 2;
}
/* Convert an address to a transaction and return the length of the transaction */
int address_to_txn(char *p2h, const char *addr, const bool script, const bool segwit)
{
if (unlikely(segwit)) {
/* It should be impossible to hit this for now */
LOGEMERG("Segwit bech32 address passed to address_to_txn while unsupported.");
return 0;
}
if (script) {
address_to_scripttxn(p2h, addr);
return 23;
}
address_to_pubkeytxn(p2h, addr);
return 25;
if (segwit)
return segaddress_to_txn(p2h, addr);
if (script)
return address_to_scripttxn(p2h, addr);
return address_to_pubkeytxn(p2h, addr);
}
/* For encoding nHeight into coinbase, return how many bytes were used */

14
src/stratifier.c

@ -389,9 +389,9 @@ static const char *ckdb_seq_names[] = {
struct stratifier_data {
ckpool_t *ckp;
char txnbin[40];
char txnbin[48];
int txnlen;
char dontxnbin[40];
char dontxnbin[48];
int dontxnlen;
pool_stats_t stats;
@ -579,7 +579,7 @@ static void generate_coinbase(const ckpool_t *ckp, workbase_t *wb)
len += wb->enonce1varlen;
len += wb->enonce2varlen;
wb->coinb2bin = ckzalloc(256);
wb->coinb2bin = ckzalloc(512);
memcpy(wb->coinb2bin, "\x0a\x63\x6b\x70\x6f\x6f\x6c", 7);
wb->coinb2len = 7;
if (ckp->btcsig) {
@ -5331,8 +5331,6 @@ static user_instance_t *generate_user(ckpool_t *ckp, stratum_instance_t *client,
/* Is this a btc address based username? */
if (!ckp->proxy && (new_user || !user->btcaddress) && (len > 26 && len < 35))
user->btcaddress = generator_checkaddr(ckp, username, &user->script, &user->segwit);
if (user->segwit) /* Bech32 addresses currently unsupported */
user->btcaddress = false;
if (new_user) {
LOGNOTICE("Added new user %s%s", username, user->btcaddress ?
" as address based registration" : "");
@ -6839,8 +6837,6 @@ static user_instance_t *generate_remote_user(ckpool_t *ckp, const char *workerna
/* Is this a btc address based username? */
if (!ckp->proxy && (new_user || !user->btcaddress) && (len > 26 && len < 35))
user->btcaddress = generator_checkaddr(ckp, username, &user->script, &user->segwit);
if (user->segwit)
user->btcaddress = false;
if (new_user) {
LOGNOTICE("Added new remote user %s%s", username, user->btcaddress ?
" as address based registration" : "");
@ -8638,10 +8634,6 @@ void *stratifier(void *arg)
LOGEMERG("Fatal: btcaddress invalid according to bitcoind");
goto out;
}
if (ckp->segwit) {
LOGEMERG("Fatal: bech32 addresses not currently supported");
goto out;
}
/* Store this for use elsewhere */
hex2bin(scriptsig_header_bin, scriptsig_header, 41);

Loading…
Cancel
Save