Exemple #1
0
static struct command_result *waitsendpay_error(struct command *cmd,
						const char *buf,
						const jsmntok_t *error,
						struct pay_command *pc)
{
	const jsmntok_t *codetok, *scidtok, *dirtok;
	int code;

	attempt_failed_tok(pc, "waitsendpay", buf, error);

	codetok = json_get_member(buf, error, "code");
	if (!json_to_int(buf, codetok, &code))
		plugin_err("waitsendpay error gave no 'code'? '%.*s'",
			   error->end - error->start, buf + error->start);

	/* FIXME: Handle PAY_UNPARSEABLE_ONION! */

	/* Many error codes are final. */
	if (code != PAY_TRY_OTHER_ROUTE) {
		return forward_error(cmd, buf, error, pc);
	}

	scidtok = json_delve(buf, error, ".data.erring_channel");
	if (!scidtok)
		plugin_err("waitsendpay error no erring_channel '%.*s'",
			   error->end - error->start, buf + error->start);
	dirtok = json_delve(buf, error, ".data.erring_direction");
	if (!dirtok)
		plugin_err("waitsendpay error no erring_direction '%.*s'",
			   error->end - error->start, buf + error->start);

	if (time_after(time_now(), pc->stoptime)) {
		return waitsendpay_expired(cmd, pc);
	}

	/* If failure is in routehint part, try next one */
	if (channel_in_routehint(pc->current_routehint, buf, scidtok))
		return next_routehint(cmd, pc);

