Update ccan/structeq.

structeq() is too dangerous: if a structure has padding, it can fail
silently.

The new ccan/structeq instead provides a macro to define foo_eq(),
which does the right thing in case of padding (which none of our
structures currently have anyway).

Upgrade ccan, and use it everywhere.  Except run-peer-wire.c, which
is only testing code and can use raw memcmp(): valgrind will tell us
if padding exists.

Interestingly, we still declared short_channel_id_eq, even though
we didn't define it any more!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-07-04 15:00:02 +09:30 committed by Christian Decker
parent 4a1ca0fb99
commit fed5a117e7
44 changed files with 172 additions and 140 deletions

View File

@ -4,12 +4,15 @@
#include "bitcoin/shadouble.h"
#include <ccan/endian/endian.h>
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/tal.h>
#include <stdbool.h>
struct bitcoin_blkid {
struct sha256_double shad;
};
/* Define bitcoin_blkid_eq (no padding) */
STRUCTEQ_DEF(bitcoin_blkid, 0, shad.sha.u);
struct bitcoin_block_hdr {
le32 version;

View File

@ -2,8 +2,12 @@
#define LIGHTNING_BITCOIN_PREIMAGE_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
struct preimage {
u8 r[32];
};
/* Define preimage_eq */
STRUCTEQ_DEF(preimage, 0, r);
#endif /* LIGHTNING_BITCOIN_PREIMAGE_H */

View File

@ -2,11 +2,14 @@
#define LIGHTNING_BITCOIN_PRIVKEY_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
/* General 256-bit secret, which must be private. Used in various places. */
struct secret {
u8 data[32];
};
/* Define secret_eq */
STRUCTEQ_DEF(secret, 0, data);
/* This is a private key. Keep it secret. */
struct privkey {

View File

@ -3,7 +3,6 @@
#include <assert.h>
#include <ccan/mem/mem.h>
#include <ccan/str/hex/hex.h>
#include <ccan/structeq/structeq.h>
#include <common/type_to_string.h>
#include <common/utils.h>
@ -61,6 +60,7 @@ char *pubkey_to_hexstr(const tal_t *ctx, const struct pubkey *key)
pubkey_to_der(der, key);
return tal_hexstr(ctx, der, sizeof(der));
}
REGISTER_TYPE_TO_STRING(pubkey, pubkey_to_hexstr);
char *secp256k1_pubkey_to_hexstr(const tal_t *ctx, const secp256k1_pubkey *key)
{
@ -74,13 +74,6 @@ char *secp256k1_pubkey_to_hexstr(const tal_t *ctx, const secp256k1_pubkey *key)
}
REGISTER_TYPE_TO_STRING(secp256k1_pubkey, secp256k1_pubkey_to_hexstr);
bool pubkey_eq(const struct pubkey *a, const struct pubkey *b)
{
return structeq(&a->pubkey, &b->pubkey);
}
REGISTER_TYPE_TO_STRING(pubkey, pubkey_to_hexstr);
int pubkey_cmp(const struct pubkey *a, const struct pubkey *b)
{
u8 keya[33], keyb[33];

View File

@ -4,6 +4,7 @@
#include <ccan/crypto/ripemd160/ripemd160.h>
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/tal.h>
#include <secp256k1.h>
@ -15,6 +16,8 @@ struct pubkey {
/* Unpacked pubkey (as used by libsecp256k1 internally) */
secp256k1_pubkey pubkey;
};
/* Define pubkey_eq (no padding) */
STRUCTEQ_DEF(pubkey, 0, pubkey.data);
/* Convert from hex string of DER (scriptPubKey from validateaddress) */
bool pubkey_from_hexstr(const char *derstr, size_t derlen, struct pubkey *key);
@ -35,9 +38,6 @@ bool pubkey_from_der(const u8 *der, size_t len, struct pubkey *key);
/* Pubkey to DER encoding: must be valid pubkey. */
void pubkey_to_der(u8 der[PUBKEY_DER_LEN], const struct pubkey *key);
/* Are these keys equal? */
bool pubkey_eq(const struct pubkey *a, const struct pubkey *b);
/* Compare the keys `a` and `b`. Return <0 if `a`<`b`, 0 if equal and >0 otherwise */
int pubkey_cmp(const struct pubkey *a, const struct pubkey *b);

View File

@ -2,18 +2,18 @@
#define LIGHTNING_BITCOIN_SHORT_CHANNEL_ID_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/tal.h>
#include <stdbool.h>
#include <stddef.h>
/* Short Channel ID is composed of 3 bytes for the block height, 3
* bytes of tx index in block and 2 bytes of output index. The
* bitfield is mainly for unit tests where it is nice to be able to
* just memset them and not have to take care about the extra byte for
* u32 */
* bytes of tx index in block and 2 bytes of output index. */
struct short_channel_id {
u64 u64;
};
/* Define short_channel_id_eq (no padding) */
STRUCTEQ_DEF(short_channel_id, 0, u64);
static inline u32 short_channel_id_blocknum(const struct short_channel_id *scid)
{

View File

@ -5,11 +5,14 @@
#include "signature.h"
#include "varint.h"
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/tal.h>
struct bitcoin_txid {
struct sha256_double shad;
};
/* Define bitcoin_txid_eq */
STRUCTEQ_DEF(bitcoin_txid, 0, shad.sha.u);
struct bitcoin_tx {
u32 version;

View File

@ -1,3 +1,3 @@
CCAN imported from http://ccodearchive.net.
CCAN version: init-2434-gac8694de
CCAN version: init-2435-g92be2eff

View File

@ -116,6 +116,8 @@ bool shachain_add_hash(struct shachain *chain,
*
* Example:
* #include <ccan/structeq/structeq.h>
* // Defines sha256_eq
* STRUCTEQ_DEF(sha256, 0, u);
*
* static void next_hash(const struct sha256 *hash)
* {
@ -127,7 +129,7 @@ bool shachain_add_hash(struct shachain *chain,
* else {
* struct sha256 check;
* assert(shachain_get_hash(&chain, index+1, &check));
* assert(structeq(&check, hash));
* assert(sha256_eq(&check, hash));
* }
* }
*/

View File

@ -1 +1 @@
../../licenses/CC0
../../licenses/BSD-MIT

View File

@ -6,9 +6,11 @@
* structeq - bitwise comparison of structs.
*
* This is a replacement for memcmp, which checks the argument types are the
* same.
* same, and takes into account padding in the structure. When there is no
* padding, it becomes a memcmp at compile time (assuming a
* constant-optimizing compiler).
*
* License: CC0 (Public domain)
* License: BSD-MIT
* Author: Rusty Russell <rusty@rustcorp.com.au>
*
* Example:
@ -19,26 +21,22 @@
* struct mydata {
* int start, end;
* };
* // Defines mydata_eq(a, b)
* STRUCTEQ_DEF(mydata, 0, start, end);
*
* int main(void)
* {
* struct mydata a, b;
*
* // No padding in struct, otherwise this doesn't work!
* BUILD_ASSERT(sizeof(a) == sizeof(a.start) + sizeof(a.end));
*
* a.start = 100;
* a.end = 101;
*
* b.start = 100;
* b.end = 101;
*
* // They are equal.
* assert(structeq(&a, &b));
* assert(mydata_eq(&a, &b));
*
* b.end++;
* // Now they are not.
* assert(!structeq(&a, &b));
* assert(!mydata_eq(&a, &b));
*
* return 0;
* }
@ -50,6 +48,8 @@ int main(int argc, char *argv[])
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/build_assert\n");
printf("ccan/cppmagic\n");
return 0;
}

View File

@ -1,17 +1,45 @@
/* CC0 (Public domain) - see LICENSE file for details */
/* MIT (BSD) license - see LICENSE file for details */
#ifndef CCAN_STRUCTEQ_H
#define CCAN_STRUCTEQ_H
#include <ccan/build_assert/build_assert.h>
#include <ccan/cppmagic/cppmagic.h>
#include <string.h>
#include <stdbool.h>
/**
* structeq - are two structures bitwise equal (including padding!)
* @a: a pointer to a structure
* @b: a pointer to a structure of the same type.
* STRUCTEQ_DEF - define an ..._eq function to compare two structures.
* @sname: name of the structure, and function (<sname>_eq) to define.
* @padbytes: number of bytes of expected padding, or -1 if unknown.
* @...: name of every member of the structure.
*
* If you *know* a structure has no padding, you can memcmp them. At
* least this way, the compiler will issue a warning if the structs are
* different types!
* This generates a single memcmp() call in the common case where the
* structure contains no padding. Since it can't tell the difference between
* padding and a missing member, @padbytes can be used to assert that
* there isn't any, or how many we expect. -1 means "expect some", since
* it can be platform dependent.
*/
#define structeq(a, b) \
(memcmp((a), (b), sizeof(*(a)) + 0 * sizeof((a) == (b))) == 0)
#define STRUCTEQ_DEF(sname, padbytes, ...) \
static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \
const struct sname *_b) \
{ \
BUILD_ASSERT(((padbytes) < 0 && \
CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \
__VA_ARGS__)) \
> sizeof(*_a)) \
|| CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \
__VA_ARGS__)) \
+ (padbytes) == sizeof(*_a)); \
if (CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, __VA_ARGS__)) \
== sizeof(*_a)) \
return memcmp(_a, _b, sizeof(*_a)) == 0; \
else \
return CPPMAGIC_JOIN(&&, \
CPPMAGIC_MAP(STRUCTEQ_MEMBER_CMP_, \
__VA_ARGS__)); \
}
/* Helpers */
#define STRUCTEQ_MEMBER_SIZE_(m) sizeof((_a)->m)
#define STRUCTEQ_MEMBER_CMP_(m) memcmp(&_a->m, &_b->m, sizeof(_a->m)) == 0
#endif /* CCAN_STRUCTEQ_H */

