Skip to content

Added output_witscript field to sign_remote_commitment_tx #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 122 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
3c038e4
hsm encryption: don't include '\n' when deriving the encryption key
darosior Oct 16, 2019
f89d7c1
hsm encryption: correct salt length
darosior Oct 16, 2019
79e2c3f
gossipd: don't crash if we're forced to discard corrupt gossip store.
rustyrussell Oct 17, 2019
4083e07
configure: test XChaCha20Poly1305 stream state for HAVE_GOOD_LIBSODIUM
darosior Oct 17, 2019
2ab5621
json-rpc: Fix spacing issue in error report
cdecker Oct 14, 2019
894627a
db: Fix report and commit order for DB transactions
cdecker Oct 14, 2019
12f40f2
db: Add _or_default variants for column accesses
cdecker Oct 17, 2019
ec8d774
db: Make column access way more pedantic
cdecker Oct 17, 2019
0a641c9
pytest: Don't assume UTXO ordering when selecting coins
cdecker Oct 17, 2019
6b1b99d
release 0.7.3
niftynei Oct 17, 2019
3c3d7e2
connectd: Do not clobber the for-variable when resolving over DNS
cdecker Oct 18, 2019
d35ec90
elements: Work around libwally getting upset with helpful flags
cdecker Oct 18, 2019
be49a59
elements: Do not get upset if we see a confidential asset or value
cdecker Oct 18, 2019
79df507
gossipd: exclude early blocks from random probes.
rustyrussell Oct 18, 2019
4b33b50
gossipd: ask a peer for *every* channel it knows on startup.
rustyrussell Oct 18, 2019
78c9d69
gossipd: makes probe larger.
rustyrussell Oct 18, 2019
f5e4a30
add gettext to build release script
niftynei Oct 18, 2019
712595f
db: Wire in the logs into the database so we can give feedback
cdecker Oct 21, 2019
1ecad0c
db: Maybe a bit too pedantic?
cdecker Oct 20, 2019
396e822
db: Add a migration to set received_time on forwards in rare cases
cdecker Oct 20, 2019
21c8eaf
pytest: Check for null access warnings in tests
cdecker Oct 20, 2019
e16ac08
Change order of paragraphs in manpage of fundchannel
kristapsk Oct 18, 2019
bc430cc
gossipd: fix false-positive memleak detection in pending_node_map.
rustyrussell Oct 15, 2019
2801d98
pytest: allow bad gossip in test_pay_direct.
rustyrussell Oct 15, 2019
35bbba6
Revert "gossipd: query_messages: fail the connection if peer says it …
rustyrussell Oct 20, 2019
d5706b8
rc3
niftynei Oct 18, 2019
4d0c2e9
common: remove spammy debug msg.
rustyrussell Oct 22, 2019
0985c6e
Fix build fail on 32bit OS.
arowser Oct 21, 2019
f657146
configure: fix FreeBSD which has sqlite3 in /usr/local
rustyrussell Oct 28, 2019
61e1d64
pytest: stress fee_update code, trigger bug.
rustyrussell Oct 28, 2019
21d2cc6
lightningd: apply feerate changes correctly.
rustyrussell Oct 28, 2019
0cee553
remove reverted feature desc
niftynei Oct 28, 2019
5bc2de8
update version to 0.7.3
niftynei Oct 28, 2019
8a9650c
pylightning: reorder imports
darosior Oct 14, 2019
f690c35
cleanup lightning-pay
darosior Oct 14, 2019
35ee800
json-rpc: show lightning-dir in getinfo
gorazdko Oct 25, 2019
90667a2
devtools/.gitignore: Ignore create-gossipstore checkchannels mkquery …
arowser Oct 28, 2019
d1060e1
.gitignore: Remove devtools/create-gossipstore
arowser Oct 28, 2019
cd89446
remove repeat install dependencies
arowser Oct 29, 2019
67ce27a
remove repeat line in doc/requirements.txt
arowser Oct 29, 2019
a3851f2
wallet: always create signatures with low r-value
gorazdko Oct 28, 2019
6fa965c
CHANGELOG.md: reset to Unreleased.
rustyrussell Oct 30, 2019
6138340
pay: Return error when trying to pay to an invoice from unkown or dif…
jtimon Sep 25, 2019
82a2c6b
change psycopg2 to psycopg2-binary
arowser Nov 1, 2019
c581fd9
releases: update with niftynei's notes from release 0.7.3
niftynei Oct 28, 2019
16fde5c
releases: break up first git tag for verification purposes
niftynei Oct 28, 2019
7374134
doc: add reminder to close out Milestone to Making-Releases
niftynei Oct 30, 2019
fe17acf
TAGS: reformat to fix when PRINTF_FMT() used.
rustyrussell Oct 31, 2019
4c2f51c
Fix syntax error in sql-rewrite.py
sgeisler Nov 2, 2019
04403ed
pytest: fix flaky 'Bad gossip' error in test_block_backfill
rustyrussell Oct 31, 2019
2d8e936
pytest: prepare test_gossip_timestamp_filter to be spammed.
rustyrussell Nov 4, 2019
bb370e6
gossipd: handle a "push" marker into the gossip_store.
rustyrussell Nov 4, 2019
7f45e55
gossipd: set the push marker for our own messages.
rustyrussell Nov 4, 2019
f0f47ce
warnings: if behind blockchain, don't show cannot afford
niftynei Oct 29, 2019
181e0d4
test: amend 'behind sync' tests
niftynei Nov 1, 2019
f4d888e
lightningd: obscure sensitive bitcoin args when bitcoind unreachable.
rustyrussell Nov 5, 2019
de65369
channeld: if we can't restore HTLCs, log at level broken, not debug.
rustyrussell Nov 4, 2019
7b6a1c8
pytest: add test for bug found by Travis
rustyrussell Nov 4, 2019
c96cee9
channeld: fix invalid assumption in htlc restore.
rustyrussell Nov 5, 2019
30634aa
pytest: fix test_gossip_notices_close where we really do inject bad g…
rustyrussell Nov 6, 2019
40d34fe
pytest: clean up test_gossip_notices_close now that gossipwith has mo…
rustyrussell Nov 6, 2019
abe7133
gossipd: use in_txout_failures to do lookup in channel_announcement.
rustyrussell Nov 6, 2019
5a8677e
gossipd: add txout_failure when a close is seen.
rustyrussell Nov 6, 2019
a70f2dc
pytest: two more timeouts on Travis.
rustyrussell Nov 6, 2019
122fc1f
config file: fix line count in error message
gorazdko Nov 7, 2019
290b4d6
changelog: Add a tool to extract changelog entries from the commits
cdecker Nov 2, 2019
5766231
pay: restore payment value randomization through shadow routing
darosior Nov 4, 2019
16f5af0
common/json: add a helper for json to u16
darosior Nov 6, 2019
f3d3049
pay: add a dev-only parameter to deactivate shadow routing
darosior Nov 4, 2019
7dac7a8
pytest: deactivate shadow routing for some tests that use 'pay'
darosior Nov 2, 2019
2081237
pytest: test shadow routing in pay plugin
darosior Nov 2, 2019
c62f0cb
sphinx: fix potential data leak.
rustyrussell Nov 6, 2019
5df9e5b
gossipd: allow node_announcements and channel_announcements with unsu…
rustyrussell Nov 6, 2019
187d2e0
We state not to do 'any local DNS' if --always-use-proxy flag is set,…
Saibato Nov 8, 2019
dd10b54
lightningd/json: Add a json helper to append any jsmn token to a stream
darosior Sep 26, 2019
a0df497
lightningd/jsonrpc: Add a 'rpc_command' hook
darosior Sep 27, 2019
95c6513
pytest: test the 'rpc_command' hook
darosior Sep 9, 2019
6427ccb
Document the 'rpc_command' hook
darosior Nov 3, 2019
1171b5d
pytest: clean up hsm_secret_encryption test
darosior Oct 16, 2019
04762a1
tools/hsmtool: add a tool for decrypting hsm_secret
darosior Oct 19, 2019
dccad77
tools/hsmtool: add a tool for encrypting hsm_secret
darosior Oct 19, 2019
f97d548
pytest: test hsm_secret management with hsmtool
darosior Oct 19, 2019
c61b60b
README: move hsm_secret encryption infos into a dedicated part
darosior Oct 22, 2019
de91eda
hsmtool: add a tool to dump commitment points and secrets
darosior Oct 22, 2019
81f7978
pyln: Migrate implementation from pylightning to pyln-client
cdecker Oct 26, 2019
a2a3d33
pyln-testing: Copy basic support infrastructure into pyln.testing
cdecker Oct 26, 2019
f6a016c
pytest: Consolidate access to environment variables
cdecker Oct 27, 2019
b31defd
make: Add in-tree pyln-testing to python path
cdecker Oct 27, 2019
b7e7e53
pytest: Migrate `env` to pyln-testing
cdecker Oct 27, 2019
d58339b
pytest: Migrate to in-tree pyln-testing
cdecker Oct 28, 2019
53a2789
pyln: Default to DEVELOPER=0 when running outside of tree
cdecker Oct 28, 2019
bc9b1c4
pyln: Move RPC and daemon instantiation into the LightningNode
cdecker Oct 28, 2019
9378be7
pyln: Allow users to override the LightningNode class
cdecker Oct 30, 2019
7679f25
devtools: fix mkcommit crash.
rustyrussell Nov 12, 2019
604c30b
Started on hsmd python embed
ksedgwic Oct 19, 2019
b912ee9
Fixed py_none syntax.
ksedgwic Oct 19, 2019
76a4795
Added handle_ecdh, handle_get_channel_basepoints, handle_get_per_comm…
ksedgwic Oct 19, 2019
7056f40
Added handle_pass_client_hsmfd, flushed debugging
ksedgwic Oct 22, 2019
6b8f1f9
Duplicated handle_ecdh in hsmd.py with exfiltrated secret.
ksedgwic Oct 22, 2019
7dcdb71
Improved error handling
ksedgwic Oct 25, 2019
f75b14d
Added stub call
ksedgwic Oct 26, 2019
293410b
Backed handle_ecdh path out to restore functionality w/o liposig server.
ksedgwic Oct 30, 2019
07d4210
Plumbed SignWithdrawalTx in prep for LiPoSig
ksedgwic Oct 31, 2019
4607db2
Commented out exit on ecdh shared secret mismatch
ksedgwic Nov 3, 2019
928ade3
Added python translation of c-lightning bitcoin_tx
ksedgwic Nov 4, 2019
96420f4
Started formatting raw tx.
ksedgwic Nov 5, 2019
1781df8
Progress on SignWithdrawalTx
ksedgwic Nov 5, 2019
0e2b486
Fixed stdout_exceptions wrapper.
ksedgwic Nov 5, 2019
e22bd9a
populate KeyLocator
Nov 7, 2019
8d332d6
Fixed debug print of the raw signatures.
ksedgwic Nov 8, 2019
b3c6b24
populate input values
Nov 8, 2019
473c104
Added self_node_id to all hsmd protocol requests.
ksedgwic Nov 11, 2019
2d6843e
Framed SignRemoteCommitmentTx
ksedgwic Nov 12, 2019
5162afa
Tweaks to make running as server work.
ksedgwic Nov 12, 2019
c91b578
Added InitHSM
ksedgwic Nov 12, 2019
972f05c
Debug log self_node_id
ksedgwic Nov 12, 2019
039124c
Implemented ECDH
ksedgwic Nov 13, 2019
713c810
Added SignRemoteHTLCTx and SignMutualCloseTx
ksedgwic Nov 14, 2019
cb8d226
Added logging of secrets for now.
ksedgwic Nov 15, 2019
94d60c1
Added PassClientHSMFd and GetPerCommitmentPoint
ksedgwic Nov 15, 2019
bf6fa28
Normalized channel_nonce field order and naming.
ksedgwic Nov 15, 2019
f0a0703
Logging get_per_commitment_point fields.
ksedgwic Nov 16, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,3 @@ contrib/pylightning/pylightning.egg-info/
contrib/pyln-*/build/
contrib/pyln-*/dist/
contrib/pyln-*/pyln_*.egg-info/
devtools/create-gossipstore
27 changes: 24 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.7.3rc2] - 2019-10-15: T.B.D.
## [Unreleased]

