prysm-pulse/third_party/README.md

142 lines
5.3 KiB
Markdown
Raw Normal View History

# Third Party Package Patching
This directory includes local patches to third party dependencies we use in Prysm. Sometimes,
we need to make a small change to some dependency for ease of use in Prysm without wanting
to maintain our own fork of the dependency ourselves. Our build tool, [Bazel](https://bazel.build)
allows us to include patches in a seamless manner based on simple diff rules.
This README outlines how patching works in Prysm and an explanation of previously
created patches.
**Given maintaining a patch can be difficult and tedious,
patches are NOT the recommended way of modifying dependencies in Prysm
unless really needed**
## Table of Contents
- [Prerequisites](#prerequisites)
- [Creating a Patch](#creating-a-patch)
- [Ethereum APIs Patch](#ethereum-apis-patch)
- [Updating Patches](#updating-patches)
## Prerequisites
**Bazel Installation:**
- The latest release of [Bazel](https://docs.bazel.build/versions/master/install.html)
- A modern UNIX operating system (MacOS included)
## Creating a Patch
To create a patch, we need an original version of a dependency which we will refer to as `a`
and the patched version referred to as `b`.
```
cd /tmp
git clone https://github.com/someteam/somerepo a
git clone https://github.com/someteam/somerepo b && cd b
```
Then, make all your changes in `b` and finally create the diff of all your changes as follows:
```
cd ..
diff -ur --exclude=".git" a b > $GOPATH/src/github.com/prysmaticlabs/prysm/third_party/YOURPATCH.patch
```
Next, we need to tell the Bazel [WORKSPACE](https://github.com/prysmaticlabs/prysm/blob/master/WORKSPACE) to patch the specific dependency.
Here's an example for a patch we use today for the [Ethereum APIs](https://github.com/prysmaticlabs/ethereumapis)
dependency:
```
go_repository(
name = "com_github_prysmaticlabs_ethereumapis",
commit = "367ca574419a062ae26818f60bdeb5751a6f538",
patch_args = ["-p1"],
patches = [
"//third_party:com_github_prysmaticlabs_ethereumapis-tags.patch",
],
importpath = "github.com/prysmaticlabs/ethereumapis",
)
```
Now, when used in Prysm, the dependency you patched will have the patched modifications
when you run your code.
## Ethereum APIs Patch
As mentioned earlier, patches aren't a recommended approach when needing to modify dependencies
in Prysm save for a few use cases. In particular, all of our public APIs and most canonical
data structures for Prysm are kept in the [Ethereum APIs](https://github.com/prysmaticlabs/ethereumapis) repo.
The purpose of the repo is to serve as a well-documented, well-maintained schema for a full-featured
eth2 API. It is written in protobuf format, and specifies JSON over HTTP mappings as well
as a [Swagger API](https://api.prylabs.network) front-end configuration.
The Prysm repo specifically requires its data structures to have certain struct tags
for serialization purposes as well as other package-related annotations for proper functionality.
Given a protobuf schema is meant to be generic, easily readable, accessible, and language agnostic
(at least for languages which support protobuf generation), it would be wrong for us to include
Go-specific annotations in the Ethereum APIs repo. Instead of maintaining a duplicate of it
within Prysm, we can apply a patch to include those struct tags as needed, while being able
to use the latest changes in the Ethereum APIs repo. This is an appropriate use-case for a patch.
Here's an example:
```
// The block body of an Ethereum 2.0 beacon block.
message BeaconBlockBody {
// The validators RANDAO reveal 96 byte value.
- bytes randao_reveal = 1;
+ bytes randao_reveal = 1 [(gogoproto.moretags) = "ssz-size:\"96\""];
// A reference to the Ethereum 1.x chain.
Eth1Data eth1_data = 2;
// 32 byte field of arbitrary data. This field may contain any data and
// is not used for anything other than a fun message.
- bytes graffiti = 3;
+ bytes graffiti = 3 [(gogoproto.moretags) = "ssz-size:\"32\""];
...
}
```
Above, we're telling Prysm to patch a few lines to include protobuf tags
for SSZ (the serialization library used by Prysm).
## Updating Patches
Say a new change was pushed out to a dependency you're patching in Prysm. In order to update your
patch or add any other modifications, you would need to:
1. First, clone the repo of the dependency you're patching and the specific commit Prysm is
currently using for the dependency in the WORKSPACE file. For example, Ethereum APIs could have
the following definition in the WORKSPACE:
```
go_repository(
name = "com_github_prysmaticlabs_ethereumapis",
commit = "367ca574419a062ae26818f60bdeb5751a6f538",
...
```
Then, checkout that commit
```
git clone https://github.com/prysmaticlabs/ethereumapis && cd ethereumapis
git checkout 367ca574419a062ae26818f60bdeb5751a6f538
```
2. Apply the patch currently in Prysm
```
git apply $GOPATH/src/github.com/prysmaticlabs/prysm/third_party/somepatch.patch
```
3. Resolve any conflicts, commit the changes you want to make
```
git commit -m 'added more changes since patch'
```
4. Generate a new diff by comparing your latest changes to the original commit
the patch was for and output it directly into Prysm's third_party directory
```
git diff 367ca574419a062ae26818f60bdeb5751a6f538 > $GOPATH/src/github.com/prysmaticlabs/prysm/third_party/somepatch.patch
```
5. Build Prysm and ensure tests pass
```
bazel test //...
```