View File

@ -8,6 +8,8 @@ struct mydata2 {
int start, end;
};
STRUCTEQ_DEF(mydata1, 0, start, end);
int main(void)
{
struct mydata1 a = { 0, 100 };
@ -18,5 +20,5 @@ int main(void)
#endif
b = { 0, 100 };
return structeq(&a, &b);
return mydata1_eq(&a, &b);
}

View File

@ -5,6 +5,8 @@ struct mydata {
int start, end;
};
STRUCTEQ_DEF(mydata, 0, start, end);
int main(void)
{
struct mydata a, b;
@ -14,13 +16,13 @@ int main(void)
a.start = 0;
a.end = 100;
ok1(structeq(&a, &a));
ok1(mydata_eq(&a, &a));
b = a;
ok1(structeq(&a, &b));
ok1(mydata_eq(&a, &b));
b.end++;
ok1(!structeq(&a, &b));
ok1(!mydata_eq(&a, &b));
/* This exits depending on whether all tests passed */
return exit_status();

View File

@ -19,7 +19,6 @@
#include <ccan/err/err.h>
#include <ccan/fdpass/fdpass.h>
#include <ccan/mem/mem.h>
#include <ccan/structeq/structeq.h>
#include <ccan/take/take.h>
#include <ccan/tal/str/str.h>
#include <ccan/time/time.h>
@ -434,8 +433,8 @@ static void check_short_ids_match(struct peer *peer)
assert(peer->have_sigs[LOCAL]);
assert(peer->have_sigs[REMOTE]);
if (!structeq(&peer->short_channel_ids[LOCAL],
&peer->short_channel_ids[REMOTE]))
if (!short_channel_id_eq(&peer->short_channel_ids[LOCAL],
&peer->short_channel_ids[REMOTE]))
peer_failed(&peer->cs,
&peer->channel_id,
"We disagree on short_channel_ids:"
@ -515,7 +514,7 @@ static void handle_peer_funding_locked(struct peer *peer, const u8 *msg)
&peer->channel_id,
"Bad funding_locked %s", tal_hex(msg, msg));
if (!structeq(&chanid, &peer->channel_id))
if (!channel_id_eq(&chanid, &peer->channel_id))
peer_failed(&peer->cs,
&peer->channel_id,
"Wrong channel id in %s (expected %s)",
@ -547,7 +546,7 @@ static void handle_peer_announcement_signatures(struct peer *peer, const u8 *msg
tal_hex(msg, msg));
/* Make sure we agree on the channel ids */
if (!structeq(&chanid, &peer->channel_id)) {
if (!channel_id_eq(&chanid, &peer->channel_id)) {
peer_failed(&peer->cs,
&peer->channel_id,
"Wrong channel_id: expected %s, got %s",

View File

@ -4,7 +4,6 @@
#include <bitcoin/tx.h>
#include <ccan/array_size/array_size.h>
#include <ccan/mem/mem.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <channeld/commit_tx.h>
#include <channeld/full_channel.h>
@ -334,7 +333,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
if (old->state != htlc->state
|| old->msatoshi != htlc->msatoshi
|| old->expiry.locktime != htlc->expiry.locktime
|| !structeq(&old->rhash, &htlc->rhash))
|| !sha256_eq(&old->rhash, &htlc->rhash))
return CHANNEL_ERR_DUPLICATE_ID_DIFFERENT;
else
return CHANNEL_ERR_DUPLICATE;
@ -515,7 +514,7 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel,
* doesn't SHA256 hash to the corresponding HTLC `payment_hash`:
* - MUST fail the channel.
*/
if (!structeq(&hash, &htlc->rhash))
if (!sha256_eq(&hash, &htlc->rhash))
return CHANNEL_ERR_BAD_PREIMAGE;
htlc->r = tal_dup(htlc, struct preimage, preimage);

View File

@ -1,6 +1,5 @@
/* FIXME: We don't relay from gossipd at all here. */
#include <bitcoin/script.h>
#include <ccan/structeq/structeq.h>
#include <closingd/gen_closing_wire.h>
#include <common/close_tx.h>
#include <common/crypto_sync.h>

View File

@ -5,7 +5,6 @@
#include <ccan/array_size/array_size.h>
#include <ccan/cast/cast.h>
#include <ccan/endian/endian.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <common/bech32.h>
#include <common/bech32_util.h>
@ -653,7 +652,7 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
return decode_fail(b11, fail,
"h: no description to check");
sha256(&sha, description, strlen(description));
if (!structeq(b11->description_hash, &sha))
if (!sha256_eq(b11->description_hash, &sha))
return decode_fail(b11, fail,
"h: does not match description");
}

View File

@ -1,4 +1,3 @@
#include <ccan/structeq/structeq.h>
#include <common/crypto_sync.h>
#include <common/peer_failed.h>
#include <common/ping.h>
@ -139,16 +138,18 @@ u8 *read_peer_msg_(const tal_t *ctx,
* message:
* - MUST ignore the message.
*/
if (structeq(&chanid, channel) || channel_id_is_all(&chanid))
if (channel_id_eq(&chanid, channel)
|| channel_id_is_all(&chanid)) {
peer_failed_received_errmsg(peer_fd, gossip_fd,
cs, err, &chanid);
}
return tal_free(msg);
}
/* They're talking about a different channel? */
if (extract_channel_id(msg, &chanid)
&& !structeq(&chanid, channel)) {
&& !channel_id_eq(&chanid, channel)) {
status_trace("Rejecting %s for unknown channel_id %s",
wire_type_name(fromwire_peektype(msg)),
type_to_string(tmpctx, struct channel_id, &chanid));

View File

@ -83,7 +83,7 @@ static void test_b11(const char *b11str,
assert(!expect_b11->msatoshi);
else
assert(*b11->msatoshi == *expect_b11->msatoshi);
assert(structeq(&b11->payment_hash, &expect_b11->payment_hash));
assert(sha256_eq(&b11->payment_hash, &expect_b11->payment_hash));
if (!b11->description)
assert(!expect_b11->description);
else

View File

@ -1,7 +1,10 @@
#ifndef LIGHTNING_COMMON_UTILS_H
#define LIGHTNING_COMMON_UTILS_H
#include "config.h"
#include <ccan/crypto/ripemd160/ripemd160.h>
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/tal.h>
#include <secp256k1.h>
@ -28,4 +31,10 @@ void setup_tmpctx(void);
/* Free any children of tmpctx. */
void clean_tmpctx(void);
/* Define sha256_eq. */
STRUCTEQ_DEF(sha256, 0, u);
/* Define ripemd160_eq. */
STRUCTEQ_DEF(ripemd160, 0, u);
#endif /* LIGHTNING_COMMON_UTILS_H */

View File

@ -202,9 +202,8 @@ Subtleties
There are a few subtleties you should be aware of as you modify deeper
parts of the code:
* `structeq` will not work on some structures.
For example, it will not work with `struct short_channel_id` --- use
`short_channel_id_eq` for comparing those.
* `ccan/structeq`'s STRUCTEQ_DEF will define safe comparison function foo_eq()
for struct foo, failing the build if the structure has implied padding.
* `command_success`, `command_fail`, and `command_fail_detailed` will free the
`cmd` you pass in.
This also means that if you `tal`-allocated anything from the `cmd`, they

View File

@ -11,7 +11,6 @@
#include <ccan/list/list.h>
#include <ccan/mem/mem.h>
#include <ccan/noerr/noerr.h>
#include <ccan/structeq/structeq.h>
#include <ccan/take/take.h>
#include <ccan/tal/str/str.h>
#include <ccan/timer/timer.h>
@ -881,7 +880,7 @@ static void handle_query_short_channel_ids(struct peer *peer, u8 *msg)
return;
}
if (!structeq(&rstate->chain_hash, &chain)) {
if (!bitcoin_blkid_eq(&rstate->chain_hash, &chain)) {
status_trace("%s sent query_short_channel_ids chainhash %s",
type_to_string(tmpctx, struct pubkey, &peer->id),
type_to_string(tmpctx, struct bitcoin_blkid, &chain));
@ -940,7 +939,7 @@ static void handle_gossip_timestamp_filter(struct peer *peer, u8 *msg)
return;
}
if (!structeq(&peer->daemon->rstate->chain_hash, &chain_hash)) {
if (!bitcoin_blkid_eq(&peer->daemon->rstate->chain_hash, &chain_hash)) {
status_trace("%s sent gossip_timestamp_filter chainhash %s",
type_to_string(tmpctx, struct pubkey, &peer->id),
type_to_string(tmpctx, struct bitcoin_blkid,
@ -1060,7 +1059,7 @@ static void handle_query_channel_range(struct peer *peer, u8 *msg)
return;
}
if (!structeq(&peer->daemon->rstate->chain_hash, &chain_hash)) {
if (!bitcoin_blkid_eq(&peer->daemon->rstate->chain_hash, &chain_hash)) {
status_trace("%s sent query_channel_range chainhash %s",
type_to_string(tmpctx, struct pubkey, &peer->id),
type_to_string(tmpctx, struct bitcoin_blkid,
@ -1114,7 +1113,7 @@ static void handle_reply_short_channel_ids_end(struct peer *peer, u8 *msg)
return;
}
if (!structeq(&peer->daemon->rstate->chain_hash, &chain)) {
if (!bitcoin_blkid_eq(&peer->daemon->rstate->chain_hash, &chain)) {
peer_error(peer, "reply_short_channel_ids_end for bad chain: %s",
tal_hex(tmpctx, msg));
return;
@ -1148,7 +1147,7 @@ static void handle_reply_channel_range(struct peer *peer, u8 *msg)
return;
}
if (!structeq(&peer->daemon->rstate->chain_hash, &chain)) {
if (!bitcoin_blkid_eq(&peer->daemon->rstate->chain_hash, &chain)) {
peer_error(peer, "reply_channel_range for bad chain: %s",
tal_hex(tmpctx, msg));
return;

View File

@ -5,7 +5,6 @@
#include <ccan/array_size/array_size.h>
#include <ccan/endian/endian.h>
#include <ccan/mem/mem.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <common/features.h>
#include <common/pseudorand.h>
@ -69,7 +68,7 @@ pending_node_announce_keyof(const struct pending_node_announce *a)
static bool pending_node_announce_eq(const struct pending_node_announce *pna,
const struct pubkey *key)
{
return structeq(&pna->nodeid, key);
return pubkey_eq(&pna->nodeid, key);
}
HTABLE_DEFINE_TYPE(struct pending_node_announce, pending_node_announce_keyof,
@ -121,7 +120,7 @@ size_t node_map_hash_key(const struct pubkey *key)
bool node_map_node_eq(const struct node *n, const struct pubkey *key)
{
return structeq(&n->id, key);
return pubkey_eq(&n->id, key);
}
static void destroy_node(struct node *node, struct routing_state *rstate)
@ -664,7 +663,7 @@ find_pending_cannouncement(struct routing_state *rstate,
struct pending_cannouncement *i;
list_for_each(&rstate->pending_cannouncement, i, list) {
if (structeq(scid, &i->short_channel_id))
if (short_channel_id_eq(scid, &i->short_channel_id))
return i;
}
return NULL;
@ -826,7 +825,7 @@ u8 *handle_channel_announcement(struct routing_state *rstate,
* - if the specified `chain_hash` is unknown to the receiver:
* - MUST ignore the message.
*/
if (!structeq(&chain_hash, &rstate->chain_hash)) {
if (!bitcoin_blkid_eq(&chain_hash, &rstate->chain_hash)) {
status_trace(
"Received channel_announcement %s for unknown chain %s",
type_to_string(pending, struct short_channel_id,
@ -1119,7 +1118,7 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update,
* active on the specified chain):
* - MUST ignore the channel update.
*/
if (!structeq(&chain_hash, &rstate->chain_hash)) {
if (!bitcoin_blkid_eq(&chain_hash, &rstate->chain_hash)) {
status_trace("Received channel_update for unknown chain %s",
type_to_string(tmpctx, struct bitcoin_blkid,
&chain_hash));
@ -1577,8 +1576,7 @@ void routing_failure(struct routing_state *rstate,
u8 *err;
if (tal_len(channel_update) == 0) {
/* Suppress UNUSUAL log if local failure */
if (structeq(&erring_node_pubkey->pubkey,
&rstate->local_id.pubkey))
if (pubkey_eq(erring_node_pubkey, &rstate->local_id))
return;
status_unusual("routing_failure: "
"UPDATE bit set, no channel_update. "

View File

@ -6,7 +6,6 @@
#include <unistd.h>
#include <ccan/err/err.h>
#include <ccan/io/io.h>
#include <ccan/structeq/structeq.h>
#include <common/status.h>
/* AUTOGENERATED MOCKS START */
@ -72,12 +71,12 @@ static struct privkey privkey(const char *str)
return p;
}
static bool secret_eq(const struct secret *s, const char *str)
static bool secret_eq_str(const struct secret *s, const char *str)
{
struct secret expect;
if (!hex_decode(str, strlen(str), &expect, sizeof(expect)))
abort();
return structeq(s, &expect);
return secret_eq(s, &expect);
}
secp256k1_context *secp256k1_ctx;
@ -182,8 +181,8 @@ static struct io_plan *success(struct io_conn *conn UNUSED,
{
assert(pubkey_eq(them, &rs_pub));
assert(secret_eq(&cs->sk, expect_sk));
assert(secret_eq(&cs->rk, expect_rk));
assert(secret_eq_str(&cs->sk, expect_sk));
assert(secret_eq_str(&cs->rk, expect_rk));
/* No memory leaks please */
secp256k1_context_destroy(secp256k1_ctx);

View File

@ -6,7 +6,6 @@
#include <unistd.h>
#include <ccan/err/err.h>
#include <ccan/io/io.h>
#include <ccan/structeq/structeq.h>
#include <common/status.h>
/* AUTOGENERATED MOCKS START */
@ -72,12 +71,12 @@ static struct privkey privkey(const char *str)
return p;
}
static bool secret_eq(const struct secret *s, const char *str)
static bool secret_eq_str(const struct secret *s, const char *str)
{
struct secret expect;
if (!hex_decode(str, strlen(str), &expect, sizeof(expect)))
abort();
return structeq(s, &expect);
return secret_eq(s, &expect);
}
secp256k1_context *secp256k1_ctx;
@ -179,8 +178,8 @@ static struct io_plan *success(struct io_conn *conn UNUSED,
const struct crypto_state *cs,
void *unused UNUSED)
{
assert(secret_eq(&cs->sk, expect_sk));
assert(secret_eq(&cs->rk, expect_rk));
assert(secret_eq_str(&cs->sk, expect_sk));
assert(secret_eq_str(&cs->rk, expect_rk));
/* No memory leaks please */
secp256k1_context_destroy(secp256k1_ctx);

View File

@ -38,7 +38,7 @@ static bool we_broadcast(const struct chain_topology *topo,
const struct outgoing_tx *otx;
list_for_each(&topo->outgoing_txs, otx, list) {
if (structeq(&otx->txid, txid))
if (bitcoin_txid_eq(&otx->txid, txid))
return true;
}
return false;
@ -447,7 +447,7 @@ static void have_new_block(struct bitcoind *bitcoind UNUSED,
struct chain_topology *topo)
{
/* Unexpected predecessor? Free predecessor, refetch it. */
if (!structeq(&topo->tip->blkid, &blk->hdr.prev_hash))
if (!bitcoin_blkid_eq(&topo->tip->blkid, &blk->hdr.prev_hash))
remove_tip(topo);
else
add_tip(topo, new_block(topo, blk, topo->tip->height + 1));

View File

@ -72,7 +72,7 @@ static inline size_t hash_sha(const struct bitcoin_blkid *key)
static inline bool block_eq(const struct block *b, const struct bitcoin_blkid *key)
{
return structeq(&b->blkid, key);
return bitcoin_blkid_eq(&b->blkid, key);
}
HTABLE_DEFINE_TYPE(struct block, keyof_block_map, hash_sha, block_eq, block_map);

View File

@ -7,7 +7,6 @@
#include <bitcoin/base58.h>
#include <bitcoin/script.h>
#include <ccan/str/hex/hex.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <common/bech32.h>
#include <common/bolt11.h>

View File

@ -343,7 +343,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
bitcoin_txid(fundingtx, &funding_txid);
if (!structeq(&funding_txid, &expected_txid)) {
if (!bitcoin_txid_eq(&funding_txid, &expected_txid)) {
log_broken(fc->uc->log,
"Funding txid mismatch:"
" satoshi %"PRIu64" change %"PRIu64

View File

@ -1,6 +1,5 @@
#include "pay.h"
#include <ccan/str/hex/hex.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <common/bolt11.h>
#include <common/timeout.h>
@ -81,7 +80,7 @@ static void waitsendpay_resolve(const tal_t *ctx,
struct sendpay_command *pc;
struct sendpay_command *next;
list_for_each_safe(&ld->waitsendpay_commands, pc, next, list) {
if (!structeq(payment_hash, &pc->payment_hash))
if (!sha256_eq(payment_hash, &pc->payment_hash))
continue;
/* Delete later (in our own caller) if callback did
@ -407,7 +406,7 @@ void payment_store(struct lightningd *ld,
/* Trigger any sendpay commands waiting for the store to occur. */
list_for_each_safe(&ld->sendpay_commands, pc, next, list) {
if (!structeq(payment_hash, &pc->payment_hash))
if (!sha256_eq(payment_hash, &pc->payment_hash))
continue;
/* Delete later if callback did not delete. */
@ -700,7 +699,7 @@ send_payment(const tal_t *ctx,
cb(result, cbarg);
return false;
}
if (!structeq(&payment->destination, &ids[n_hops-1])) {
if (!pubkey_eq(&payment->destination, &ids[n_hops-1])) {
char *msg = tal_fmt(tmpctx,
"Already succeeded to %s",
type_to_string(tmpctx,

View File

@ -543,7 +543,7 @@ static struct channel *channel_by_channel_id(struct peer *peer,
derive_channel_id(&cid,
&channel->funding_txid,
channel->funding_outnum);
if (structeq(&cid, channel_id))
if (channel_id_eq(&cid, channel_id))
return channel;
}
return NULL;
@ -997,7 +997,7 @@ command_find_channel(struct command *cmd,
derive_channel_id(&channel_cid,
&channel->funding_txid,
channel->funding_outnum);
if (structeq(&channel_cid, &cid))
if (channel_id_eq(&channel_cid, &cid))
return channel;
}
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
@ -1437,7 +1437,7 @@ static void json_dev_forget_channel(struct command *cmd, const char *buffer,
if (scidtok) {
if (!channel->scid)
continue;
if (!structeq(channel->scid, &scid))
if (!short_channel_id_eq(channel->scid, &scid))
continue;
}
if (forget->channel) {

View File

@ -741,7 +741,7 @@ void onchain_fulfilled_htlc(struct channel *channel,
if (hout->failcode != 0 || hout->failuremsg)
continue;
if (!structeq(&hout->payment_hash, &payment_hash))
if (!sha256_eq(&hout->payment_hash, &payment_hash))
continue;
/* We may have already fulfilled before going onchain, or
@ -803,7 +803,7 @@ struct htlc_out *find_htlc_out_by_ripemd(const struct channel *channel,
ripemd160(&hash,
&hout->payment_hash, sizeof(hout->payment_hash));
if (structeq(&hash, ripemd))
if (ripemd160_eq(&hash, ripemd))
return hout;
}
return NULL;

View File

@ -29,7 +29,6 @@
#include <bitcoin/script.h>
#include <ccan/crypto/siphash24/siphash24.h>
#include <ccan/ptrint/ptrint.h>
#include <ccan/structeq/structeq.h>
#include <common/pseudorand.h>
#include <common/timeout.h>
#include <lightningd/bitcoind.h>
@ -88,7 +87,7 @@ size_t txo_hash(const struct txwatch_output *out)
bool txowatch_eq(const struct txowatch *w, const struct txwatch_output *out)
{
return structeq(&w->out.txid, &out->txid)
return bitcoin_txid_eq(&w->out.txid, &out->txid)
&& w->out.index == out->index;
}
@ -110,7 +109,7 @@ size_t txid_hash(const struct bitcoin_txid *txid)
bool txwatch_eq(const struct txwatch *w, const struct bitcoin_txid *txid)
{
return structeq(&w->txid, txid);
return bitcoin_txid_eq(&w->txid, txid);
}
static void destroy_txwatch(struct txwatch *w)

View File

@ -2,7 +2,6 @@
#include <bitcoin/script.h>
#include <ccan/crypto/shachain/shachain.h>
#include <ccan/mem/mem.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <common/derive_basepoints.h>
#include <common/htlc_tx.h>
@ -442,7 +441,7 @@ static bool is_valid_sig(const u8 *e)
static bool input_similar(const struct bitcoin_tx_input *i1,
const struct bitcoin_tx_input *i2)
{
if (!structeq(&i1->txid, &i2->txid))
if (!bitcoin_txid_eq(&i1->txid, &i2->txid))
return false;
if (i1->index != i2->index)
@ -599,7 +598,7 @@ static bool is_mutual_close(const struct bitcoin_tx *tx,
static bool is_local_commitment(const struct bitcoin_txid *txid,
const struct bitcoin_txid *our_broadcast_txid)
{
return structeq(txid, our_broadcast_txid);
return bitcoin_txid_eq(txid, our_broadcast_txid);
}
/* BOLT #5:
@ -754,7 +753,7 @@ static void handle_htlc_onchain_fulfill(struct tracked_output *out,
sha256(&sha, &preimage, sizeof(preimage));
ripemd160(&ripemd, &sha, sizeof(sha));
if (!structeq(&ripemd, &out->htlc->ripemd))
if (!ripemd160_eq(&ripemd, &out->htlc->ripemd))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"%s/%s spent with bad preimage %s (ripemd not %s)",
tx_type_name(out->tx_type),
@ -865,7 +864,7 @@ static void output_spent(struct tracked_output ***outs,
if (tx->input[input_num].index != out->outnum)
continue;
if (!structeq(&tx->input[input_num].txid, &out->txid))
if (!bitcoin_txid_eq(&tx->input[input_num].txid, &out->txid))
continue;
/* Was this our resolution? */
@ -993,7 +992,7 @@ static void tx_new_depth(struct tracked_output **outs,
size_t i;
/* Special handling for commitment tx reaching depth */
if (structeq(&outs[0]->resolved->txid, txid)
if (bitcoin_txid_eq(&outs[0]->resolved->txid, txid)
&& depth >= reasonable_depth
&& missing_htlc_msgs) {
status_trace("Sending %zu missing htlc messages",
@ -1006,12 +1005,12 @@ static void tx_new_depth(struct tracked_output **outs,
for (i = 0; i < tal_count(outs); i++) {
/* Update output depth. */
if (structeq(&outs[i]->txid, txid))
if (bitcoin_txid_eq(&outs[i]->txid, txid))
outs[i]->depth = depth;
/* Is this tx resolving an output? */
if (outs[i]->resolved) {
if (structeq(&outs[i]->resolved->txid, txid)) {
if (bitcoin_txid_eq(&outs[i]->resolved->txid, txid)) {
update_resolution_depth(outs[i], depth);
}
continue;
@ -1020,7 +1019,7 @@ static void tx_new_depth(struct tracked_output **outs,
/* Otherwise, is this something we have a pending
* resolution for? */
if (outs[i]->proposal
&& structeq(&outs[i]->txid, txid)
&& bitcoin_txid_eq(&outs[i]->txid, txid)
&& depth >= outs[i]->proposal->depth_required) {
proposal_meets_depth(outs[i]);
}
@ -1069,7 +1068,7 @@ static void handle_preimage(struct tracked_output **outs,
if (outs[i]->output_type != THEIR_HTLC)
continue;
if (!structeq(&outs[i]->htlc->ripemd, &ripemd))
if (!ripemd160_eq(&outs[i]->htlc->ripemd, &ripemd))
continue;
/* Too late? */

View File

@ -1,4 +1,3 @@
#include <ccan/structeq/structeq.h>
#include <common/htlc_wire.h>
#include <onchaind/onchain_wire.h>
#include <wire/wire.h>

View File

@ -5,7 +5,6 @@
#include <ccan/breakpoint/breakpoint.h>
#include <ccan/cast/cast.h>
#include <ccan/fdpass/fdpass.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <common/crypto_sync.h>
#include <common/derive_basepoints.h>
@ -343,7 +342,7 @@ static u8 *funder_channel(struct state *state,
*
* The `temporary_channel_id` MUST be the same as the
* `temporary_channel_id` in the `open_channel` message. */
if (!structeq(&id_in, &state->channel_id))
if (!channel_id_eq(&id_in, &state->channel_id))
peer_failed(&state->cs,
&state->channel_id,
"accept_channel ids don't match: sent %s got %s",
@ -487,7 +486,7 @@ static u8 *funder_channel(struct state *state,
derive_channel_id(&state->channel_id,
&state->funding_txid, state->funding_txout);
if (!structeq(&id_in, &state->channel_id))
if (!channel_id_eq(&id_in, &state->channel_id))
peer_failed(&state->cs, &id_in,
"funding_signed ids don't match: expected %s got %s",
type_to_string(msg, struct channel_id,
@ -596,7 +595,8 @@ static u8 *fundee_channel(struct state *state,
* set to a hash of a chain that is unknown to the receiver:
* - MUST reject the channel.
*/
if (!structeq(&chain_hash, &state->chainparams->genesis_blockhash)) {
if (!bitcoin_blkid_eq(&chain_hash,
&state->chainparams->genesis_blockhash)) {
negotiation_failed(state,
"Unknown chain-hash %s",
type_to_string(peer_msg,
@ -707,7 +707,7 @@ static u8 *fundee_channel(struct state *state,
* The `temporary_channel_id` MUST be the same as the
* `temporary_channel_id` in the `open_channel` message.
*/
if (!structeq(&id_in, &state->channel_id))
if (!channel_id_eq(&id_in, &state->channel_id))
peer_failed(&state->cs, &id_in,
"funding_created ids don't match: sent %s got %s",
type_to_string(msg, struct channel_id,

View File

@ -3,7 +3,6 @@
#include "wallet.h"
#include <assert.h>
#include <ccan/list/list.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <ccan/time/time.h>
#include <ccan/timer/timer.h>

View File

@ -18,7 +18,6 @@ static void db_log_(struct log *log UNUSED, enum log_level level UNUSED, const c
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <ccan/structeq/structeq.h>
#include <common/memleak.h>
#include <stdarg.h>
#include <stddef.h>
@ -653,7 +652,8 @@ static bool channelseq(struct channel *c1, struct channel *c2)
CHECK(c1->peer == c2->peer);
CHECK(c1->their_shachain.id == c2->their_shachain.id);
CHECK_MSG(pubkey_eq(&p1->id, &p2->id), "NodeIDs do not match");
CHECK((c1->scid == NULL && c2->scid == NULL) || structeq(c1->scid, c2->scid));
CHECK((c1->scid == NULL && c2->scid == NULL)
|| short_channel_id_eq(c1->scid, c2->scid));
CHECK(c1->our_msatoshi == c2->our_msatoshi);
CHECK((c1->remote_shutdown_scriptpubkey == NULL && c2->remote_shutdown_scriptpubkey == NULL) || memeq(
c1->remote_shutdown_scriptpubkey,
@ -968,7 +968,7 @@ static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx)
CHECK(pubkey_cmp(&t2->destination, &t->destination) == 0);
CHECK(t2->msatoshi == t->msatoshi);
CHECK(t2->msatoshi_sent == t->msatoshi_sent);
CHECK(structeq(t->payment_preimage, t2->payment_preimage));
CHECK(preimage_eq(t->payment_preimage, t2->payment_preimage));
db_commit_transaction(w->db);
return true;

View File

@ -4,7 +4,6 @@
#include <ccan/build_assert/build_assert.h>
#include <ccan/crypto/ripemd160/ripemd160.h>
#include <ccan/mem/mem.h>
#include <ccan/structeq/structeq.h>
#include <common/memleak.h>
#include <common/pseudorand.h>
#include <common/utils.h>
@ -31,7 +30,7 @@ static size_t outpoint_hash(const struct outpointfilter_entry *out)
static bool outpoint_eq(const struct outpointfilter_entry *o1,
const struct outpointfilter_entry *o2)
{
return structeq(&o1->txid, &o2->txid) && o1->outnum == o2->outnum;
return bitcoin_txid_eq(&o1->txid, &o2->txid) && o1->outnum == o2->outnum;
}
static const struct outpointfilter_entry *outpoint_keyof(const struct outpointfilter_entry *out)

View File

@ -2,7 +2,6 @@
#include "wallet.h"
#include <bitcoin/script.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <common/key_derive.h>
#include <common/wireaddr.h>
@ -1525,7 +1524,7 @@ find_unstored_payment(struct wallet *wallet, const struct sha256 *payment_hash)
struct wallet_payment *i;
list_for_each(&wallet->unstored_payments, i, list) {
if (structeq(payment_hash, &i->payment_hash))
if (sha256_eq(payment_hash, &i->payment_hash))
return i;
}
return NULL;
@ -1892,7 +1891,7 @@ wallet_payment_list(const tal_t *ctx,
/* Now attach payments not yet in db. */
list_for_each(&wallet->unstored_payments, p, list) {
if (payment_hash && !structeq(&p->payment_hash, payment_hash))
if (payment_hash && !sha256_eq(&p->payment_hash, payment_hash))
continue;
tal_resize(&payments, i+1);
payments[i++] = p;
@ -1929,7 +1928,8 @@ bool wallet_network_check(struct wallet *w,
if (stmt && sqlite3_step(stmt) == SQLITE_ROW) {
sqlite3_column_sha256_double(stmt, 0, &chainhash.shad);
db_stmt_done(stmt);
if (!structeq(&chainhash, &chainparams->genesis_blockhash)) {
if (!bitcoin_blkid_eq(&chainhash,
&chainparams->genesis_blockhash)) {
log_broken(w->log, "Wallet blockchain hash does not "
"match network blockchain hash: %s "
"!= %s. "

View File

@ -37,8 +37,4 @@ bool extract_channel_id(const u8 *in_pkt, struct channel_id *channel_id);
* - MUST set `funding_satoshis` to less than 2^24 satoshi.
*/
#define MAX_FUNDING_SATOSHI ((1 << 24) - 1)
/* Compare two short_channel_ids and return true if they are the equal */
bool short_channel_id_eq(const struct short_channel_id *a,
const struct short_channel_id *b);
#endif /* LIGHTNING_WIRE_PEER_WIRE_H */

View File

@ -11,7 +11,6 @@ void fromwire_pad_orig(const u8 **cursor, size_t *max, size_t num);
#undef towire_pad
#undef fromwire_pad
#include <ccan/structeq/structeq.h>
#include <assert.h>
#include <stdio.h>
#include <common/sphinx.h>
@ -704,21 +703,22 @@ static bool channel_announcement_eq(const struct msg_channel_announcement *a,
return eq_upto(a, b, features)
&& eq_var(a, b, features)
&& eq_field(a, b, chain_hash)
&& structeq(&a->short_channel_id, &b->short_channel_id)
&& short_channel_id_eq(&a->short_channel_id,
&b->short_channel_id)
&& eq_between(a, b, node_id_1, bitcoin_key_2);
}
static bool funding_locked_eq(const struct msg_funding_locked *a,
const struct msg_funding_locked *b)
{
return structeq(a, b);
return memcmp(a, b, sizeof(*a)) == 0;
}
static bool announcement_signatures_eq(const struct msg_announcement_signatures *a,
const struct msg_announcement_signatures *b)
{
return eq_upto(a, b, short_channel_id) &&
structeq(&a->short_channel_id, &b->short_channel_id);
short_channel_id_eq(&a->short_channel_id, &b->short_channel_id);
}
static bool update_fail_htlc_eq(const struct msg_update_fail_htlc *a,
@ -738,19 +738,19 @@ static bool commitment_signed_eq(const struct msg_commitment_signed *a,
static bool funding_signed_eq(const struct msg_funding_signed *a,
const struct msg_funding_signed *b)
{
return structeq(a, b);
return memcmp(a, b, sizeof(*a)) == 0;
}
static bool closing_signed_eq(const struct msg_closing_signed *a,
const struct msg_closing_signed *b)
{
return structeq(a, b);
return memcmp(a, b, sizeof(*a)) == 0;
}
static bool update_fulfill_htlc_eq(const struct msg_update_fulfill_htlc *a,
const struct msg_update_fulfill_htlc *b)
{
return structeq(a, b);
return memcmp(a, b, sizeof(*a)) == 0;
}
static bool error_eq(const struct msg_error *a,
@ -770,7 +770,7 @@ static bool init_eq(const struct msg_init *a,
static bool update_fee_eq(const struct msg_update_fee *a,
const struct msg_update_fee *b)
{
return structeq(a, b);
return memcmp(a, b, sizeof(*a)) == 0;
}
static bool shutdown_eq(const struct msg_shutdown *a,
@ -790,7 +790,7 @@ static bool funding_created_eq(const struct msg_funding_created *a,
static bool revoke_and_ack_eq(const struct msg_revoke_and_ack *a,
const struct msg_revoke_and_ack *b)
{
return structeq(a, b);
return memcmp(a, b, sizeof(*a)) == 0;
}
static bool open_channel_eq(const struct msg_open_channel *a,
@ -804,7 +804,7 @@ static bool channel_update_eq(const struct msg_channel_update *a,
const struct msg_channel_update *b)
{
return eq_upto(a, b, short_channel_id) &&
structeq(&a->short_channel_id, &b->short_channel_id);
short_channel_id_eq(&a->short_channel_id, &b->short_channel_id);
}
static bool accept_channel_eq(const struct msg_accept_channel *a,

View File

@ -9,12 +9,15 @@
#include <bitcoin/signature.h>
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <secp256k1_recovery.h>
#include <stdlib.h>
struct channel_id {
u8 id[32];
};
/* Define channel_id_eq (no padding) */
STRUCTEQ_DEF(channel_id, 0, id);
struct bitcoin_blkid;
struct bitcoin_txid;