Scaffold noah cli (#10)

* CLI skeleton

* noah CLI: send flags

* add cypher.go file

* fix .PHONY

* add password_hash in state.json

* encode public key using common pkg

* use common.DecodeUrl

* remove cli.Exit calls

* redeem command: make --amount flag optional only if --force is not set

* remove validateURL func

* chmod +x scripts/build-noah

* Update cmd/noah/redeem.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* Update cmd/noah/redeem.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* Update cmd/noah/init.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* Update cmd/noah/main.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* Update cmd/noah/send.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* rework receive and send

* Update cmd/noah/send.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* Update cmd/noah/send.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* Update cmd/noah/redeem.go

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* receive command: return ark address

---------

Co-authored-by: bordalix <joao.bordalo@gmail.com>
Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>
This commit is contained in:
Louis Singer
2023-11-23 13:53:19 +01:00
committed by GitHub
parent 27b54f4c41
commit 20bc94087a
13 changed files with 742 additions and 3 deletions

View File

@@ -1,10 +1,14 @@
.PHONY: build clean cov help intergrationtest lint run test vet proto proto-lint
.PHONY: build build-noah clean cov help intergrationtest lint run test vet proto proto-lint
## build: build for all platforms
build:
@echo "Building coordinatord binary..."
@bash ./scripts/build
build-noah:
@echo "Building noah binary..."
@bash ./scripts/build-noah
## clean: cleans the binary
clean:
@echo "Cleaning..."

18
cmd/noah/balance.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"fmt"
"github.com/urfave/cli/v2"
)
var balanceCommand = cli.Command{
Name: "balance",
Usage: "Print balance of the Noah wallet",
Action: balanceAction,
}
func balanceAction(ctx *cli.Context) error {
fmt.Println("balance is not implemented yet")
return nil
}

114
cmd/noah/common.go Normal file
View File

@@ -0,0 +1,114 @@
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"syscall"
"github.com/ark-network/ark/common"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"golang.org/x/term"
)
func hashPassword(password []byte) []byte {
hash := sha256.Sum256(password)
return hash[:]
}
func verifyPassword(password []byte) error {
state, err := getState()
if err != nil {
return err
}
passwordHashString, ok := state["password_hash"]
if !ok {
return fmt.Errorf("password hash not found")
}
passwordHash, err := hex.DecodeString(passwordHashString)
if err != nil {
return err
}
currentPassHash := hashPassword(password)
if !bytes.Equal(passwordHash, currentPassHash) {
return fmt.Errorf("invalid password")
}
return nil
}
func readPassword() ([]byte, error) {
fmt.Print("password: ")
passwordInput, err := term.ReadPassword(int(syscall.Stdin))
fmt.Println() // new line
if err != nil {
return nil, err
}
err = verifyPassword(passwordInput)
if err != nil {
return nil, err
}
return passwordInput, nil
}
func privateKeyFromPassword() (*secp256k1.PrivateKey, error) {
state, err := getState()
if err != nil {
return nil, err
}
encryptedPrivateKeyString, ok := state["encrypted_private_key"]
if !ok {
return nil, fmt.Errorf("encrypted private key not found")
}
encryptedPrivateKey, err := hex.DecodeString(encryptedPrivateKeyString)
if err != nil {
return nil, err
}
password, err := readPassword()
if err != nil {
return nil, err
}
cypher := NewAES128Cypher()
privateKeyBytes, err := cypher.Decrypt(encryptedPrivateKey, password)
if err != nil {
return nil, err
}
privateKey := secp256k1.PrivKeyFromBytes(privateKeyBytes)
return privateKey, nil
}
func getServiceProviderPublicKey() (*secp256k1.PublicKey, error) {
state, err := getState()
if err != nil {
return nil, err
}
arkURL, ok := state["ark_url"]
if !ok {
return nil, fmt.Errorf("ark url not found")
}
arkPubKey, _, err := common.DecodeUrl(arkURL)
if err != nil {
return nil, err
}
_, publicKey, err := common.DecodePubKey(arkPubKey)
if err != nil {
return nil, err
}
return publicKey, nil
}