### Added

### Changed

### Deprecated

Note: You should always set `allow-deprecated-apis=false` to test for changes.

### Removed

### Fixed

### Security


## [0.7.3] - 2019-10-18: "Bitcoin's Proof of Stake"

This release named by @trueptolemy.

### Added

Expand Down Expand Up @@ -36,7 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- JSON API: The `plugin` command now returns on error. A timeout of 20 seconds is added to `start` and `startdir` subcommands at the end of which the plugin is errored if it did not complete the handshake with `lightningd`.
- JSON API: The `plugin` command does not allow to start static plugins after `lightningd` startup anymore.
- Protocol: We now push our own gossip to all peers, independent of their filter.
- Protocol: Now follows spec in responses to short channel id queries on unknown chainhashes; correspondingly, disconnects from peers that signal they do not maintain up-to-date information for the requested chain.
- Protocol: Now follows spec in responses to short channel id queries on unknown chainhashes
- Tor: We default now with autotor to generate if possible temporary ED25519-V3 onions. You can use new option `enable-autotor-v2-mode` to fallback to V2 RSA1024 mode.

### Deprecated
Expand All @@ -57,6 +76,7 @@ Note: You should always set `allow-deprecated-apis=false` to test for changes.

### Fixed

- Fixed bogus "Bad commit_sig signature" which caused channel closures when reconnecting after updating fees under simultaneous bidirectional traffic.
- Relative `--lightning_dir` is now working again.
- Build: MacOS now builds again (missing pwritev).

