static void parse_request(struct json_connection *jcon, const jsmntok_t tok[]) { const jsmntok_t *method, *id, *params; const struct json_command *cmd; assert(!jcon->current); if (tok[0].type != JSMN_OBJECT) { json_command_malformed(jcon, "null", "Expected {} for json command"); return; } method = json_get_member(jcon->buffer, tok, "method"); params = json_get_member(jcon->buffer, tok, "params"); id = json_get_member(jcon->buffer, tok, "id"); if (!id) { json_command_malformed(jcon, "null", "No id"); return; } if (id->type != JSMN_STRING && id->type != JSMN_PRIMITIVE) { json_command_malformed(jcon, "null", "Expected string/primitive for id"); return; } /* This is a convenient tal parent for durarion of command * (which may outlive the conn!). */ jcon->current = tal(jcon->dstate, struct command); jcon->current->jcon = jcon; jcon->current->dstate = jcon->dstate; jcon->current->id = tal_strndup(jcon->current, json_tok_contents(jcon->buffer, id), json_tok_len(id)); if (!method || !params) { command_fail(jcon->current, method ? "No params" : "No method"); return; } if (method->type != JSMN_STRING) { command_fail(jcon->current, "Expected string for method"); return; } cmd = find_cmd(jcon->buffer, method); if (!cmd) { command_fail(jcon->current, "Unknown command '%.*s'", (int)(method->end - method->start), jcon->buffer + method->start); return; } if (params->type != JSMN_ARRAY && params->type != JSMN_OBJECT) { command_fail(jcon->current, "Expected array or object for params"); return; } cmd->dispatch(jcon->current, jcon->buffer, params); }
static const char *get_first_input_addr(const tal_t *ctx, const char *buffer, const jsmntok_t *txid) { const jsmntok_t *toks, *intxid, *onum, *type, *address; unsigned int outnum; const char *delve, *txstr; /* eg: getrawtransaction e84b0c87934a146d211fcaa6f1ec187da33e205fb250400cf66620a82a9111a0 1 { "hex" : "010000000193721eadf1bb2a40498b41ca6be2adaddf4c1780884637fedf05cf37015ac508000000006b4830450221008ce700a0c872af67612e5d5226f1e8bdcb2329549883b8fa02df002409f54c43022029b10a885ca3c5103574f06ab90e6f5a7c9c2cafe6e583f17316c967d678bab4012103c511c82cf0aae4541c026eee5d9f738dc1cb4a2114e20b3f5710a22dc94825ceffffffff02d0f88774030000001976a9144e81b0986efad3643012783f016ec10a9c3d35cd88ac005a6202000000001976a91434f89b68a07bd841bbca98f9b7b1521ce1a3d17688ac00000000", "txid" : "e84b0c87934a146d211fcaa6f1ec187da33e205fb250400cf66620a82a9111a0", "version" : 1, "locktime" : 0, "vin" : [ { "txid" : "08c55a0137cf05dffe37468880174cdfadade26bca418b49402abbf1ad1e7293", "vout" : 0, "scriptSig" : { "asm" : "30450221008ce700a0c872af67612e5d5226f1e8bdcb2329549883b8fa02df002409f54c43022029b10a885ca3c5103574f06ab90e6f5a7c9c2cafe6e583f17316c967d678bab401 03c511c82cf0aae4541c026eee5d9f738dc1cb4a2114e20b3f5710a22dc94825ce", "hex" : "4830450221008ce700a0c872af67612e5d5226f1e8bdcb2329549883b8fa02df002409f54c43022029b10a885ca3c5103574f06ab90e6f5a7c9c2cafe6e583f17316c967d678bab4012103c511c82cf0aae4541c026eee5d9f738dc1cb4a2114e20b3f5710a22dc94825ce" }, "sequence" : 4294967295 } ], "vout" : [ { "value" : 148.39970000, "n" : 0, "scriptPubKey" : { "asm" : "OP_DUP OP_HASH160 4e81b0986efad3643012783f016ec10a9c3d35cd OP_EQUALVERIFY OP_CHECKSIG", "hex" : "76a9144e81b0986efad3643012783f016ec10a9c3d35cd88ac", "reqSigs" : 1, "type" : "pubkeyhash", "addresses" : [ "mng4N2LZqin7joL7GAjs4tp8WNNt8GjcYz" ] } }, { "value" : 0.40000000, "n" : 1, "scriptPubKey" : { "asm" : "OP_DUP OP_HASH160 34f89b68a07bd841bbca98f9b7b1521ce1a3d176 OP_EQUALVERIFY OP_CHECKSIG", "hex" : "76a91434f89b68a07bd841bbca98f9b7b1521ce1a3d17688ac", "reqSigs" : 1, "type" : "pubkeyhash", "addresses" : [ "mkM3FYuYoKFiXS3YL99JdJEdPM5HVGpZTj" ] } } ], "blockhash" : "0000000022a3a02881f56c24bbe7556eef98b1e29267b4015a4fbfc83bab5735", "confirmations" : 14, "time" : 1406252550, "blocktime" : 1406252550 } */ txstr = tal_fmt(ctx, "%.*s", (int)(txid->end - txid->start), buffer + txid->start); toks = json_bitcoind(ctx, &buffer, "getrawtransaction", txstr, "1", NULL); if (!toks) err(1, "getrawtransaction of tx %s", txstr); /* This can happen in if someone aims their block reward at the gateway. */ intxid = json_delve(buffer, toks, ".vin[0].txid"); onum = json_delve(buffer, toks, ".vin[0].vout"); if (!intxid || !onum) errx(1, "Missing txid/vout in '%s'", buffer); /* Get this before we replace buffer. */ outnum = num_of(buffer, onum); /* Get details of *that* tx. */ txstr = tal_fmt(ctx, "%.*s", (int)(intxid->end - intxid->start), buffer + intxid->start); toks = json_bitcoind(ctx, &buffer, "getrawtransaction", txstr, "1", NULL); if (!toks) err(1, "getrawtransaction of input tx %s", txstr); /* make sure it's a pubkeyhash */ delve = tal_fmt(ctx, ".vout[%u].scriptPubKey.type", outnum); type = json_delve(buffer, toks, delve); if (!type || !json_tok_streq(buffer, type, "pubkeyhash")) errx(1, "'%s' was not a pubkeyhash in '%s'", delve, buffer); delve = tal_fmt(ctx, ".vout[%u].scriptPubKey.addresses[0]", outnum); address = json_delve(buffer, toks, delve); if (!address) errx(1, "Can't find %s in '%s'", delve, buffer); return tal_strndup(ctx, buffer + address->start, address->end - address->start); }
int main(void) { char *parent, *c; plan_tests(43); parent = tal(NULL, char); ok1(parent); c = tal_strdup(parent, "hello"); ok1(strcmp(c, "hello") == 0); ok1(tal_parent(c) == parent); ok1(tal_count(c) == strlen(c) + 1); tal_free(c); c = tal_strndup(parent, "hello", 3); ok1(strcmp(c, "hel") == 0); ok1(tal_parent(c) == parent); ok1(tal_count(c) == strlen(c) + 1); tal_free(c); #ifdef TAL_USE_TALLOC c = tal_talloc_typechk_(parent, char *); #else c = tal_typechk_(parent, char *); #endif c = tal_dup_arr(parent, char, "hello", 6, 0); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_count(c) == 6); ok1(tal_parent(c) == parent); tal_free(c); /* Now with an extra byte. */ c = tal_dup_arr(parent, char, "hello", 6, 1); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_count(c) == 7); ok1(tal_parent(c) == parent); strcat(c, "x"); tal_free(c); c = tal_fmt(parent, "hello %s", "there"); ok1(strcmp(c, "hello there") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); tal_free(c); c = tal_strcat(parent, "hello ", "there"); ok1(strcmp(c, "hello there") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); /* Make sure take works correctly. */ c = tal_strcat(parent, take(c), " again"); ok1(strcmp(c, "hello there again") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); c = tal_strcat(parent, "And ", take(c)); ok1(tal_count(c) == strlen(c) + 1); ok1(strcmp(c, "And hello there again") == 0); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); /* NULL pass through works... */ c = tal_strcat(parent, take(NULL), take(c)); ok1(!c); ok1(no_children(parent)); c = tal_strcat(parent, take(tal_strdup(parent, "hi")), take(NULL)); ok1(!c); ok1(no_children(parent)); c = tal_strcat(parent, take(NULL), take(NULL)); ok1(!c); ok1(no_children(parent)); /* Appending formatted strings. */ c = tal_strdup(parent, "hi"); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_append_fmt(&c, "%s %s", "there", "world")); ok1(strcmp(c, "hithere world") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(!tal_append_fmt(&c, take(NULL), "there", "world")); ok1(strcmp(c, "hithere world") == 0); ok1(tal_count(c) == strlen(c) + 1); tal_free(parent); return exit_status(); }