docs: add code contribution guidelines
This commit adds a document which outlines some of the traits desired in future contributions to the daemon. It’s my hope that this document will allow new contributors to quickly get up to speed on what is desired in new contributions, possibly directly speeding up review times.
This commit is contained in:
parent
767c550d65
commit
97b9b2ff09
427
docs/code_contribution_guidelines.md
Normal file
427
docs/code_contribution_guidelines.md
Normal file
@ -0,0 +1,427 @@
|
||||
### Table of Contents
|
||||
1. [Overview](#Overview)<br />
|
||||
2. [Minimum Recommended Skillset](#MinSkillset)<br />
|
||||
3. [Required Reading](#ReqReading)<br />
|
||||
4. [Development Practices](#DevelopmentPractices)<br />
|
||||
4.1. [Share Early, Share Often](#ShareEarly)<br />
|
||||
4.2. [Testing](#Testing)<br />
|
||||
4.3. [Code Documentation and Commenting](#CodeDocumentation)<br />
|
||||
4.4. [Model Git Commit Messages](#ModelGitCommitMessages)<br />
|
||||
4.5 [Code Spacing](#CodeSpacing)<br />
|
||||
5. [Code Approval Process](#CodeApproval)<br />
|
||||
5.1 [Code Review](#CodeReview)<br />
|
||||
5.2 [Rework Code (if needed)](#CodeRework)<br />
|
||||
5.3 [Acceptance](#CodeAcceptance)<br />
|
||||
6. [Contribution Standards](#Standards)<br />
|
||||
6.1. [Contribution Checklist](#Checklist)<br />
|
||||
6.2. [Licensing of Contributions](#Licensing)<br />
|
||||
|
||||
<a name="Overview" />
|
||||
### 1. Overview
|
||||
|
||||
Developing cryptocurrencies is an exciting endeavor that touches a wide variety
|
||||
of areas such as wire protocols, peer-to-peer networking, databases,
|
||||
cryptography, language interpretation (transaction scripts), adversarial
|
||||
threat-modeling, and RPC systems. They also represent a radical shift to the
|
||||
current fiscal system and as a result provide an opportunity to help reshape
|
||||
the entire financial system. With the advent of the [Lightning Network
|
||||
(LN)](https://lightning.network/), new layers are being constructed upon the
|
||||
base blockchain layer which have the potential to aleviate many of the
|
||||
limitations and constraints inherent in the design of blockchains. There are
|
||||
few projects that offer this level of diversity and impact all in one code
|
||||
base.
|
||||
|
||||
However, as exciting as it is, one must keep in mind that cryptocurrencies
|
||||
represent real money and introducing bugs and security vulnerabilities can have
|
||||
far more dire consequences than in typical projects where having a small bug is
|
||||
minimal by comparison. In the world of cryptocurrencies, even the smallest bug
|
||||
in the wrong area can cost people a significant amount of money. For this
|
||||
reason, the Lightning Network Daemon (lnd) has a formalized and rigorous
|
||||
development process (heavily insipred by
|
||||
[btcsuite](https://github.com/btcsuite)) which is outlined on this page.
|
||||
|
||||
We highly encourage code contributions, however it is imperative that you adhere
|
||||
to the guidelines established on this page.
|
||||
|
||||
<a name="MinSkillset" />
|
||||
### 2. Minimum Recommended Skillset
|
||||
|
||||
The following list is a set of core competencies that we recommend you possess
|
||||
before you really start attempting to contribute code to the project. These are
|
||||
not hard requirements as we will gladly accept code contributions as long as
|
||||
they follow the guidelines set forth on this page. That said, if you don't have
|
||||
the following basic qualifications you will likely find it quite difficult to
|
||||
contribute to the core layers of Lightning. However, there are still a number
|
||||
of low hanging fruit which can be tackled without having full competency in the
|
||||
areas mentioned below.
|
||||
|
||||
- A reasonable understanding of bitcoin at a high level (see the
|
||||
[Required Reading](#ReqReading) section for the original white paper)
|
||||
- A reasonable understanding of the Lightning Network at a high level
|
||||
- Experience in some type of C-like language
|
||||
- An understanding of data structures and their performance implications
|
||||
- Familiarity with unit testing
|
||||
- Debugging experience
|
||||
- Ability to understand not only the area you are making a change in, but also
|
||||
the code your change relies on, and the code which relies on your changed code
|
||||
|
||||
Building on top of those core competencies, the recommended skill set largely
|
||||
depends on the specific areas you are looking to contribute to. For example,
|
||||
if you wish to contribute to the cryptography code, you should have a good
|
||||
understanding of the various aspects involved with cryptography such as the
|
||||
security and performance implications.
|
||||
|
||||
<a name="ReqReading" />
|
||||
### 3. Required Reading
|
||||
|
||||
- [Effective Go](http://golang.org/doc/effective_go.html) - The entire btcd
|
||||
suite follows the guidelines in this document. For your code to be accepted,
|
||||
it must follow the guidelines therein.
|
||||
- [Original Satoshi Whitepaper](http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCkQFjAA&url=http%3A%2F%2Fbitcoin.org%2Fbitcoin.pdf&ei=os3VUuH8G4SlsASV74GoAg&usg=AFQjCNEipPLigou_1MfB7DQjXCNdlylrBg&sig2=FaHDuT5z36GMWDEnybDJLg&bvm=bv.59378465,d.b2I) - This is the white paper that started it all. Having a solid
|
||||
foundation to build on will make the code much more comprehensible.
|
||||
- [Lightning Network Whitepaper](https://lightning.network/lightning-network-paper.pdf) - This is the white paper that kicked off the Layer 2 revolution. Having a good graps of the concepts of Lightning will make the core logic within the daemon much more comprehensible: Bitcoin Script, off-chain blockchain protocols, payment channels, bi-directional payment channels, relative and absolute time-locks, commitment state revocations, and Segregated Witness.
|
||||
- The original LN was written for a rather narrow audience, the paper may be a bit unapproachable to many. Thanks to the Bitcoin community, there exist many easily accessible suplemental resources which can help one see how all the pieces fit together from double-spend protection all the way up to commitment state transitions and Hash Time Locked Contracts (HTLC's):
|
||||
- [Lightning Network Summary](https://lightning.network/lightning-network-summary.pdf)
|
||||
- [Understanding the Lightning Network 3-Part series](https://bitcoinmagazine.com/articles/understanding-the-lightning-network-part-building-a-bidirectional-payment-channel-1464710791)
|
||||
- [Deployable Lightning](https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf)
|
||||
|
||||
|
||||
Note that the core design of the Lightning Network has shifted over time as
|
||||
concrete implementation and design has expanded our knowledge beyond the
|
||||
original white paper. Therefore, specific information outlined in the resources
|
||||
above may be a bit out of date. Many implementers are currently working on an
|
||||
initial [Version 1 Specification](https://medium.com/@lightningnetwork/lightning-network-meeting-on-interoperability-and-specifications-ea49e47696a4).
|
||||
Once the specification is finalized, it will be the most up-to-date
|
||||
comprehensive document explaining the Lightning Network. As a result, it will
|
||||
be recommened for new comers to read first in order to get up to speed.
|
||||
|
||||
<a name="DevelopmentPractices" />
|
||||
### 4. Development Practices
|
||||
|
||||
Developers are expected to work in their own trees and submit pull requests when
|
||||
they feel their feature or bug fix is ready for integration into the master
|
||||
branch.
|
||||
|
||||
<a name="ShareEarly" />
|
||||
### 4.1 Share Early, Share Often
|
||||
|
||||
We firmly believe in the share early, share often approach. The basic premise
|
||||
of the approach is to announce your plans **before** you start work, and once
|
||||
you have started working, craft your changes into a stream of small and easily
|
||||
reviewable commits.
|
||||
|
||||
This approach has several benefits:
|
||||
|
||||
- Announcing your plans to work on a feature **before** you begin work avoids
|
||||
duplicate work
|
||||
- It permits discussions which can help you achieve your goals in a way that is
|
||||
consistent with the existing architecture
|
||||
- It minimizes the chances of you spending time and energy on a change that
|
||||
might not fit with the consensus of the community or existing architecture and
|
||||
potentially be rejected as a result
|
||||
- The quicker your changes are merged to master, the less time you will need to
|
||||
spend rebasing and otherwise trying to keep up with the main code base
|
||||
|
||||
<a name="Testing" />
|
||||
### 4.2 Testing
|
||||
|
||||
One of the major design goals of all of lnd's packages and the daemon itself is
|
||||
to aim for a high degree of test coverage. This is financial software so bugs
|
||||
and regressions in the core logic can cost people real money. For this reason
|
||||
every effort must be taken to ensure the code is as accurate and bug-free as
|
||||
possible. Thorough testing is a good way to help achieve that goal.
|
||||
|
||||
Unless a new feature you submit is completely trivial, it will probably be
|
||||
rejected unless it is also accompanied by adequate test coverage for both
|
||||
positive and negative conditions. That is to say, the tests must ensure your
|
||||
code works correctly when it is fed correct data as well as incorrect data
|
||||
(error paths).
|
||||
|
||||
|
||||
Go provides an excellent test framework that makes writing test code and
|
||||
checking coverage statistics straight forward. For more information about the
|
||||
test coverage tools, see the [golang cover blog post](http://blog.golang.org/cover).
|
||||
|
||||
A quick summary of test practices follows:
|
||||
- All new code should be accompanied by tests that ensure the code behaves
|
||||
correctly when given expected values, and, perhaps even more importantly, that
|
||||
it handles errors gracefully
|
||||
- When you fix a bug, it should be accompanied by tests which exercise the bug
|
||||
to both prove it has been resolved and to prevent future regressions
|
||||
- Changes to publicly exported packages such as
|
||||
[brontide](https://github.com/lightningnetwork/lnd/tree/master/brontide) should
|
||||
be accompanied by unittest excersising the new or changed behavior.
|
||||
- Changes to behavior within the daemon's interaction with the P2P protocol,
|
||||
or RPC's will need to be accompanied by integration tests which use the
|
||||
[`networkHarness`framework](https://github.com/lightningnetwork/lnd/blob/master/networktest.go)
|
||||
contained within `lnd`. For example integration tests, see
|
||||
[`lnd_test.go`](https://github.com/lightningnetwork/lnd/blob/master/lnd_test.go#L181).
|
||||
|
||||
<a name="CodeDocumentation" />
|
||||
### 4.3 Code Documentation and Commenting
|
||||
|
||||
- At a minimum every function must be commented with its intended purpose and
|
||||
any assumptions that it makes
|
||||
- Function comments must always begin with the name of the function per
|
||||
[Effective Go](http://golang.org/doc/effective_go.html)
|
||||
- Function comments should be complete sentences since they allow a wide
|
||||
variety of automated presentations such as [godoc.org](https://godoc.org)
|
||||
- The general rule of thumb is to look at it as if you were completely
|
||||
unfamiliar with the code and ask yourself, would this give me enough
|
||||
information to understand what this function does and how I'd probably want
|
||||
to use it?
|
||||
- Exported functions should also include detailed information the caller of the
|
||||
function will likely need to know and/or understand:<br /><br />
|
||||
**WRONG**
|
||||
```go
|
||||
// generates a revocation key
|
||||
func DeriveRevocationPubkey(commitPubKey *btcec.PublicKey,
|
||||
revokePreimage []byte) *btcec.PublicKey {
|
||||
```
|
||||
**RIGHT**
|
||||
```go
|
||||
// DeriveRevocationPubkey derives the revocation public key given the
|
||||
// counter-party's commitment key, and revocation pre-image derived via a
|
||||
// pseudo-random-function. In the event that we (for some reason) broadcast a
|
||||
// revoked commitment transaction, then if the other party knows the revocation
|
||||
// pre-image, then they'll be able to derive the corresponding private key to
|
||||
// this private key by exploiting the homomorphism in the elliptic curve group:
|
||||
// * https://en.wikipedia.org/wiki/Group_homomorphism#Homomorphisms_of_abelian_groups
|
||||
//
|
||||
// The derivation is performed as follows:
|
||||
//
|
||||
// revokeKey := commitKey + revokePoint
|
||||
// := G*k + G*h
|
||||
// := G * (k+h)
|
||||
//
|
||||
// Therefore, once we divulge the revocation pre-image, the remote peer is able to
|
||||
// compute the proper private key for the revokeKey by computing:
|
||||
// revokePriv := commitPriv + revokePreimge mod N
|
||||
//
|
||||
// Where N is the order of the sub-group.
|
||||
func DeriveRevocationPubkey(commitPubKey *btcec.PublicKey,
|
||||
revokePreimage []byte) *btcec.PublicKey {
|
||||
```
|
||||
- Comments in the body of the code are highly encouraged, but they should
|
||||
explain the intention of the code as opposed to just calling out the
|
||||
obvious<br /><br />
|
||||
**WRONG**
|
||||
```Go
|
||||
// return err if amt is less than 546
|
||||
if amt < 546 {
|
||||
return err
|
||||
}
|
||||
```
|
||||
**RIGHT**
|
||||
```go
|
||||
// Treat transactions with amounts less than the amount which is considered dust
|
||||
// as non-standard.
|
||||
if amt < 546 {
|
||||
return err
|
||||
}
|
||||
```
|
||||
**NOTE:** The above should really use a constant as opposed to a magic number,
|
||||
but it was left as a magic number to show how much of a difference a good
|
||||
comment can make.
|
||||
|
||||
<a name="ModelGitCommitMessages" />
|
||||
### 4.4 Code Documentation and Commenting
|
||||
|
||||
This project prefers to keep a clean commit history with well-formed commit
|
||||
messages. This section illustrates a model commit message and provides a bit
|
||||
of background for it. This content was originally created by Tim Pope and made
|
||||
available on his website, however that website is no longer active, so it is
|
||||
being provided here.
|
||||
|
||||
Here’s a model Git commit message:
|
||||
|
||||
```
|
||||
Short (50 chars or less) summary of changes
|
||||
|
||||
More detailed explanatory text, if necessary. Wrap it to about 72
|
||||
characters or so. In some contexts, the first line is treated as the
|
||||
subject of an email and the rest of the text as the body. The blank
|
||||
line separating the summary from the body is critical (unless you omit
|
||||
the body entirely); tools like rebase can get confused if you run the
|
||||
two together.
|
||||
|
||||
Write your commit message in the present tense: "Fix bug" and not "Fixed
|
||||
bug." This convention matches up with commit messages generated by
|
||||
commands like git merge and git revert.
|
||||
|
||||
Further paragraphs come after blank lines.
|
||||
|
||||
- Bullet points are okay, too
|
||||
- Typically a hyphen or asterisk is used for the bullet, preceded by a
|
||||
single space, with blank lines in between, but conventions vary here
|
||||
- Use a hanging indent
|
||||
```
|
||||
|
||||
Here are some of the reasons why wrapping your commit messages to 72 columns is
|
||||
a good thing.
|
||||
|
||||
- git log doesn’t do any special special wrapping of the commit messages. With
|
||||
the default pager of less -S, this means your paragraphs flow far off the edge
|
||||
of the screen, making them difficult to read. On an 80 column terminal, if we
|
||||
subtract 4 columns for the indent on the left and 4 more for symmetry on the
|
||||
right, we’re left with 72 columns.
|
||||
- git format-patch --stdout converts a series of commits to a series of emails,
|
||||
using the messages for the message body. Good email netiquette dictates we
|
||||
wrap our plain text emails such that there’s room for a few levels of nested
|
||||
reply indicators without overflow in an 80 column terminal.
|
||||
|
||||
In addition to the Git commit message structure adhered to within the daemon
|
||||
all short-[commit messages are to be prefixed according to the convention
|
||||
outlined in the Go project](https://golang.org/doc/contribute.html#change). All
|
||||
commits should begin with the sub-system or package primarliy affected by the
|
||||
change. In the case of a widespread change, the packages are to be delimited by
|
||||
either a '+' or a ','. This prefix seems minor but can be extremly helpful it
|
||||
determining the scope of a commit at a glance, or when bug hunting to find a
|
||||
commit which introduced a bug or regression.
|
||||
|
||||
<a name="CodeSpacing" />
|
||||
### 4.5 Code Spacing
|
||||
|
||||
Blocks of code within lnd should be segmented into logical stanzas of
|
||||
operation. Such spacing makes the code easier to follow at a skim, and reduces
|
||||
uncessary line noise. Coupled commenting scheme specified above, proper spacing
|
||||
allows readers to quickly scan code, extracting semantics quickly. Functions
|
||||
should _not_ just be layed out as a bare contigious block of code.
|
||||
|
||||
- **Wrong**
|
||||
```go
|
||||
witness := make([][]byte, 4)
|
||||
witness[0] = nil
|
||||
if bytes.Compare(pubA, pubB) == -1 {
|
||||
witness[1] = sigB
|
||||
witness[2] = sigA
|
||||
} else {
|
||||
witness[1] = sigA
|
||||
witness[2] = sigB
|
||||
}
|
||||
witness[3] = witnessScript
|
||||
return witness
|
||||
```
|
||||
- **Right**
|
||||
```go
|
||||
witness := make([][]byte, 4)
|
||||
|
||||
// When spending a p2wsh multi-sig script, rather than an OP_0, we add
|
||||
// a nil stack element to eat the extra pop.
|
||||
witness[0] = nil
|
||||
|
||||
// When initially generating the witnessScript, we sorted the serialized
|
||||
// public keys in descending order. So we do a quick comparison in order
|
||||
// ensure the signatures appear on the Script Virtual Machine stack in
|
||||
// the correct order.
|
||||
if bytes.Compare(pubA, pubB) == -1 {
|
||||
witness[1] = sigB
|
||||
witness[2] = sigA
|
||||
} else {
|
||||
witness[1] = sigA
|
||||
witness[2] = sigB
|
||||
}
|
||||
|
||||
// Finally, add the pre-image as the last witness element.
|
||||
witness[3] = witnessScript
|
||||
|
||||
return witness
|
||||
```
|
||||
|
||||
<a name="CodeApproval" />
|
||||
### 5. Code Approval Process
|
||||
|
||||
This section describes the code approval process that is used for code
|
||||
contributions. This is how to get your changes into btcd.
|
||||
|
||||
<a name="CodeReview" />
|
||||
### 5.1 Code Review
|
||||
|
||||
All code which is submitted will need to be reviewed before inclusion into the
|
||||
master branch. This process is performed by the project maintainers and usually
|
||||
other committers who are interested in the area you are working in as well.
|
||||
|
||||
##### Code Review Timeframe
|
||||
|
||||
The timeframe for a code review will vary greatly depending on factors such as
|
||||
the number of other pull requests which need to be reviewed, the size and
|
||||
complexity of the contribution, how well you followed the guidelines presented
|
||||
on this page, and how easy it is for the reviewers to digest your commits. For
|
||||
example, if you make one monolithic commit that makes sweeping changes to things
|
||||
in multiple subsystems, it will obviously take much longer to review. You will
|
||||
also likely be asked to split the commit into several smaller, and hence more
|
||||
manageable, commits.
|
||||
|
||||
Keeping the above in mind, most small changes will be reviewed within a few
|
||||
days, while large or far reaching changes may take weeks. This is a good reason
|
||||
to stick with the [Share Early, Share Often](#ShareOften) development practice
|
||||
outlined above.
|
||||
|
||||
##### What is the review looking for?
|
||||
|
||||
The review is mainly ensuring the code follows the [Development Practices](#DevelopmentPractices)
|
||||
and [Code Contribution Standards](#Standards). However, there are a few other
|
||||
checks which are generally performed as follows:
|
||||
|
||||
- The code is stable and has no stability or security concerns
|
||||
- The code is properly using existing APIs and generally fits well into the
|
||||
overall architecture
|
||||
- The change is not something which is deemed inappropriate by community
|
||||
consensus
|
||||
|
||||
<a name="CodeRework" />
|
||||
### 5.2 Rework Code (if needed)
|
||||
|
||||
After the code review, the change will be accepted immediately if no issues are
|
||||
found. If there are any concerns or questions, you will be provided with
|
||||
feedback along with the next steps needed to get your contribution merged with
|
||||
master. In certain cases the code reviewer(s) or interested committers may help
|
||||
you rework the code, but generally you will simply be given feedback for you to
|
||||
make the necessary changes.
|
||||
|
||||
This process will continue until the code is finally accepted.
|
||||
|
||||
<a name="CodeAcceptance" />
|
||||
### 5.3 Acceptance
|
||||
|
||||
Once your code is accepted, it will be integrated with the master branch.
|
||||
Typically it will be rebased and fast-forward merged to master as we prefer to
|
||||
keep a clean commit history over a tangled weave of merge commits. However,
|
||||
regardless of the specific merge method used, the code will be integrated with
|
||||
the master branch and the pull request will be closed.
|
||||
|
||||
Rejoice as you will now be listed as a [contributor](https://github.com/lightningnetwork/lnd/graphs/contributors)!
|
||||
|
||||
<a name="Standards" />
|
||||
### 6. Contribution Standards
|
||||
|
||||
<a name="Checklist" />
|
||||
### 6.1. Contribution Checklist
|
||||
|
||||
- [ ] All changes are Go version 1.5 compliant
|
||||
- [ ] The code being submitted is commented according to the
|
||||
[Code Documentation and Commenting](#CodeDocumentation) section
|
||||
- [ ] For new code: Code is accompanied by tests which exercise both
|
||||
the positive and negative (error paths) conditions (if applicable)
|
||||
- [ ] For bug fixes: Code is accompanied by new tests which trigger
|
||||
the bug being fixed to prevent regressions
|
||||
- [ ] Any new logging statements use an appropriate subsystem and
|
||||
logging level
|
||||
- [ ] Code has been formatted with `go fmt`
|
||||
- [ ] Running `go test` does not fail any tests
|
||||
- [ ] Running `go vet` does not report any issues
|
||||
- [ ] Running [golint](https://github.com/golang/lint) does not
|
||||
report any **new** issues that did not already exist
|
||||
|
||||
<a name="Licensing" />
|
||||
### 6.2. Licensing of Contributions
|
||||
****
|
||||
All contributions must be licensed with the
|
||||
[MIT license](https://github.com/lightningnetwork/lnd/blob/master/LICENSE). This is
|
||||
the same license as all of the code found within lnd.
|
||||
|
||||
|
||||
## Aknolwedgements
|
||||
This document was heavily inspired by a [similar document outlining the code
|
||||
contribution](https://github.com/btcsuite/btcd/blob/master/docs/code_contribution_guidelines.md)
|
||||
guidelines for btcd.
|
Loading…
Reference in New Issue
Block a user