677 lines
30 KiB
C
677 lines
30 KiB
C
/*
|
|
* Copyright 2016 Luke Dashjr
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the standard MIT license. See COPYING for more details.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include <gcrypt.h>
|
|
|
|
#include "blktemplate.h"
|
|
#include "blkmaker.h"
|
|
#include "blkmaker_jansson.h"
|
|
|
|
static bool my_sha256(void *digest, const void *buffer, size_t length) {
|
|
gcry_md_hash_buffer(GCRY_MD_SHA256, digest, buffer, length);
|
|
return true;
|
|
}
|
|
|
|
static void capabilityname_test() {
|
|
for (unsigned int i = 0; i < GBT_CAPABILITY_COUNT; ++i) {
|
|
const gbt_capabilities_t capid = (1 << i);
|
|
const char * const capname = blktmpl_capabilityname(capid);
|
|
if (!capname) {
|
|
continue;
|
|
}
|
|
const size_t strlen_capname = strlen(capname);
|
|
assert(strlen_capname > 0);
|
|
assert(strlen_capname <= BLKTMPL_LONGEST_CAPABILITY_NAME);
|
|
assert(blktmpl_getcapability(capname) == capid);
|
|
}
|
|
}
|
|
|
|
static void blktxn_test(const int c) {
|
|
struct blktxn_t * const txn = malloc(sizeof(*txn));
|
|
memset(txn, c, sizeof(*txn));
|
|
blktxn_init(txn);
|
|
blktxn_clean(txn);
|
|
free(txn);
|
|
}
|
|
|
|
static bool caps_includes(const uint32_t caps, const uint32_t expected_caps) {
|
|
return (caps & expected_caps) == expected_caps;
|
|
}
|
|
|
|
static void blktmpl_test() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
|
|
{
|
|
static const uint32_t expected_fresh_caps = GBT_CBTXN | GBT_WORKID | BMM_TIMEINC | BMM_CBAPPEND | BMM_VERFORCE | BMM_VERDROP | BMAb_COINBASE | BMAb_TRUNCATE;
|
|
assert(caps_includes(blktmpl_addcaps(tmpl), expected_fresh_caps));
|
|
}
|
|
|
|
assert(!tmpl->version);
|
|
assert(!blktmpl_get_longpoll(tmpl));
|
|
assert(!blktmpl_get_submitold(tmpl));
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static bool json_are_equal(json_t * const ja, json_t * const jb) {
|
|
char *sa, *sb;
|
|
sa = json_dumps(ja, JSON_COMPACT | JSON_SORT_KEYS);
|
|
sb = json_dumps(jb, JSON_COMPACT | JSON_SORT_KEYS);
|
|
const bool rv = !strcmp(sa, sb);
|
|
free(sa);
|
|
free(sb);
|
|
return rv;
|
|
}
|
|
|
|
static void rulecompare(json_t * const jb, const char * const * const rulelist) {
|
|
const size_t z = json_array_size(jb);
|
|
const char *sa;
|
|
json_t *jc;
|
|
|
|
for (size_t i = 0; i < z; ++i) {
|
|
assert((jc = json_array_get(jb, i)));
|
|
assert((sa = json_string_value(jc)));
|
|
assert(!strcmp(sa, rulelist[i]));
|
|
}
|
|
assert(!rulelist[z]);
|
|
}
|
|
|
|
static void check_request(json_t * const ja, const char * const * const rulelist, uint32_t * const out_caps) {
|
|
const char *sa;
|
|
json_t *jb, *jc;
|
|
|
|
assert(json_object_get(ja, "id"));
|
|
assert((jb = json_object_get(ja, "method")));
|
|
assert((sa = json_string_value(jb)));
|
|
assert(!strcmp(sa, "getblocktemplate"));
|
|
assert((jb = json_object_get(ja, "params")));
|
|
assert(json_is_array(jb));
|
|
assert(json_array_size(jb) >= 1);
|
|
jc = json_array_get(jb, 0);
|
|
assert(json_is_object(jc));
|
|
assert((jb = json_object_get(jc, "maxversion")));
|
|
assert(json_number_value(jb) == BLKMAKER_MAX_BLOCK_VERSION);
|
|
assert((jb = json_object_get(jc, "rules")));
|
|
assert(json_is_array(jb));
|
|
rulecompare(jb, rulelist);
|
|
if (out_caps) {
|
|
*out_caps = 0;
|
|
if ((jb = json_object_get(jc, "capabilities")) && json_is_array(jb)) {
|
|
const size_t z = json_array_size(jb);
|
|
for (size_t i = 0; i < z; ++i) {
|
|
assert((jc = json_array_get(jb, i)));
|
|
assert((sa = json_string_value(jc)));
|
|
uint32_t capid = blktmpl_getcapability(sa);
|
|
assert(capid);
|
|
*out_caps |= capid;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void blktmpl_request_jansson_test_old() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
json_t *ja, *jb;
|
|
|
|
ja = blktmpl_request_jansson2(0, NULL, blkmk_supported_rules);
|
|
jb = blktmpl_request_jansson(0, NULL);
|
|
assert(json_are_equal(ja, jb));
|
|
json_decref(jb);
|
|
|
|
check_request(ja, blkmk_supported_rules, NULL);
|
|
|
|
json_decref(ja);
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_request_jansson_test_custom_rulelist() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
json_t *ja;
|
|
const char *custom_rulelist[] = {
|
|
"abc",
|
|
"xyz",
|
|
NULL
|
|
};
|
|
|
|
ja = blktmpl_request_jansson2(0, NULL, custom_rulelist);
|
|
check_request(ja, custom_rulelist, NULL);
|
|
|
|
json_decref(ja);
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_request_jansson_test_custom_caps_i(json_t * const ja, const uint32_t test_caps) {
|
|
uint32_t caps;
|
|
check_request(ja, blkmk_supported_rules, &caps);
|
|
assert(caps == test_caps);
|
|
json_decref(ja);
|
|
}
|
|
|
|
static void blktmpl_request_jansson_test_custom_caps() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
json_t *ja;
|
|
uint32_t test_caps = GBT_SERVICE | GBT_LONGPOLL;
|
|
|
|
ja = blktmpl_request_jansson2(test_caps, NULL, blkmk_supported_rules);
|
|
blktmpl_request_jansson_test_custom_caps_i(ja, test_caps);
|
|
|
|
test_caps |= blktmpl_addcaps(tmpl);
|
|
ja = blktmpl_request_jansson2(test_caps, NULL, blkmk_supported_rules);
|
|
blktmpl_request_jansson_test_custom_caps_i(ja, test_caps);
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_request_jansson_test_longpoll() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
static const char * const lpid = "mylpid00";
|
|
const char *sa;
|
|
json_t *ja, *jb, *jc;
|
|
|
|
ja = blktmpl_request_jansson2(0, lpid, blkmk_supported_rules);
|
|
check_request(ja, blkmk_supported_rules, NULL);
|
|
|
|
jb = json_array_get(json_object_get(ja, "params"), 0);
|
|
assert((jc = json_object_get(jb, "longpollid")));
|
|
assert((sa = json_string_value(jc)));
|
|
assert(!strcmp(sa, lpid));
|
|
|
|
json_decref(ja);
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static const char *blktmpl_add_jansson_str(blktemplate_t * const tmpl, const char * const s, const time_t time_rcvd) {
|
|
json_t * const j = json_loads(s, 0, NULL);
|
|
assert(j);
|
|
const char * const rv = blktmpl_add_jansson(tmpl, j, time_rcvd);
|
|
json_decref(j);
|
|
return rv;
|
|
}
|
|
|
|
static const time_t simple_time_rcvd = 0x777;
|
|
|
|
static void blktmpl_jansson_simple() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":2,\"height\":3,\"bits\":\"1d00ffff\",\"curtime\":777,\"previousblockhash\":\"0000000077777777777777777777777777777777777777777777777777777777\",\"coinbasevalue\":512}", simple_time_rcvd));
|
|
assert(tmpl->version == 2);
|
|
assert(tmpl->height == 3);
|
|
assert(!memcmp(tmpl->diffbits, "\xff\xff\0\x1d", 4));
|
|
assert(tmpl->curtime == 777);
|
|
for (int i = 0; i < 7; ++i) {
|
|
assert(tmpl->prevblk[i] == 0x77777777);
|
|
}
|
|
assert(!tmpl->prevblk[7]);
|
|
assert(tmpl->cbvalue == 512);
|
|
|
|
// Check clear values
|
|
assert(tmpl->txncount == 0);
|
|
assert(tmpl->txns_datasz == 0);
|
|
assert(tmpl->txns_sigops == 0);
|
|
assert(!tmpl->cbtxn);
|
|
assert(!tmpl->workid);
|
|
assert(!blktmpl_get_longpoll(tmpl));
|
|
assert(blktmpl_get_submitold(tmpl));
|
|
assert(!tmpl->target);
|
|
assert(!tmpl->mutations);
|
|
assert(tmpl->aux_count == 0);
|
|
assert(!tmpl->rules);
|
|
assert(!tmpl->unsupported_rule);
|
|
assert(!tmpl->vbavailable);
|
|
assert(!tmpl->vbrequired);
|
|
|
|
// Check reasonable default ranges
|
|
assert(tmpl->sigoplimit >= 20000);
|
|
assert(tmpl->sizelimit >= 1000000);
|
|
assert(tmpl->expires >= 60);
|
|
assert(tmpl->maxtime >= tmpl->curtime + 60);
|
|
assert(tmpl->maxtimeoff >= 60);
|
|
assert(tmpl->mintime <= tmpl->curtime - 60);
|
|
assert(tmpl->mintimeoff <= -60);
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_bip22_required() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd));
|
|
assert(tmpl->version == 3);
|
|
assert(tmpl->height == 4);
|
|
assert(!memcmp(tmpl->diffbits, "\xff\x7f\0\x1d", 4));
|
|
assert(tmpl->curtime == 877);
|
|
for (int i = 0; i < 7; ++i) {
|
|
assert(tmpl->prevblk[i] == 0xa7777777);
|
|
}
|
|
assert(!tmpl->prevblk[7]);
|
|
assert(tmpl->cbvalue == 640);
|
|
assert(tmpl->sigoplimit == 100);
|
|
assert(tmpl->sizelimit == 1000);
|
|
assert(tmpl->txncount == 3);
|
|
assert(tmpl->txns);
|
|
assert(tmpl->txns[0].data);
|
|
assert(tmpl->txns[0].datasz == 57);
|
|
assert(!memcmp(tmpl->txns[0].data, "\x01\0\0\0\x01\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xaa\xaa\xaa\xaa\0\x22\x22\x22\x22\x01\0\x10\0\0\x01\x51\0\0\0\0", 57));
|
|
assert(tmpl->txns[0].dependscount == -1);
|
|
assert(tmpl->txns[0].fee_ == -1);
|
|
assert(tmpl->txns[0].required);
|
|
assert(tmpl->txns[0].sigops_ == -1);
|
|
assert(tmpl->txns[1].data);
|
|
assert(tmpl->txns[1].datasz == 57);
|
|
assert(!memcmp(tmpl->txns[1].data, "\x01\0\0\0\x01\x1c\x69\xf2\x12\xe6\x2f\x2c\xdd\x80\x93\x7c\x9c\x08\x57\xce\xde\xc0\x05\xb1\x1d\x3b\x90\x2d\x21\0\x7c\x93\x2c\x1c\x7c\xd2\x0f\0\0\0\0\0\x44\x44\x44\x44\x01\0\x10\0\0\x01\x51\0\0\0\0", 57));
|
|
assert(tmpl->txns[1].dependscount == 1);
|
|
assert(tmpl->txns[1].depends);
|
|
assert(tmpl->txns[1].depends[0] == 1);
|
|
assert(tmpl->txns[1].fee_ == 12);
|
|
assert(!tmpl->txns[1].required);
|
|
assert(tmpl->txns[1].sigops_ == 4);
|
|
assert(!memcmp(tmpl->txns[1].hash_, "\x8d\x7e\x01\x67\x43\x9d\xab\x18\x6e\x86\xf9\x13\xb2\x7f\x3a\xc2\x15\x67\xdd\x4e\xde\xf8\x9a\xa8\x01\x64\x99\x67\x8b\x1a\xda\x8e", 32));
|
|
assert(tmpl->txns[2].data);
|
|
assert(tmpl->txns[2].datasz == 57);
|
|
assert(!memcmp(tmpl->txns[2].data, "\x01\0\0\0\x01\0\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xaa\xaa\xaa\xaa\0\x55\x55\x55\x55\x01\0\x10\0\0\x01\x51\0\0\0\0", 57));
|
|
assert(tmpl->txns[2].dependscount == -1);
|
|
assert(tmpl->txns[2].fee_ == -1);
|
|
assert(!tmpl->txns[2].required);
|
|
assert(tmpl->txns[2].sigops_ == -1);
|
|
assert(tmpl->cbtxn->data);
|
|
assert(tmpl->cbtxn->datasz == 64);
|
|
assert(!memcmp(tmpl->cbtxn->data, "\x01\0\0\0\x01\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\xff\xff\xff\xff\x07\x01\x04\x04\xde\xad\xbe\xef\x33\x33\x33\x33\x01\0\x10\0\0\x01\x51\0\0\0\0", 64));
|
|
assert(tmpl->aux_count == 1);
|
|
assert(tmpl->auxs);
|
|
assert(tmpl->auxs[0].auxname);
|
|
assert(!strcmp(tmpl->auxs[0].auxname, "dummy"));
|
|
assert(tmpl->auxs[0].datasz == 4);
|
|
assert(!memcmp(tmpl->auxs[0].data, "\xde\xad\xbe\xef", 4));
|
|
assert(tmpl->workid);
|
|
assert(!strcmp(tmpl->workid, "mywork"));
|
|
assert(blktmpl_get_submitold(tmpl));
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_bip22_longpoll() {
|
|
blktemplate_t *tmpl = blktmpl_create();
|
|
const struct blktmpl_longpoll_req *lp;
|
|
|
|
assert(!blktmpl_get_longpoll(tmpl));
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"longpollid\":\"mylpid\"}", simple_time_rcvd));
|
|
lp = blktmpl_get_longpoll(tmpl);
|
|
assert(lp->id);
|
|
assert(!strcmp(lp->id, "mylpid"));
|
|
assert(!lp->uri);
|
|
assert(blktmpl_get_submitold(tmpl));
|
|
|
|
blktmpl_free(tmpl);
|
|
tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"longpollid\":\"myLPid\",\"longpolluri\":\"/LP\",\"submitold\":false}", simple_time_rcvd));
|
|
lp = blktmpl_get_longpoll(tmpl);
|
|
assert(lp->id);
|
|
assert(!strcmp(lp->id, "myLPid"));
|
|
assert(lp->uri);
|
|
assert(!strcmp(lp->uri, "/LP"));
|
|
assert(!blktmpl_get_submitold(tmpl));
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_bip23_bpe() {
|
|
blktemplate_t *tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"expires\":99,\"target\":\"0000000077777777777777777777777777777777777777777777777777777777\"}", simple_time_rcvd));
|
|
assert(tmpl->expires == 99);
|
|
assert(!(*tmpl->target)[0]);
|
|
for (int i = 1; i < 8; ++i) {
|
|
assert((*tmpl->target)[i] == 0x77777777);
|
|
}
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_bip23_mutations() {
|
|
blktemplate_t *tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"maxtime\":2113929216,\"maxtimeoff\":50,\"mintime\":800,\"mintimeoff\":-50,\"mutable\":[\"prevblock\",\"version/force\"],\"noncerange\":\"01000000f0000000\"}", simple_time_rcvd));
|
|
assert(tmpl->maxtime == 2113929216);
|
|
assert(tmpl->maxtimeoff == 50);
|
|
assert(tmpl->mintime == 800);
|
|
assert(tmpl->mintimeoff == -50);
|
|
// As of right now, implied mutations are not included in the value
|
|
// assert(tmpl->mutations == (BMM_CBAPPEND | BMM_CBSET | BMM_GENERATE | BMM_TIMEINC | BMM_TIMEDEC | BMM_TXNADD | BMM_PREVBLK | BMM_VERFORCE));
|
|
assert(caps_includes(tmpl->mutations, BMM_PREVBLK | BMM_VERFORCE));
|
|
|
|
blktmpl_free(tmpl);
|
|
tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"mutable\":[\"version/reduce\",\"coinbase/append\",\"generation\",\"time\",\"transactions\"],\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"transactions\":[]}", simple_time_rcvd));
|
|
assert(tmpl->mutations == (BMM_CBAPPEND | BMM_GENERATE | BMM_TIMEINC | BMM_TIMEDEC | BMM_TXNADD | BMM_VERDROP));
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_bip23_abbrev() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"mutable\":[\"submit/hash\",\"submit/coinbase\",\"submit/truncate\"]}", simple_time_rcvd));
|
|
assert(tmpl->mutations == (BMA_TXNHASH | BMAb_COINBASE | BMAb_TRUNCATE));
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_bip9() {
|
|
blktemplate_t *tmpl;
|
|
|
|
tmpl = blktmpl_create();
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\"],\"vbavailable\":{\"!segwit\":7}}", simple_time_rcvd));
|
|
assert(tmpl->version == 0x20000080);
|
|
assert(tmpl->rules);
|
|
assert(tmpl->rules[0]);
|
|
assert(!strcmp(tmpl->rules[0], "csv"));
|
|
assert(!tmpl->rules[1]);
|
|
assert(!tmpl->unsupported_rule);
|
|
assert(tmpl->vbavailable);
|
|
assert(tmpl->vbavailable[0]);
|
|
assert(tmpl->vbavailable[0]->name);
|
|
assert(!strcmp(tmpl->vbavailable[0]->name, "!segwit"));
|
|
assert(tmpl->vbavailable[0]->bitnum == 7);
|
|
assert(!tmpl->vbavailable[1]);
|
|
assert(!tmpl->vbrequired);
|
|
|
|
blktmpl_free(tmpl);
|
|
tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\"],\"vbavailable\":{\"!segwit\":7},\"vbrequired\":128}", simple_time_rcvd));
|
|
assert(tmpl->version == 0x20000080);
|
|
assert(tmpl->rules);
|
|
assert(tmpl->rules[0]);
|
|
assert(!strcmp(tmpl->rules[0], "csv"));
|
|
assert(!tmpl->rules[1]);
|
|
assert(!tmpl->unsupported_rule);
|
|
assert(tmpl->vbavailable);
|
|
assert(tmpl->vbavailable[0]);
|
|
assert(tmpl->vbavailable[0]->name);
|
|
assert(!strcmp(tmpl->vbavailable[0]->name, "!segwit"));
|
|
assert(tmpl->vbavailable[0]->bitnum == 7);
|
|
assert(!tmpl->vbavailable[1]);
|
|
assert(tmpl->vbrequired == 0x80);
|
|
|
|
blktmpl_free(tmpl);
|
|
tmpl = blktmpl_create();
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\",\"foo\"],\"vbavailable\":{}}", simple_time_rcvd));
|
|
assert(tmpl->version == 0x20000080);
|
|
assert(tmpl->rules);
|
|
assert(tmpl->rules[0]);
|
|
assert(!strcmp(tmpl->rules[0], "csv"));
|
|
assert(tmpl->rules[1]);
|
|
assert(!strcmp(tmpl->rules[1], "foo"));
|
|
assert(!tmpl->rules[2]);
|
|
assert(tmpl->unsupported_rule);
|
|
assert(tmpl->vbavailable);
|
|
assert(!tmpl->vbavailable[0]);
|
|
assert(!tmpl->vbrequired);
|
|
|
|
blktmpl_free(tmpl);
|
|
tmpl = blktmpl_create();
|
|
|
|
assert(blktmpl_add_jansson_str(tmpl, "{\"version\":536871040,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"rules\":[\"csv\",\"!foo\"],\"vbavailable\":{}}", simple_time_rcvd));
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_submit_data_check(const char * const sa, const int level) {
|
|
assert(strlen(sa) >= 160);
|
|
assert(!memcmp(sa, "03000000777777a7777777a7777777a7777777a7777777a7777777a7777777a700000000", 72));
|
|
// Don't check merkle root
|
|
assert(!memcmp(&sa[136], "6d030000ff7f001d", 16));
|
|
// Don't check nonce
|
|
size_t pos = 160;
|
|
if (level > 0) {
|
|
assert(!strncmp(&sa[pos], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000", 130));
|
|
pos += 130;
|
|
if (level > 1) {
|
|
assert(!strcmp(&sa[pos], "01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa0022222222010010000001510000000001000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f000000000044444444010010000001510000000001000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000"));
|
|
pos += strlen(&sa[pos]);
|
|
}
|
|
}
|
|
if (level >= 0) {
|
|
assert(sa[pos] == '\0');
|
|
}
|
|
}
|
|
|
|
static void blktmpl_jansson_propose_check(json_t *j, const int level) {
|
|
const char *sa;
|
|
|
|
j = json_array_get(json_object_get(j, "params"), 0);
|
|
assert((j = json_object_get(j, "data")));
|
|
assert((sa = json_string_value(j)));
|
|
return blktmpl_jansson_submit_data_check(sa, level);
|
|
}
|
|
|
|
static void blktmpl_jansson_propose() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
const char *sa;
|
|
json_t *j, *ja, *jb;
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\"}", simple_time_rcvd));
|
|
|
|
assert((j = blktmpl_propose_jansson(tmpl, 0, false)));
|
|
check_request(j, blkmk_supported_rules, NULL);
|
|
|
|
ja = json_array_get(json_object_get(j, "params"), 0);
|
|
assert((jb = json_object_get(ja, "mode")));
|
|
assert((sa = json_string_value(jb)));
|
|
assert(!strcmp(sa, "proposal"));
|
|
assert((jb = json_object_get(ja, "workid")));
|
|
assert((sa = json_string_value(jb)));
|
|
assert(!strcmp(sa, "mywork"));
|
|
blktmpl_jansson_propose_check(j, 2);
|
|
json_decref(j);
|
|
|
|
tmpl->mutations |= BMAb_COINBASE;
|
|
assert((j = blktmpl_propose_jansson(tmpl, 0, false)));
|
|
check_request(j, blkmk_supported_rules, NULL);
|
|
blktmpl_jansson_propose_check(j, 1);
|
|
json_decref(j);
|
|
|
|
tmpl->mutations |= BMAb_TRUNCATE;
|
|
assert((j = blktmpl_propose_jansson(tmpl, 0, false)));
|
|
check_request(j, blkmk_supported_rules, NULL);
|
|
blktmpl_jansson_propose_check(j, 0);
|
|
json_decref(j);
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_submit() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
const char *sa;
|
|
uint8_t data[76];
|
|
int16_t i16;
|
|
unsigned int dataid;
|
|
json_t *j, *ja, *jb, *jc;
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\",\"mutable\":[\"submit/coinbase\",\"submit/truncate\",\"coinbase/append\"]}", simple_time_rcvd));
|
|
|
|
assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid));
|
|
|
|
assert((j = blkmk_submit_foreign_jansson(tmpl, data, 0, 0x12345678)));
|
|
assert((ja = json_object_get(j, "params")));
|
|
assert(json_is_array(ja));
|
|
assert(json_array_size(ja) >= 1);
|
|
assert((sa = json_string_value(json_array_get(ja, 0))));
|
|
blktmpl_jansson_submit_data_check(sa, 2);
|
|
if (json_array_size(ja) >= 2) {
|
|
assert(json_is_object((jb = json_array_get(ja, 1))));
|
|
assert(!json_object_get(jb, "workid"));
|
|
}
|
|
json_decref(j);
|
|
|
|
assert((j = blkmk_submit_jansson(tmpl, data, 0, 0x12345678)));
|
|
assert(json_object_get(j, "id"));
|
|
assert((ja = json_object_get(j, "method")));
|
|
assert((sa = json_string_value(ja)));
|
|
assert(!strcmp(sa, "submitblock"));
|
|
assert((ja = json_object_get(j, "params")));
|
|
assert(json_is_array(ja));
|
|
assert(json_array_size(ja) >= 2);
|
|
assert((sa = json_string_value(json_array_get(ja, 0))));
|
|
blktmpl_jansson_submit_data_check(sa, 0);
|
|
assert(!memcmp(&sa[72], "512a63f45f96f0269a2d23ccd96bcf0322ee4f60254748e30b89e2b59431aba16d030000ff7f001d12345678", 64)); // merkle root
|
|
assert(!memcmp(&sa[152], "12345678", 8)); // nonce
|
|
assert(json_is_object((jb = json_array_get(ja, 1))));
|
|
assert((jc = json_object_get(jb, "workid")));
|
|
assert((sa = json_string_value(jc)));
|
|
assert(!strcmp(sa, "mywork"));
|
|
json_decref(j);
|
|
|
|
assert(76 == blkmk_get_data(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &dataid));
|
|
|
|
assert((j = blkmk_submit_jansson(tmpl, data, dataid, 0x12345678)));
|
|
assert((ja = json_object_get(j, "params")));
|
|
assert(json_is_array(ja));
|
|
assert(json_array_size(ja) >= 2);
|
|
assert((sa = json_string_value(json_array_get(ja, 0))));
|
|
blktmpl_jansson_submit_data_check(sa, -1);
|
|
// TODO: Check inserted dataid
|
|
assert(json_is_object((jb = json_array_get(ja, 1))));
|
|
assert((jc = json_object_get(jb, "workid")));
|
|
assert((sa = json_string_value(jc)));
|
|
assert(!strcmp(sa, "mywork"));
|
|
json_decref(j);
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void blktmpl_jansson_submitm() {
|
|
blktemplate_t * const tmpl = blktmpl_create();
|
|
const char *sa;
|
|
uint8_t data[76], *cbtxn, *branches, extranonce[10];
|
|
size_t cbextranonceoffset, cbtxnsize;
|
|
int branchcount;
|
|
int16_t i16;
|
|
json_t *j, *ja, *jb, *jc;
|
|
|
|
assert(!blktmpl_add_jansson_str(tmpl, "{\"version\":3,\"height\":4,\"bits\":\"1d007fff\",\"curtime\":877,\"previousblockhash\":\"00000000a7777777a7777777a7777777a7777777a7777777a7777777a7777777\",\"coinbasevalue\":640,\"sigoplimit\":100,\"sizelimit\":1000,\"transactions\":[{\"data\":\"01000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa00222222220100100000015100000000\",\"required\":true},{\"hash\":\"8eda1a8b67996401a89af8de4edd6715c23a7fb213f9866e18ab9d4367017e8d\",\"data\":\"01000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f0000000000444444440100100000015100000000\",\"depends\":[1],\"fee\":12,\"required\":false,\"sigops\":4},{\"data\":\"01000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000\"}],\"coinbaseaux\":{\"dummy\":\"deadbeef\"},\"coinbasetxn\":{\"data\":\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07010404deadbeef333333330100100000015100000000\"},\"workid\":\"mywork\",\"mutable\":[\"submit/coinbase\",\"submit/truncate\",\"coinbase/append\"]}", simple_time_rcvd));
|
|
|
|
assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 1, false));
|
|
free(cbtxn);
|
|
free(branches);
|
|
memset(&data[36], '\xee', 32); // merkle root, must be provided by caller
|
|
|
|
extranonce[0] = 11;
|
|
assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 1, 0x12345678, false)));
|
|
assert(json_object_get(j, "id"));
|
|
assert((ja = json_object_get(j, "method")));
|
|
assert((sa = json_string_value(ja)));
|
|
assert(!strcmp(sa, "submitblock"));
|
|
assert((ja = json_object_get(j, "params")));
|
|
assert(json_is_array(ja));
|
|
assert(json_array_size(ja) >= 2);
|
|
assert((sa = json_string_value(json_array_get(ja, 0))));
|
|
blktmpl_jansson_submit_data_check(sa, -1);
|
|
assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08010404deadbeef0b333333330100100000015100000000"));
|
|
assert(json_is_object((jb = json_array_get(ja, 1))));
|
|
assert((jc = json_object_get(jb, "workid")));
|
|
assert((sa = json_string_value(jc)));
|
|
assert(!strcmp(sa, "mywork"));
|
|
json_decref(j);
|
|
|
|
extranonce[0] = 22;
|
|
assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 1, 0x12345678, true)));
|
|
assert((ja = json_object_get(j, "params")));
|
|
assert(json_is_array(ja));
|
|
assert(json_array_size(ja) >= 2);
|
|
assert((sa = json_string_value(json_array_get(ja, 0))));
|
|
blktmpl_jansson_submit_data_check(sa, -1);
|
|
assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08010404deadbeef1633333333010010000001510000000001000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa0022222222010010000001510000000001000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f000000000044444444010010000001510000000001000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000"));
|
|
json_decref(j);
|
|
|
|
assert(blkmk_get_mdata(tmpl, data, sizeof(data), simple_time_rcvd, &i16, &cbtxn, &cbtxnsize, &cbextranonceoffset, &branchcount, &branches, 3, false));
|
|
free(cbtxn);
|
|
free(branches);
|
|
|
|
extranonce[0] = 0x11;
|
|
extranonce[1] = 0x22;
|
|
extranonce[2] = 0x33;
|
|
assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 3, 0x12345678, false)));
|
|
assert((ja = json_object_get(j, "params")));
|
|
assert(json_is_array(ja));
|
|
assert(json_array_size(ja) >= 2);
|
|
assert((sa = json_string_value(json_array_get(ja, 0))));
|
|
blktmpl_jansson_submit_data_check(sa, -1);
|
|
assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0a010404deadbeef112233333333330100100000015100000000"));
|
|
json_decref(j);
|
|
|
|
extranonce[2] = 0xed;
|
|
assert((j = blkmk_submitm_jansson(tmpl, data, extranonce, 3, 0x12345678, true)));
|
|
assert((ja = json_object_get(j, "params")));
|
|
assert(json_is_array(ja));
|
|
assert(json_array_size(ja) >= 2);
|
|
assert((sa = json_string_value(json_array_get(ja, 0))));
|
|
blktmpl_jansson_submit_data_check(sa, -1);
|
|
assert(!strcmp(&sa[160], "0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0a010404deadbeef1122ed33333333010010000001510000000001000000019999999999999999999999999999999999999999999999999999999999999999aaaaaaaa0022222222010010000001510000000001000000011c69f212e62f2cdd80937c9c0857cedec005b11d3b902d21007c932c1c7cd20f000000000044444444010010000001510000000001000000010099999999999999999999999999999999999999999999999999999999999999aaaaaaaa00555555550100100000015100000000"));
|
|
json_decref(j);
|
|
|
|
blktmpl_free(tmpl);
|
|
}
|
|
|
|
static void test_blkmk_supports_rule() {
|
|
for (const char **rule = blkmk_supported_rules; *rule; ++rule) {
|
|
assert(blkmk_supports_rule(*rule));
|
|
char important_rule[strlen(*rule) + 2];
|
|
important_rule[0] = '!';
|
|
strcpy(&important_rule[1], *rule);
|
|
assert(!blkmk_supports_rule(important_rule));
|
|
}
|
|
assert(!blkmk_supports_rule("foo"));
|
|
assert(!blkmk_supports_rule(""));
|
|
}
|
|
|
|
int main() {
|
|
blkmk_sha256_impl = my_sha256;
|
|
|
|
puts("capabilityname");
|
|
capabilityname_test();
|
|
|
|
puts("blktxn");
|
|
blktxn_test('\0');
|
|
blktxn_test('\xa5');
|
|
blktxn_test('\xff');
|
|
|
|
puts("blktmpl");
|
|
blktmpl_test();
|
|
|
|
puts("blktmpl_request_jansson");
|
|
blktmpl_request_jansson_test_old();
|
|
blktmpl_request_jansson_test_custom_rulelist();
|
|
blktmpl_request_jansson_test_custom_caps();
|
|
blktmpl_request_jansson_test_longpoll();
|
|
|
|
puts("blktmpl_jansson");
|
|
blktmpl_jansson_simple();
|
|
blktmpl_jansson_bip22_required();
|
|
blktmpl_jansson_bip22_longpoll();
|
|
blktmpl_jansson_bip23_bpe();
|
|
blktmpl_jansson_bip23_mutations();
|
|
blktmpl_jansson_bip23_abbrev();
|
|
blktmpl_jansson_bip9();
|
|
blktmpl_jansson_propose();
|
|
blktmpl_jansson_submit();
|
|
blktmpl_jansson_submitm();
|
|
|
|
puts("blkmk_supports_rule");
|
|
test_blkmk_supports_rule();
|
|
}
|