Commit Graph

192 Commits

Author SHA1 Message Date
Rusty Russell 77094b7df8 lightningd: avoid plugin timer indirection.
Now we know whether the command completed or not, we can correctly
call command_still_pending() if it didn't complete.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-05-05 13:45:17 +09:30
Rusty Russell fc8672061f lightningd: fix false positive on leak detection.
Commit 9aedb0c61f changed this from allocating off `c` to allocating
off NULL, knowing that it's tal_steal() in the callback.  But before
that, it can be detected as a mem leak:

```
    @pytest.fixture
    def teardown_checks(request):
        """A simple fixture to collect errors during teardown.

        We need to collect the errors and raise them as the very last step in the
        fixture tree, otherwise some fixtures may not be cleaned up
        correctly. Require this fixture in all other fixtures that need to either
        cleanup before reporting an error or want to add an error that is to be
        reported.

        """
        errors = TeardownErrors()
        yield errors

        if errors.has_errors():
            # Format a nice list of everything that went wrong and raise an exception
            request.node.has_errors = True
>           raise ValueError(str(errors))
E           ValueError:
E           Node errors:
E           Global errors:
E            - Node /tmp/ltests-iz9y1chb/test_hsmtool_secret_decryption_1/lightning-1/ has memory leaks: [
E               {
E                   "backtrace": [
E                       "ccan/ccan/tal/tal.c:442 (tal_alloc_)",
E                       "lightningd/jsonrpc.c:848 (parse_request)",
E                       "lightningd/jsonrpc.c:941 (read_json)",
E                       "ccan/ccan/io/io.c:59 (next_plan)",
E                       "ccan/ccan/io/io.c:407 (do_plan)",
E                  avis/build/ElementsProject/lightning/lightningd/../plugins/pay
```

Reported-by: @niftynei
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-04-21 13:02:42 -05:00
Rusty Russell deac09950a plugins: make chained hooks have two different callbacks.
One is called on every plugin return, and tells us whether to continue;
the other is only called if every plugin says ok.

This works for things like payload replacement, where we need to process
the results from each plugin, not just the final one!

