Skip to content
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

The Great Code Documentation Effort, Part I #1899

Merged
merged 11 commits into from
Sep 3, 2018

Conversation

rustyrussell
Copy link
Contributor

Obviously, I couldn't resist some cleanups along the way. Part II is finished already, but I wanted feedback on this one.

The idea is to walk through the code and along the way point out the techniques and style we use; as it goes on, it will concentrate more on the specifics of the particular daemon. It should be read in order, however.

Copy link
Collaborator

@renepickhardt renepickhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for this documentation. Would have helped a lot one month ago but still helped me right now. I guess there is still a large gap for most people to get onborded

@@ -14,24 +14,10 @@ Getting Started
It's in C, to encourage alternate implementations. Patches are welcome!
You should read our [Style Guide](STYLE.md).

To read the code, you'll probably need to understand `ccan/tal`: it's a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It lookes like the hint about ccan/tal is now completely removed. When I first sterted reading the code it was actually helpful for me to know about this particular data structure. Acutally I would rather have enjoyed some more explaination and paterns how to use it. (for example in the beginning I thought ctx is short for commitment tx and not for context was quite confusing)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll move this to the first occurrence in the code then.

* The role of this daemon is to start the subdaemons, shuffle peers
* between them, handle the JSON RPC requests, bitcoind, the database
* and centralize logging. In theory, it doesn't trust the other
* daemons, though we expect hsmd to be responsive.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When being completely new I will wonder what hsmd is. first of all I do not even realize that it is hsm-daemon I don't know wht hsm is and I don't understant why it is cruicial.

@@ -18,11 +48,14 @@
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
#include <ccan/tal/str/str.h>

/*~ This is common code: routines shared by one or more programs. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

programms or daemons?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lightning-cli in at least one case... I've expanded.

* It's another one of Rusty's projects, and we copy and paste it
* automatically into the source tree here, so you should never edit
* it. There's a Makefile target update-ccan to update it (and add modules
* if CCAN_NEW is specified). */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe include the removed comments from HACKING.md here?

if (getenv("LIGHTNINGD_DEV_MEMLEAK"))
memleak_init();
#endif

/*~ These are CCAN lists: an embedded double-linked list. It's not
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I remember correnctly there are c-macros involved to create such CCAN data structure. As someone new to the project I am confused when to use such macros, if they are autogenerated and how the general process should look like. Maybe we could include a link examples or even provide some small CCAN best practices in a seperate code folder.
on a more meta level: I am not an experienced c programmer. I realize that the CCAN libs seem to ease up stuff but they made the code rather hard to read for me

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to simple put an example inline if we need it. Having a single go-to place to read is always better than some out-of-the-way file nobody will read or maintain...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up just listing some helpers and fleshing it out a bit more. I'd rather reference them as we see their use. I tried to create a minimal example, but it was contrived and still 20 lines :(


/* Initialize wallet, now that we are in the correct directory */
/*~ Our "wallet" code really wraps the db, which is more than a simple
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what more is it?

io_poll_debug = io_poll_override(io_poll_lightningd);

/* Set up HSM. */
/*~ Set up HSM: it knows our node secret key, so tells us who we are. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as the hsmd was mentioned to be the one daemon that needs to be responsive we should explain this a little bit more here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.


/* Create RPC socket (if any) */
/*~ Create RPC socket (if any): now we can talk to clients. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this one is ncessary to have lightning-cli. Maybe it is standard stuff for people familar with rpc but how is such an API exposed (sure over unix domain socket) but where in the code are api calls provided? I guess this doesnot happen in jsonrpc so a hint in this comment would be nice.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the JSON-RPC autoregisters callbacks using the ccan/autodata module, however that poses some issues if we'd like to use clang based sanitizers since it does weird things with uninitialized data, so maybe we'd want to ween off that anyway at some point.

crashlog = ld->log;

/*~ The root of every backtrace (almost). */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the event loop?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if yes where does io_loop come from? would elaborate here a little bit

@@ -482,5 +699,7 @@ int main(int argc, char *argv[])
memleak_cleanup();
#endif
daemon_shutdown();

