mirror of
https://github.com/aljazceru/nigiri.git
synced 2026-02-23 15:24:18 +01:00
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1 +1,4 @@
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
vendor/
|
||||
build/
|
||||
190
Gopkg.lock
generated
Normal file
190
Gopkg.lock
generated
Normal file
@@ -0,0 +1,190 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd"
|
||||
name = "github.com/fsnotify/fsnotify"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
|
||||
version = "v1.4.7"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
|
||||
name = "github.com/hashicorp/hcl"
|
||||
packages = [
|
||||
".",
|
||||
"hcl/ast",
|
||||
"hcl/parser",
|
||||
"hcl/printer",
|
||||
"hcl/scanner",
|
||||
"hcl/strconv",
|
||||
"hcl/token",
|
||||
"json/parser",
|
||||
"json/scanner",
|
||||
"json/token",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
|
||||
name = "github.com/inconshreveable/mousetrap"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:31e761d97c76151dde79e9d28964a812c46efc5baee4085b86f68f0c654450de"
|
||||
name = "github.com/konsorten/go-windows-terminal-sequences"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "f55edac94c9bbba5d6182a4be46d86a2c9b5b50e"
|
||||
version = "v1.0.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c568d7727aa262c32bdf8a3f7db83614f7af0ed661474b24588de635c20024c7"
|
||||
name = "github.com/magiconair/properties"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "c2353362d570a7bfa228149c62842019201cfb71"
|
||||
version = "v1.8.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:5d231480e1c64a726869bc4142d270184c419749d34f167646baa21008eb0a79"
|
||||
name = "github.com/mitchellh/go-homedir"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "af06845cf3004701891bf4fdb884bfe4920b3727"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:53bc4cd4914cd7cd52139990d5170d6dc99067ae31c56530621b18b35fc30318"
|
||||
name = "github.com/mitchellh/mapstructure"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe"
|
||||
version = "v1.1.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e"
|
||||
name = "github.com/pelletier/go-toml"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:e4c72127d910a96daf869a44f3dd563b86dbe6931a172863a0e99c5ff04b59e4"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "dae0fa8d5b0c810a8ab733fbd5510c7cae84eca4"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:bb495ec276ab82d3dd08504bbc0594a65de8c3b22c6f2aaa92d05b73fbf3a82e"
|
||||
name = "github.com/spf13/afero"
|
||||
packages = [
|
||||
".",
|
||||
"mem",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "588a75ec4f32903aa5e39a2619ba6a4631e28424"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:08d65904057412fc0270fc4812a1c90c594186819243160dc779a402d4b6d0bc"
|
||||
name = "github.com/spf13/cast"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "8c9545af88b134710ab1cd196795e7f2388358d7"
|
||||
version = "v1.3.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939"
|
||||
name = "github.com/spf13/cobra"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:1b753ec16506f5864d26a28b43703c58831255059644351bbcb019b843950900"
|
||||
name = "github.com/spf13/jwalterweatherman"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "94f6ae3ed3bceceafa716478c5fbf8d29ca601a1"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2"
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
|
||||
version = "v1.0.3"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:1b773526998f3dbde3a51a4a5881680c4d237d3600f570d900f97ac93c7ba0a8"
|
||||
name = "github.com/spf13/viper"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "9e56dacc08fbbf8c9ee2dbc717553c758ce42bc9"
|
||||
version = "v1.3.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:bbe51412d9915d64ffaa96b51d409e070665efc5194fcf145c4a27d4133107a4"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
pruneopts = "UT"
|
||||
revision = "a5d413f7728c81fb97d96a2b722368945f651e78"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:6b3e6ddcebac95be1d690dbd53b5aa2e520715becb7e521bb526ccf3b4c53c15"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "f49334f85ddcf0f08d7fb6dd7363e9e6d6b777eb"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8029e9743749d4be5bc9f7d42ea1659471767860f0cdc34d37c3111bd308a295"
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"internal/gen",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"transform",
|
||||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
|
||||
version = "v2.2.2"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/mitchellh/go-homedir",
|
||||
"github.com/sirupsen/logrus",
|
||||
"github.com/spf13/cobra",
|
||||
"github.com/spf13/viper",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
30
Gopkg.toml
Normal file
30
Gopkg.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
42
README.md
42
README.md
@@ -1,6 +1,6 @@
|
||||
# 🍣 Nigiri Bitcoin
|
||||
|
||||
A dockerized environment hosting a bitcoin and liquid daemons in regtest network with an electrum server that indexes and keeps track of all UTXOs.
|
||||
Nigiri provides a fully dockerized ready-to-use bitcoin environment thats supports different networks and chains.
|
||||
|
||||
## Utensils
|
||||
|
||||
@@ -15,53 +15,63 @@ A dockerized environment hosting a bitcoin and liquid daemons in regtest network
|
||||
|
||||
## Directions
|
||||
|
||||
| Preparation Time: 20 min | Cooking Difficulty: Easy |
|
||||
| Preparation Time: 5 min | Cooking Difficulty: Easy |
|
||||
| --- | --- |
|
||||
|
||||
Clone the repo:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/vulpemventures/nigiri.git && cd nigiri
|
||||
$ git clone https://github.com/vulpemventures/nigiri.git
|
||||
```
|
||||
|
||||
Create and start nigiri (only the first time or after cleaning):
|
||||
Enter project directory and install dependencies:
|
||||
|
||||
```bash
|
||||
$ bash scripts/create
|
||||
nigiri $ bash scripts/install
|
||||
```
|
||||
|
||||
Build binary (Mac version):
|
||||
```
|
||||
nigiri $ bash scripts/build darwin amd64
|
||||
```
|
||||
|
||||
At the moment bitcoind, liquidd and electrs are started on *regtest* network.
|
||||
|
||||
Start nigiri:
|
||||
Create nigiri environment:
|
||||
|
||||
```bash
|
||||
$ bash scripts/start
|
||||
nigiri/build $ nigiri-linux-amd64 create
|
||||
```
|
||||
|
||||
This will start 4 containers that run the following services respectevely:
|
||||
Nigiri uses the default directory `~/.nigiri` to store the configuration file and docker stuff.
|
||||
To set a custom directory use the `--datadir` flag, but do not forget to always pass this flag to other commands, just as you do with your `bitcoind`.
|
||||
|
||||
* bitcoin daemon (regtest)
|
||||
* liquid daemon
|
||||
The environment will start with 3 containers for `regtest` bitcoin network that run the following services respectevely:
|
||||
|
||||
* bitcoin daemon
|
||||
* electrs REST server
|
||||
* API passthrough with optional faucet and mining capabilities (nigiri-chopsticks)
|
||||
|
||||
Stop nigiri:
|
||||
Use the `--liquid` flag to let you do experiments with the Liquid sidechain. A liquid daemon and a block explorer
|
||||
are also started when passing this flag.
|
||||
|
||||
Start/Stop nigiri:
|
||||
|
||||
```bash
|
||||
$ bash scripts/stop
|
||||
nigiri/build $ nigiri-linux-amd64 start|stop
|
||||
```
|
||||
|
||||
Stop and uninstall nigiri:
|
||||
Stop and delete nigiri environment:
|
||||
|
||||
```bash
|
||||
$ bash scripts/clean
|
||||
nigiri/build $ nigiri-linux-amd64 delete
|
||||
```
|
||||
|
||||
When setup is completed, you can call any endpoint at `http://localhost:3000/`.
|
||||
This command stops and deletes any active contained and deletes the configuration file and all the Docker-generated files and directories.
|
||||
|
||||
## Nutrition Facts
|
||||
|
||||
The [list](https://github.com/blockstream/esplora/blob/master/API.md) of all available endpoints has been extended with one more `POST /send` which expects a body `{ "address": <receiving_address> }`
|
||||
The [list](https://github.com/blockstream/esplora/blob/master/API.md) of all available endpoints can be extended with one more `POST /faucet` which expects a body `{ "address": <receiving_address> }` by enabling faucet.
|
||||
|
||||
## Footnotes
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# bitcoin-box docker image
|
||||
FROM ubuntu:18.04
|
||||
|
||||
# add bitcoind from the official PPA
|
||||
# install bitcoind (from PPA) and make
|
||||
RUN apt-get update && \
|
||||
apt-get install --yes clang cmake jq software-properties-common && \
|
||||
add-apt-repository --yes ppa:bitcoin/bitcoin && \
|
||||
apt-get update && \
|
||||
apt-get install --yes bitcoind
|
||||
|
||||
RUN mkdir -p /config /script
|
||||
|
||||
# copy the box files into the image
|
||||
ADD bitcoin/config /config
|
||||
ADD bitcoin/run /script
|
||||
|
||||
WORKDIR /script
|
||||
# expose two rpc ports for the nodes to allow outside container access
|
||||
EXPOSE 19001
|
||||
STOPSIGNAL SIGINT
|
||||
|
||||
CMD ["./run"]
|
||||
@@ -1,23 +0,0 @@
|
||||
# testnet-box functionality
|
||||
regtest=1
|
||||
testnet=0
|
||||
dnsseed=0
|
||||
upnp=0
|
||||
|
||||
[regtest]
|
||||
# listen on different ports than default testnet
|
||||
port=19000
|
||||
rpcport=19001
|
||||
|
||||
# always run a server, even with bitcoin-qt
|
||||
server=1
|
||||
txindex=0
|
||||
|
||||
# enable to allow non-localhost RPC connections
|
||||
# recommended to change to a subnet, such as your LAN
|
||||
rpcallowip=0.0.0.0/0
|
||||
|
||||
rpcuser=admin1
|
||||
rpcpassword=123
|
||||
|
||||
|
||||
17
bitcoin/run
17
bitcoin/run
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
b1="bitcoin-cli -datadir=/config"
|
||||
|
||||
function clean {
|
||||
$b1 stop
|
||||
}
|
||||
|
||||
trap clean SIGINT
|
||||
|
||||
bitcoind -datadir=/config &
|
||||
|
||||
sleep 10
|
||||
|
||||
$b1 generate 200
|
||||
wait $!
|
||||
@@ -1,10 +0,0 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
WORKDIR /build
|
||||
COPY chopsticks/nigiri-chopsticks-linux-amd64.tar.gz /build
|
||||
RUN ls
|
||||
RUN tar -xzf nigiri-chopsticks-linux-amd64.tar.gz && rm -rf *.tar.gz
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["./nigiri-chopsticks-linux-amd64", "--addr", "0.0.0.0:3000", "--electrs-addr", "10.10.0.12:3002", "--rpc-addr", "10.10.0.10:19001"]
|
||||
Binary file not shown.
98
cli/cmd/create.go
Normal file
98
cli/cmd/create.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulpemventures/nigiri/cli/builder"
|
||||
"github.com/vulpemventures/nigiri/cli/config"
|
||||
"github.com/vulpemventures/nigiri/cli/helpers"
|
||||
)
|
||||
|
||||
var composeBuilder = map[string]func(path string) builder.ComposeBuilder{
|
||||
"regtest": helpers.NewRegtestBuilder,
|
||||
}
|
||||
|
||||
var CreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Build and run the entire Docker environment",
|
||||
Run: create,
|
||||
PreRun: createChecks,
|
||||
}
|
||||
|
||||
func createChecks(cmd *cobra.Command, args []string) {
|
||||
network, _ := cmd.Flags().GetString("network")
|
||||
datadir, _ := cmd.Flags().GetString("datadir")
|
||||
|
||||
// check flags
|
||||
if !isNetworkOk(network) {
|
||||
log.WithField("network_flag", network).Fatal("Invalid network")
|
||||
}
|
||||
|
||||
if !isDatadirOk(datadir) {
|
||||
log.WithField("datadir_flag", datadir).Fatal("Invalid datadir, it must be an absolute path")
|
||||
}
|
||||
|
||||
// scratch datadir if not exists
|
||||
if err := os.MkdirAll(datadir, 0755); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while scratching config dir")
|
||||
}
|
||||
|
||||
// check if config file already exists in datadir
|
||||
filedir := filepath.Join(datadir, "nigiri.config.json")
|
||||
if _, err := os.Stat(filedir); !os.IsNotExist(err) {
|
||||
log.WithField("datadir", datadir).Fatal("Configuration file already exists, please delete it first")
|
||||
}
|
||||
|
||||
// write and read config file to have viper updated
|
||||
if err := config.WriteConfig(filedir); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while writing config file")
|
||||
}
|
||||
|
||||
if err := config.ReadFromFile(datadir); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while reading config file")
|
||||
}
|
||||
}
|
||||
|
||||
func create(cmd *cobra.Command, args []string) {
|
||||
composePath := getComposePath()
|
||||
|
||||
bashCmd := exec.Command("docker-compose", "-f", composePath, "up", "-d")
|
||||
bashCmd.Stdout = os.Stdout
|
||||
bashCmd.Stderr = os.Stderr
|
||||
|
||||
if err := bashCmd.Run(); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while composing Docker environment")
|
||||
}
|
||||
}
|
||||
|
||||
func isNetworkOk(network string) bool {
|
||||
var ok bool
|
||||
for _, n := range []string{"regtest"} {
|
||||
if network == n {
|
||||
ok = true
|
||||
}
|
||||
}
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func isDatadirOk(datadir string) bool {
|
||||
return filepath.IsAbs(datadir)
|
||||
}
|
||||
|
||||
func getComposePath() string {
|
||||
viper := config.Viper()
|
||||
datadir := viper.GetString("datadir")
|
||||
network := viper.GetString("network")
|
||||
attachLiquid := viper.GetBool("attachLiquid")
|
||||
if attachLiquid {
|
||||
network += "-liquid"
|
||||
}
|
||||
|
||||
return filepath.Join(datadir, "resources", fmt.Sprintf("docker-compose-%s.yml", network))
|
||||
}
|
||||
90
cli/cmd/delete.go
Normal file
90
cli/cmd/delete.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulpemventures/nigiri/cli/config"
|
||||
)
|
||||
|
||||
var DeleteCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "Delete all Docker environment components",
|
||||
Run: delete,
|
||||
PreRun: deleteChecks,
|
||||
}
|
||||
|
||||
func delete(cmd *cobra.Command, args []string) {
|
||||
composePath := getComposePath()
|
||||
|
||||
bashCmd := exec.Command("docker-compose", "-f", composePath, "down")
|
||||
bashCmd.Stdout = os.Stdout
|
||||
bashCmd.Stderr = os.Stderr
|
||||
|
||||
if err := bashCmd.Run(); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while deleting Docker environment")
|
||||
}
|
||||
|
||||
if err := cleanVolumes(); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while cleanin Docker volumes")
|
||||
}
|
||||
|
||||
if err := deleteConfig(); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while deleting config file, please delete it manually")
|
||||
}
|
||||
}
|
||||
|
||||
func deleteChecks(cmd *cobra.Command, args []string) {
|
||||
datadir, _ := cmd.Flags().GetString("datadir")
|
||||
if err := config.ReadFromFile(datadir); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
When deleting nigiri we need to clean the Docker volumes that are
|
||||
used as datadir of the bitcoin/liquid daemon. These folders contain
|
||||
both the *.conf files provided by us and files and directories created
|
||||
by the daemons.
|
||||
cleanVolumes navigates into <datadir>/resources/volumes/<network>
|
||||
and deletes all files and directories but the *.conf config files.
|
||||
*/
|
||||
func cleanVolumes() error {
|
||||
datadir := config.GetString(config.Datadir)
|
||||
network := config.GetString(config.Network)
|
||||
attachLiquid := config.GetBool(config.AttachLiquid)
|
||||
if attachLiquid {
|
||||
network = fmt.Sprintf("liquid%s", network)
|
||||
}
|
||||
volumedir := filepath.Join(datadir, "resources", "volumes", network)
|
||||
|
||||
subdirs, err := ioutil.ReadDir(volumedir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, d := range subdirs {
|
||||
volumedir := filepath.Join(volumedir, d.Name())
|
||||
subsubdirs, _ := ioutil.ReadDir(volumedir)
|
||||
for _, sd := range subsubdirs {
|
||||
if sd.IsDir() {
|
||||
if err := os.RemoveAll(filepath.Join(volumedir, sd.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteConfig() error {
|
||||
datadir := config.GetString(config.Datadir)
|
||||
configFile := filepath.Join(datadir, config.Filename)
|
||||
return os.Remove(configFile)
|
||||
}
|
||||
52
cli/cmd/flags.go
Normal file
52
cli/cmd/flags.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulpemventures/nigiri/cli/config"
|
||||
)
|
||||
|
||||
var (
|
||||
flagDatadir string
|
||||
flagNetwork string
|
||||
flagAttachLiquid bool
|
||||
)
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "nigiri",
|
||||
Short: "Nigiri lets you manage a full dockerized bitcoin environment",
|
||||
Long: "Nigiri lets you create your dockerized environment with a bitcoin and optionally a liquid node + block explorer powered by an electrum server",
|
||||
}
|
||||
|
||||
func init() {
|
||||
defaultDir := getDefaultDir()
|
||||
|
||||
RootCmd.PersistentFlags().StringVar(&flagDatadir, "datadir", defaultDir, "Set directory for config file and docker stuff")
|
||||
CreateCmd.PersistentFlags().StringVar(&flagNetwork, "network", "regtest", "Set network for containers' services - regtest only for now")
|
||||
CreateCmd.PersistentFlags().BoolVar(&flagAttachLiquid, "liquid", false, "Add liquid sidechain to bitcoin environment")
|
||||
|
||||
RootCmd.AddCommand(CreateCmd)
|
||||
RootCmd.AddCommand(StartCmd)
|
||||
RootCmd.AddCommand(StopCmd)
|
||||
RootCmd.AddCommand(DeleteCmd)
|
||||
RootCmd.AddCommand(VersionCmd)
|
||||
|
||||
viper := config.Viper()
|
||||
viper.BindPFlag(config.Datadir, RootCmd.PersistentFlags().Lookup("datadir"))
|
||||
viper.BindPFlag(config.Network, CreateCmd.PersistentFlags().Lookup("network"))
|
||||
viper.BindPFlag(config.AttachLiquid, CreateCmd.PersistentFlags().Lookup("liquid"))
|
||||
|
||||
cobra.OnInitialize(func() {
|
||||
log.SetOutput(os.Stdout)
|
||||
log.SetLevel(log.InfoLevel)
|
||||
})
|
||||
}
|
||||
|
||||
func getDefaultDir() string {
|
||||
home, _ := homedir.Expand("~")
|
||||
return filepath.Join(home, ".nigiri")
|
||||
}
|
||||
36
cli/cmd/start.go
Normal file
36
cli/cmd/start.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulpemventures/nigiri/cli/config"
|
||||
)
|
||||
|
||||
var StartCmd = &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start containers",
|
||||
Run: start,
|
||||
PreRun: startStopChecks,
|
||||
}
|
||||
|
||||
func start(cmd *cobra.Command, args []string) {
|
||||
composePath := getComposePath()
|
||||
|
||||
bashCmd := exec.Command("docker-compose", "-f", composePath, "start")
|
||||
bashCmd.Stdout = os.Stdout
|
||||
bashCmd.Stderr = os.Stderr
|
||||
|
||||
if err := bashCmd.Run(); err != nil {
|
||||
log.WithError(err).Fatal("An error occured while starting Docker containers")
|
||||
}
|
||||
}
|
||||
|
||||
func startStopChecks(cmd *cobra.Command, args []string) {
|
||||
datadir, _ := cmd.Flags().GetString("datadir")
|
||||
if err := config.ReadFromFile(datadir); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
28
cli/cmd/stop.go
Normal file
28
cli/cmd/stop.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var StopCmd = &cobra.Command{
|
||||
Use: "stop",
|
||||
Short: "Stop containers",
|
||||
Run: stop,
|
||||
PreRun: startStopChecks,
|
||||
}
|
||||
|
||||
func stop(cmd *cobra.Command, args []string) {
|
||||
composePath := getComposePath()
|
||||
|
||||
bashCmd := exec.Command("docker-compose", "-f", composePath, "stop")
|
||||
bashCmd.Stdout = os.Stdout
|
||||
bashCmd.Stderr = os.Stderr
|
||||
|
||||
if err := bashCmd.Run(); err != nil {
|
||||
log.WithError(err).Fatal("Error while stopping Docker containers:")
|
||||
}
|
||||
}
|
||||
26
cli/cmd/version.go
Normal file
26
cli/cmd/version.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulpemventures/nigiri/cli/config"
|
||||
)
|
||||
|
||||
var VersionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Get current tool version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
viper := config.Viper()
|
||||
fmt.Println(viper.GetString("version"))
|
||||
os.Exit(0)
|
||||
},
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
datadir, _ := cmd.Flags().GetString("datadir")
|
||||
if err := config.ReadFromFile(datadir); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
70
cli/config/main.go
Normal file
70
cli/config/main.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
Datadir = "datadir"
|
||||
Network = "network"
|
||||
Filename = "nigiri.config.json"
|
||||
AttachLiquid = "attachLiquid"
|
||||
Version = "version"
|
||||
)
|
||||
|
||||
var vip *viper.Viper
|
||||
|
||||
func init() {
|
||||
vip = viper.New()
|
||||
vip.SetEnvPrefix("NIGIRI")
|
||||
vip.AutomaticEnv()
|
||||
vip.BindEnv("config")
|
||||
|
||||
defaults := viper.New()
|
||||
newDefaultConfig(defaults)
|
||||
setConfigFromDefaults(vip, defaults)
|
||||
// vip.SetConfigFile(GetFullPath())
|
||||
}
|
||||
|
||||
func Viper() *viper.Viper {
|
||||
return vip
|
||||
}
|
||||
|
||||
func ReadFromFile(path string) error {
|
||||
vip.SetConfigFile(filepath.Join(path, Filename))
|
||||
return vip.ReadInConfig()
|
||||
}
|
||||
|
||||
func WriteConfig(path string) error {
|
||||
vip.SetConfigFile(path)
|
||||
return vip.WriteConfig()
|
||||
}
|
||||
|
||||
func GetString(str string) string {
|
||||
return vip.GetString(str)
|
||||
}
|
||||
|
||||
func GetBool(str string) bool {
|
||||
return vip.GetBool(str)
|
||||
}
|
||||
|
||||
func GetPath() string {
|
||||
home, _ := homedir.Expand("~")
|
||||
return filepath.Join(home, ".nigiri")
|
||||
}
|
||||
|
||||
func newDefaultConfig(v *viper.Viper) {
|
||||
v.SetDefault(Datadir, GetPath())
|
||||
v.SetDefault(Network, "regtest")
|
||||
v.SetDefault(AttachLiquid, false)
|
||||
v.SetDefault(Version, "0.1.0")
|
||||
}
|
||||
|
||||
func setConfigFromDefaults(v *viper.Viper, d *viper.Viper) {
|
||||
for key, value := range d.AllSettings() {
|
||||
v.SetDefault(key, value)
|
||||
}
|
||||
}
|
||||
7
cli/main.go
Normal file
7
cli/main.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "github.com/vulpemventures/nigiri/cli/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.RootCmd.Execute()
|
||||
}
|
||||
78
cli/resources/docker-compose-regtest-liquid.yml
Normal file
78
cli/resources/docker-compose-regtest-liquid.yml
Normal file
@@ -0,0 +1,78 @@
|
||||
version: '3'
|
||||
services:
|
||||
bitcoin:
|
||||
image: vulpemventures/bitcoin:latest
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.10
|
||||
volumes:
|
||||
- ./volumes/liquidregtest/config/:/config
|
||||
liquid:
|
||||
image: vulpemventures/liquid:latest
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.11
|
||||
volumes:
|
||||
- ./volumes/liquidregtest/liquid-config/:/config
|
||||
electrs:
|
||||
image: vulpemventures/electrs:latest
|
||||
entrypoint:
|
||||
- /build/electrs
|
||||
command:
|
||||
- -vvvv
|
||||
- --network
|
||||
- regtest
|
||||
- --daemon-dir
|
||||
- /config
|
||||
- --daemon-rpc-addr
|
||||
- 10.10.0.10:19001
|
||||
- --cookie
|
||||
- admin1:123
|
||||
- --http-addr
|
||||
- 0.0.0.0:3002
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.12
|
||||
ports:
|
||||
- 3002:3002
|
||||
volumes:
|
||||
- ./volumes/liquidregtest/config/:/config
|
||||
electrs-liquid:
|
||||
image: vulpemventures/electrs-liquid:latest
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.13
|
||||
entrypoint:
|
||||
- /build/electrs
|
||||
command:
|
||||
- -vvvv
|
||||
- --network
|
||||
- liquidregtest
|
||||
- --daemon-dir
|
||||
- /config
|
||||
- --daemon-rpc-addr
|
||||
- 10.10.0.11:18884
|
||||
- --cookie
|
||||
- admin1:123
|
||||
- --http-addr
|
||||
- 0.0.0.0:3002
|
||||
volumes:
|
||||
- ./volumes/liquidregtest/liquid-config/:/config
|
||||
ports:
|
||||
- 3022:3002
|
||||
# chopsticks:
|
||||
# build:
|
||||
# context: chopsticks/
|
||||
# dockerfile: Dockerfile
|
||||
# ports:
|
||||
# - 3000:3000
|
||||
# networks:
|
||||
# local:
|
||||
# ipv4_address: 10.10.0.13
|
||||
|
||||
networks:
|
||||
local:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 10.10.0.0/24
|
||||
50
cli/resources/docker-compose-regtest.yml
Normal file
50
cli/resources/docker-compose-regtest.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
version: '3'
|
||||
services:
|
||||
bitcoin:
|
||||
image: vulpemventures/bitcoin:latest
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.10
|
||||
ports:
|
||||
- 19001:19001
|
||||
volumes:
|
||||
- ./volumes/regtest/config/:/config
|
||||
electrs:
|
||||
image: vulpemventures/electrs:latest
|
||||
entrypoint:
|
||||
- /build/electrs
|
||||
command:
|
||||
- -vvvv
|
||||
- --network
|
||||
- regtest
|
||||
- --daemon-dir
|
||||
- /config
|
||||
- --daemon-rpc-addr
|
||||
- 10.10.0.10:19001
|
||||
- --cookie
|
||||
- admin1:123
|
||||
- --http-addr
|
||||
- 0.0.0.0:3002
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.12
|
||||
ports:
|
||||
- 3002:3002
|
||||
volumes:
|
||||
- ./volumes/regtest/config/:/config
|
||||
# chopsticks:
|
||||
# build:
|
||||
# context: chopsticks/
|
||||
# dockerfile: Dockerfile
|
||||
# ports:
|
||||
# - 3000:3000
|
||||
# networks:
|
||||
# local:
|
||||
# ipv4_address: 10.10.0.13
|
||||
|
||||
networks:
|
||||
local:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 10.10.0.0/24
|
||||
15
cli/resources/volumes/liquidregtest/config/bitcoin.conf
Normal file
15
cli/resources/volumes/liquidregtest/config/bitcoin.conf
Normal file
@@ -0,0 +1,15 @@
|
||||
regtest=1
|
||||
testnet=0
|
||||
dnsseed=0
|
||||
upnp=0
|
||||
|
||||
[regtest]
|
||||
port=19000
|
||||
rpcport=19001
|
||||
|
||||
server=1
|
||||
txindex=0
|
||||
|
||||
rpcuser=admin1
|
||||
rpcpassword=123
|
||||
rpcallowip=0.0.0.0/0
|
||||
@@ -1,23 +1,18 @@
|
||||
# Standard bitcoind stuff
|
||||
rpcuser=user1
|
||||
rpcpassword=password1
|
||||
rpcport=18884
|
||||
port=18886
|
||||
|
||||
# Over p2p we will only connect to local other liquidd
|
||||
# connect=localhost:18887
|
||||
|
||||
regtest=1
|
||||
# Make sure you set listen after -connect, otherwise neither
|
||||
# will accept incoming connections!
|
||||
listen=1
|
||||
# Just for looking at random txs
|
||||
port=18886
|
||||
txindex=0
|
||||
|
||||
# enable to allow non-localhost RPC connections
|
||||
# recommended to change to a subnet, such as your LAN
|
||||
rpcport=18884
|
||||
rpcuser=admin1
|
||||
rpcpassword=123
|
||||
rpcallowip=0.0.0.0/0
|
||||
|
||||
mainchainrpcport=19001
|
||||
mainchainrpchost=10.10.0.10
|
||||
mainchainrpcuser=admin1
|
||||
mainchainrpcpassword=123
|
||||
|
||||
# This is the script that controls pegged in funds in Bitcoin network
|
||||
# Users will be pegging into a P2SH of this, and the "watchmen"
|
||||
# can then recover these funds and send them to users who desire to peg out.
|
||||
@@ -32,15 +27,6 @@ rpcallowip=0.0.0.0/0
|
||||
# We want to validate pegins by checking with bitcoind if header exists
|
||||
# in best known chain, and how deep. We combine this with pegin
|
||||
# proof included in the pegin to get full security.
|
||||
|
||||
validatepegin=0
|
||||
|
||||
# If in the same datadir and using standard ports, these are unneeded
|
||||
# thanks to cookie auth. If not, like in our situation, liquidd needs
|
||||
# more info to connect to bitcoind:
|
||||
mainchainrpcport=19001
|
||||
mainchainrpchost=10.10.0.10
|
||||
mainchainrpcuser=admin1
|
||||
mainchainrpcpassword=123
|
||||
|
||||
# Free money to make testing easier
|
||||
initialfreecoins=10000000000
|
||||
initialfreecoins=10000000000
|
||||
15
cli/resources/volumes/regtest/config/bitcoin.conf
Normal file
15
cli/resources/volumes/regtest/config/bitcoin.conf
Normal file
@@ -0,0 +1,15 @@
|
||||
regtest=1
|
||||
testnet=0
|
||||
dnsseed=0
|
||||
upnp=0
|
||||
|
||||
[regtest]
|
||||
port=19000
|
||||
rpcport=19001
|
||||
|
||||
server=1
|
||||
txindex=0
|
||||
|
||||
rpcuser=admin1
|
||||
rpcpassword=123
|
||||
rpcallowip=0.0.0.0/0
|
||||
@@ -1,50 +0,0 @@
|
||||
version: '3'
|
||||
services:
|
||||
bitcoin:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: bitcoin/Dockerfile
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.10
|
||||
volumes:
|
||||
- bitcoin-config:/config
|
||||
liquid:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: liquid/Dockerfile
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.11
|
||||
volumes:
|
||||
- liquid-config:/config
|
||||
electrs:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: electrs/Dockerfile
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.12
|
||||
volumes:
|
||||
- bitcoin-config:/config
|
||||
- liquid-config:/liquidconfig
|
||||
chopsticks:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: chopsticks/Dockerfile
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
local:
|
||||
ipv4_address: 10.10.0.13
|
||||
|
||||
networks:
|
||||
local:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 10.10.0.0/24
|
||||
|
||||
volumes:
|
||||
bitcoin-config:
|
||||
liquid-config:
|
||||
@@ -1,16 +0,0 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update && apt-get install --yes wget
|
||||
|
||||
WORKDIR /build
|
||||
RUN wget -qO- https://github.com/vulpemventures/electrs/releases/download/v0.4.1-bin/electrs.tar.gz | tar -xvz && rm -rf electrs.tar.gz
|
||||
|
||||
# RUN cargo build --release
|
||||
WORKDIR /scripts
|
||||
ADD electrs/run /scripts
|
||||
|
||||
# Electrum REST
|
||||
EXPOSE 3002
|
||||
STOPSIGNAL SIGINT
|
||||
|
||||
CMD ["./run"]
|
||||
10
electrs/run
10
electrs/run
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
function clean {
|
||||
kill -9 $(pidof electrs)
|
||||
}
|
||||
trap clean SIGINT
|
||||
|
||||
/build/electrs -vvvv --network regtest --daemon-dir /config --daemon-rpc-addr="10.10.0.10:19001" --cookie="admin1:123" --http-addr="0.0.0.0:3002" &
|
||||
wait $!
|
||||
@@ -1,17 +0,0 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update && apt-get install --yes curl wget
|
||||
|
||||
RUN mkdir -p /tmp /config /script
|
||||
|
||||
ADD liquid/config /config
|
||||
ADD liquid/script /script
|
||||
|
||||
WORKDIR /script
|
||||
|
||||
RUN /script/install
|
||||
|
||||
EXPOSE 18884
|
||||
STOPSIGNAL SIGINT
|
||||
|
||||
CMD ["./run"]
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
LATEST_VERSION=$(curl --silent "https://api.github.com/repos/blockstream/liquid/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
VERSION_NAME=$(echo $LATEST_VERSION | sed '1,/\./s/\./\-/')
|
||||
|
||||
wget -qO- https://github.com/Blockstream/liquid/releases/download/$LATEST_VERSION/$VERSION_NAME-x86_64-linux-gnu.tar.gz | tar xvz -C /tmp
|
||||
|
||||
mv /tmp/$VERSION_NAME/bin/liquidd /usr/bin/liquidd
|
||||
mv /tmp/$VERSION_NAME/bin/liquid-cli /usr/bin/liquid-cli
|
||||
mv /tmp/$VERSION_NAME/bin/liquid-tx /usr/bin/liquid-tx
|
||||
|
||||
rm -rf /tmp
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
function clean {
|
||||
kill -9 $(pidof liquidd)
|
||||
}
|
||||
trap clean SIGINT
|
||||
|
||||
liquidd -datadir=/config &
|
||||
wait $!
|
||||
@@ -1,11 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
PARENT_PATH=$(dirname $(cd $(dirname $0); pwd -P))
|
||||
|
||||
pushd $PARENT_PATH
|
||||
|
||||
docker-compose stop
|
||||
|
||||
popd
|
||||
mkdir -p build
|
||||
GOOS=$1 GOARCH=$2 go build -o build/nigiri-$1-$2 ./cli
|
||||
popd
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
PARENT_PATH=$(dirname $(cd $(dirname $0); pwd -P))
|
||||
|
||||
pushd $PARENT_PATH
|
||||
|
||||
docker-compose down && \
|
||||
docker volume rm nigiri_bitcoin-config nigiri_liquid-config && \
|
||||
docker rmi nigiri_electrs nigiri_bitcoin nigiri_liquid
|
||||
|
||||
popd
|
||||
@@ -1,11 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
PARENT_PATH=$(dirname $(cd $(dirname $0); pwd -P))
|
||||
|
||||
pushd $PARENT_PATH
|
||||
dep ensure -v
|
||||
|
||||
docker-compose up -d
|
||||
|
||||
popd
|
||||
go generate ./...
|
||||
popd
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
PARENT_PATH=$(dirname $(cd $(dirname $0); pwd -P))
|
||||
|
||||
pushd $PARENT_PATH
|
||||
|
||||
docker-compose start
|
||||
|
||||
popd
|
||||
Reference in New Issue
Block a user