Exemple #1
0
/* Creates and adds an example file. */
static char *add_example(struct manifest *m, struct ccan_file *source,
			 struct doc_section *example)
{
	char *name, *linemarker;
	unsigned int i;
	int fd;
	struct ccan_file *f;

	name = tal_fmt(m, "example-%s-%s",
		       source->name, example->function);
	/* example->function == 'struct foo' */
	while (strchr(name, ' '))
		*strchr(name, ' ') = '_';

	name = temp_file(m, ".c", take(name));
	f = new_ccan_file(m, take(path_dirname(m, name)),
			  take(path_basename(m, name)));
	tal_steal(f, name);
	list_add_tail(&m->examples, &f->list);

	fd = open(f->fullname, O_WRONLY | O_CREAT | O_EXCL, 0600);
	if (fd < 0)
		return tal_fmt(m, "Creating temporary file %s: %s",
			       f->fullname, strerror(errno));

	/* Add #line to demark where we are from, so errors are correct! */
	linemarker = tal_fmt(f, "#line %i \"%s\"\n",
			     example->srcline+2, source->fullname);
	if (write(fd, linemarker, strlen(linemarker)) != (int)strlen(linemarker)) {
		close(fd);
		return cast_const(char *, "Failure writing to temporary file");
	}
/* See "https://en.bitcoin.it/wiki/Proper_Money_Handling_(JSON-RPC)" */
static bool pettycoin_tx(const tal_t *ctx, const char *privkey,
			 const char *destaddr, const char *amount,
			 size_t amount_len)
{
	char *out, *end, *amountstr, *pettyaddr;
	u64 amt;

	/* We expect <number>.<number>. */
	amt = strtoul(amount, &end, 10) * (u64)100000000;
	if (end >= amount + amount_len || *end != '.')
		errx(1, "Bad amount '%.*s'", (int)amount_len, amount);

	amt += strtoul(end + 1, &end, 10);
	if (end != amount + amount_len)
		errx(1, "Bad amount '%.*s'", (int)amount_len, amount);

	amountstr = tal_fmt(ctx, "%llu", (unsigned long long)amt);
	pettyaddr = tal_fmt(ctx, "P-%s", destaddr);

	out = ask_process(ctx, "pettycoin-tx", "--no-fee",
			  "from-gateway", privkey, pettyaddr, amountstr);

	if (!out)
		return false;

	out = ask_process(ctx, "pettycoin-query", "sendrawtransaction",
			  out, NULL, NULL, NULL);
	if (!out)
		return false;	

	printf("Injected gateway tx %s\n", out);
	return true;
}
/* FIXME: only print full analysis if verbose >= 2.  */
static char *get_trailing_whitespace(const tal_t *ctx, const char *line)
{
	const char *e = strchr(line, 0);
	while (e>line && (e[-1]==' ' || e[-1]=='\t'))
		e--;
	if (*e == 0)
		return NULL; //there were no trailing spaces
	if (e == line)
		return NULL; //the line only consists of spaces

	if (strlen(line) > 20)
		return tal_fmt(ctx, "...'%s'", line + strlen(line) - 20);
	return tal_fmt(ctx, "'%s'", line);
}
Exemple #4
0
/* Be careful about trying to compile over running programs (parallel make).
 * temp_file helps here. */
char *compile_info(const void *ctx, const char *dir)
{
	char *info_c_file, *info, *compiled, *output;
	int fd;

	/* Copy it to a file with proper .c suffix. */
	info = grab_file(ctx, tal_fmt(ctx, "%s/_info", dir));
	if (!info)
		return NULL;

	info_c_file = temp_file(ctx, ".c", "_info");
	fd = open(info_c_file, O_WRONLY|O_CREAT|O_EXCL, 0600);
	if (fd < 0)
		return NULL;
	if (!write_all(fd, info, tal_count(info)-1))
		return NULL;

	if (close(fd) != 0)
		return NULL;

	compiled = temp_file(ctx, "", "info");
	if (compile_and_link(ctx, info_c_file, find_ccan_dir(dir), "",
			     compiler, cflags, "", compiled, &output))
		return compiled;
	return NULL;
}
Exemple #5
0
static char *get_leaks(char *lines[], char **errs)
{
	char *leaks = tal_strdup(lines, "");
	unsigned int i;

	for (i = 0; i < tal_count(lines) - 1; i++) {
		if (strstr(lines[i], " lost ")) {
			/* A leak... */
			if (strstr(lines[i], " definitely lost ")) {
				/* Definite leak, report. */
				while (lines[i] && !blank_line(lines[i])) {
					tal_append_fmt(&leaks, "%s\n",
						       lines[i]);
					i++;
				}
			} else
				/* Not definite, ignore. */
				while (lines[i] && !blank_line(lines[i]))
					i++;
		} else {
			/* A real error. */
			while (lines[i] && !blank_line(lines[i])) {
				if (!*errs)
					*errs = tal_fmt(NULL, "%s\n", lines[i]);
				else
					tal_append_fmt(errs, "%s\n", lines[i]);
				i++;
			}
		}
	}
	return leaks;
}
Exemple #6
0
static void add_dep(struct manifest ***deps, const char *modname)
{
	unsigned int i;
	struct manifest *m;
	char *errstr;

	if (have_mod(*deps, modname))
		return;

	m = get_manifest(*deps,
			 tal_fmt(*deps, "%s/ccan/%s", ccan_dir, modname));
	errstr = build_submodule(m, cflags, COMPILE_NORMAL);
	if (errstr)
		errx(1, "%s", errstr);

	add_mod(deps, m);

	/* Get that modules depends as well... */
	assert(!safe_mode);
	if (m->info_file) {
		char **infodeps;

		infodeps = get_deps(m, m->dir, "depends", false,
				    get_or_compile_info);

		for (i = 0; infodeps[i]; i++) {
			if (strstarts(infodeps[i], "ccan/"))
				add_dep(deps, infodeps[i] + strlen("ccan/"));
		}
	}
}
Exemple #7
0
void command_fail(struct command *cmd, const char *fmt, ...)
{
	char *quote, *error;
	struct json_connection *jcon = cmd->jcon;
	va_list ap;

	if (!jcon) {
		log_unusual(cmd->dstate->base_log,
			    "Command failed after jcon close");
		tal_free(cmd);
		return;
	}

	va_start(ap, fmt);
	error = tal_vfmt(cmd, fmt, ap);
	va_end(ap);

	log_debug(jcon->log, "Failing: %s", error);

	/* Remove " */
	while ((quote = strchr(error, '"')) != NULL)
		*quote = '\'';

	/* Now surround in quotes. */
	quote = tal_fmt(cmd, "\"%s\"", error);

	assert(jcon->current == cmd);
	json_result(jcon, cmd->id, "null", quote);
	jcon->current = tal_free(cmd);
}
Exemple #8
0
char *short_channel_id_to_str(const tal_t *ctx, const struct short_channel_id *scid)
{
	return tal_fmt(ctx, "%dx%dx%d",
		       short_channel_id_blocknum(scid),
		       short_channel_id_txnum(scid),
		       short_channel_id_outnum(scid));
}
Exemple #9
0
char *short_channel_id_dir_to_str(const tal_t *ctx,
				  const struct short_channel_id_dir *scidd)
{
	char *str, *scidstr = short_channel_id_to_str(NULL, &scidd->scid);
	str = tal_fmt(ctx, "%s/%u", scidstr, scidd->dir);
	tal_free(scidstr);
	return str;
}
Exemple #10
0
static char *fmt_channel_view(const tal_t *ctx, const struct channel_view *view)
{
	return tal_fmt(ctx, "{ feerate_per_kw=%"PRIu32","
		       " owed_local=%"PRIu64","
		       " owed_remote=%"PRIu64" }",
		       view->feerate_per_kw,
		       view->owed_msat[LOCAL],
		       view->owed_msat[REMOTE]);
}
Exemple #11
0
/* FIXME: This should reference HTLCs somehow. */
static char *fmt_channel(const tal_t *ctx, const struct channel *channel)
{
	return tal_fmt(ctx, "{ funding_msat=%"PRIu64","
		       " funder=%s,"
		       " local=%s,"
		       " remote=%s }",
		       channel->funding_msat,
		       side_to_str(channel->funder),
		       fmt_channel_view(ctx, &channel->view[LOCAL]),
		       fmt_channel_view(ctx, &channel->view[REMOTE]));
}
Exemple #12
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 #13
0
static void json_result(struct json_connection *jcon,
			const char *id, const char *res, const char *err)
{
	struct json_output *out = tal(jcon, struct json_output);

	out->json = tal_fmt(out,
			    "{ \"result\" : %s,"
			    " \"error\" : %s,"
			    " \"id\" : %s }\n",
			    res, err, id);

	/* Queue for writing, and wake writer (and maybe reader). */
	list_add_tail(&jcon->output, &out->list);
	io_wake(jcon);
}
Exemple #14
0
char *netaddr_name(const tal_t *ctx, const struct netaddr *a)
{
	char name[INET6_ADDRSTRLEN];
	const void *sockaddr;
	uint16_t port;

	switch (a->saddr.s.sa_family) {
	case AF_INET:
		sockaddr = &a->saddr.ipv4.sin_addr;
		port = ntohs(a->saddr.ipv4.sin_port);
		break;
	case AF_INET6:
		sockaddr = &a->saddr.ipv6.sin6_addr;
		port = ntohs(a->saddr.ipv6.sin6_port);
		break;
	default:
		return tal_fmt(ctx, "Unknown protocol %u", a->saddr.s.sa_family);
	}

	if (!inet_ntop(a->saddr.s.sa_family, sockaddr, name, sizeof(name)))
		sprintf(name, "Unprintable-%u-address", a->saddr.s.sa_family);

	return tal_fmt(ctx, "%s:%u", name, port);
}
Exemple #15
0
static void dump_htlc(const struct htlc *htlc, const char *prefix)
{
	enum htlc_state remote_state;

	if (htlc->state <= RCVD_REMOVE_ACK_REVOCATION)
		remote_state = htlc->state + 10;
	else
		remote_state = htlc->state - 10;

	status_trace("%s: HTLC %s %"PRIu64" = %s/%s %s",
		     prefix,
		     htlc_owner(htlc) == LOCAL ? "LOCAL" : "REMOTE",
		     htlc->id,
		     htlc_state_name(htlc->state),
		     htlc_state_name(remote_state),
		     htlc->r ? "FULFILLED" : htlc->fail ? "FAILED" :
		     htlc->failcode
		     ? tal_fmt(tmpctx, "FAILCODE:%u", htlc->failcode) : "");
}
Exemple #16
0
static void handle_license_link(struct manifest *m, struct score *score)
{
	struct doc_section *d = find_license_tag(m);
	const char *prefix = link_prefix(m);
	const char *link = path_join(m, m->dir, "LICENSE");
	const char *ldest = expected_link(score, prefix, m->license);
	char *q;

	printf(
	"Most modules want a copy of their license, so usually we create a\n"
	"LICENSE symlink into %s to avoid too many copies.\n", prefix);

	/* FIXME: make ask printf-like */
	q = tal_fmt(m, "Set up link to %s (license is %s)?",
		    ldest, d->lines[0]);
	if (ask(q)) {
		if (symlink(ldest, link) != 0)
			err(1, "Creating symlink %s -> %s", link, ldest);
	}
}
Exemple #17
0
static struct command_result *waitsendpay_expired(struct command *cmd,
						  struct pay_command *pc)
{
	char *errmsg, *data;