We should probably turn everything into a chained callback next
release.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-04-16 09:40:39 +09:30
Rusty Russell 9aedb0c61f plugin: simplify hooks calling methods, and make lifetime requirements explicit.
They callback must take ownership of the payload (almost all do, but
now it's explicit).

And since the payload and cb_arg arguments to plugin_hook_call_() are
always identical, make them a single parameter.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-04-16 09:40:39 +09:30
Christian Decker d2688bbaf5 plugin: Unwrap the rpc_command payload
We were nesting like the following:

```json
{"params": {
  "rpc_command": {
    "rpc_command": {
    }
  }
}
```

This is really excessive, so we unwrap once, and now have the following:

```json
{"params": {
  "rpc_command": {
  }
}
```

Still more wrapping than necessary (the method is repeated in the `params`
object), but it's getting closer.

Changelog-Deprecated: JSON-RPC: Removed double wrapping of `rpc_command` payload in `rpc_command` JSON field.

Suggested-by: @fiatjaf
Signed-off-by: Christian Decker <@cdecker>
2020-03-10 11:42:58 +10:30
Rusty Russell 2aad3ffcf8 common: tal_dup_talarr() helper.
This is a common thing to do, so create a macro.

Unfortunately, it still needs the type arg, because the paramter may
be const, and the return cannot be, and C doesn't have a general
"(-const)" cast.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-02-27 14:16:16 +10:30
Rusty Russell df50faba6a lightningd: fix crash when plugin has been unloaded and we abort cmd.
I reproduced this by putting a sleep(60) in the pay plugin, then
'lightning-cli pay', 'lightning-cli plugin stop pay' and then ^C
the `lightning-cli pay`:

2020-02-14T00:33:11.217Z INFO plugin-pay: Killing plugin: pay stopped by lightningd via RPC
2020-02-14T00:33:15.250Z DEBUG lightningd: Still waiting for initial block download
==5157== Invalid read of size 8
==5157==    at 0x12A29C: destroy_jcon (jsonrpc.c:149)
==5157==    by 0x1C6F2A: notify (tal.c:235)
==5157==    by 0x1C7441: del_tree (tal.c:397)
==5157==    by 0x1C7493: del_tree (tal.c:407)
==5157==    by 0x1C77DD: tal_free (tal.c:481)
==5157==    by 0x1B7380: io_close (io.c:450)
==5157==    by 0x1B71A7: do_plan (io.c:401)
==5157==    by 0x1B7214: io_ready (io.c:417)
==5157==    by 0x1B94AC: io_loop (poll.c:445)
==5157==    by 0x1291C9: io_loop_with_timers (io_loop_with_timers.c:24)
==5157==    by 0x12EC7E: main (lightningd.c:928)
==5157==  Address 0x4ebab98 is 40 bytes inside a block of size 88 free'd
==5157==    at 0x483BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==5157==    by 0x1C750F: del_tree (tal.c:416)
==5157==    by 0x1C7493: del_tree (tal.c:407)
==5157==    by 0x1C77DD: tal_free (tal.c:481)
==5157==    by 0x153856: clear_plugin (plugin_control.c:209)
==5157==    by 0x1538FF: plugin_dynamic_stop (plugin_control.c:225)
==5157==    by 0x153C51: json_plugin_control (plugin_control.c:295)
==5157==    by 0x12B4EC: command_exec (jsonrpc.c:588)
==5157==    by 0x12B8AB: rpc_command_hook_callback (jsonrpc.c:679)
==5157==    by 0x154575: plugin_hook_call_ (plugin_hook.c:170)
==5157==    by 0x12BCD3: plugin_hook_call_rpc_command (jsonrpc.c:756)
==5157==    by 0x12BD04: call_rpc_command_hook (jsonrpc.c:764)
==5157==  Block was alloc'd at
==5157==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==5157==    by 0x1C6F98: allocate (tal.c:245)
==5157==    by 0x1C7559: tal_alloc_ (tal.c:423)
==5157==    by 0x15135A: plugin_rpcmethod_add (plugin.c:706)
==5157==    by 0x151600: plugin_rpcmethods_add (plugin.c:756)
==5157==    by 0x151BDD: plugin_parse_getmanifest_response (plugin.c:893)
==5157==    by 0x151C9C: plugin_manifest_cb (plugin.c:915)
==5157==    by 0x14FFB9: plugin_response_handle (plugin.c:258)
==5157==    by 0x150165: plugin_read_json_one (plugin.c:356)
==5157==    by 0x1502BC: plugin_read_json (plugin.c:388)
==5157==    by 0x1B65ED: next_plan (io.c:59)
==5157==    by 0x1B71D2: do_plan (io.c:407)

Fixes: #3509
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-02-15 08:49:18 +10:30
Christian Decker 9a2a09efd6 plugin: Introduce plugin type to allow singleton and chaining
The newly introduced type is used to determine what the call semantics of the
hook are. We have `single` corresponding to the old behavior, as well as
`chain` which allows multiple plugins to register for the hook, and they are
then called sequentially (if all plugins return `{"result": "continue"}`) or
exit the chain if the hook event was handled.
2020-02-11 15:57:22 +10:30
ZmnSCPxj jxPCSnmZ 6e34aa233a lightningd/: Hooks now support a consistent interface for 'no operation'.
Changelog-Changed: The hooks `db_write`, `invoice_payment`, and `rpc_command` now accept `{ "result": "continue" }` to mean "do default action", in addition to `true` (`db_write`), `{}` (`invoice_payment`), and `{"continue": true}` (`rpc_command`). The older "default" indicators are now deprecated and are now recognized only if `--deprecated-apis` is set.
2020-02-04 01:07:59 +00:00
Vasil Dimov 55173a56b7 Use dedicated type for error codes
Before this patch we used `int` for error codes. The problem with
`int` is that we try to pass it to/from wire and the size of `int` is
not defined by the standard. So a sender with 4-byte `int` would write
4 bytes to the wire and a receiver with 2-byte `int` (for example) would
read just 2 bytes from the wire.

To resolve this:

* Introduce an error code type with a known size:
  `typedef s32 errcode_t`.

* Change all error code macros to constants of type `errcode_t`.
  Constants also play better with gdb - it would visualize the name of
  the constant instead of the numeric value.

* Change all functions that take error codes to take the new type
  `errcode_t` instead of `int`.

* Introduce towire / fromwire functions to send / receive the newly added
  type `errcode_t` and use it instead of `towire_int()`.

In addition:

* Remove the now unneeded `towire_int()`.

* Replace a hardcoded error code `-2` with a new constant
  `INVOICE_EXPIRED_DURING_WAIT` (903).

Changelog-Changed: The waitinvoice command would now return error code 903 to designate that the invoice expired during wait, instead of the previous -2
2020-01-31 06:02:47 +00:00
ZmnSCPxj jxPCSnmZ 7f4ed54b46 lightningd/jsonrpc.c: Set JSON-RPC socket permissions by command line.
Changelog-Added: Can now set the permissions on the JSON-RPC socket by `--rpc-file-mode`.
2020-01-27 21:11:57 +01:00
Rusty Russell 30c8db148d lightningd: make sure rpc_command replacement is well-formed.
In particular:
1. It must redirect to an existing command.
2. It must contain method, params and id.

And update the docs to show the id, which is vital.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-12-07 21:26:31 +01:00
Rusty Russell 8b1aa3ef8b lightningd: move basic parameter parsing into common/configdir
lightning-cli is going to need to know what network we're on, so
it will need to parse the config files.  Move the code which does
the initial bootstrap parsing into common, as well as the config
file parsing core.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-11-23 22:42:34 +00:00
Rusty Russell 709c98f539 logging: remove spaces from subsystem names.
Spaces just make life a little harder for everyone.

(Plus, fix documentation: it's 'jsonrpc' not 'json' subsystem).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-11-18 04:50:22 +00:00
Rusty Russell ef7a820ab1 log: make formatting more consistent.
1. Printed form is always "[<nodeid>-]<prefix>: <string>"
2. "jcon fd %i" becomes "jsonrpc #%i".
3. "jsonrpc" log is only used once, and is removed.
4. "database" log prefix is use for db accesses.
5. "lightningd(%i)" becomes simply "lightningd" without the pid.
6. The "lightningd_" prefix is stripped from subd log prefixes, and pid removed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-changed: Logging: formatting made uniform: [NODEID-]SUBSYSTEM: MESSAGE
Changelog-removed: `lightning_` prefixes removed from subdaemon names, including in listpeers `owner` field.
2019-11-18 04:50:22 +00:00
Rusty Russell 86fb54a33b lightningd: remove per-peer log book.
We had a separate logbook for each peer, and copy log entries above
the printable log level into the master logbook.  This didn't always
work well, since we didn't dump it on crash for example.

Keep a single global logbook instead, and remove this infrastructure.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-11-18 04:50:22 +00:00
Rusty Russell e433d4ddc1 lightningd: have logging include an optional node_id for each entry.
A log can have a default node_id, which can be overridden on a per-entry
basis.  This changes the format of logging, so some tests need rework.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-11-18 04:50:22 +00:00
darosior a0df49718a lightningd/jsonrpc: Add a 'rpc_command' hook
The 'rpc_command' hook allows a plugin to take over any RPC command.
It sends the complete JSONRPC request to the plugin, which can then respond
with :
- {'continue'}: executes the command normally
- {'replace': {a_jsonrpc_request}}: replaces the request made
- {'return': {'result': {}}}: send a custom response
- {'return': {'error': {}}}: send a custom error

This way, a plugin can modify (/reimplement) or restrict the usage of
any of `lightningd`'s commands.

Changelog-Added: Plugin: A new plugin hook, `rpc_command` allows a plugin to take over `lightningd` for any RPC command.
2019-11-11 22:30:01 +01:00
trueptolemy 8346d5c353 josn: Move `json_tok_address_scriptpubkey` from lightningd/jsonrpc.c to lightningd/json.c
Its declaration is in lightningd/json.h, so we should move it to lightningd/json.c.
2019-10-09 21:04:16 -05:00
trueptolemy 7db3f1b8a6 json: Rename `json_tok_address_scriptpubkey` to `json_to_address_scriptpubkey`
Our json naming style is like `json_to_***`.
2019-10-09 16:51:42 -05:00
Rusty Russell aca2e4f722 common/memleak: add dynamic hooks for assisting memleak.
Rather than reaching into data structures, let them register their own
callbacks.  This avoids us having to expose "memleak_remove_xxx"
functions, and call them manually.

Under the hood, this is done by having a specially-named tal child of
the thing we want to assist, containing the callback.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-09-06 14:35:01 +02:00
trueptolemy 4929034a40 json: Make payment_hash use `json_add_sha256` 2019-08-21 09:32:21 +08:00
trueptolemy 5f6196a42d cleanup: Use the most common abbreviation of 'ctx' in `json_tok_address_scriptpubkey` 2019-08-21 09:30:50 +08:00
Rusty Russell 4274b9f0af lightingd: increase listen queue on rpc socket.
I suspect multiple plugins trying to connect at the same
time are overrunning the 1-deep listen queue:

From man listen(2):

       The backlog argument defines the maximum length to which the  queue  of
       pending  connections  for sockfd may grow.  If a connection request ar‐
       rives when the queue is full, the client may receive an error  with  an
       indication  of ECONNREFUSED

Fixes: #2922
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-08-10 10:03:07 +00:00
darosior 5fbb15bd59 Document the 'dev' command 2019-08-07 01:50:42 +00:00
darosior f3f33dceb1 lightningd/jsonrpc: Remove unused dev-rhash command code
'dev-rhash' is now part of the 'dev' multiplex command
2019-08-07 01:50:42 +00:00
Rusty Russell 6da420a65b lightning-cli: change default printing in response to "format-hint": "simple".
And set it for 'help <command>'.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-07-28 06:09:56 +00:00
Rusty Russell b03369ea2d common: generalize json_tok_remove.
It assumes the head of the array is the object/array we want to remove from,
but that's not true if we're trying to remove from a sub-object.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-07-28 06:09:56 +00:00
Rusty Russell 39e8e98b49 options: make option registration a single function.
No code changes, just move.

Put all the dev options into the one function, and register (and
comment on) the early args first.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-07-27 05:16:22 +00:00
Karl-Johan Alm 918e130448 add signet support 2019-07-22 16:38:32 -05:00
Rusty Russell fb6870c139 param: implement helpers for multiplex commands.
Our previous param support was a bit limited in this case.

We create a dev- command multiplexer, so we can exercise it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-07-16 21:39:14 +00:00
Rusty Russell ef541afd8a lightningd: free strmap of commands on shutdown.
Indirect leak of 48 byte(s) in 1 object(s) allocated from:
    #0 0x7f4c84ce4448 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55d11b77d270 in strmap_add_ ccan/ccan/strmap/strmap.c:90
    #2 0x55d11b704603 in command_set_usage lightningd/jsonrpc.c:891
    #3 0x55d11b733cb5 in param common/param.c:295
    #4 0x55d11b6f7b37 in json_connect lightningd/connect_control.c:96
    #5 0x55d11b7042ef in setup_command_usage lightningd/jsonrpc.c:841
    #6 0x55d11b70443b in jsonrpc_command_add_perm lightningd/jsonrpc.c:863
    #7 0x55d11b704533 in jsonrpc_setup lightningd/jsonrpc.c:876
    #8 0x55d11b705695 in new_lightningd lightningd/lightningd.c:210
    #9 0x55d11b706062 in main lightningd/lightningd.c:644
    #10 0x7f4c84696b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-06-30 16:41:30 +09:30
Rusty Russell d5bd1682f5 lightningd: free timers on shutdown.
Direct leak of 1024 byte(s) in 2 object(s) allocated from:
    #0 0x7f4c84ce4448 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55d11b782c96 in timer_default_alloc ccan/ccan/timer/timer.c:16
    #2 0x55d11b7832b7 in add_level ccan/ccan/timer/timer.c:166
    #3 0x55d11b783864 in timer_fast_forward ccan/ccan/timer/timer.c:334
    #4 0x55d11b78396a in timers_expire ccan/ccan/timer/timer.c:359
    #5 0x55d11b774993 in io_loop ccan/ccan/io/poll.c:395
    #6 0x55d11b72322f in plugins_init lightningd/plugin.c:1013
    #7 0x55d11b7060ea in main lightningd/lightningd.c:664
    #8 0x7f4c84696b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)

To fix this, we actually make 'ld->timers' a pointer, so we can clean
it up last of all.  We can't free it before ld, because that causes
timers to be destroyed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-06-30 16:41:30 +09:30
Rusty Russell 841fba7295 lightningd: restore ' ' before '}' for older pylightning.
It needs this in compat mode to detect old (pre-0.6.3) end of JSON.
But it always does the first command in compat mode.

This was never really reliable, since the first command could be to
a plugin for which we simply pass through the JSON (though, carefully
appending the expected '\n\n' if not already there).

Reported-by: @laanwj
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-06-17 21:46:25 +02:00
Rusty Russell c6ec9443b9 jsonrpc: don't return "stop" until we actually have freed resources.
This is a painpoint with testing, that there's a noticable delay between
"Shutting down" from lightning-cli and being able to restart lightningd.

This fixes that by creating a canned response for this case, which is
simply written out immediately before exit.  At this point, the pidfile
has been deleted, the sockets have been closed, and the database
has been closed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-06-12 02:00:15 +00:00
Rusty Russell 7f75043ab2 lightningd: tighten interal json_stream API.
Move it closer to ccan/json_out, in preparation for using that as a
replacement.

In particular:

1. Add a 'quote' field in json_add_member.
2. json_add_member now always escapes if 'quote' is true.
3. json_member_direct is exposed to allow avoiding of escaping.
4. json_add_hex can use this, so no longer needs to be in json_stream.c.
5. We don't make JSON manually, but always use helpers.
6. We now flush the stream (wake reader) only when we close it, or mark
   command as pending.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-06-12 02:00:15 +00:00
Rusty Russell bb7bbd03c5 lightningd: have json_stream_success start the "result" object.
"result" should always be an object (so that we can add new fields),
so make that implicit in json_stream_success.

This makes our primitives well-formed: we previously used NULL as our
fieldname when calling the first json_object_start, which is a hack
since we're actually in an object and the fieldname is 'result' (which
was already written by json_object_start).

There were only two cases which didn't do this:
1. dev-memdump returned an array.  No API guarantees on this.
2. shutdown returned a string.

I temporarily made shutdown return an empty object, which shouldn't
break anything, but I want to fix that later anyway.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-06-12 02:00:15 +00:00
Rusty Russell 220449e1cd ccan: import ccan/json_out and ccan/json_escape.
These are generalized from our internal implementations.

The main difference is that 'struct json_escaped' is now 'struct
json_escape', so we replace that immediately.

The difference between lightningd's json-writing ringbuffer and the
more generic ccan/json_out is that the latter has a better API and
handles escaping transparently if something slips through (though
it does offer direct accessors so you can mess things up yourself!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-06-12 02:00:15 +00:00
darosior 323adb467a jsonrpc: Add a category field to commands.
A new string field is added to the command structure and is specified at the creation of each native command, and in the JSON created by 'json_add_help_command()'.
2019-06-03 00:02:25 +00:00
Simon Vrouwe db57d9c5d2 lightningd: suppress IO_OUT logging for getlog command
Before this, the response of `getlog io` blew up quickly
when called multiple times.
2019-05-26 23:53:20 +00:00
darosior f65eecee27 Rpc: sort help output by command name 2019-05-21 09:16:39 +00:00
Christian Decker 7c3e441cc8 json-rpc: Use chainparams when parsing bech32 addresses
We were checking against a hard-coded list, now we return a valid address only
if the hrp matches the chainparams.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
2019-05-10 23:07:49 +00:00
Christian Decker aa9284eaa3 base58: Simplified the address parsing
We were deciding whether an address is a testnet address or not in the parser,
and then checking whether it matches our expectation outside as well. This
just returns the address version instead, and still checks it against our
expectation, but without having the parser need to know about address types.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
2019-05-01 12:37:30 +02:00
Rusty Russell 2632cc3f34 lightningd/json: make wallet_tx functions take amount_sat.
Using param_tok is generally deprecated, as it doesn't give any sanity checking
for the JSON 'check' command.  So make param_wtx usable directly, and
also make it have a struct amount_sat.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-02-21 03:44:44 +00:00
Rusty Russell 53423e8a55 lightningd: re-enable IO logging for JSON output.
Hex format is terrible, but sometimes it's the only way to tell WTF is
going on.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-02-21 00:44:57 +00:00
Rusty Russell 5770e0c700 jsonrpc: probe sites for usage information once, at start.
We store it in a strmap.  This means we call the jsonrpc handler earlier,
so all callers need to call param() before they do anything else; only
json_listaddrs and json_help needed fixing.

Plugins still use '[usage]' for now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-02-07 20:33:50 +00:00
Rusty Russell dabdefefae jsonrpc: populate ld->jsonrpc ourselves, so we can use it.
Next patch will call commands to get usage inside jsonrpc_new(): to do
this it will need access to ld->jsonrpc, so we can't use the current
pattern.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-02-07 20:33:50 +00:00
Rusty Russell cc76416447 jsonrpc: use tal destructor to remove json commands when required.
This fixes a bug with a plugin duplicating an existing name
where we'd crash, too.

This doesn't work for builtins, which aren't tal objects, so
create a separate path for them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-02-07 20:33:50 +00:00
Rusty Russell da355284de jsonrpc: help, even for a single item, should be in an array.
This is what we do for every other can-be-single JSON API.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-02-07 20:33:50 +00:00
Christian Decker 5d05694920 json-rpc: Remove double-quoting on errors in JSON-RPC
The use of `json_tok_full_len` and `json_tok_full` in addition to
single quotes will result in double quoting, which is really weird. I
opted to single quoting using `'` instead which does not need to be
escaped.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
2019-01-29 00:50:09 +00:00