54
cmd/noah/config.go Normal file
View File

@@ -0,0 +1,54 @@
package main
import (
"fmt"
"github.com/ark-network/ark/common"
"github.com/urfave/cli/v2"
)
var configCommand = cli.Command{
Name: "config",
Usage: "Print local configuration of the Noah CLI",
Action: printConfigAction,
Subcommands: []*cli.Command{
{
Name: "connect",
Usage: "connect <ARK_URL>",
Action: connectAction,
},
},
}
func printConfigAction(ctx *cli.Context) error {
state, err := getState()
if err != nil {
return err
}
for key, value := range state {
fmt.Println(key + ": " + value)
}
return nil
}
func connectAction(ctx *cli.Context) error {
if ctx.NArg() != 1 {
return fmt.Errorf("missing ark URL")
}
url := ctx.Args().Get(0)
_, _, err := common.DecodeUrl(url)
if err != nil {
return err
}
if err := setState(map[string]string{"ark_url": url}); err != nil {
return err
}
fmt.Println("Connected to " + url)
return nil
}

106
cmd/noah/cypher.go Normal file
View File

@@ -0,0 +1,106 @@
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"runtime/debug"
"golang.org/x/crypto/scrypt"
)
type Cypher struct{}
func NewAES128Cypher() *Cypher {
return &Cypher{}
}
func (c *Cypher) Encrypt(privateKey, password []byte) ([]byte, error) {
// Due to https://github.com/golang/go/issues/7168.
// This call makes sure that memory is freed in case the GC doesn't do that
// right after the encryption/decryption.
defer debug.FreeOSMemory()
if len(privateKey) == 0 {
return nil, fmt.Errorf("missing plaintext private key")
}
if len(password) == 0 {
return nil, fmt.Errorf("missing encryption password")
}
key, salt, err := deriveKey(password, nil)
if err != nil {
return nil, err
}
blockCipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(blockCipher)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err = rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nonce, nonce, privateKey, nil)
ciphertext = append(ciphertext, salt...)
return ciphertext, nil
}
func (c *Cypher) Decrypt(encrypted, password []byte) ([]byte, error) {
defer debug.FreeOSMemory()
if len(encrypted) == 0 {
return nil, fmt.Errorf("missing encrypted mnemonic")
}
if len(password) == 0 {
return nil, fmt.Errorf("missing decryption password")
}
salt := encrypted[len(encrypted)-32:]
data := encrypted[:len(encrypted)-32]
key, _, err := deriveKey(password, salt)
if err != nil {
return nil, err
}
blockCipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(blockCipher)
if err != nil {
return nil, err
}
nonce, text := data[:gcm.NonceSize()], data[gcm.NonceSize():]
plaintext, err := gcm.Open(nil, nonce, text, nil)
if err != nil {
return nil, fmt.Errorf("invalid password")
}
return plaintext, nil
}
// deriveKey derives a 32 byte array key from a custom passhprase
func deriveKey(password, salt []byte) ([]byte, []byte, error) {
if salt == nil {
salt = make([]byte, 32)
if _, err := rand.Read(salt); err != nil {
return nil, nil, err
}
}
// 2^20 = 1048576 recommended length for key-stretching
// check the doc for other recommended values:
// https://godoc.org/golang.org/x/crypto/scrypt
key, err := scrypt.Key(password, salt, 1048576, 8, 1, 32)
if err != nil {
return nil, nil, err
}
return key, salt, nil
}

90
cmd/noah/init.go Normal file
View File