	/* Otherwise, add erring channel to exclusion list. */
	tal_arr_expand(&pc->excludes,
		       tal_fmt(pc->excludes, "%.*s/%c",
			       scidtok->end - scidtok->start,
			       buf + scidtok->start,
			       buf[dirtok->start]));
	/* Try again. */
	return start_pay_attempt(cmd, pc, "Excluded channel %s",
				 pc->excludes[tal_count(pc->excludes)-1]);
}
Exemple #2
0
int main(void)
{
	jsmntok_t *toks_arr, *toks_obj,
		*arg1, *arg2, *arg3, *arg4, *arg5;
	const jsmntok_t *arr_params, *obj_params;
	void *ctx;
	bool valid;
	char *cmd_arr, *cmd_obj;
	struct protocol_double_sha sha;

	ctx = tal(NULL, char);

	cmd_arr = tal_strdup(ctx,
			     "{ \"method\" : \"dev-echo\", "
			     "\"params\" : [ null, [ 1, 2, 3 ], { \"one\" : 1 }, \"four\" ], "
			     "\"id\" : \"1\" }");

	cmd_obj = tal_strdup(ctx,
			     "{ \"method\" : \"dev-echo\", "
			     "\"params\" : { \"arg2\" : [ 1, 2, 3 ],"
				" \"arg3\" : { \"one\" : 1 },"
				" \"arg4\" : \"four\" }, "
			     "\"id\" : \"1\" }");

	/* Partial id we skip } */
	toks_arr = json_parse_input(cmd_arr, strlen(cmd_arr) - 1, &valid);
	assert(!toks_arr);
	assert(valid);
	toks_obj = json_parse_input(cmd_obj, strlen(cmd_obj) - 1, &valid);
	assert(!toks_obj);
	assert(valid);

	/* This should work */
	toks_arr = json_parse_input(cmd_arr, strlen(cmd_arr), &valid);
	assert(toks_arr);
	assert(tal_count(toks_arr) == 17);
	assert(valid);
	toks_obj = json_parse_input(cmd_obj, strlen(cmd_obj), &valid);
	assert(toks_obj);
	assert(tal_count(toks_obj) == 19);
	assert(valid);

	assert(toks_arr[0].type == JSMN_OBJECT);
	assert(json_tok_len(toks_arr) == strlen(cmd_arr));
	assert(strncmp(json_tok_contents(cmd_arr, toks_arr), cmd_arr,
		       json_tok_len(toks_arr)) == 0);

	assert(toks_obj[0].type == JSMN_OBJECT);
	assert(json_tok_len(toks_obj) == strlen(cmd_obj));
	assert(strncmp(json_tok_contents(cmd_obj, toks_obj), cmd_obj,
		       json_tok_len(toks_obj)) == 0);

	/* It's not a string, so this will fail. */
	assert(!json_tok_streq(cmd_arr, toks_arr, cmd_obj));
	assert(json_tok_streq(cmd_arr, toks_arr+1, "method"));
	assert(json_tok_streq(cmd_obj, toks_obj+1, "method"));

	assert(json_tok_is_null(cmd_arr, toks_arr + 5));
	assert(!json_tok_is_null(cmd_arr, toks_arr + 6));
	assert(!json_tok_is_null(cmd_arr, toks_arr + 7));

	assert(json_get_member(cmd_arr, toks_arr, "method") == toks_arr+2);
	assert(json_get_member(cmd_obj, toks_obj, "method") == toks_obj+2);
	assert(!json_get_member(cmd_arr, toks_arr, "dev-echo"));
	assert(!json_get_member(cmd_obj, toks_obj, "arg2"));

	arr_params = json_get_member(cmd_arr, toks_arr, "params");
	assert(arr_params == toks_arr+4);
	assert(arr_params->type == JSMN_ARRAY);
	obj_params = json_get_member(cmd_obj, toks_obj, "params");
	assert(obj_params == toks_obj+4);
	assert(obj_params->type == JSMN_OBJECT);

	assert(json_get_member(cmd_arr, toks_arr, "id") == toks_arr+15);
	assert(json_get_member(cmd_obj, toks_obj, "id") == toks_obj+17);

	/* get_member works in sub objects */
	assert(json_get_member(cmd_obj, obj_params, "arg4") == toks_obj + 15);

	json_get_params(cmd_arr, arr_params,
			"arg1", &arg1,
			"arg2", &arg2,
			"arg3", &arg3,
			"arg4", &arg4,
			"arg5", &arg5,
			NULL);
	assert(arg1 == NULL);
	assert(arg2 == toks_arr + 6);
	assert(arg2->type == JSMN_ARRAY);
	assert(arg3 == toks_arr + 10);
	assert(arg3->type == JSMN_OBJECT);
	assert(arg4 == toks_arr + 13);
	assert(arg4->type == JSMN_STRING);
	assert(arg5 == NULL);

	json_get_params(cmd_obj, obj_params,
			"arg1", &arg1,
			"arg2", &arg2,
			"arg3", &arg3,
			"arg4", &arg4,
			"arg5", &arg5,
			NULL);
	assert(arg1 == NULL);
	assert(arg2 == toks_obj + 6);
	assert(arg2->type == JSMN_ARRAY);
	assert(arg3 == toks_obj + 11);
	assert(arg3->type == JSMN_OBJECT);
	assert(arg4 == toks_obj + 15);
	assert(arg4->type == JSMN_STRING);	
	assert(arg5 == NULL);

	/* Test json_delve() */
	assert(json_delve(cmd_arr, toks_arr, ".method") == toks_arr + 2);
	assert(json_delve(cmd_arr, toks_arr, ".params[0]") == toks_arr + 5);
	assert(json_delve(cmd_arr, toks_arr, ".params[1]") == toks_arr + 6);
	assert(json_delve(cmd_arr, toks_arr, ".params[2]") == toks_arr + 10);
	assert(json_delve(cmd_arr, toks_arr, ".params[1][2]") == toks_arr + 9);
	assert(json_delve(cmd_arr, toks_arr, ".params[4]") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".params[1][4]") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".params[3][4]") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".unknown") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".unknown[1]") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".param") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".params\"") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".dev-echo") == NULL);
	assert(json_delve(cmd_arr, toks_arr, ".id[0]") == NULL);

	assert(json_delve(cmd_obj, toks_obj, ".params.arg3.one")
	       == toks_obj + 13);

	/* More exotic object creation */
	cmd_arr = tal_arr(ctx, char, 0);
	json_add_object(&cmd_arr,
			"arg2", JSMN_ARRAY, "[ 1, 2, 3 ]",
			"arg3", JSMN_OBJECT, "{ \"one\" : 1 }",
			"arg4", JSMN_STRING, "four",
			NULL);
	assert(streq(cmd_arr,
		     "{ \"arg2\" : [ 1, 2, 3 ],"
		     " \"arg3\" : { \"one\" : 1 },"
		     " \"arg4\" : \"four\" }"));

	cmd_arr = tal_arr(ctx, char, 0);
	json_object_start(&cmd_arr, NULL);

	json_add_pubkey(&cmd_arr, "key", helper_public_key(0));
	memset(&sha, 42, sizeof(sha));
	json_add_double_sha(&cmd_arr, "sha", &sha);
	json_add_address(&cmd_arr, "test-address", true, helper_addr(0));
	json_add_address(&cmd_arr, "address", false, helper_addr(0));
	json_object_end(&cmd_arr);

	assert(streq(cmd_arr, "{ \"key\" : \"0214f24666a59e62c8b92a0b4b58f2a1cdeb573ea377e42f411be028292ff81926\","
		     " \"sha\" : \"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a\","
		     " \"test-address\" : \"qKCafy33t92L9Nmoxx8H6NHDuiyGViqWBZ\","
		     " \"address\" : \"PZZyf1xcSbNFodrGQ6ot4LrsdSUu1bgmkc\" }"));
	tal_free(ctx);
	return 0;
}
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);
}