Expand Down Expand Up @@ -493,7 +513,8 @@ There predate the BOLT specifications, and are only of vague historic interest:
6. [0.5.1] - 2016-10-21
7. [0.5.2] - 2016-11-21: "Bitcoin Savings & Trust Daily Interest II"

[Unreleased]: https://github.com/ElementsProject/lightning/compare/v0.7.2.1...HEAD
[Unreleased]: https://github.com/ElementsProject/lightning/compare/v0.7.3...HEAD
[0.7.3]: https://github.com/ElementsProject/lightning/releases/tag/v0.7.3
[0.7.2.1]: https://github.com/ElementsProject/lightning/releases/tag/v0.7.2.1
[0.7.1]: https://github.com/ElementsProject/lightning/releases/tag/v0.7.1
[0.7.0]: https://github.com/ElementsProject/lightning/releases/tag/v0.7.0
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ ifeq ($(PYTEST),)
exit 1
else
# Explicitly hand DEVELOPER and VALGRIND so you can override on make cmd line.
PYTHONPATH=`pwd`/contrib/pylightning:$$PYTHONPATH TEST_DEBUG=1 DEVELOPER=$(DEVELOPER) VALGRIND=$(VALGRIND) $(PYTEST) tests/ $(PYTEST_OPTS)
PYTHONPATH=`pwd`/contrib/pyln-client:`pwd`/contrib/pyln-testing:$$PYTHONPATH TEST_DEBUG=1 DEVELOPER=$(DEVELOPER) VALGRIND=$(VALGRIND) $(PYTEST) tests/ $(PYTEST_OPTS)
endif