@@ -0,0 +1,90 @@
package main
import (
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/urfave/cli/v2"
)
var (
passwordFlag = cli.StringFlag{
Name: "password",
Usage: "password to encrypt private key",
Value: "",
Required: true,
}
privateKeyFlag = cli.StringFlag{
Name: "prvkey",
Usage: "optional, private key to encrypt",
Value: "",
Required: false,
}
)
var initCommand = cli.Command{
Name: "init",
Usage: "Initialize Noah wallet private key, encrypted with password",
Action: initAction,
Flags: []cli.Flag{
&passwordFlag,
&privateKeyFlag,
},
}
func initAction(ctx *cli.Context) error {
privateKeyString := ctx.String("prvkey")
password := ctx.String("password")
if len(password) <= 0 {
return fmt.Errorf("missing password flag (--password)")
}
var privateKey *secp256k1.PrivateKey
if len(privateKeyString) <= 0 {
privKey, err := generateRandomPrivateKey()
if err != nil {
return err
}
privateKey = privKey
} else {
privKeyBytes, err := hex.DecodeString(privateKeyString)
if err != nil {
return err
}
privateKey = secp256k1.PrivKeyFromBytes(privKeyBytes)
}
cypher := NewAES128Cypher()
encryptedPrivateKey, err := cypher.Encrypt(privateKey.Serialize(), []byte(password))
if err != nil {
return err
}
passwordHash := hashPassword([]byte(password))
state := map[string]string{
"encrypted_private_key": hex.EncodeToString(encryptedPrivateKey),
"password_hash": hex.EncodeToString(passwordHash),
}
if err := setState(state); err != nil {
return err
}
return nil
}
func generateRandomPrivateKey() (*secp256k1.PrivateKey, error) {
privKey, err := btcec.NewPrivateKey()
if err != nil {
return nil, err
}
return privKey, nil
}

158
cmd/noah/main.go Normal file
View File

@@ -0,0 +1,158 @@
package main
import (
"encoding/json"
"fmt"
"os"
"os/user"
"path/filepath"
"strings"
"github.com/ark-network/ark/common"
"github.com/urfave/cli/v2"
)
const (
DATADIR_ENVVAR = "NOAH_DATADIR"
STATE_FILE = "state.json"
defaultArkURL = "ark://apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x?relays=arelay1qt6f8p7h5f6tm7fv2z5wg92sz92rn9desfhd5733se4lkrptqtdrq65987l-arelay1qt6f8p7h5f6tm7fv2z5wg92sz92rn9desfhd5733se4lkrptqtdrq65987l"
)
var (
version = "alpha"
noahDataDirectory = common.AppDataDir("noah", false)
statePath = filepath.Join(noahDataDirectory, STATE_FILE)
initialState = map[string]string{
"ark_url": defaultArkURL,
"encrypted_private_key": "",
"password_hash": "",
}
)
func initCLIEnv() {
dataDir := cleanAndExpandPath(os.Getenv(DATADIR_ENVVAR))
if len(dataDir) <= 0 {
return
}
noahDataDirectory = dataDir
statePath = filepath.Join(noahDataDirectory, STATE_FILE)
}
func main() {
initCLIEnv()
app := cli.NewApp()
app.Version = version
app.Name = "noah CLI"
app.Usage = "Command line interface for Ark wallet"
app.Commands = append(
app.Commands,
&balanceCommand,
&configCommand,
&initCommand,
&receiveCommand,
&redeemCommand,
&sendCommand,
)
app.Before = func(ctx *cli.Context) error {
if _, err := os.Stat(noahDataDirectory); os.IsNotExist(err) {
return os.Mkdir(noahDataDirectory, os.ModeDir|0755)
}
return nil
}
err := app.Run(os.Args)
if err != nil {
fmt.Println(fmt.Errorf("error: %v", err))
os.Exit(1)
}
}
// cleanAndExpandPath expands environment variables and leading ~ in the
// passed path, cleans the result, and returns it.
// This function is taken from https://github.com/btcsuite/btcd
func cleanAndExpandPath(path string) string {
if path == "" {
return ""
}
// Expand initial ~ to OS specific home directory.
if strings.HasPrefix(path, "~") {
var homeDir string
u, err := user.Current()
if err == nil {
homeDir = u.HomeDir
} else {
homeDir = os.Getenv("HOME")
}
path = strings.Replace(path, "~", homeDir, 1)
}
// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
// but the variables can still be expanded via POSIX-style $VARIABLE.
return filepath.Clean(os.ExpandEnv(path))
}
func getState() (map[string]string, error) {
file, err := os.ReadFile(statePath)
if err != nil {
if !os.IsNotExist(err) {
return nil, err
}
if err := setInitialState(); err != nil {
return nil, err
}
return initialState, nil
}
data := map[string]string{}
if err := json.Unmarshal(file, &data); err != nil {
return nil, err
}
return data, nil
}
func setInitialState() error {
jsonString, err := json.Marshal(initialState)
if err != nil {
return err
}
return os.WriteFile(statePath, jsonString, 0755)
}
func setState(data map[string]string) error {
currentData, err := getState()
if err != nil {
return err
}
mergedData := merge(currentData, data)
jsonString, err := json.Marshal(mergedData)
if err != nil {
return err
}
err = os.WriteFile(statePath, jsonString, 0755)
if err != nil {
return fmt.Errorf("writing to file: %w", err)
}
return nil
}
func merge(maps ...map[string]string) map[string]string {
merge := make(map[string]string, 0)
for _, m := range maps {
for k, v := range m {
merge[k] = v
}
}
return merge
}

37
cmd/noah/receive.go Normal file
View File

@@ -0,0 +1,37 @@
package main
import (
"fmt"
"github.com/ark-network/ark/common"
"github.com/urfave/cli/v2"
)
var receiveCommand = cli.Command{
Name: "receive",
Usage: "Print the Ark address associated with your wallet and the connected Ark",
Action: receiveAction,
}
func receiveAction(ctx *cli.Context) error {
privateKey, err := privateKeyFromPassword()
if err != nil {
return err
}
publicKey := privateKey.PubKey()
aspPublicKey, err := getServiceProviderPublicKey()
if err != nil {
return err
}
addr, err := common.EncodeAddress(common.MainNet.Addr, publicKey, aspPublicKey)
if err != nil {
return err
}
fmt.Println(addr)
return nil
}

67
cmd/noah/redeem.go Normal file
View File

@@ -0,0 +1,67 @@
package main
import (
"fmt"
"github.com/urfave/cli/v2"
)
var (
addressFlag = cli.StringFlag{
Name: "address",
Usage: "main chain address receiving the redeeemed VTXO",
Value: "",
Required: true,
}
amountToRedeemFlag = cli.Uint64Flag{
Name: "amount",
Usage: "amount to redeem",
Value: 0,
Required: false,
}
forceFlag = cli.BoolFlag{
Name: "force",
Usage: "force redemption without collaborate with the Ark service provider",
Value: false,
Required: false,
}
)
var redeemCommand = cli.Command{
Name: "redeem",
Usage: "Redeem VTXO(s) to onchain",
Flags: []cli.Flag{&addressFlag, &amountToRedeemFlag, &forceFlag},
Action: redeemAction,
}
func redeemAction(ctx *cli.Context) error {
address := ctx.String("address")
amount := ctx.Uint64("amount")
force := ctx.Bool("force")
if len(address) <= 0 {
return fmt.Errorf("missing address flag (--address)")
}
if !force && amount <= 0 {
return fmt.Errorf("missing amount flag (--amount)")
}
if force {
return unilateralRedeem(address)
}
return collaborativeRedeem(address, amount)
}
func collaborativeRedeem(address string, amount uint64) error {
fmt.Println("collaborative redeem is not implemented yet")
return nil
}
func unilateralRedeem(address string) error {
fmt.Println("unilateral redeem is not implemented yet")
return nil
}

60
cmd/noah/send.go Normal file
View File

@@ -0,0 +1,60 @@
package main
import (
"encoding/json"
"fmt"
"github.com/ark-network/ark/common"
"github.com/urfave/cli/v2"
)
var (
receiversFlag = cli.StringFlag{
Name: "receivers",
Usage: "receivers of the send transaction, JSON encoded: '[{\"to\": \"<...>\", \"amount\": <...>}, ...]'",
Value: "",
Required: true,
}
)
var sendCommand = cli.Command{
Name: "send",
Usage: "Send VTXOs to a list of addresses",
Action: sendAction,
Flags: []cli.Flag{&receiversFlag},
}
func sendAction(ctx *cli.Context) error {
receivers := ctx.String("receivers")
// parse json encoded receivers
var receiversJSON []receiverJSON
if err := json.Unmarshal([]byte(receivers), &receiversJSON); err != nil {
return fmt.Errorf("invalid receivers: %s", err)
}
if len(receiversJSON) <= 0 {
return fmt.Errorf("no receivers specified")
}
for _, receiver := range receiversJSON {
// TODO: check if receiver asp public key is valid
_, _, _, err := common.DecodeAddress(receiver.To)
if err != nil {
return fmt.Errorf("invalid receiver address: %s", err)
}
if receiver.Amount <= 0 {
return fmt.Errorf("invalid amount: %d", receiver.Amount)
}
}
fmt.Println("send command is not implemented yet")
return nil
}
type receiverJSON struct {
To string `json:"to"`
Amount int64 `json:"amount"`
}

9
go.mod
View File

@@ -6,23 +6,26 @@ replace github.com/ark-network/ark/common => ./pkg/common
require (
github.com/ark-network/ark/common v0.0.0-00010101000000-000000000000
github.com/btcsuite/btcd/btcec/v2 v2.2.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
github.com/google/uuid v1.3.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.17.0
github.com/urfave/cli/v2 v2.25.7
github.com/vulpemventures/go-elements v0.4.7
golang.org/x/term v0.13.0
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0
)
require (
github.com/btcsuite/btcd v0.23.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/btcutil v1.1.3 // indirect
github.com/btcsuite/btcd/btcutil/psbt v1.1.4 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
@@ -30,6 +33,7 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
@@ -38,6 +42,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.14.0 // indirect

10
go.sum
View File

@@ -75,6 +75,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -212,6 +214,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
@@ -242,12 +246,16 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 h1:CTcw80hz/Sw8hqlKX5ZYvBUF5gAHSHwdjXxRf/cjDcI=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:GXBJykxW2kUcktGdsgyay7uwwWvkljASfljNcT0mbh8=
github.com/vulpemventures/go-elements v0.4.7 h1:M5dtBHwRXqct75DJeEv5b0PUFS93t0gh2naJaGlvp60=
github.com/vulpemventures/go-elements v0.4.7/go.mod h1:aBGuWXHaiAIUIcwqCdtEh2iQ3kJjKwHU9ywvhlcRSeU=
github.com/vulpemventures/go-secp256k1-zkp v1.1.6 h1:BmsrmXRLUibwa75Qkk8yELjpzCzlAjYFGLiLiOdq7Xo=
github.com/vulpemventures/go-secp256k1-zkp v1.1.6/go.mod h1:zo7CpgkuPgoe7fAV+inyxsI9IhGmcoFgyD8nqZaPSOM=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -410,6 +418,8 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

16
scripts/build-noah Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -e
PARENT_PATH=$(dirname $(
cd $(dirname $0)
pwd -P
))
OS=$(eval "go env GOOS")
ARCH=$(eval "go env GOARCH")
pushd $PARENT_PATH
mkdir -p build
GO111MODULE=on go build -ldflags="-s -w" -o build/noah-$OS-$ARCH ./cmd/noah
popd