	errmsg = tal_fmt(pc, "Gave up after %zu attempts",
			 tal_count(pc->ps->attempts));
	data = tal_strdup(pc, "'attempts': [ ");
	for (size_t i = 0; i < tal_count(pc->ps->attempts); i++) {
		if (pc->ps->attempts[i].route)
			tal_append_fmt(&data, "%s { 'route': %s,\n 'failure': %s\n }",
				       i == 0 ? "" : ",",
				       pc->ps->attempts[i].route,
				       pc->ps->attempts[i].failure);
		else
			tal_append_fmt(&data, "%s { 'failure': %s\n }",
				       i == 0 ? "" : ",",
				       pc->ps->attempts[i].failure);
	}
	tal_append_fmt(&data, "]");
	return command_done_err(cmd, PAY_STOPPED_RETRYING, errmsg, data);
}
Exemple #18
0
/* We only handle simple function definitions here. */
static char *add_func(const tal_t *ctx, char *others, const char *line)
{
	const char *p, *end = strchr(line, '(') - 1;
	char *use;

	while (cisspace(*end)) {
		end--;
		if (end == line)
			return others;
	}

	for (p = end; cisalnum(*p) || *p == '_'; p--) {
		if (p == line)
			return others;
	}

	use = tal_fmt(ctx, "printf(\"%%p\", %.*s);\n",
		      (unsigned)(end - p), p+1);
	if (others)
		use = tal_strcat(ctx, take(others), take(use));

	return use;
}
Exemple #19
0
int main(int argc, char *argv[])
{
	size_t i, j, num;
	struct timeabs start, stop;
	char **w;
	ENTRY *words, *misswords;

	w = tal_strsplit(NULL, grab_file(NULL,
					 argv[1] ? argv[1] : "/usr/share/dict/words"), "\n", STR_NO_EMPTY);
	num = tal_count(w) - 1;
	printf("%zu words\n", num);

	hcreate(num+num/3);

	words = tal_arr(w, ENTRY, num);
	for (i = 0; i < num; i++) {
		words[i].key = w[i];
		words[i].data = words[i].key;
	}

	/* Append and prepend last char for miss testing. */
	misswords = tal_arr(w, ENTRY, num);
	for (i = 0; i < num; i++) {
		char lastc;
		if (strlen(w[i]))
			lastc = w[i][strlen(w[i])-1];
		else
			lastc = 'z';
		misswords[i].key = tal_fmt(misswords, "%c%s%c%c",
					   lastc, w[i], lastc, lastc);
	}

	printf("#01: Initial insert: ");
	fflush(stdout);
	start = time_now();
	for (i = 0; i < num; i++)
		hsearch(words[i], ENTER);
	stop = time_now();
	printf(" %zu ns\n", normalize(&start, &stop, num));

	printf("#02: Initial lookup (match): ");
	fflush(stdout);
	start = time_now();
	for (i = 0; i < num; i++)
		if (hsearch(words[i], FIND)->data != words[i].data)
			abort();
	stop = time_now();
	printf(" %zu ns\n", normalize(&start, &stop, num));

	printf("#03: Initial lookup (miss): ");
	fflush(stdout);
	start = time_now();
	for (i = 0; i < num; i++) {
		if (hsearch(misswords[i], FIND))
			abort();
	}
	stop = time_now();
	printf(" %zu ns\n", normalize(&start, &stop, num));

	/* Lookups in order are very cache-friendly for judy; try random */
	printf("#04: Initial lookup (random): ");
	fflush(stdout);
	start = time_now();
	for (i = 0, j = 0; i < num; i++, j = (j + 10007) % num)
		if (hsearch(words[i], FIND)->data != words[i].data)
			abort();
	stop = time_now();
	printf(" %zu ns\n", normalize(&start, &stop, num));

	return 0;
}
Exemple #20
0
static char *ask_process(const tal_t *ctx,
			 const char *name,
			 const char *arg1,
			 const char *arg2,
			 const char *arg3,
			 const char *arg4,
			 const char *arg5)
{
	struct json_result *response = new_json_result(ctx);

	if (streq(name, "bitcoind")) {
		assert(streq(arg1, "-testnet"));
		if (streq(arg2, "listtransactions")) {
			unsigned int i, num, skip;

			assert(streq(arg3, "gateway"));
			num = atoi(arg4 ? arg4 : "10");
			assert(num);
			skip = atoi(arg5 ? arg5 : "0");

			json_array_start(response, NULL);
			/* Like bitcoind, list oldest first. */
			for (i = skip; i < skip+num; i++) {
				unsigned int confs;

				if (i >= ARRAY_SIZE(listtxs_response))
					break;
				/* We only show one the first time. */
				if (i > sleeps)
					break;
				/* First one is 16 confs, then 4, 1, then 0,
				 * plus one each time you ask. */
				confs = (1 << ((ARRAY_SIZE(listtxs_response)
						- i) * 2)) + sleeps;

				result_append_fmt(response, listtxs_response[i],
						  confs);
			}
			json_array_end(response);
			assert(!response->indent);
			return response->s;
		} else if (streq(arg2, "getrawtransaction")) {
			unsigned int i;

			/* We only do verbose mode */
			assert(streq(arg4, "1"));
			assert(arg5 == NULL);

			/* Search through responses for this txid */
			for (i = 0; i < ARRAY_SIZE(getrawtxs_response); i++) {
				const char *p;
				p = strstr(getrawtxs_response[i],
					   "    \"txid\" : \"");
				if (strstarts(p + strlen("    \"txid\" : \""),
					      arg3))
					return tal_strdup(ctx,
							  getrawtxs_response[i]);
			}
		} else if (streq(arg2, "getinfo")) {
			return tal_strdup(ctx, getinfo_response);
		} else if (streq(arg2, "sendtoaddress")) {
			if (mark_off_payment(arg3,
					     amount_in_satoshis(arg4,
								strlen(arg4))))
				return tal_strdup(ctx, "some-new-bitcoin-txid");
		}
	} else if (streq(name, "pettycoin-tx")) {
		assert(streq(arg1, "--no-fee"));
		assert(streq(arg2, "from-gateway"));
		assert(streq(arg3, "FAKE-gateway-privkey"));

		if (mark_off_payment(arg4, atol(arg5)))
			return tal_fmt(ctx, "raw-transaction-%s", arg4);
	} else if (streq(name, "pettycoin-query")) {
		assert(streq(arg1, "sendrawtransaction"));
		assert(strstarts(arg2, "raw-transaction-"));
		assert(arg3 == NULL);
		assert(arg4 == NULL);
		assert(arg5 == NULL);
		return tal_fmt(ctx, "txid for %s", arg2);
	}

	printf("ask_process: name=%s arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s",
	       name, arg1, arg2, arg3, arg4, arg5);
	return NULL;
}
Exemple #21
0
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();
}
Exemple #22
0
int main(void)
{
	struct amount_msat msat;
	struct amount_sat sat;

	setup_locale();
	setup_tmpctx();

	/* Grossly malformed */
	FAIL_MSAT(&msat, "x");
	FAIL_MSAT(&msat, "x100");

	PASS_MSAT(&msat, "0", 0);
	PASS_MSAT(&msat, "1", 1);
	PASS_MSAT(&msat, "2100000000000000000", 2100000000000000000ULL);
	FAIL_MSAT(&msat, "0.0");
	FAIL_MSAT(&msat, "0.00000000");
	FAIL_MSAT(&msat, "0.00000000000");
	FAIL_MSAT(&msat, "0.00000000msat");
	FAIL_MSAT(&msat, "-1");

	PASS_MSAT(&msat, "0msat", 0);
	PASS_MSAT(&msat, "1msat", 1);
	PASS_MSAT(&msat, "2100000000000000000msat", 2100000000000000000ULL);
	FAIL_MSAT(&msat, "-1msat");

	PASS_MSAT(&msat, "0sat", 0);
	PASS_MSAT(&msat, "1sat", 1000);
	PASS_MSAT(&msat, "2100000000000000sat", 2100000000000000000ULL);
	FAIL_MSAT(&msat, "-1sat");

	PASS_MSAT(&msat, "0.00000000btc", 0);
	PASS_MSAT(&msat, "0.00000000000btc", 0);
	PASS_MSAT(&msat, "0.00000001btc", 1000);
	PASS_MSAT(&msat, "0.00000000001btc", 1);
	PASS_MSAT(&msat, "1.2btc", 120000000000);
	PASS_MSAT(&msat, "1.23btc", 123000000000);
	PASS_MSAT(&msat, "1.234btc", 123400000000);
	PASS_MSAT(&msat, "1.2345btc", 123450000000);
	PASS_MSAT(&msat, "1.23456btc", 123456000000);
	PASS_MSAT(&msat, "1.234567btc", 123456700000);
	PASS_MSAT(&msat, "1.2345678btc", 123456780000);
	PASS_MSAT(&msat, "1.23456789btc", 123456789000);
	PASS_MSAT(&msat, "1.234567890btc", 123456789000);
	PASS_MSAT(&msat, "1.2345678901btc", 123456789010);
	PASS_MSAT(&msat, "1.23456789012btc", 123456789012);
	FAIL_MSAT(&msat, "1btc");
	FAIL_MSAT(&msat, "1.000000000000btc");
	FAIL_MSAT(&msat, "-1.23456789btc");
	FAIL_MSAT(&msat, "-1.23456789012btc");

	/* Overflowingly big. */
	FAIL_MSAT(&msat, "21000000000000000000000000.00000000btc");

	/* Grossly malformed */
	FAIL_SAT(&sat, "x");
	FAIL_SAT(&sat, "x100");

	PASS_SAT(&sat, "0", 0);
	PASS_SAT(&sat, "1", 1);
	PASS_SAT(&sat, "2100000000000000", 2100000000000000ULL);
	FAIL_SAT(&sat, "0.0");
	FAIL_SAT(&sat, "0.00000000");
	FAIL_SAT(&sat, "0.00000000000");
	FAIL_SAT(&sat, "0.00000000sat");
	FAIL_SAT(&sat, "0.00000000000msat");
	FAIL_SAT(&sat, "-1");

	PASS_SAT(&sat, "0sat", 0);
	PASS_SAT(&sat, "1sat", 1);
	PASS_SAT(&sat, "2100000000000000sat", 2100000000000000ULL);
	FAIL_SAT(&sat, "-1sat");

	PASS_SAT(&sat, "1000msat", 1);
	PASS_SAT(&sat, "1000000msat", 1000);
	PASS_SAT(&sat, "2100000000000000000msat", 2100000000000000ULL);
	FAIL_SAT(&sat, "0msat");
	FAIL_SAT(&sat, "100msat");
	FAIL_SAT(&sat, "2000000000000000999msat");
	FAIL_SAT(&sat, "-1000msat");

	PASS_SAT(&sat, "0.00000000btc", 0);
	FAIL_SAT(&sat, "0.00000000000btc");
	PASS_SAT(&sat, "0.00000001btc", 1);
	FAIL_SAT(&sat, "0.00000000001btc");
	PASS_SAT(&sat, "1.23456789btc", 123456789);
	PASS_SAT(&sat, "1.2btc", 120000000);
	PASS_SAT(&sat, "1.23btc", 123000000);
	PASS_SAT(&sat, "1.234btc", 123400000);
	PASS_SAT(&sat, "1.2345btc", 123450000);
	PASS_SAT(&sat, "1.23456btc", 123456000);
	PASS_SAT(&sat, "1.234567btc", 123456700);
	PASS_SAT(&sat, "1.2345678btc", 123456780);
	PASS_SAT(&sat, "1.23456789btc", 123456789);
	FAIL_SAT(&sat, "1.234567890btc");
	FAIL_SAT(&sat, "1btc");
	FAIL_SAT(&sat, "-1.23456789btc");

	/* Overflowingly big. */
	FAIL_SAT(&sat, "21000000000000000000000000.00000000btc");

	/* Test fmt_amount_msat_btc, fmt_amount_msat */
	for (u64 i = 0; i <= UINT64_MAX / 10; i = i ? i * 10 : 1) {
		const char *with, *without;

		msat.millisatoshis = i;
		with = fmt_amount_msat_btc(tmpctx, &msat, true);
		without = fmt_amount_msat_btc(tmpctx, &msat, false);
		assert(strends(with, "btc"));
		assert(strlen(with) == strlen(without) + 3);
		assert(strncmp(with, without, strlen(without)) == 0);
		/* Make sure it overwrites. */
		msat.millisatoshis++;
		assert(parse_amount_msat(&msat, with, strlen(with)));
		assert(msat.millisatoshis == i);

		with = fmt_amount_msat(tmpctx, &msat);
		without = tal_fmt(tmpctx, "%"PRIu64, msat.millisatoshis);
		assert(strends(with, "msat"));
		assert(strlen(with) == strlen(without) + 4);
		assert(strncmp(with, without, strlen(without)) == 0);
		/* Make sure it overwrites. */
		msat.millisatoshis++;
		assert(parse_amount_msat(&msat, with, strlen(with)));
		assert(msat.millisatoshis == i);
	}

	/* Test fmt_amount_sat_btc, fmt_amount_sat */
	for (u64 i = 0; i <= UINT64_MAX / 10; i = i ? i * 10 : 1) {
		const char *with, *without;

		sat.satoshis = i;
		with = fmt_amount_sat_btc(tmpctx, &sat, true);
		without = fmt_amount_sat_btc(tmpctx, &sat, false);
		assert(strends(with, "btc"));
		assert(strlen(with) == strlen(without) + 3);
		assert(strncmp(with, without, strlen(without)) == 0);
		/* Make sure it overwrites. */
		sat.satoshis++;
		assert(parse_amount_sat(&sat, with, strlen(with)));
		assert(sat.satoshis == i);

		with = fmt_amount_sat(tmpctx, &sat);
		without = tal_fmt(tmpctx, "%"PRIu64, sat.satoshis);
		assert(strends(with, "sat"));
		assert(strlen(with) == strlen(without) + 3);
		assert(strncmp(with, without, strlen(without)) == 0);
		/* Make sure it overwrites. */
		sat.satoshis++;
		assert(parse_amount_sat(&sat, with, strlen(with)));
		assert(sat.satoshis == i);
	}

	tal_free(tmpctx);
}
Exemple #23
0
/* Note: we already test safe_mode in run_tests.c */
static const char *can_run_vg(struct manifest *m)
{
	if (!do_valgrind)
		return tal_fmt(m, "No valgrind support");
	return NULL;
}
/* Simple test code to create a gateway transaction */
int main(int argc, char *argv[])
{
	int fd, i, off;
	const char *method;
	char *cmd, *resp, *idstr, *rpc_filename;
	char *result_end;
	struct sockaddr_un addr;
	jsmntok_t *toks;
	const jsmntok_t *result, *error, *id;
	char *pettycoin_dir;
	const tal_t *ctx = tal(NULL, char);
	size_t num_opens, num_closes;
	bool valid;

	err_set_progname(argv[0]);

	opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn);
	pettycoin_dir_register_opts(ctx, &pettycoin_dir, &rpc_filename);

	opt_register_noarg("--help|-h", opt_usage_and_exit,
			   "<command> [<params>...]", "Show this message");
	opt_register_noarg("--version|-V", opt_version_and_exit, VERSION,
			   "Display version and exit");

	opt_early_parse(argc, argv, opt_log_stderr_exit);
	opt_parse(&argc, argv, opt_log_stderr_exit);

	method = argv[1];
	if (!method)
		errx(ERROR_USAGE, "Need at least one argument\n%s",
		     opt_usage(argv[0], NULL));

	if (chdir(pettycoin_dir) != 0)
		err(ERROR_TALKING_TO_PETTYCOIN, "Moving into '%s'",
		    pettycoin_dir);

	fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (strlen(rpc_filename) + 1 > sizeof(addr.sun_path))
		errx(ERROR_USAGE, "rpc filename '%s' too long", rpc_filename);
	strcpy(addr.sun_path, rpc_filename);
	addr.sun_family = AF_UNIX;

	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
		err(ERROR_TALKING_TO_PETTYCOIN,
		    "Connecting to '%s'", rpc_filename);

	idstr = tal_fmt(ctx, "pettycoin_query-%i", getpid());
	cmd = tal_fmt(ctx,
		      "{ \"method\" : \"%s\", \"id\" : \"%s\", \"params\" : [ ",
		      method, idstr);

	for (i = 2; i < argc; i++) {
		/* Numbers are left unquoted, and quoted things left alone. */
		if (strspn(argv[i], "0123456789") == strlen(argv[i])
		    || argv[i][0] == '"')
			tal_append_fmt(&cmd, "%s", argv[i]);
		else
			tal_append_fmt(&cmd, "\"%s\"", argv[i]);
		if (i != argc - 1)
			tal_append_fmt(&cmd, ", ");
	}
	tal_append_fmt(&cmd, "] }");

	if (!write_all(fd, cmd, strlen(cmd)))
		err(ERROR_TALKING_TO_PETTYCOIN, "Writing command");

	resp = tal_arr(cmd, char, 100);
	off = 0;
	num_opens = num_closes = 0;
	while ((i = read(fd, resp + off, tal_count(resp) - 1 - off)) > 0) {
		resp[off + i] = '\0';
		num_opens += strcount(resp + off, "{");
		num_closes += strcount(resp + off, "}");

		off += i;
		if (off == tal_count(resp) - 1)
			tal_resize(&resp, tal_count(resp) * 2);

		/* parsing huge outputs is slow: do quick check first. */
		if (num_opens == num_closes && strstr(resp, "\"result\""))
			break;
	}
	if (i < 0)
		err(ERROR_TALKING_TO_PETTYCOIN, "reading response");

	/* Parsing huge results is too slow, so hack fastpath common case */
	result_end = tal_fmt(ctx, ", \"error\" : null, \"id\" : \"%s\" }\n",
			     idstr);

	if (strstarts(resp, "{ \"result\" : ") && strends(resp, result_end)) {
		/* Result is OK, so dump it */
		resp += strlen("{ \"result\" : ");
		printf("%.*s\n", (int)(strlen(resp) - strlen(result_end)), resp);
		tal_free(ctx);
		return 0;
	}

	toks = json_parse_input(resp, off, &valid);
	if (!toks || !valid)
		errx(ERROR_TALKING_TO_PETTYCOIN,
		     "Malformed response '%s'", resp);

	result = json_get_member(resp, toks, "result");
	if (!result)
		errx(ERROR_TALKING_TO_PETTYCOIN,
		     "Missing 'result' in response '%s'", resp);
	error = json_get_member(resp, toks, "error");
	if (!error)
		errx(ERROR_TALKING_TO_PETTYCOIN,
		     "Missing 'error' in response '%s'", resp);
	id = json_get_member(resp, toks, "id");
	if (!id)
		errx(ERROR_TALKING_TO_PETTYCOIN,
		     "Missing 'id' in response '%s'", resp);
	if (!json_tok_streq(resp, id, idstr))
		errx(ERROR_TALKING_TO_PETTYCOIN,
		     "Incorrect 'id' in response: %.*s",
		     json_tok_len(id), json_tok_contents(resp, id));

	if (json_tok_is_null(resp, error)) {
		printf("%.*s\n",
		       json_tok_len(result),
		       json_tok_contents(resp, result));
		tal_free(ctx);
		return 0;
	}

	printf("%.*s\n",
	       json_tok_len(error), json_tok_contents(resp, error));
	tal_free(ctx);
	return 1;
}
Exemple #25
0
static void check_has_license(struct manifest *m,
			      unsigned int *timeleft, struct score *score)
{
	char buf[PATH_MAX];
	ssize_t len;
	char *license = path_join(m, m->dir, "LICENSE");
	const char *expected;
	struct doc_section *d;
	const char *prefix = link_prefix(m);

	d = find_license_tag(m);
	if (!d) {
		score->error = tal_strdup(score, "No License: tag in _info");
		return;
	}

	m->license = which_license(d);
	if (m->license == LICENSE_UNKNOWN) {
		score_file_error(score, m->info_file, d->srcline,
				 "WARNING: unknown License: in _info: %s",
				 d->lines[0]);
		/* FIXME: For historical reasons, don't fail here. */
		score->pass = true;
		return;
	}

	/* If they have a license tag at all, we pass. */
	score->pass = true;

	expected = expected_link(m, prefix, m->license);

	len = readlink(license, buf, sizeof(buf));
	if (len < 0) {
		/* Could be a real file... OK if not a standard license. */
		if (errno == EINVAL) {
			if (!expected) {
				score->score = score->total;
				return;
			}
			score->error
				= tal_fmt(score,
					  "License in _info is '%s',"
					  " expect LICENSE symlink '%s'",
					  d->lines[0], expected);
			return;
		}
		if (errno == ENOENT) {
			/* Public domain doesn't really need a file. */
			if (m->license == LICENSE_PUBLIC_DOMAIN) {
				score->score = score->total;
				return;
			}
			score->error = tal_strdup(score,
						     "LICENSE does not exist");
			if (expected)
				license_exists.handle = handle_license_link;
			return;
		}
		err(1, "readlink on %s", license);
	}
	if (len >= sizeof(buf))
		errx(1, "Reading symlink %s gave huge result", license);

	buf[len] = '\0';

	if (!strstarts(buf, prefix)) {
		score->error = tal_fmt(score,
				       "Expected symlink into %s not %s",
				       prefix, buf);
		return;
	}

	if (!expected) {
		score->error = tal_fmt(score,
				       "License in _info is unknown '%s',"
				       " but LICENSE symlink is '%s'",
				       d->lines[0], buf);
		return;
	}

	if (!streq(buf, expected)) {
		score->error = tal_fmt(score,
				       "Expected symlink to %s not %s",
				       expected, buf);
		return;
	}
	score->pass = true;
	score->score = score->total;
}
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);
}