/*~ Farewell. Next stop: hsmd/hsm.c. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it actually lightningd.c with a d but hsm.c without d ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. That's bugged me for a while too, so I renamed them all...

wythe added a commit to wythe/lightning that referenced this pull request Aug 30, 2018
Signed-off-by: Mark Beckwith <wythe@intrig.com>
@rustyrussell
Copy link
Contributor Author

@renepickhardt Thank youso much for the detailed review. And sorry I didn't write this s month ago :(

My initial reservations were that I was using too much space with these comments, but I see that my problem was too little, not too much! I'll go through and create a fix-up using your feedback as a guide...

/*~ There's always a battle between what a constructor like this
* should do, and what should be added later by the caller. In
* general, because we use valgrind heavily for testing, we prefer not
* to intialize unused fields which we expect the caller to set:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "intialize"


/* Get the blockheight we are currently at, UINT32_MAX is used to signal
/*~ Get the blockheight we are currently at, UINT32_MAX is used to signal
* an unitialized wallet and that we should start off of bitcoind's
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "unitialized"


/*~ The core lightning object: it's passed everywhere, and is basically a
* global variable. This new_xxx pattern is something we'll see often:
* it allocates and initializes a new structure, using *tal*, the heirarchitcal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "heirarchitcal"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we call lightningd the context object, or maybe root of the entire program?

* elements, which can be accessed with tal_count() (or tal_bytelen()
* for raw bytecount). It's common for simple arrays to use
* tal_resize(), which is a typesafe realloc function, but as all
* talocations need a parent, we start with an empty array rather than
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "talocations"


/*~ These are hash tables of incoming and outgoing HTLCs (contracts),
* defined as `struct htlc_in` and `struct htlc_out`in htlc_end.h.
* The hash tables are declared ther using the very ugly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "ther"

*
* Comments beginning with a ~ (like this one!) are part of our shared
* adventure through the source, so they're more meta than normal code
* comments, and mean to be read in a certain order.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mean -> meant

* 'tallocated' off it are also freed. In this case, freeing 'ctx'
* will free 'ld'.
*
* It's incredibly useful for grouping object lifetimes, as we'll see.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"For the technically inclined: tal allocations usually build a tree, and tal_freeing any node in the tree will result in the entire subtree rooted at that node to be freed.

Be careful though that a any cycle in the allocation graph may end up causing an infinite loop."

Also for my personal understanding: the allocations are freed in post-order right? (first children, then the parent).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't loop on cycles. Freeing is done in two phases: object is marked destroyed, destructor called, then recurse into children, then finally free(object). So destructors are pre-order, deallocation is post-order.

It's common to want to access parents in a destructor (eg. delete from its linked list), so deallocation has to be deferred.

struct ext_key ext;
/*~ Note the use of ccan/short_types u64 rather than uint64_t.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do I always imagine the creepy voice from Portal when the comments speak in first person? :-)

if (chdir(cwd) != 0)
fatal("Could not return to directory %s: %s",
cwd, strerror(errno));

db_reopen_after_fork(ld->wallet->db);

/*~ Why not allocate cwd off tmpctx? Probably because this code predates
* tmpctx. So we free manually here. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the it's more because the global tmpctx is an event loop concept and this is outside of the loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but it's before the loop; we tend to allow that elsewhere...

rustyrussell pushed a commit that referenced this pull request Sep 3, 2018
Signed-off-by: Mark Beckwith <wythe@intrig.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We're a daemon.  They're subdaemons.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We already have access via the ld object, and we initialized this one
twice anyway.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We have a transaction anyway, and it's simpler.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@rustyrussell
Copy link
Contributor Author

Despite lack of (concrete) acks, I'm going to merge now; it's going to cause rebase hell to delay further, and I'm already itching to post parts II and III :)

Also, wallet has no business wiring up HTLCs; move that code to
peer_htlcs.c.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@rustyrussell rustyrussell force-pushed the guilt/docs branch 2 times, most recently from fa6fc14 to a66afbf Compare September 3, 2018 03:00
@renepickhardt: why is it actually lightningd.c with a d but hsm.c without d ?

And delete unused gossipd/gossip.h.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Code changes:
1. Expose daemon_poll() so lightningd can call it directly, which avoids us
   having store a global and document it.
2. Remove the (undocumented, unused, forgotten) --rpc-file="" option to disable
   JSON RPC.
3. Move the ickiness of finding the executable path into subd.c, so it doesn't
   distract from lightningd.c overview.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Documentation changes:
1. Lots of extra detail suggested by @renepickhardt.
2. typo fixes from @practicalswift.
3. A section on 'const' usage.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Suggested-by: @practicalswift and @cdecker.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@rustyrussell rustyrussell merged commit f2e0857 into ElementsProject:master Sep 3, 2018
@rustyrussell rustyrussell deleted the guilt/docs branch September 3, 2018 11:35
@jb55
Copy link
Collaborator

jb55 commented Sep 3, 2018

Knuth would be proud. Thanks rusty!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants