Compare commits
69 Commits
master
...
service_pr
Author | SHA1 | Date |
---|---|---|
Aditya Kulkarni | f913c64e6f | 5 years ago |
Marshall Gaucher | 50a2667703 | 5 years ago |
Larry Ruane | e4445ddace | 5 years ago |
Larry Ruane | 886250e660 | 5 years ago |
Marshall Gaucher | ac5aa8e42f | 5 years ago |
Marshall Gaucher | 57b12e5841 | 5 years ago |
Marshall Gaucher | 6e2bb5b62b | 5 years ago |
mdr0id | 2d2007925a | 5 years ago |
mdr0id | f2c657e877 | 5 years ago |
mdr0id | f3023fc5b5 | 5 years ago |
mdr0id | 6f909b1443 | 5 years ago |
Marshall Gaucher | 12119fa13d | 5 years ago |
Marshall Gaucher | e3a7c58f1d | 5 years ago |
Marshall Gaucher | 6b04ab1449 | 5 years ago |
Marshall Gaucher | caddc14410 | 5 years ago |
Marshall Gaucher | 559a04b145 | 5 years ago |
Marshall Gaucher | b4ade08c89 | 5 years ago |
Marshall Gaucher | 4b6b77336a | 5 years ago |
Marshall Gaucher | e7e200ede3 | 5 years ago |
mdr0id | 1e8cfac8a9 | 5 years ago |
Marshall Gaucher | a457821949 | 5 years ago |
mdr0id | 13280b15e6 | 5 years ago |
mdr0id | c47132e63b | 5 years ago |
mdr0id | 2f13056825 | 5 years ago |
Marshall Gaucher | 0cc64dd8f1 | 5 years ago |
Larry Ruane | 20763199c1 | 5 years ago |
Larry Ruane | da2231f423 | 5 years ago |
Marshall Gaucher | 6302175a00 | 5 years ago |
Marshall Gaucher | bc6e857e72 | 5 years ago |
Dimitris Apostolou | e8d93c0687 | 5 years ago |
mdr0id | 86b915288c | 5 years ago |
Larry Ruane | 20d0a040e3 | 5 years ago |
Marshall Gaucher | 6f01d40f2e | 5 years ago |
mdr0id | d285e34775 | 5 years ago |
Marshall Gaucher | 57128c12d7 | 5 years ago |
Marshall Gaucher | 094c2f08e4 | 5 years ago |
Marshall Gaucher | 9a1b929b1e | 5 years ago |
Marshall Gaucher | 5b675f9102 | 5 years ago |
Marshall Gaucher | 5b9b54aa50 | 5 years ago |
Marshall Gaucher | 0e96c9d855 | 5 years ago |
Marshall Gaucher | 5f37c7ed68 | 5 years ago |
Marshall Gaucher | 6ac80494ab | 5 years ago |
Marshall Gaucher | 7c0883ebfc | 5 years ago |
Marshall Gaucher | 1a24524691 | 5 years ago |
Marshall Gaucher | 13245d99ea | 5 years ago |
Marshall Gaucher | a9a1da015b | 5 years ago |
Marshall Gaucher | b246be3e45 | 5 years ago |
Marshall Gaucher | b141021ac0 | 5 years ago |
Taylor Hornby | 5224340b92 | 5 years ago |
Marshall Gaucher | c1279fa239 | 5 years ago |
Marshall Gaucher | 7e34619fb8 | 5 years ago |
Marshall Gaucher | ef2e78e850 | 5 years ago |
Marshall Gaucher | 731b3393d9 | 5 years ago |
mdr0id | b86dda72e5 | 5 years ago |
Marshall Gaucher | c5b37391ed | 5 years ago |
Marshall Gaucher | ce12fee640 | 5 years ago |
mdr0id | ecf43dc353 | 5 years ago |
Marshall Gaucher | a91acdbdec | 5 years ago |
mdr0id | 4a2d22ca3a | 5 years ago |
mdr0id | 28ed413092 | 5 years ago |
mdr0id | 42eb73db32 | 5 years ago |
mdr0id | 148a1da8c7 | 5 years ago |
Francisco Gindre | 9f6cf742b6 | 5 years ago |
zebambam | fc6c2f1342 | 5 years ago |
zebambam | f1ac9c1337 | 5 years ago |
mdr0id | ea3b3c119f | 5 years ago |
mdr0id | f8a0274f7d | 5 years ago |
str4d | f2aacce0ca | 5 years ago |
mdr0id | ed4591ecc4 | 5 years ago |
26 changed files with 1387 additions and 126 deletions
@ -0,0 +1,7 @@ |
|||
*.conf |
|||
*.config |
|||
*.log |
|||
*.sqlite |
|||
*.pem |
|||
*.key |
|||
*.elf |
@ -0,0 +1,122 @@ |
|||
# /************************************************************************ |
|||
# File: .gitlab-ci.yml |
|||
# Author: mdr0id |
|||
# Date: 7/16/2019 |
|||
# Description: Used to setup runners/jobs for lightwalletd |
|||
# Usage: Commit source and the pipeline will trigger the according jobs. |
|||
# |
|||
# Known bugs/missing features: |
|||
# |
|||
# IMPORTANT NOTE: any job with preceeding '.'' is ignored in pipeline |
|||
# ************************************************************************/ |
|||
|
|||
image: golang:1.11-alpine |
|||
|
|||
stages: |
|||
- build |
|||
- test |
|||
- deploy |
|||
- monitor |
|||
|
|||
before_script: |
|||
- apk update && apk add make git gcc musl-dev curl bash |
|||
|
|||
# ************************************************************************/ |
|||
# BUILD |
|||
# ************************************************************************/ |
|||
.lint-check: |
|||
stage: build |
|||
script: |
|||
- make lint |
|||
|
|||
.build-docs: |
|||
stage: build |
|||
script: |
|||
- made docs |
|||
|
|||
build:build-linux: |
|||
stage: build |
|||
script: |
|||
- make |
|||
artifacts: |
|||
paths: |
|||
- ./server |
|||
- ./ingest |
|||
|
|||
.build-windows: |
|||
stage: build |
|||
script: |
|||
- make |
|||
|
|||
.build-mac: |
|||
stage: build |
|||
script: |
|||
- make |
|||
|
|||
# Build against latest Golang |
|||
.build-latest: |
|||
stage: build |
|||
image: golang:latest-alpine |
|||
script: |
|||
- make |
|||
allow_failure: true |
|||
|
|||
# ************************************************************************/ |
|||
# TEST |
|||
# ************************************************************************/ |
|||
test:test-unittest: |
|||
stage: test |
|||
dependencies: |
|||
- build:build-linux |
|||
script: |
|||
- make test |
|||
after_script: |
|||
- bash <(curl -s https://codecov.io/bash) -t $CODECOV_TOKEN |
|||
|
|||
.test:test-race-conditions: |
|||
stage: test |
|||
dependencies: |
|||
- build:build-linux |
|||
script: |
|||
- make race |
|||
allow_failure: true |
|||
|
|||
test:test-coverage: |
|||
stage: test |
|||
dependencies: |
|||
- build:build-linux |
|||
script: |
|||
- make coverage |
|||
- make coverage_report |
|||
- make coverage_html |
|||
after_script: |
|||
- bash <(curl -s https://codecov.io/bash) -t $CODECOV_TOKEN |
|||
artifacts: |
|||
paths: |
|||
- ./coverage.html |
|||
|
|||
# ************************************************************************/ |
|||
# DEPLOY |
|||
# ************************************************************************/ |
|||
.release-candidate: |
|||
stage: deploy |
|||
script: |
|||
- echo "Generating v0.0.1-rc" |
|||
when: manual |
|||
|
|||
.release-production: |
|||
stage: deploy |
|||
script: |
|||
- echo "Generating v0.0.1" |
|||
when: manual |
|||
|
|||
|
|||
# ************************************************************************/ |
|||
# MONITOR |
|||
# ************************************************************************/ |
|||
.monitor-release: |
|||
stage: deploy |
|||
script: |
|||
- echo "Building docker image for v0.0.0" |
|||
- make image |
|||
when: manual |
@ -0,0 +1,53 @@ |
|||
# Contributor Code of Conduct |
|||
|
|||
As contributors and maintainers of this project, and in the interest of |
|||
fostering an open and welcoming community, we pledge to respect all people who |
|||
contribute through reporting issues, posting feature requests, updating |
|||
documentation, submitting pull requests or patches, and other activities. |
|||
|
|||
We are committed to making participation in this project a harassment-free |
|||
experience for everyone, regardless of level of experience, gender, gender |
|||
identity and expression, sexual orientation, disability, personal appearance, |
|||
body size, race, ethnicity, age, religion, or nationality. |
|||
|
|||
Examples of unacceptable behavior by participants include: |
|||
|
|||
* The use of sexualized language or imagery |
|||
* Personal attacks |
|||
* Trolling or insulting/derogatory comments |
|||
* Public or private harassment |
|||
* Publishing other's private information, such as physical or electronic |
|||
addresses, without explicit permission |
|||
* Other unethical or unprofessional conduct |
|||
|
|||
Project maintainers have the right and responsibility to remove, edit, or |
|||
reject comments, commits, code, wiki edits, issues, and other contributions |
|||
that are not aligned to this Code of Conduct, or to ban temporarily or |
|||
permanently any contributor for other behaviors that they deem inappropriate, |
|||
threatening, offensive, or harmful. |
|||
|
|||
By adopting this Code of Conduct, project maintainers commit themselves to |
|||
fairly and consistently applying these principles to every aspect of managing |
|||
this project. Project maintainers who do not follow or enforce the Code of |
|||
Conduct may be permanently removed from the project team. |
|||
|
|||
This Code of Conduct applies both within project spaces and in public spaces |
|||
when an individual is representing the project or its community. |
|||
|
|||
Instances of abusive, harassing, or otherwise unacceptable behavior may be |
|||
reported by contacting a project maintainer (see below). All |
|||
complaints will be reviewed and investigated and will result in a response that |
|||
is deemed necessary and appropriate to the circumstances. Maintainers are |
|||
obligated to maintain confidentiality with regard to the reporter of an |
|||
incident. |
|||
|
|||
If you wish to contact specific maintainers directly, the following have made |
|||
themselves available for conduct issues: |
|||
|
|||
- Marshall Gaucher (marshall@z.cash) |
|||
- Larry Ruane (larry@z.cash) |
|||
|
|||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], |
|||
version 1.3.0, available at https://www.contributor-covenant.org/version/1/3/0/code-of-conduct.html |
|||
|
|||
[homepage]: https://www.contributor-covenant.org |
@ -0,0 +1,207 @@ |
|||
# Development Workflow |
|||
This document describes the standard workflows and terminology for developers at Zcash. It is intended to provide procedures that will allow users to contribute to the open-source code base. Below are common workflows users will encounter: |
|||
|
|||
1. Fork lightwalletd Repository |
|||
2. Create Branch |
|||
3. Make & Commit Changes |
|||
4. Create Pull Request |
|||
5. Discuss / Review PR |
|||
6. Deploy / Merge PR |
|||
|
|||
Before continuing, please ensure you have an existing GitHub or GitLab account. If not, visit [GitHub](https://github.com) or [GitLab](https://gitlab.com) to create an account. |
|||
|
|||
## Fork Repository |
|||
This step assumes you are starting with a new GitHub/GitLab environment. If you have already forked the Lightwalletd repository, please continue to [Create Branch] section. Otherwise, open up a terminal and issue the below commands: |
|||
|
|||
Note: Please replace `your_username`, with your actual GitHub username |
|||
|
|||
```bash |
|||
git clone git@github.com:your_username/lightwalletd.git |
|||
cd lightwalletd |
|||
git remote set-url origin git@github.com:your_username/lightwalletd.git |
|||
git remote add upstream git@github.com:zcash-hackworks/lightwalletd.git |
|||
git remote set-url --push upstream DISABLED |
|||
git fetch upstream |
|||
git branch -u upstream/master master |
|||
``` |
|||
After issuing the above commands, your `.git/config` file should look similar to the following: |
|||
|
|||
```bash |
|||
[core] |
|||
repositoryformatversion = 0 |
|||
filemode = true |
|||
bare = false |
|||
logallrefupdates = true |
|||
[remote "origin"] |
|||
url = git@github.com:your_username/lightwalletd.git |
|||
fetch = +refs/heads/*:refs/remotes/origin/* |
|||
[branch "master"] |
|||
remote = upstream |
|||
merge = refs/heads/master |
|||
[remote "upstream"] |
|||
url = git@github.com:zcash-hackworks/lightalletd.git |
|||
fetch = +refs/heads/*:refs/remotes/upstream/* |
|||
pushurl = DISABLED |
|||
``` |
|||
This setup provides a single cloned environment to develop for Lightwalletd. There are alternative methods using multiple clones, but this document does not cover that process. |
|||
|
|||
## Create Branch |
|||
While working on the Lightwalletd project, you are going to have bugs, features, and ideas to work on. Branching exists to aid these different tasks while you write code. Below are some conventions of branching at Zcash: |
|||
|
|||
1. `master` branch is **ALWAYS** deployable |
|||
2. Branch names **MUST** be descriptive: |
|||
* General format: `issue#_short_description` |
|||
|
|||
To create a new branch (assuming you are in `lightwalletd` directory): |
|||
|
|||
```bash |
|||
git checkout -b [new_branch_name] |
|||
``` |
|||
Note: Even though you have created a new branch, until you `git push` this local branch, it will not show up in your Lightwalletd fork on GitHub (e.g. https://github.com/your_username/lightwalletd) |
|||
|
|||
To checkout an existing branch (assuming you are in `lightwalletd` directory): |
|||
|
|||
```bash |
|||
git checkout [existing_branch_name] |
|||
``` |
|||
If you are fixing a bug or implementing a new feature, you likely will want to create a new branch. If you are reviewing code or working on existing branches, you likely will checkout an existing branch. To view the list of current Lightwalletd GitHub issues, click [here](https://github.com/zcash-hackworks/lightwalletd/issues). |
|||
|
|||
## Make & Commit Changes |
|||
If you have created a new branch or checked out an existing one, it is time to make changes to your local source code. Below are some formalities for commits: |
|||
|
|||
1. Commit messages **MUST** be clear |
|||
2. Commit messages **MUST** be descriptive |
|||
3. Commit messages **MUST** be clean (see squashing commits for details) |
|||
|
|||
While continuing to do development on a branch, keep in mind that other approved commits are getting merged into `master`. In order to ensure there are minimal to no merge conflicts, we need `rebase` with master. |
|||
|
|||
If you are new to this process, please sanity check your remotes: |
|||
|
|||
``` |
|||
git remote -v |
|||
``` |
|||
```bash |
|||
origin git@github.com:your_username/lightwalletd.git (fetch) |
|||
origin git@github.com:your_username/lightwalletd.git (push) |
|||
upstream git@github.com:zcash-hackworks/lightwalletd.git (fetch) |
|||
upstream DISABLED (push) |
|||
``` |
|||
This output should be consistent with your `.git/config`: |
|||
|
|||
```bash |
|||
[branch "master"] |
|||
remote = upstream |
|||
merge = refs/heads/master |
|||
[remote "origin"] |
|||
url = git@github.com:your_username/lightwalletd.git |
|||
fetch = +refs/heads/*:refs/remotes/origin/* |
|||
[remote "upstream"] |
|||
url = git@github.com:zcash-hackworks/lightwalletd.git |
|||
fetch = +refs/heads/*:refs/remotes/upstream/* |
|||
pushurl = DISABLED |
|||
``` |
|||
Once you have confirmed your branch/remote is valid, issue the following commands (assumes you have **NO** existing uncommitted changes): |
|||
|
|||
```bash |
|||
git fetch upstream |
|||
git rebase upstream/master |
|||
git push -f |
|||
``` |
|||
If you have uncommitted changes, use `git stash` to preserve them: |
|||
|
|||
```bash |
|||
git stash |
|||
git fetch upstream |
|||
git rebase upstream/master |
|||
git push -f |
|||
git stash pop |
|||
``` |
|||
Using `git stash` allows you to temporarily store your changes while you rebase with `master`. Without this, you will rebase with master and lose your local changes. |
|||
|
|||
Before committing changes, ensure your commit messages follow these guidelines: |
|||
|
|||
1. Separate subject from body with a blank line |
|||
2. Limit the subject line to 50 characters |
|||
3. Capitalize the subject line |
|||
4. Do not end the subject line with a period |
|||
5. Wrap the body at 72 characters |
|||
6. Use the body to explain *what* and *why* vs. *how* |
|||
|
|||
Once synced with `master`, let's commit our changes: |
|||
|
|||
```bash |
|||
git add [files...] # default is all files, be careful not to add unintended files |
|||
git commit -m 'Message describing commit' |
|||
git push |
|||
``` |
|||
Now that all the files changed have been committed, let's continue to Create Pull Request section. |
|||
|
|||
## Create Pull Request |
|||
On your GitHub page (e.g. https://github.com/your_username/lightwalletd), you will notice a newly created banner containing your recent commit with a big green `Compare & pull request`. Click on it. |
|||
|
|||
First, write a brief summary comment for your PR -- this first comment should be no more than a few lines because it ends up in the merge commit message. This comment should mention the issue number preceded by a hash symbol (for example, #2984). |
|||
|
|||
Add a second comment if more explanation is needed. It's important to explain why this pull request should be accepted. State whether the proposed change fixes part of the problem or all of it; if the change is temporary (a workaround) or permanent; if the problem also exists upstream (Bitcoin) and, if so, if and how it was fixed there. |
|||
|
|||
If you click on `Commits`, you should see the diff of that commit; it's advisable to verify it's what you expect. You can also click on the small plus signs that appear when you hover over the lines on either the left or right side and add a comment specific to that part of the code. This is very helpful, as you don't have to tell the reviewers (in a general comment) that you're referring to a certain line in a certain file. |
|||
|
|||
Add comments **before** adding reviewers, otherwise they will get a separate email for each comment you add. Once you're happy with the documentation you've added to your PR, select reviewers along the right side. For a trivial change (like the example here), one reviewer is enough, but generally you should have at least two reviewers, at least one of whom should be experienced. It may be good to add one less experienced engineer as a learning experience for that person. |
|||
|
|||
## Discuss / Review PR |
|||
In order to merge your PR with `master`, you will need to convince the reviewers of the intentions of your code. |
|||
|
|||
**IMPORTANT:** If your PR introduces code that does not have existing tests to ensure it operates gracefully, you **MUST** also create these tests to accompany your PR. |
|||
|
|||
Reviewers will investigate your PR and provide feedback. Generally the comments are explicitly requesting code changes or clarifying implementations. Otherwise Reviewers will reply with PR terminology: |
|||
|
|||
> **Concept ACK** - Agree with the idea and overall direction, but have neither reviewed nor tested the code changes. |
|||
|
|||
> **utACK (untested ACK)**- Reviewed and agree with the code changes but haven't actually tested them. |
|||
|
|||
> **Tested ACK** - Reviewed the code changes and have verified the functionality or bug fix. |
|||
|
|||
> **ACK** - A loose ACK can be confusing. It's best to avoid them unless it's a documentation/comment only change in which case there is nothing to test/verify; therefore the tested/untested distinction is not there. |
|||
|
|||
> **NACK** - Disagree with the code changes/concept. Should be accompanied by an explanation. |
|||
|
|||
### Squashing Commits |
|||
Before your PR is accepted, you might be requested to squash your commits to clean up the logs. This can be done using the following approach: |
|||
|
|||
```bash |
|||
git checkout branch_name |
|||
git rebase -i HEAD~4 |
|||
``` |
|||
The integer value after `~` represents the number of commits you would like to interactively rebase. You can pick a value that makes sense for your situation. A template will pop-up in your terminal requesting you to specify what commands you would like to do with each prior commit: |
|||
|
|||
```bash |
|||
Commands: |
|||
p, pick = use commit |
|||
r, reword = use commit, but edit the commit message |
|||
e, edit = use commit, but stop for amending |
|||
s, squash = use commit, but meld into previous commit |
|||
f, fixup = like "squash", but discard this commit's log message |
|||
x, exec = run command (the rest of the line) using shell |
|||
``` |
|||
Modify each line with the according command, followed by the hash of the commit. For example, if I wanted to squash my last 4 commits into the most recent commit for this PR: |
|||
|
|||
```bash |
|||
p 1fc6c95 Final commit message |
|||
s 6b2481b Third commit message |
|||
s dd1475d Second commit message |
|||
s c619268 First commit message |
|||
``` |
|||
```bash |
|||
git push origin branch-name --force |
|||
``` |
|||
|
|||
## Deploy / Merge PR |
|||
Once your PR/MR has been properly reviewed, it will be ran in the build pipeline to ensure it is valid to merge with master. |
|||
|
|||
Sometimes there will be times when your PR is waiting for some portion of the above process. If you are requested to rebase your PR, in order to gracefully merge into `master`, please do the following: |
|||
|
|||
```bash |
|||
git checkout branch_name |
|||
git fetch upstream |
|||
git rebase upstream/master |
|||
git push -f |
|||
``` |
@ -0,0 +1,102 @@ |
|||
# /************************************************************************ |
|||
# File: Dockerfile |
|||
# Author: mdr0id |
|||
# Date: 9/3/2019 |
|||
# Description: Used for devs that have not built zcash or lightwalletd on |
|||
# on existing system |
|||
# USAGE: |
|||
# |
|||
# To build image: make docker_img |
|||
# To run container: make docker_image_run |
|||
# |
|||
# This will place you into the container where you can run zcashd, zcash-cli, |
|||
# lightwalletd ingester, and lightwalletd server etc.. |
|||
# |
|||
# First you need to get zcashd sync to current height on testnet, from outside container: |
|||
# make docker_img_run_zcashd |
|||
# |
|||
# Sometimes you need to manually start zcashd for the first time, from insdie the container: |
|||
# zcashd -printtoconsole |
|||
# |
|||
# Once the block height is atleast 280,000 you can go ahead and start lightwalletd components |
|||
# make docker_img_run_lightwalletd_ingest |
|||
# make docker_img_run_lightwalletd_insecure_server |
|||
# |
|||
# If you need a random bash session in the container, use: |
|||
# make docker_img_bash |
|||
# |
|||
# If you get kicked out of docker or it locks up... |
|||
# To restart, check to see what container you want to restart via docker ps -a |
|||
# Then, docker restart <container id> |
|||
# The reattach to it, docker attach <container id> |
|||
# |
|||
# Known bugs/missing features/todos: |
|||
# |
|||
# *** DO NOT USE IN PRODUCTION *** |
|||
# |
|||
# - Create docker-compose with according .env scaffolding |
|||
# - Determine librustzcash bug that breaks zcashd alpine builds at runtime |
|||
# - Once versioning is stable add config flags for images |
|||
# - Add mainnet config once lightwalletd stack supports it |
|||
# |
|||
# ************************************************************************/ |
|||
|
|||
# Create layer in case you want to modify local lightwalletd code |
|||
FROM golang:1.11 AS lightwalletd_base |
|||
|
|||
ENV ZCASH_CONF=/root/.zcash/zcash.conf |
|||
ENV LIGHTWALLETD_URL=https://github.com/zcash-hackworks/lightwalletd.git |
|||
|
|||
RUN apt-get update && apt-get install make git gcc |
|||
WORKDIR /home |
|||
|
|||
# Comment out line below to use local lightwalletd repo changes |
|||
RUN git clone ${LIGHTWALLETD_URL} |
|||
|
|||
# To add local changes to container uncomment this line |
|||
#ADD . /home |
|||
|
|||
RUN cd ./lightwalletd && make |
|||
RUN /usr/bin/install -c /home/lightwalletd/ingest /home/lightwalletd/server /usr/bin/ |
|||
|
|||
# Setup layer for zcashd and zcash-cli binary |
|||
FROM golang:1.11 AS zcash_builder |
|||
|
|||
ENV ZCASH_URL=https://github.com/zcash/zcash.git |
|||
|
|||
RUN apt-get update && apt-get install \ |
|||
build-essential pkg-config libc6-dev m4 g++-multilib \ |
|||
autoconf libtool ncurses-dev unzip git python python-zmq \ |
|||
zlib1g-dev wget curl bsdmainutils automake python-pip -y |
|||
|
|||
WORKDIR /build |
|||
RUN git clone ${ZCASH_URL} |
|||
|
|||
RUN ./zcash/zcutil/build.sh -j$(nproc) |
|||
RUN bash ./zcash/zcutil/fetch-params.sh |
|||
RUN /usr/bin/install -c /build/zcash/src/zcashd /build/zcash/src/zcash-cli /usr/bin/ |
|||
|
|||
# Create layer for lightwalletd and zcash binaries to reduce image size |
|||
FROM golang:1.11 AS zcash_runner |
|||
ENV ZCASH_CONF=/root/.zcash/zcash.conf |
|||
|
|||
RUN mkdir -p /root/.zcash/ && \ |
|||
mkdir -p /root/.zcash-params/ && \ |
|||
mkdir /logs/ && \ |
|||
mkdir /db/ |
|||
|
|||
# Use lightwallet server and ingest binaries from prior layer |
|||
COPY --from=lightwalletd_base /usr/bin/ingest /usr/bin/server /usr/bin/ |
|||
COPY --from=zcash_builder /usr/bin/zcashd /usr/bin/zcash-cli /usr/bin/ |
|||
COPY --from=zcash_builder /root/.zcash-params/ /root/.zcash-params/ |
|||
|
|||
# Configure zcash.conf |
|||
RUN echo "testnet=1" >> ${ZCASH_CONF} && \ |
|||
echo "addnode=testnet.z.cash" >> ${ZCASH_CONF} && \ |
|||
echo "rpcbind=127.0.0.1" >> ${ZCASH_CONF} && \ |
|||
echo "rpcport=18232" >> ${ZCASH_CONF} && \ |
|||
echo "rpcuser=lwd" >> ${ZCASH_CONF} && \ |
|||
echo "rpcpassword=`head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''`" >> ${ZCASH_CONF} |
|||
|
|||
VOLUME [/root/.zcash] |
|||
VOLUME [/root/.zcash-params] |
@ -0,0 +1,21 @@ |
|||
MIT License |
|||
|
|||
Copyright (c) 2019 Electric Coin Company |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
@ -0,0 +1,103 @@ |
|||
# /************************************************************************
|
|||
# File: Makefile |
|||
# Author: mdr0id |
|||
# Date: 7/16/2019 |
|||
# Description: Used for local and container dev in CI deployments |
|||
# Usage: make <target_name> |
|||
# |
|||
# Known bugs/missing features: |
|||
# 1. make msan is not stable as of 9/20/2019 |
|||
# |
|||
# ************************************************************************/ |
|||
PROJECT_NAME := "lightwalletd" |
|||
GO_FILES := $(shell find . -name '*.go' | grep -v /vendor/ | grep -v '*_test.go') |
|||
GO_TEST_FILES := $(shell find . -name '*_test.go' -type f | rev | cut -d "/" -f2- | rev | sort -u) |
|||
GO_BUILD_FILES := $(shell find . -name 'main.go') |
|||
|
|||
.PHONY: all dep build clean test coverage coverhtml lint |
|||
|
|||
all: build |
|||
|
|||
# Lint golang files
|
|||
lint: |
|||
@golint -set_exit_status |
|||
|
|||
show_tests: |
|||
@echo ${GO_TEST_FILES} |
|||
|
|||
# Run unittests
|
|||
test: |
|||
@go test -v -coverprofile=coverage.txt -covermode=atomic ./... |
|||
|
|||
# Run data race detector
|
|||
race: |
|||
GO111MODULE=on CGO_ENABLED=1 go test -v -race -short ./... |
|||
|
|||
# Run memory sanitizer (need to ensure proper build flag is set)
|
|||
msan: |
|||
@go test -v -msan -short ${GO_TEST_FILES} |
|||
|
|||
# Generate global code coverage report
|
|||
coverage: |
|||
@go test -coverprofile=coverage.out -covermode=atomic ./... |
|||
|
|||
# Generate code coverage report
|
|||
coverage_report: |
|||
@go tool cover -func=coverage.out |
|||
|
|||
# Generate code coverage report in HTML
|
|||
coverage_html: |
|||
@go tool cover -html=coverage.out -o coverage.html |
|||
|
|||
# Generate documents
|
|||
docs: |
|||
@echo "Generating docs..." |
|||
|
|||
# Generate docker image
|
|||
docker_img: |
|||
docker build -t zcash_lwd_base . |
|||
|
|||
# Run the above docker image in a container
|
|||
docker_img_run: |
|||
docker run -i --name zcashdlwd zcash_lwd_base |
|||
|
|||
# Execture a bash process on zcashdlwdcontainer
|
|||
docker_img_bash: |
|||
docker exec -it zcashdlwd bash |
|||
|
|||
# Start the zcashd process in the zcashdlwd container
|
|||
docker_img_run_zcashd: |
|||
docker exec -i zcashdlwd zcashd -printtoconsole |
|||
|
|||
# Stop the zcashd process in the zcashdlwd container
|
|||
docker_img_stop_zcashd: |
|||
docker exec -i zcashdlwd zcash-cli stop |
|||
|
|||
# Start the lightwalletd ingester in the zcashdlwd container
|
|||
docker_img_run_lightwalletd_ingest: |
|||
docker exec -i zcashdlwd ingest --conf-file /root/.zcash/zcash.conf --db-path /db/sql.db --log-file /logs/ingest.log |
|||
|
|||
# Start the lightwalletd server in the zcashdlwd container
|
|||
docker_img_run_lightwalletd_insecure_server: |
|||
docker exec -i zcashdlwd server --very-insecure=true --conf-file /root/.zcash/zcash.conf --db-path /db/sql.db --log-file /logs/server.log --bind-addr 127.0.0.1:18232 |
|||
|
|||
# Remove and delete ALL images and containers in Docker; assumes containers are stopped
|
|||
docker_remove_all: |
|||
docker system prune -f |
|||
|
|||
# Get dependencies
|
|||
dep: |
|||
@go get -v -d ./... |
|||
|
|||
# Build binary
|
|||
build: |
|||
GO111MODULE=on CGO_ENABLED=1 go build -i -v ./cmd/ingest |
|||
GO111MODULE=on CGO_ENABLED=1 go build -i -v ./cmd/server |
|||
|
|||
# Install binaries into Go path
|
|||
install: |
|||
go install ./... |
|||
|
|||
clean: |
|||
@echo "clean project..." |
|||
#rm -f $(PROJECT_NAME) |
@ -0,0 +1,8 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"testing" |
|||
) |
|||
|
|||
func TestString_read(t *testing.T) { |
|||
} |
@ -0,0 +1,8 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"testing" |
|||
) |
|||
|
|||
func TestString_read(t *testing.T) { |
|||
} |
@ -0,0 +1,8 @@ |
|||
package frontend |
|||
|
|||
import ( |
|||
"testing" |
|||
) |
|||
|
|||
func TestString_read(t *testing.T) { |
|||
} |
@ -1,39 +0,0 @@ |
|||
package frontend |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"strconv" |
|||
"strings" |
|||
"testing" |
|||
) |
|||
|
|||
// a well-formed raw transaction
|
|||
const coinbaseTxHex = "0400008085202f89010000000000000000000000000000000000000" + |
|||
"000000000000000000000000000ffffffff03580101ffffffff0200ca9a3b000000001976a9146b" + |
|||
"9ae8c14e917966b0afdf422d32dbac40486d3988ac80b2e60e0000000017a9146708e6670db0b95" + |
|||
"0dac68031025cc5b63213a4918700000000000000000000000000000000000000" |
|||
|
|||
func TestSendTransaction(t *testing.T) { |
|||
client, err := NewZRPCFromCreds("127.0.0.1:8232", "user", "password") |
|||
if err != nil { |
|||
t.Fatalf("Couldn't init JSON-RPC client: %v", err) |
|||
} |
|||
|
|||
params := make([]json.RawMessage, 1) |
|||
params[0] = json.RawMessage("\"" + coinbaseTxHex + "\"") |
|||
_, err = client.RawRequest("sendrawtransaction", params) |
|||
if err == nil { |
|||
t.Fatal("somehow succeeded at sending a coinbase tx") |
|||
} |
|||
|
|||
errParts := strings.SplitN(err.Error(), ":", 2) |
|||
errCode, err := strconv.ParseInt(errParts[0], 10, 64) |
|||
if err != nil { |
|||
t.Errorf("couldn't parse error code: %v", err) |
|||
} |
|||
errMsg := strings.TrimSpace(errParts[1]) |
|||
|
|||
if errCode != -26 || errMsg != "16: coinbase" { |
|||
t.Error("got the wrong errors") |
|||
} |
|||
} |
@ -0,0 +1,550 @@ |
|||
package bytestring |
|||
|
|||
import ( |
|||
"bytes" |
|||
"testing" |
|||
) |
|||
|
|||
func TestString_read(t *testing.T) { |
|||
s := String{} |
|||
if !(s).Empty() { |
|||
t.Fatal("initial string not empty") |
|||
} |
|||
s = String{22, 33, 44} |
|||
if s.Empty() { |
|||
t.Fatal("string unexpectedly empty") |
|||
} |
|||
r := s.read(2) |
|||
if len(r) != 2 { |
|||
t.Fatal("unexpected string length after read()") |
|||
} |
|||
if !bytes.Equal(r, []byte{22, 33}) { |
|||
t.Fatal("miscompare mismatch after read()") |
|||
} |
|||
r = s.read(0) |
|||
if !bytes.Equal(r, []byte{}) { |
|||
t.Fatal("miscompare mismatch after read()") |
|||
} |
|||
if s.read(2) != nil { |
|||
t.Fatal("unexpected successful too-large read()") |
|||
} |
|||
r = s.read(1) |
|||
if !bytes.Equal(r, []byte{44}) { |
|||
t.Fatal("miscompare after read()") |
|||
} |
|||
r = s.read(0) |
|||
if !bytes.Equal(r, []byte{}) { |
|||
t.Fatal("miscompare after read()") |
|||
} |
|||
if s.read(1) != nil { |
|||
t.Fatal("unexpected successful too-large read()") |
|||
} |
|||
} |
|||
|
|||
func TestString_Read(t *testing.T) { |
|||
s := String{22, 33, 44} |
|||
b := make([]byte, 10) |
|||
n, err := s.Read(b) |
|||
if err != nil { |
|||
t.Fatal("Read() failed") |
|||
} |
|||
if n != 3 { |
|||
t.Fatal("Read() returned incorrect length") |
|||
} |
|||
if !bytes.Equal(b[:3], []byte{22, 33, 44}) { |
|||
t.Fatal("miscompare after Read()") |
|||
} |
|||
|
|||
// s should now be empty
|
|||
n, err = s.Read(b) |
|||
if err == nil { |
|||
t.Fatal("Read() unexpectedly succeeded") |
|||
} |
|||
if n != 0 { |
|||
t.Fatal("Read() failed as expected but returned incorrect length") |
|||
} |
|||
// s empty, the passed-in slice has zero length is not an error
|
|||
n, err = s.Read([]byte{}) |
|||
if err != nil { |
|||
t.Fatal("Read() failed") |
|||
} |
|||
if n != 0 { |
|||
t.Fatal("Read() returned non-zero length") |
|||
} |
|||
|
|||
// make sure we can advance through string s (this time buffer smaller than s)
|
|||
s = String{55, 66, 77} |
|||
b = make([]byte, 2) |
|||
n, err = s.Read(b) |
|||
if err != nil { |
|||
t.Fatal("Read() failed") |
|||
} |
|||
if n != 2 { |
|||
t.Fatal("Read() returned incorrect length") |
|||
} |
|||
if !bytes.Equal(b[:2], []byte{55, 66}) { |
|||
t.Fatal("miscompare after Read()") |
|||
} |
|||
|
|||
// keep reading s, one byte remaining
|
|||
n, err = s.Read(b) |
|||
if err != nil { |
|||
t.Fatal("Read() failed") |
|||
} |
|||
if n != 1 { |
|||
t.Fatal("Read() returned incorrect length") |
|||
} |
|||
if !bytes.Equal(b[:1], []byte{77}) { |
|||
t.Fatal("miscompare after Read()") |
|||
} |
|||
|
|||
// If the buffer to read into is zero-length...
|
|||
s = String{88} |
|||
n, err = s.Read([]byte{}) |
|||
if err != nil { |
|||
t.Fatal("Read() into zero-length buffer failed") |
|||
} |
|||
if n != 0 { |
|||
t.Fatal("Read() failed as expected but returned incorrect length") |
|||
} |
|||
} |
|||
|
|||
func TestString_Skip(t *testing.T) { |
|||
s := String{22, 33, 44} |
|||
b := make([]byte, 10) |
|||
if !s.Skip(1) { |
|||
t.Fatal("Skip() failed") |
|||
} |
|||
n, err := s.Read(b) |
|||
if err != nil { |
|||
t.Fatal("Read() failed") |
|||
} |
|||
if n != 2 { |
|||
t.Fatal("Read() returned incorrect length") |
|||
} |
|||
if !bytes.Equal(b[:2], []byte{33, 44}) { |
|||
t.Fatal("miscompare after Read()") |
|||
} |
|||
|
|||
// we're at the end of the string
|
|||
if s.Skip(1) { |
|||
t.Fatal("Skip() unexpectedly succeeded") |
|||
} |
|||
if !s.Skip(0) { |
|||
t.Fatal("Skip(0) failed") |
|||
} |
|||
} |
|||
|
|||
func TestString_ReadByte(t *testing.T) { |
|||
s := String{22, 33} |
|||
var b byte |
|||
if !s.ReadByte(&b) { |
|||
t.Fatal("ReadByte() failed") |
|||
} |
|||
if b != 22 { |
|||
t.Fatal("ReadByte() unexpected value") |
|||
} |
|||
if !s.ReadByte(&b) { |
|||
t.Fatal("ReadByte() failed") |
|||
} |
|||
if b != 33 { |
|||
t.Fatal("ReadByte() unexpected value") |
|||
} |
|||
|
|||
// we're at the end of the string
|
|||
if s.ReadByte(&b) { |
|||
t.Fatal("ReadByte() unexpectedly succeeded") |
|||
} |
|||
} |
|||
|
|||
func TestString_ReadBytes(t *testing.T) { |
|||
s := String{22, 33, 44} |
|||
var b []byte |
|||
if !s.ReadBytes(&b, 2) { |
|||
t.Fatal("ReadBytes() failed") |
|||
} |
|||
if !bytes.Equal(b, []byte{22, 33}) { |
|||
t.Fatal("miscompare after ReadBytes()") |
|||
} |
|||
|
|||
// s is now [44]
|
|||
if len(s) != 1 { |
|||
t.Fatal("unexpected updated s following ReadBytes()") |
|||
} |
|||
if s.ReadBytes(&b, 2) { |
|||
t.Fatal("ReadBytes() unexpected success") |
|||
} |
|||
if !s.ReadBytes(&b, 1) { |
|||
t.Fatal("ReadBytes() failed") |
|||
} |
|||
if !bytes.Equal(b, []byte{44}) { |
|||
t.Fatal("miscompare after ReadBytes()") |
|||
} |
|||
} |
|||
|
|||
var readCompactSizeTests = []struct { |
|||
s String |
|||
ok bool |
|||
expected int |
|||
}{ |
|||
/* 00 */ {String{}, false, 0}, |
|||
/* 01 */ {String{43}, true, 43}, |
|||
/* 02 */ {String{252}, true, 252}, |
|||
/* 03 */ {String{253, 1, 0}, false, 0}, // 1 < minSize (253)
|
|||
/* 04 */ {String{253, 252, 0}, false, 0}, // 252 < minSize (253)
|
|||
/* 05 */ {String{253, 253, 0}, true, 253}, |
|||
/* 06 */ {String{253, 255, 255}, true, 0xffff}, |
|||
/* 07 */ {String{254, 0xff, 0xff, 0, 0}, false, 0}, // 0xffff < minSize
|
|||
/* 08 */ {String{254, 0, 0, 1, 0}, true, 0x00010000}, |
|||
/* 09 */ {String{254, 7, 0, 1, 0}, true, 0x00010007}, |
|||
/* 10 */ {String{254, 0, 0, 0, 2}, true, 0x02000000}, |
|||
/* 11 */ {String{254, 1, 0, 0, 2}, false, 0}, // > maxCompactSize
|
|||
/* 12 */ {String{255, 0, 0, 0, 2, 0, 0, 0, 0}, false, 0}, |
|||
} |
|||
|
|||
func TestString_ReadCompactSize(t *testing.T) { |
|||
for i, tt := range readCompactSizeTests { |
|||
var expected int |
|||
ok := tt.s.ReadCompactSize(&expected) |
|||
if ok != tt.ok { |
|||
t.Fatalf("ReadCompactSize case %d: want: %v, have: %v", i, tt.ok, ok) |
|||
} |
|||
if expected != tt.expected { |
|||
t.Fatalf("ReadCompactSize case %d: want: %v, have: %v", i, tt.expected, expected) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func TestString_ReadCompactLengthPrefixed(t *testing.T) { |
|||
// a stream of 3 bytes followed by 2 bytes into the value variable, v
|
|||
s := String{3, 55, 66, 77, 2, 88, 99} |
|||
v := String{} |
|||
|
|||
// read the 3 and thus the following 3 bytes
|
|||
if !s.ReadCompactLengthPrefixed(&v) { |
|||
t.Fatalf("ReadCompactLengthPrefix failed") |
|||
} |
|||
if len(v) != 3 { |
|||
t.Fatalf("ReadCompactLengthPrefix incorrect length") |
|||
} |
|||
if !bytes.Equal(v, String{55, 66, 77}) { |
|||
t.Fatalf("ReadCompactLengthPrefix unexpected return") |
|||
} |
|||
|
|||
// read the 2 and then two bytes
|
|||
if !s.ReadCompactLengthPrefixed(&v) { |
|||
t.Fatalf("ReadCompactLengthPrefix failed") |
|||
} |
|||
if len(v) != 2 { |
|||
t.Fatalf("ReadCompactLengthPrefix incorrect length") |
|||
} |
|||
if !bytes.Equal(v, String{88, 99}) { |
|||
t.Fatalf("ReadCompactLengthPrefix unexpected return") |
|||
} |
|||
|
|||
// at the end of the String, another read should return false
|
|||
if s.ReadCompactLengthPrefixed(&v) { |
|||
t.Fatalf("ReadCompactLengthPrefix unexpected success") |
|||
} |
|||
|
|||
// this string is too short (less than 2 bytes of data)
|
|||
s = String{3, 55, 66} |
|||
if s.ReadCompactLengthPrefixed(&v) { |
|||
t.Fatalf("ReadCompactLengthPrefix unexpected success") |
|||
} |
|||
} |
|||
|
|||
var readInt32Tests = []struct { |
|||
s String |
|||
expected int32 |
|||
}{ |
|||
// Little-endian (least-significant byte first)
|
|||
/* 00 */ {String{0, 0, 0, 0}, 0}, |
|||
/* 01 */ {String{17, 0, 0, 0}, 17}, |
|||
/* 02 */ {String{0xde, 0x8a, 0x7b, 0x72}, 0x727b8ade}, |
|||
/* 03 */ {String{0xde, 0x8a, 0x7b, 0x92}, -1837397282}, // signed overflow
|
|||
/* 04 */ {String{0xff, 0xff, 0xff, 0xff}, -1}, |
|||
} |
|||
|
|||
var readInt32FailTests = []struct { |
|||
s String |
|||
}{ |
|||
/* 00 */ {String{}}, |
|||
/* 01 */ {String{1, 2, 3}}, // too few bytes (must be >= 4)
|
|||
} |
|||
|
|||
func TestString_ReadInt32(t *testing.T) { |
|||
// create one large string to ensure a sequences of values can be read
|
|||
var s String |
|||
for _, tt := range readInt32Tests { |
|||
s = append(s, tt.s...) |
|||
} |
|||
for i, tt := range readInt32Tests { |
|||
var v int32 |
|||
if !s.ReadInt32(&v) { |
|||
t.Fatalf("ReadInt32 case %d: failed", i) |
|||
} |
|||
if v != tt.expected { |
|||
t.Fatalf("ReadInt32 case %d: want: %v, have: %v", i, tt.expected, v) |
|||
} |
|||
} |
|||
if len(s) > 0 { |
|||
t.Fatalf("ReadInt32 bytes remaining: %d", len(s)) |
|||
} |
|||
for i, tt := range readInt32FailTests { |
|||
var v int32 |
|||
prevlen := len(tt.s) |
|||
if tt.s.ReadInt32(&v) { |
|||
t.Fatalf("ReadInt32 fail case %d: unexpected success", i) |
|||
} |
|||
if v != 0 { |
|||
t.Fatalf("ReadInt32 fail case %d: value should be zero", i) |
|||
} |
|||
if len(tt.s) != prevlen { |
|||
t.Fatalf("ReadInt32 fail case %d: some bytes consumed", i) |
|||
} |
|||
} |
|||
} |
|||
|
|||
var readInt64Tests = []struct { |
|||
s String |
|||
expected int64 |
|||
}{ |
|||
// Little-endian (least-significant byte first)
|
|||
/* 00 */ {String{0, 0, 0, 0, 0, 0, 0, 0}, 0}, |
|||
/* 01 */ {String{17, 0, 0, 0, 0, 0, 0, 0}, 17}, |
|||
/* 02 */ {String{0xde, 0x8a, 0x7b, 0x72, 0x27, 0xa3, 0x94, 0x55}, 0x5594a327727b8ade}, |
|||
/* 03 */ {String{0xde, 0x8a, 0x7b, 0x72, 0x27, 0xa3, 0x94, 0x85}, -8821246380292207906}, // signed overflow
|
|||
/* 04 */ {String{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, -1}, |
|||
} |
|||
|
|||
var readInt64FailTests = []struct { |
|||
s String |
|||
}{ |
|||
/* 00 */ {String{}}, |
|||
/* 01 */ {String{1, 2, 3, 4, 5, 6, 7}}, // too few bytes (must be >= 8)
|
|||
} |
|||
|
|||
func TestString_ReadInt64(t *testing.T) { |
|||
// create one large string to ensure a sequences of values can be read
|
|||
var s String |
|||
for _, tt := range readInt64Tests { |
|||
s = append(s, tt.s...) |
|||
} |
|||
for i, tt := range readInt64Tests { |
|||
var v int64 |
|||
if !s.ReadInt64(&v) { |
|||
t.Fatalf("ReadInt64 case %d: failed", i) |
|||
} |
|||
if v != tt.expected { |
|||
t.Fatalf("ReadInt64 case %d: want: %v, have: %v", i, tt.expected, v) |
|||
} |
|||
} |
|||
if len(s) > 0 { |
|||
t.Fatalf("ReadInt64 bytes remaining: %d", len(s)) |
|||
} |
|||
for i, tt := range readInt64FailTests { |
|||
var v int64 |
|||
prevlen := len(tt.s) |
|||
if tt.s.ReadInt64(&v) { |
|||
t.Fatalf("ReadInt64 fail case %d: unexpected success", i) |
|||
} |
|||
if v != 0 { |
|||
t.Fatalf("ReadInt32 fail case %d: value should be zero", i) |
|||
} |
|||
if len(tt.s) != prevlen { |
|||
t.Fatalf("ReadInt64 fail case %d: some bytes consumed", i) |
|||
} |
|||
} |
|||
} |
|||
|
|||
var readUint16Tests = []struct { |
|||
s String |
|||
expected uint16 |
|||
}{ |
|||
// Little-endian (least-significant byte first)
|
|||
/* 00 */ {String{0, 0}, 0}, |
|||
/* 01 */ {String{23, 0}, 23}, |
|||
/* 02 */ {String{0xde, 0x8a}, 0x8ade}, |
|||
/* 03 */ {String{0xff, 0xff}, 0xffff}, |
|||
} |
|||
|
|||
var readUint16FailTests = []struct { |
|||
s String |
|||
}{ |
|||
/* 00 */ {String{}}, |
|||
/* 01 */ {String{1}}, // too few bytes (must be >= 2)
|
|||
} |
|||
|
|||
func TestString_ReadUint16(t *testing.T) { |
|||
// create one large string to ensure a sequences of values can be read
|
|||
var s String |
|||
for _, tt := range readUint16Tests { |
|||
s = append(s, tt.s...) |
|||
} |
|||
for i, tt := range readUint16Tests { |
|||
var v uint16 |
|||
if !s.ReadUint16(&v) { |
|||
t.Fatalf("ReadUint16 case %d: failed", i) |
|||
} |
|||
if v != tt.expected { |
|||
t.Fatalf("ReadUint16 case %d: want: %v, have: %v", i, tt.expected, v) |
|||
} |
|||
} |
|||
if len(s) > 0 { |
|||
t.Fatalf("ReadUint16 bytes remaining: %d", len(s)) |
|||
} |
|||
for i, tt := range readUint16FailTests { |
|||
var v uint16 |
|||
prevlen := len(tt.s) |
|||
if tt.s.ReadUint16(&v) { |
|||
t.Fatalf("ReadUint16 fail case %d: unexpected success", i) |
|||
} |
|||
if v != 0 { |
|||
t.Fatalf("ReadInt32 fail case %d: value should be zero", i) |
|||
} |
|||
if len(tt.s) != prevlen { |
|||
t.Fatalf("ReadUint16 fail case %d: some bytes consumed", i) |
|||
} |
|||
} |
|||
} |
|||
|
|||
var readUint32Tests = []struct { |
|||
s String |
|||
expected uint32 |
|||
}{ |
|||
// Little-endian (least-significant byte first)
|
|||
/* 00 */ {String{0, 0, 0, 0}, 0}, |
|||
/* 01 */ {String{23, 0, 0, 0}, 23}, |
|||
/* 02 */ {String{0xde, 0x8a, 0x7b, 0x92}, 0x927b8ade}, |
|||
/* 03 */ {String{0xff, 0xff, 0xff, 0xff}, 0xffffffff}, |
|||
} |
|||
|
|||
var readUint32FailTests = []struct { |
|||
s String |
|||
}{ |
|||
/* 00 */ {String{}}, |
|||
/* 01 */ {String{1, 2, 3}}, // too few bytes (must be >= 4)
|
|||
} |
|||
|
|||
func TestString_ReadUint32(t *testing.T) { |
|||
// create one large string to ensure a sequences of values can be read
|
|||
var s String |
|||
for _, tt := range readUint32Tests { |
|||
s = append(s, tt.s...) |
|||
} |
|||
for i, tt := range readUint32Tests { |
|||
var v uint32 |
|||
if !s.ReadUint32(&v) { |
|||
t.Fatalf("ReadUint32 case %d: failed", i) |
|||
} |
|||
if v != tt.expected { |
|||
t.Fatalf("ReadUint32 case %d: want: %v, have: %v", i, tt.expected, v) |
|||
} |
|||
} |
|||
if len(s) > 0 { |
|||
t.Fatalf("ReadUint32 bytes remaining: %d", len(s)) |
|||
} |
|||
for i, tt := range readUint32FailTests { |
|||
var v uint32 |
|||
prevlen := len(tt.s) |
|||
if tt.s.ReadUint32(&v) { |
|||
t.Fatalf("ReadUint32 fail case %d: unexpected success", i) |
|||
} |
|||
if v != 0 { |
|||
t.Fatalf("ReadInt32 fail case %d: value should be zero", i) |
|||
} |
|||
if len(tt.s) != prevlen { |
|||
t.Fatalf("ReadUint32 fail case %d: some bytes consumed", i) |
|||
} |
|||
} |
|||
} |
|||
|
|||
var readUint64Tests = []struct { |
|||
s String |
|||
expected uint64 |
|||
}{ |
|||
// Little-endian (least-significant byte first)
|
|||
/* 00 */ {String{0, 0, 0, 0, 0, 0, 0, 0}, 0}, |
|||
/* 01 */ {String{17, 0, 0, 0, 0, 0, 0, 0}, 17}, |
|||
/* 03 */ {String{0xde, 0x8a, 0x7b, 0x72, 0x27, 0xa3, 0x94, 0x55}, 0x5594a327727b8ade}, |
|||
/* 04 */ {String{0xde, 0x8a, 0x7b, 0x72, 0x27, 0xa3, 0x94, 0x85}, 0x8594a327727b8ade}, |
|||
/* 05 */ {String{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0xffffffffffffffff}, |
|||
} |
|||
|
|||
var readUint64FailTests = []struct { |
|||
s String |
|||
}{ |
|||
/* 00 */ {String{}}, |
|||
/* 01 */ {String{1, 2, 3, 4, 5, 6, 7}}, // too few bytes (must be >= 8)
|
|||
} |
|||
|
|||
func TestString_ReadUint64(t *testing.T) { |
|||
// create one large string to ensure a sequences of values can be read
|
|||
var s String |
|||
for _, tt := range readUint64Tests { |
|||
s = append(s, tt.s...) |
|||
} |
|||
for i, tt := range readUint64Tests { |
|||
var v uint64 |
|||
if !s.ReadUint64(&v) { |
|||
t.Fatalf("ReadUint64 case %d: failed", i) |
|||
} |
|||
if v != tt.expected { |
|||
t.Fatalf("ReadUint64 case %d: want: %v, have: %v", i, tt.expected, v) |
|||
} |
|||
} |
|||
if len(s) > 0 { |
|||
t.Fatalf("ReadUint64 bytes remaining: %d", len(s)) |
|||
} |
|||
for i, tt := range readUint64FailTests { |
|||
var v uint64 |
|||
prevlen := len(tt.s) |
|||
if tt.s.ReadUint64(&v) { |
|||
t.Fatalf("ReadUint64 fail case %d: unexpected success", i) |
|||
} |
|||
if v != 0 { |
|||
t.Fatalf("ReadInt64 fail case %d: value should be zero", i) |
|||
} |
|||
if len(tt.s) != prevlen { |
|||
t.Fatalf("ReadUint64 fail case %d: some bytes consumed", i) |
|||
} |
|||
} |
|||
} |
|||
|
|||
var readScriptInt64Tests = []struct { |
|||
s String |
|||
ok bool |
|||
expected int64 |
|||
}{ |
|||
// Little-endian (least-significant byte first).
|
|||
/* 00 */ {String{}, false, 0}, |
|||
/* 01 */ {String{0x4f}, true, -1}, |
|||
/* 02 */ {String{0x00}, true, 0x00}, |
|||
/* 03 */ {String{0x51}, true, 0x01}, |
|||
/* 04 */ {String{0x52}, true, 0x02}, |
|||
/* 05 */ {String{0x5f}, true, 0x0f}, |
|||
/* 06 */ {String{0x60}, true, 0x10}, |
|||
/* 07 */ {String{0x01}, false, 0}, // should be one byte following count 0x01
|
|||
/* 07 */ {String{0x01, 0xbd}, true, 0xbd}, |
|||
/* 07 */ {String{0x02, 0xbd, 0xac}, true, 0xacbd}, |
|||
/* 07 */ {String{0x08, 0xbd, 0xac, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x44}, true, 0x449a78563412acbd}, |
|||
/* 07 */ {String{0x08, 0xbd, 0xac, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x94}, true, -7738740698046616387}, |
|||
} |
|||
|
|||
func TestString_ReadScriptInt64(t *testing.T) { |
|||
for i, tt := range readScriptInt64Tests { |
|||
var v int64 |
|||
ok := tt.s.ReadScriptInt64(&v) |
|||
if ok != tt.ok { |
|||
t.Fatalf("ReadScriptInt64 case %d: want: %v, have: %v", i, tt.ok, ok) |
|||
} |
|||
if v != tt.expected { |
|||
t.Fatalf("ReadScriptInt64 case %d: want: %v, have: %v", i, tt.expected, v) |
|||
} |
|||
// there should be no bytes remaining
|
|||
if ok && len(tt.s) != 0 { |
|||
t.Fatalf("ReadScriptInt64 case %d: stream mispositioned", i) |
|||
} |
|||
} |
|||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@ |
|||
package walletrpc |
|||
|
|||
import ( |
|||
"testing" |
|||
) |
|||
|
|||
func TestString_read(t *testing.T) { |
|||
} |
Loading…
Reference in new issue