mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-22 11:39:15 +00:00
Compare commits
5 Commits
v0.6.9-dev
...
v0.6.10-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1743dc694a | ||
|
|
8fb30a5895 | ||
|
|
d59ed71465 | ||
|
|
ea0f5ca60e | ||
|
|
bf74341257 |
@@ -44,8 +44,12 @@ func (m *Manager) routerInitializer(router *router.Router, netConnection *netada
|
||||
err := m.handleIncomingMessages(router, incomingRoute)
|
||||
m.handleError(err, netConnection)
|
||||
})
|
||||
|
||||
notificationListener := m.context.NotificationManager.AddListener(router)
|
||||
spawn("routerInitializer-handleOutgoingNotifications", func() {
|
||||
err := m.handleOutgoingNotifications(router)
|
||||
defer m.context.NotificationManager.RemoveListener(router)
|
||||
|
||||
err := m.handleOutgoingNotifications(notificationListener)
|
||||
m.handleError(err, netConnection)
|
||||
})
|
||||
}
|
||||
@@ -72,9 +76,7 @@ func (m *Manager) handleIncomingMessages(router *router.Router, incomingRoute *r
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) handleOutgoingNotifications(router *router.Router) error {
|
||||
notificationListener := m.context.NotificationManager.AddListener(router)
|
||||
defer m.context.NotificationManager.RemoveListener(router)
|
||||
func (m *Manager) handleOutgoingNotifications(notificationListener *rpccontext.NotificationListener) error {
|
||||
for {
|
||||
err := notificationListener.ProcessNextNotification()
|
||||
if err != nil {
|
||||
|
||||
34
cmd/kaspactl/docker/Dockerfile
Normal file
34
cmd/kaspactl/docker/Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
||||
# -- multistage docker build: stage #1: build stage
|
||||
FROM golang:1.14-alpine AS build
|
||||
|
||||
RUN mkdir -p /go/src/github.com/kaspanet/kaspad
|
||||
|
||||
WORKDIR /go/src/github.com/kaspanet/kaspad
|
||||
|
||||
RUN apk add --no-cache curl git openssh binutils gcc musl-dev
|
||||
RUN go get -u golang.org/x/lint/golint
|
||||
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
WORKDIR /go/src/github.com/kaspanet/kaspad/cmd/kaspactl
|
||||
|
||||
RUN GOFMT_RESULT=`go fmt ./...`; echo $GOFMT_RESULT; test -z "$GOFMT_RESULT"
|
||||
RUN go vet ./...
|
||||
RUN golint -set_exit_status ./...
|
||||
RUN GOOS=linux go build -a -installsuffix cgo -o kaspactl .
|
||||
|
||||
# --- multistage docker build: stage #2: runtime image
|
||||
FROM alpine
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache ca-certificates tini
|
||||
|
||||
COPY --from=build /go/src/github.com/kaspanet/kaspad/cmd/kaspactl/kaspactl /app/
|
||||
|
||||
USER nobody
|
||||
ENTRYPOINT [ "/sbin/tini", "--" ]
|
||||
@@ -6,8 +6,6 @@ package config
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -92,18 +90,13 @@ type Flags struct {
|
||||
BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"`
|
||||
BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
|
||||
Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"`
|
||||
RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"`
|
||||
RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||
RPCLimitUser string `long:"rpclimituser" description:"Username for limited RPC connections"`
|
||||
RPCLimitPass string `long:"rpclimitpass" default-mask:"-" description:"Password for limited RPC connections"`
|
||||
RPCListeners []string `long:"rpclisten" description:"Add an interface/port to listen for RPC connections (default port: 16110, testnet: 16210)"`
|
||||
RPCCert string `long:"rpccert" description:"File containing the certificate file"`
|
||||
RPCKey string `long:"rpckey" description:"File containing the certificate key"`
|
||||
RPCMaxClients int `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"`
|
||||
RPCMaxWebsockets int `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"`
|
||||
RPCMaxConcurrentReqs int `long:"rpcmaxconcurrentreqs" description:"Max number of concurrent RPC requests that may be processed concurrently"`
|
||||
DisableRPC bool `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass or rpclimituser/rpclimitpass is specified"`
|
||||
DisableTLS bool `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"`
|
||||
DisableRPC bool `long:"norpc" description:"Disable built-in RPC server"`
|
||||
DisableDNSSeed bool `long:"nodnsseed" description:"Disable DNS seeding for peers"`
|
||||
DNSSeed string `long:"dnsseed" description:"Override DNS seeds with specified hostname (Only 1 hostname allowed)"`
|
||||
GRPCSeed string `long:"grpcseed" description:"Hostname of gRPC server for seeding peers"`
|
||||
@@ -317,24 +310,6 @@ func LoadConfig() (cfg *Config, remainingArgs []string, err error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !cfg.DisableRPC {
|
||||
if cfg.RPCUser == "" {
|
||||
str := "%s: rpcuser cannot be empty"
|
||||
err := errors.Errorf(str, funcName)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, usageMessage)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if cfg.RPCPass == "" {
|
||||
str := "%s: rpcpass cannot be empty"
|
||||
err := errors.Errorf(str, funcName)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, usageMessage)
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = cfg.ResolveNetwork(parser)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -476,32 +451,6 @@ func LoadConfig() (cfg *Config, remainingArgs []string, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check to make sure limited and admin users don't have the same username
|
||||
if cfg.RPCUser == cfg.RPCLimitUser && cfg.RPCUser != "" {
|
||||
str := "%s: --rpcuser and --rpclimituser must not specify the " +
|
||||
"same username"
|
||||
err := errors.Errorf(str, funcName)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, usageMessage)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Check to make sure limited and admin users don't have the same password
|
||||
if cfg.RPCPass == cfg.RPCLimitPass && cfg.RPCPass != "" {
|
||||
str := "%s: --rpcpass and --rpclimitpass must not specify the " +
|
||||
"same password"
|
||||
err := errors.Errorf(str, funcName)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, usageMessage)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// The RPC server is disabled if no username or password is provided.
|
||||
if (cfg.RPCUser == "" || cfg.RPCPass == "") &&
|
||||
(cfg.RPCLimitUser == "" || cfg.RPCLimitPass == "") {
|
||||
cfg.DisableRPC = true
|
||||
}
|
||||
|
||||
if cfg.DisableRPC {
|
||||
log.Infof("RPC service is disabled")
|
||||
}
|
||||
@@ -604,36 +553,6 @@ func LoadConfig() (cfg *Config, remainingArgs []string, err error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Only allow TLS to be disabled if the RPC is bound to localhost
|
||||
// addresses.
|
||||
if !cfg.DisableRPC && cfg.DisableTLS {
|
||||
allowedTLSListeners := map[string]struct{}{
|
||||
"localhost": {},
|
||||
"127.0.0.1": {},
|
||||
"::1": {},
|
||||
}
|
||||
for _, addr := range cfg.RPCListeners {
|
||||
host, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
str := "%s: RPC listen interface '%s' is " +
|
||||
"invalid: %s"
|
||||
err := errors.Errorf(str, funcName, addr, err)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, usageMessage)
|
||||
return nil, nil, err
|
||||
}
|
||||
if _, ok := allowedTLSListeners[host]; !ok {
|
||||
str := "%s: the --notls option may not be used " +
|
||||
"when binding RPC to non localhost " +
|
||||
"addresses: %s"
|
||||
err := errors.Errorf(str, funcName, addr)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, usageMessage)
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disallow --addpeer and --connect used together
|
||||
if len(cfg.AddPeers) > 0 && len(cfg.ConnectPeers) > 0 {
|
||||
str := "%s: --addpeer and --connect can not be used together"
|
||||
@@ -708,22 +627,6 @@ func createDefaultConfigFile(destinationPath string) error {
|
||||
}
|
||||
sampleConfigPath := filepath.Join(path, sampleConfigFilename)
|
||||
|
||||
// We generate a random user and password
|
||||
randomBytes := make([]byte, 20)
|
||||
_, err = rand.Read(randomBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
generatedRPCUser := base64.StdEncoding.EncodeToString(randomBytes)
|
||||
rpcUserString := fmt.Sprintf("rpcuser=%s\n", generatedRPCUser)
|
||||
|
||||
_, err = rand.Read(randomBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
generatedRPCPass := base64.StdEncoding.EncodeToString(randomBytes)
|
||||
rpcPassString := fmt.Sprintf("rpcpass=%s\n", generatedRPCPass)
|
||||
|
||||
dest, err := os.OpenFile(destinationPath,
|
||||
os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
@@ -731,25 +634,13 @@ func createDefaultConfigFile(destinationPath string) error {
|
||||
}
|
||||
defer dest.Close()
|
||||
|
||||
// If the sample config file is missing because e.g. kaspad was
|
||||
// installed using go install, simply create the destination
|
||||
// file and write the RPC credentials into it as is.
|
||||
if _, err := os.Stat(sampleConfigPath); os.IsNotExist(err) {
|
||||
toWrite := rpcUserString + rpcPassString
|
||||
if _, err := dest.WriteString(toWrite); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
src, err := os.Open(sampleConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// We copy every line from the sample config file to the destination,
|
||||
// only replacing the two lines for rpcuser and rpcpass
|
||||
// We copy every line from the sample config file to the destination
|
||||
reader := bufio.NewReader(src)
|
||||
for err != io.EOF {
|
||||
var line string
|
||||
@@ -758,12 +649,6 @@ func createDefaultConfigFile(destinationPath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(line, "rpcuser=") {
|
||||
line = rpcUserString
|
||||
} else if strings.Contains(line, "rpcpass=") {
|
||||
line = rpcPassString
|
||||
}
|
||||
|
||||
if _, err := dest.WriteString(line); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,18 +4,12 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||
)
|
||||
|
||||
var (
|
||||
rpcuserRegexp = regexp.MustCompile("(?m)^rpcuser=.+$")
|
||||
rpcpassRegexp = regexp.MustCompile("(?m)^rpcpass=.+$")
|
||||
)
|
||||
|
||||
func TestCreateDefaultConfigFile(t *testing.T) {
|
||||
// find out where the sample config lives
|
||||
_, path, _, ok := runtime.Caller(0)
|
||||
@@ -54,23 +48,9 @@ func TestCreateDefaultConfigFile(t *testing.T) {
|
||||
}()
|
||||
|
||||
err = createDefaultConfigFile(testpath)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a default config file: %v", err)
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(testpath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read generated default config file: %v", err)
|
||||
}
|
||||
|
||||
if !rpcuserRegexp.Match(content) {
|
||||
t.Error("Could not find rpcuser in generated default config file.")
|
||||
}
|
||||
|
||||
if !rpcpassRegexp.Match(content) {
|
||||
t.Error("Could not find rpcpass in generated default config file.")
|
||||
}
|
||||
}
|
||||
|
||||
// TestConstants makes sure that all constants hard-coded into the help text were not modified.
|
||||
|
||||
@@ -12,9 +12,13 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// OnErrorHandler defines a handler function for when errors occur
|
||||
type OnErrorHandler func(err error)
|
||||
|
||||
// GRPCClient is a gRPC-based RPC client
|
||||
type GRPCClient struct {
|
||||
stream protowire.RPC_MessageStreamClient
|
||||
stream protowire.RPC_MessageStreamClient
|
||||
onErrorHandler OnErrorHandler
|
||||
}
|
||||
|
||||
// Connect connects to the RPC server with the given address
|
||||
@@ -41,6 +45,11 @@ func (c *GRPCClient) Disconnect() error {
|
||||
return c.stream.CloseSend()
|
||||
}
|
||||
|
||||
// SetOnErrorHandler sets the client's onErrorHandler
|
||||
func (c *GRPCClient) SetOnErrorHandler(onErrorHandler OnErrorHandler) {
|
||||
c.onErrorHandler = onErrorHandler
|
||||
}
|
||||
|
||||
// AttachRouter attaches the given router to the client and starts
|
||||
// sending/receiving messages via it
|
||||
func (c *GRPCClient) AttachRouter(router *router.Router) {
|
||||
@@ -101,5 +110,9 @@ func (c *GRPCClient) handleError(err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if c.onErrorHandler != nil {
|
||||
c.onErrorHandler(err)
|
||||
return
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ type RPCClient struct {
|
||||
func NewRPCClient(rpcAddress string) (*RPCClient, error) {
|
||||
rpcClient, err := grpcclient.Connect(rpcAddress)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error connecting to address %s", rpcClient)
|
||||
return nil, errors.Wrapf(err, "error connecting to address %s", rpcAddress)
|
||||
}
|
||||
rpcRouter, err := buildRPCRouter()
|
||||
if err != nil {
|
||||
|
||||
@@ -152,20 +152,8 @@
|
||||
; ------------------------------------------------------------------------------
|
||||
; RPC server options - The following options control the built-in RPC server
|
||||
; which is used to control and query information from a running kaspad process.
|
||||
;
|
||||
; NOTE: The RPC server is disabled by default if rpcuser AND rpcpass, or
|
||||
; rpclimituser AND rpclimitpass, are not specified.
|
||||
; ------------------------------------------------------------------------------
|
||||
|
||||
; Secure the RPC API by specifying the username and password. You can also
|
||||
; specify a limited username and password. You must specify at least one
|
||||
; full set of credentials - limited or admin - or the RPC server will
|
||||
; be disabled.
|
||||
; rpcuser=whatever_admin_username_you_want
|
||||
; rpcpass=
|
||||
; rpclimituser=whatever_limited_username_you_want
|
||||
; rpclimitpass=
|
||||
|
||||
; Specify the interfaces for the RPC server listen on. One listen address per
|
||||
; line. NOTE: The default port is modified by some options such as 'testnet',
|
||||
; so it is recommended to not specify a port and allow a proper default to be
|
||||
@@ -199,19 +187,9 @@
|
||||
; Specify the maximum number of concurrent RPC clients for standard connections.
|
||||
; rpcmaxclients=10
|
||||
|
||||
; Specify the maximum number of concurrent RPC websocket clients.
|
||||
; rpcmaxwebsockets=25
|
||||
|
||||
; Use the following setting to disable the RPC server even if the rpcuser and
|
||||
; rpcpass are specified above. This allows one to quickly disable the RPC
|
||||
; server without having to remove credentials from the config file.
|
||||
; Use the following setting to disable the RPC server.
|
||||
; norpc=1
|
||||
|
||||
; Use the following setting to disable TLS for the RPC server. NOTE: This
|
||||
; option only works if the RPC server is bound to localhost interfaces (which is
|
||||
; the default).
|
||||
; notls=1
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------------
|
||||
; Mempool Settings - The following options
|
||||
|
||||
@@ -18,9 +18,6 @@ const (
|
||||
rpcAddress2 = "127.0.0.1:12346"
|
||||
rpcAddress3 = "127.0.0.1:12347"
|
||||
|
||||
rpcUser = "user"
|
||||
rpcPass = "pass"
|
||||
|
||||
miningAddress1 = "kaspasim:qzmdkk8ay8sgvp8cnwts8gtdylz9j7572slwdh85qv"
|
||||
miningAddress1PrivateKey = "be9e9884f03e687166479e22d21b064db7903d69b5a46878aae66521c01a6094"
|
||||
|
||||
@@ -47,9 +44,6 @@ func commonConfig() *config.Config {
|
||||
commonConfig.ActiveNetParams.BlockCoinbaseMaturity = 10
|
||||
commonConfig.TargetOutboundPeers = 0
|
||||
commonConfig.DisableDNSSeed = true
|
||||
commonConfig.RPCUser = rpcUser
|
||||
commonConfig.RPCPass = rpcPass
|
||||
commonConfig.DisableTLS = true
|
||||
commonConfig.Simnet = true
|
||||
|
||||
return commonConfig
|
||||
|
||||
@@ -224,7 +224,16 @@ func HashToBig(hash *Hash) *big.Int {
|
||||
// +1 if hash > target
|
||||
//
|
||||
func (hash *Hash) Cmp(target *Hash) int {
|
||||
return HashToBig(hash).Cmp(HashToBig(target))
|
||||
// We compare the hashes backwards because Hash is stored as a little endian byte array.
|
||||
for i := HashSize - 1; i >= 0; i-- {
|
||||
switch {
|
||||
case hash[i] < target[i]:
|
||||
return -1
|
||||
case hash[i] > target[i]:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Less returns true iff hash a is less than hash b
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
@@ -425,3 +426,43 @@ func TestSort(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hashFlipBit(hash Hash, bit int) Hash {
|
||||
word := bit / 8
|
||||
bit = bit % 8
|
||||
hash[word] ^= 1 << bit
|
||||
return hash
|
||||
}
|
||||
|
||||
func TestHash_Cmp(t *testing.T) {
|
||||
r := rand.New(rand.NewSource(1))
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
hash := Hash{}
|
||||
n, err := r.Read(hash[:])
|
||||
if err != nil {
|
||||
t.Fatalf("Failed generating a random hash '%s'", err)
|
||||
} else if n != len(hash) {
|
||||
t.Fatalf("Failed generating a random hash, expected reading: %d. instead read: %d.", len(hash), n)
|
||||
|
||||
}
|
||||
hashBig := HashToBig(&hash)
|
||||
// Iterate bit by bit, flip it and compare.
|
||||
for bit := 0; bit < HashSize*8; bit++ {
|
||||
newHash := hashFlipBit(hash, bit)
|
||||
if hash.Cmp(&newHash) != hashBig.Cmp(HashToBig(&newHash)) {
|
||||
t.Errorf("Hash.Cmp disagrees with big.Int.Cmp newHash: %s, hash: %s", newHash, hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHash_Cmp(b *testing.B) {
|
||||
hash0, err := NewHashFromStr("3333333333333333333333333333333333333333333333333333333333333333")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
for n := 0; n < b.N; n++ {
|
||||
hash0.Cmp(hash0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs
|
||||
const (
|
||||
appMajor uint = 0
|
||||
appMinor uint = 6
|
||||
appPatch uint = 9
|
||||
appPatch uint = 10
|
||||
)
|
||||
|
||||
// appBuild is defined as a variable so it can be overridden during the build
|
||||
|
||||
Reference in New Issue
Block a user