# Keep includes in alpha order.
Expand Down Expand Up @@ -316,7 +316,7 @@ check-python:
@# W503: line break before binary operator
@flake8 --ignore=E501,E731,W503 --exclude=contrib/pylightning/lightning/__init__.py ${PYSRC}

PYTHONPATH=contrib/pylightning:$$PYTHONPATH $(PYTEST) contrib/pylightning/
PYTHONPATH=contrib/pyln-client:$$PYTHONPATH $(PYTEST) contrib/pyln-client/

check-includes:
@tools/check-includes.sh
Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ c-lightning is a lighweight, highly customizable and [standard compliant][std] i
* [Configuration File](#configuration-file)
* [Further Information](#further-information)
* [Pruning](#pruning)
* [HD wallet encryption](#hd-wallet-encryption)
* [Developers](#developers)

## Project Status
Expand Down Expand Up @@ -102,8 +103,6 @@ Once you've started for the first time, there's a script called
`contrib/bootstrap-node.sh` which will connect you to other nodes on
the lightning network.

You can encrypt the BIP32 root seed (what is stored in `hsm_secret`) by passing the `--encrypted-hsm` startup argument. You can start `lightningd` with `--encrypted-hsm` on an already existing `lightning-dir` (with a not encrypted `hsm_secret`). If you pass that option, you __will not__ be able to start `lightningd` (with the same wallet) again without the password, so please beware with your password management. Also beware of not feeling too safe with an encrypted `hsm_secret`: unlike for `bitcoind` where the wallet encryption can restrict the usage of some RPC command, `lightningd` always need to access keys from the wallet which is thus __not locked__ (yet), even with an encrypted BIP32 master seed.

There are also numerous plugins available for c-lightning which add
capabilities: in particular there's a collection at:

Expand All @@ -112,6 +111,9 @@ capabilities: in particular there's a collection at:
Including [helpme][helpme-github] which guides you through setting up
your first channels and customizing your node.

For a less reckless experience, you can encrypt the HD wallet seed:
see [HD wallet encryption](#hd-wallet-encryption).

You can also chat to other users at [#c-lightning @ freenode.net][irc2];
we are always happy to help you get started!

Expand Down Expand Up @@ -202,6 +204,12 @@ If `bitcoind` prunes a block that c-lightning has not processed yet, e.g., c-lig
In order to avoid this situation you should be monitoring the gap between c-lightning's blockheight using `lightning-cli getinfo` and `bitcoind`'s blockheight using `bitcoin-cli getblockchaininfo`.
If the two blockheights drift apart it might be necessary to intervene.

### HD wallet encryption

You can encrypt the `hsm_secret` content (which is used to derive the HD wallet's master key) by passing the `--encrypted-hsm` startup argument, or by using the `hsmtool` (which you can find in the `tool/` directory at the root of this repo) with the `encrypt` method. You can unencrypt an encrypted `hsm_secret` using the `hsmtool` with the `decrypt` method.

If you encrypt your `hsm_secret`, you will have to pass the `--encrypted-hsm` startup option to `lightningd`. Once your `hsm_secret` is encrypted, you __will not__ be able to access your funds without your password, so please beware with your password management. Also beware of not feeling too safe with an encrypted `hsm_secret`: unlike for `bitcoind` where the wallet encryption can restrict the usage of some RPC command, `lightningd` always need to access keys from the wallet which is thus __not locked__ (yet), even with an encrypted BIP32 master seed.

### Developers

Developers wishing to contribute should start with the developer guide [here](doc/HACKING.md).
Expand Down
32 changes: 27 additions & 5 deletions bitcoin/signature.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,38 @@ static void dump_tx(const char *msg UNUSED,
}
#endif

/* Taken from https://github.com/bitcoin/bitcoin/blob/master/src/key.cpp */
/* Check that the sig has a low R value and will be less than 71 bytes */
static bool sig_has_low_r(const secp256k1_ecdsa_signature* sig)
{
unsigned char compact_sig[64];
secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, compact_sig, sig);

/* In DER serialization, all values are interpreted as big-endian, signed
* integers. The highest bit in the integer indicates its signed-ness; 0 is
* positive, 1 is negative. When the value is interpreted as a negative
* integer, it must be converted to a positive value by prepending a 0x00
* byte so that the highest bit is 0. We can avoid this prepending by
* ensuring that our highest bit is always 0, and thus we must check that
* the first byte is less than 0x80. */
return compact_sig[0] < 0x80;
}

void sign_hash(const struct privkey *privkey,
const struct sha256_double *h,
secp256k1_ecdsa_signature *s)
{
bool ok;

ok = secp256k1_ecdsa_sign(secp256k1_ctx,
s,
h->sha.u.u8,
privkey->secret.data, NULL, NULL);
unsigned char extra_entropy[32] = {0};

/* Grind for low R */
do {
ok = secp256k1_ecdsa_sign(secp256k1_ctx,
s,
h->sha.u.u8,
privkey->secret.data, NULL, extra_entropy);
((u32 *)extra_entropy)[0]++;
} while (!sig_has_low_r(s));
assert(ok);
}

Expand Down
2 changes: 1 addition & 1 deletion bitcoin/signature.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct bitcoin_signature {
};

/**
* sign_hash - produce a raw secp256k1 signature.
* sign_hash - produce a raw secp256k1 signature (with low R value).
* @p: secret key
* @h: hash to sign.
* @sig: signature to fill in and return.
Expand Down
26 changes: 13 additions & 13 deletions bitcoin/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,6 @@ bool bitcoin_tx_check(const struct bitcoin_tx *tx)
if (wally_tx_get_length(tx->wtx, flags, &written) != WALLY_OK)
return false;

if (chainparams->is_elements) {
flags |= WALLY_TX_FLAG_USE_ELEMENTS;
}

newtx = tal_arr(tmpctx, u8, written);
if (wally_tx_to_bytes(tx->wtx, flags, newtx, written, &written) !=
WALLY_OK)
Expand Down Expand Up @@ -208,6 +204,8 @@ const u8 *bitcoin_tx_output_get_script(const tal_t *ctx,
return res;
}

/* FIXME(cdecker) Make the caller pass in a reference to amount_asset, and
* return false if unintelligible/encrypted. (WARN UNUSED). */
struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx,
int outnum)
{
Expand All @@ -220,13 +218,18 @@ struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx,
output = &tx->wtx->outputs[outnum];

if (chainparams->is_elements) {
/* We currently only support v1 asset tags */
assert(output->asset_len == sizeof(amount.asset) &&
output->asset[0] == 0x01);
assert(output->asset_len == sizeof(amount.asset));
memcpy(&amount.asset, output->asset, sizeof(amount.asset));
memcpy(&raw, output->value + 1, sizeof(raw));
amount.value = be64_to_cpu(raw);

/* We currently only support explicit value asset tags, others
* are confidential, so don't even try to assign a value to
* it. */
if (output->asset[0] == 0x01) {
memcpy(&raw, output->value + 1, sizeof(raw));
amount.value = be64_to_cpu(raw);
} else {
amount.value = 0;
}
} else {
/* Do not assign amount.asset, we should never touch it in
* non-elements scenarios. */
Expand Down Expand Up @@ -319,10 +322,7 @@ static void push_tx(const struct bitcoin_tx *tx,
if (bip144 && uses_witness(tx))
flag |= WALLY_TX_FLAG_USE_WITNESS;

if (chainparams->is_elements)
flag |= WALLY_TX_FLAG_USE_ELEMENTS;

res = wally_tx_get_length(tx->wtx, flag & WALLY_TX_FLAG_USE_WITNESS, &len);
res = wally_tx_get_length(tx->wtx, flag, &len);
assert(res == WALLY_OK);
serialized = tal_arr(tmpctx, u8, len);

Expand Down
4 changes: 2 additions & 2 deletions ccan/ccan/json_out/json_out.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ bool json_out_end(struct json_out *jout, char type);
* If the resulting string requires escaping, and @quote is true, we
* call json_escape().
*/
PRINTF_FMT(4,5)
bool json_out_add(struct json_out *jout,
const char *fieldname,
bool quote,
const char *fmt, ...);
const char *fmt, ...)
PRINTF_FMT(4,5);

/**
* json_out_addv - add a formatted member (vararg variant)
Expand Down
Loading