diff --git a/asp/Makefile b/asp/Makefile index e6da110..9f233d4 100755 --- a/asp/Makefile +++ b/asp/Makefile @@ -34,6 +34,7 @@ lint: run: clean @echo "Running arkd in dev mode..." @export ARK_WALLET_ADDR=localhost:18000; \ + export ARK_ROUND_INTERVAL=30; \ go run ./cmd/arkd ## test: runs unit and component tests diff --git a/asp/cmd/arkd/main.go b/asp/cmd/arkd/main.go index cd0f5f7..5b2c085 100755 --- a/asp/cmd/arkd/main.go +++ b/asp/cmd/arkd/main.go @@ -5,7 +5,9 @@ import ( "os/signal" "syscall" - service_interface "github.com/ark-network/ark/internal/interface" + appconfig "github.com/ark-network/ark/internal/app-config" + "github.com/ark-network/ark/internal/config" + grpcservice "github.com/ark-network/ark/internal/interface/grpc" log "github.com/sirupsen/logrus" ) @@ -17,7 +19,27 @@ var ( ) func main() { - svc, err := service_interface.NewService(service_interface.Options{}) // TODO populate options + cfg, err := config.LoadConfig() + if err != nil { + log.WithError(err).Fatal("invalid config") + } + + log.SetLevel(log.Level(cfg.LogLevel)) + + svcConfig := grpcservice.Config{ + Port: cfg.Port, + NoTLS: cfg.NoTLS, + } + appConfig := &appconfig.Config{ + DbType: cfg.DbType, + DbDir: cfg.DbDir, + RoundInterval: cfg.RoundInterval, + Network: cfg.Network, + SchedulerType: cfg.SchedulerType, + TxBuilderType: cfg.TxBuilderType, + WalletAddr: cfg.WalletAddr, + } + svc, err := grpcservice.NewService(svcConfig, appConfig) if err != nil { log.Fatal(err) } diff --git a/asp/go.mod b/asp/go.mod index f37d518..07565e4 100644 --- a/asp/go.mod +++ b/asp/go.mod @@ -6,11 +6,12 @@ replace github.com/ark-network/ark/common => ../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/dgraph-io/badger/v4 v4.1.0 github.com/go-co-op/gocron v1.36.0 + github.com/gogo/protobuf v1.3.2 github.com/google/uuid v1.4.0 + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.17.0 @@ -23,41 +24,34 @@ require ( google.golang.org/protobuf v1.31.0 ) -require ( - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.1.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/flatbuffers v23.5.9+incompatible // indirect - github.com/klauspost/compress v1.17.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect -) - require ( github.com/btcsuite/btcd v0.23.1 // indirect - github.com/btcsuite/btcd/btcutil v1.1.3 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/btcsuite/btcd/btcutil v1.1.3 github.com/btcsuite/btcd/btcutil/psbt v1.1.4 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/golang/glog v1.1.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/flatbuffers v23.5.9+incompatible // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect 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/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/robfig/cron/v3 v3.0.1 // 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 @@ -66,12 +60,16 @@ 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.opencensus.io v0.24.0 // 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 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/asp/go.sum b/asp/go.sum index bcf877b..a41443a 100644 --- a/asp/go.sum +++ b/asp/go.sum @@ -40,6 +40,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= @@ -125,6 +126,9 @@ github.com/go-co-op/gocron v1.36.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISk github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -201,6 +205,8 @@ github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U= github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -223,6 +229,7 @@ github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -249,10 +256,12 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= @@ -274,6 +283,7 @@ github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9c 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= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -293,6 +303,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -336,10 +347,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -459,6 +474,7 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -495,6 +511,7 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -538,6 +555,7 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -625,6 +643,7 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= @@ -692,8 +711,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/asp/internal/app-config/config.go b/asp/internal/app-config/config.go new file mode 100644 index 0000000..827a502 --- /dev/null +++ b/asp/internal/app-config/config.go @@ -0,0 +1,170 @@ +package appconfig + +import ( + "fmt" + "strings" + + "github.com/ark-network/ark/common" + "github.com/ark-network/ark/internal/core/application" + "github.com/ark-network/ark/internal/core/ports" + "github.com/ark-network/ark/internal/infrastructure/db" + oceanwallet "github.com/ark-network/ark/internal/infrastructure/ocean-wallet" + txbuilder "github.com/ark-network/ark/internal/infrastructure/tx-builder/dummy" + log "github.com/sirupsen/logrus" + "github.com/vulpemventures/go-elements/network" +) + +var ( + supportedDbs = supportedType{ + "badger": {}, + } + supportedSchedulers = supportedType{ + "gocron": {}, + } + supportedTxBuilders = supportedType{ + "dummy": {}, + } +) + +type Config struct { + DbType string + DbDir string + RoundInterval int64 + Network common.Network + SchedulerType string + TxBuilderType string + WalletAddr string + + repo ports.RepoManager + svc application.Service + wallet ports.WalletService + txBuilder ports.TxBuilder +} + +func (c *Config) Validate() error { + if !supportedDbs.supports(c.DbType) { + return fmt.Errorf("db type not supported, please select one of: %s", supportedDbs) + } + if !supportedSchedulers.supports(c.SchedulerType) { + return fmt.Errorf("scheduler type not supported, please select one of: %s", supportedSchedulers) + } + if !supportedTxBuilders.supports(c.TxBuilderType) { + return fmt.Errorf("tx builder type not supported, please select one of: %s", supportedTxBuilders) + } + if c.RoundInterval < 5 { + return fmt.Errorf("invalid round interval, must be at least 5 seconds") + } + if c.Network.Name != "liquid" && c.Network.Name != "testnet" { + return fmt.Errorf("invalid network, must be either liquid or testnet") + } + if len(c.WalletAddr) <= 0 { + return fmt.Errorf("missing onchain wallet address") + } + if err := c.repoManager(); err != nil { + return err + } + if err := c.walletService(); err != nil { + return fmt.Errorf("failed to connect to wallet: %s", err) + } + if err := c.txBuilderService(); err != nil { + return err + } + if err := c.appService(); err != nil { + return err + } + return nil +} + +func (c *Config) AppService() application.Service { + return c.svc +} + +func (c *Config) repoManager() error { + var svc ports.RepoManager + var err error + switch c.DbType { + case "badger": + logger := log.New() + svc, err = db.NewService(db.ServiceConfig{ + EventStoreType: c.DbType, + RoundStoreType: c.DbType, + VtxoStoreType: c.DbType, + + EventStoreConfig: []interface{}{c.DbDir, logger}, + RoundStoreConfig: []interface{}{c.DbDir, logger}, + VtxoStoreConfig: []interface{}{c.DbDir, logger}, + }) + default: + return fmt.Errorf("unknown db type") + } + if err != nil { + return err + } + + c.repo = svc + return nil +} + +func (c *Config) walletService() error { + svc, err := oceanwallet.NewService(c.WalletAddr) + if err != nil { + return err + } + + c.wallet = svc + return nil +} + +func (c *Config) txBuilderService() error { + var svc ports.TxBuilder + var err error + net := c.mainChain() + switch c.TxBuilderType { + case "dummy": + svc = txbuilder.NewTxBuilder(net) + default: + err = fmt.Errorf("unknown db type") + } + if err != nil { + return err + } + + c.txBuilder = svc + return nil +} + +func (c *Config) appService() error { + net := c.mainChain() + svc, err := application.NewService( + c.RoundInterval, c.Network, net, c.wallet, c.repo, c.txBuilder, + ) + if err != nil { + return err + } + + c.svc = svc + return nil +} + +func (c *Config) mainChain() network.Network { + net := network.Liquid + if c.Network.Name != "mainnet" { + net = network.Testnet + } + return net +} + +type supportedType map[string]struct{} + +func (t supportedType) String() string { + types := make([]string, 0, len(t)) + for tt := range t { + types = append(types, tt) + } + return strings.Join(types, " | ") +} + +func (t supportedType) supports(typeStr string) bool { + _, ok := t[typeStr] + return ok +} diff --git a/asp/internal/config/config.go b/asp/internal/config/config.go index ffe7d1f..8428c13 100644 --- a/asp/internal/config/config.go +++ b/asp/internal/config/config.go @@ -3,6 +3,8 @@ package config import ( "fmt" "os" + "path/filepath" + "strings" common "github.com/ark-network/ark/common" "github.com/spf13/viper" @@ -11,15 +13,37 @@ import ( type Config struct { WalletAddr string RoundInterval int64 + Port uint32 + DbType string + DbDir string + SchedulerType string + TxBuilderType string + NoTLS bool + Network common.Network + LogLevel int } var ( Datadir = "DATADIR" WalletAddr = "WALLET_ADDR" RoundInterval = "ROUND_INTERVAL" + Port = "PORT" + DbType = "DB_TYPE" + SchedulerType = "SCHEDULER_TYPE" + TxBuilderType = "TX_BUILDER_TYPE" + Insecure = "INSECURE" + LogLevel = "LOG_LEVEL" + Network = "NETWORK" defaultDatadir = common.AppDataDir("arkd", false) defaultRoundInterval = 60 + defaultPort = 6000 + defaultDbType = "badger" + defaultSchedulerType = "gocron" + defaultTxBuilderType = "dummy" + defaultInsecure = true + defaultNetwork = "testnet" + defaultLogLevel = 5 ) func LoadConfig() (*Config, error) { @@ -28,30 +52,35 @@ func LoadConfig() (*Config, error) { viper.SetDefault(Datadir, defaultDatadir) viper.SetDefault(RoundInterval, defaultRoundInterval) + viper.SetDefault(Port, defaultPort) + viper.SetDefault(DbType, defaultDbType) + viper.SetDefault(SchedulerType, defaultSchedulerType) + viper.SetDefault(TxBuilderType, defaultTxBuilderType) + viper.SetDefault(Insecure, defaultInsecure) + viper.SetDefault(LogLevel, defaultLogLevel) + viper.SetDefault(Network, defaultNetwork) + + net, err := getNetwork() + if err != nil { + return nil, err + } if err := initDatadir(); err != nil { return nil, fmt.Errorf("error while creating datadir: %s", err) } - cfg := &Config{ + return &Config{ WalletAddr: viper.GetString(WalletAddr), RoundInterval: viper.GetInt64(RoundInterval), - } - - if err := cfg.validate(); err != nil { - return nil, err - } - return cfg, nil -} - -func (c *Config) validate() error { - if len(c.WalletAddr) <= 0 { - return fmt.Errorf("missing wallet address") - } - if c.RoundInterval < 5 { - return fmt.Errorf("round interval must be at least 5 seconds") - } - return nil + Port: viper.GetUint32(Port), + DbType: viper.GetString(DbType), + SchedulerType: viper.GetString(SchedulerType), + TxBuilderType: viper.GetString(TxBuilderType), + NoTLS: viper.GetBool(Insecure), + DbDir: filepath.Join(viper.GetString(Datadir), "db"), + LogLevel: viper.GetInt(LogLevel), + Network: net, + }, nil } func initDatadir() error { @@ -65,3 +94,14 @@ func makeDirectoryIfNotExists(path string) error { } return nil } + +func getNetwork() (common.Network, error) { + switch strings.ToLower(viper.GetString(Network)) { + case "mainnet": + return common.MainNet, nil + case "testnet": + return common.TestNet, nil + default: + return common.Network{}, fmt.Errorf("unknown network") + } +} diff --git a/asp/internal/core/application/service.go b/asp/internal/core/application/service.go index 799f24b..05afbef 100644 --- a/asp/internal/core/application/service.go +++ b/asp/internal/core/application/service.go @@ -10,7 +10,7 @@ import ( "github.com/ark-network/ark/common" "github.com/ark-network/ark/internal/core/domain" "github.com/ark-network/ark/internal/core/ports" - "github.com/btcsuite/btcd/btcec/v2" + "github.com/decred/dcrd/dcrec/secp256k1/v4" log "github.com/sirupsen/logrus" "github.com/vulpemventures/go-elements/address" "github.com/vulpemventures/go-elements/network" @@ -28,14 +28,16 @@ var ( ) type Service interface { + Start() error + Stop() SpendVtxos(ctx context.Context, inputs []domain.VtxoKey) (string, error) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error SignVtxos(ctx context.Context, forfeitTxs []string) error - FaucetVtxos(ctx context.Context, pubkey string) error + FaucetVtxos(ctx context.Context, pubkey *secp256k1.PublicKey) error GetRoundByTxid(ctx context.Context, poolTxid string) (*domain.Round, error) GetEventsChannel(ctx context.Context) <-chan domain.RoundEvent UpdatePaymentStatus(ctx context.Context, id string) error - ListVtxos(ctx context.Context, pubkey string) ([]domain.Vtxo, error) + ListVtxos(ctx context.Context, pubkey *secp256k1.PublicKey) ([]domain.Vtxo, error) GetPubkey(ctx context.Context) (string, error) } @@ -43,10 +45,9 @@ type service struct { roundInterval int64 network common.Network onchainNework network.Network - pubkey string + pubkey *secp256k1.PublicKey wallet ports.WalletService - scheduler ports.SchedulerService repoManager ports.RepoManager builder ports.TxBuilder paymentRequests *paymentsMap @@ -57,16 +58,18 @@ type service struct { func NewService( interval int64, network common.Network, onchainNetwork network.Network, - walletSvc ports.WalletService, schedulerSvc ports.SchedulerService, - repoManager ports.RepoManager, builder ports.TxBuilder, -) Service { - pubkey := "" + walletSvc ports.WalletService, repoManager ports.RepoManager, builder ports.TxBuilder, +) (Service, error) { eventsCh := make(chan domain.RoundEvent) paymentRequests := newPaymentsMap(nil) forfeitTxs := newForfeitTxsMap() + pubkey, err := walletSvc.GetPubkey(context.Background()) + if err != nil { + return nil, fmt.Errorf("failed to fetch pubkey: %s", err) + } svc := &service{ interval, network, onchainNetwork, pubkey, - walletSvc, schedulerSvc, repoManager, builder, paymentRequests, forfeitTxs, + walletSvc, repoManager, builder, paymentRequests, forfeitTxs, eventsCh, } repoManager.RegisterEventsHandler( @@ -75,13 +78,21 @@ func NewService( svc.propagateEvents(round) }, ) - return svc + return svc, nil } func (s *service) Start() error { + log.Debug("starting app service") return s.start() } +func (s *service) Stop() { + s.wallet.Close() + log.Debug("closed connection to wallet") + s.repoManager.Close() + log.Debug("closed connection to db") +} + func (s *service) SpendVtxos(ctx context.Context, inputs []domain.VtxoKey) (string, error) { vtxos, err := s.repoManager.Vtxos().GetVtxos(ctx, inputs) if err != nil { @@ -120,13 +131,15 @@ func (s *service) UpdatePaymentStatus(_ context.Context, id string) error { return s.paymentRequests.updatePingTimestamp(id) } -func (s *service) FaucetVtxos(ctx context.Context, pubkey string) error { +func (s *service) FaucetVtxos(ctx context.Context, userPubkey *secp256k1.PublicKey) error { + pubkey := hex.EncodeToString(userPubkey.SerializeCompressed()) + payment, err := domain.NewPayment([]domain.Vtxo{ { VtxoKey: faucetVtxo, Receiver: domain.Receiver{ Pubkey: pubkey, - Amount: 100000, + Amount: 10000, }, }, }) @@ -135,16 +148,16 @@ func (s *service) FaucetVtxos(ctx context.Context, pubkey string) error { } if err := payment.AddReceivers([]domain.Receiver{ - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, - {Pubkey: pubkey, Amount: 10000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, + {Pubkey: pubkey, Amount: 1000}, }); err != nil { return err } @@ -162,8 +175,9 @@ func (s *service) SignVtxos(ctx context.Context, forfeitTxs []string) error { return nil } -func (s *service) ListVtxos(ctx context.Context, pubkey string) ([]domain.Vtxo, error) { - return s.repoManager.Vtxos().GetSpendableVtxosWithPubkey(ctx, pubkey) +func (s *service) ListVtxos(ctx context.Context, pubkey *secp256k1.PublicKey) ([]domain.Vtxo, error) { + pk := hex.EncodeToString(pubkey.SerializeCompressed()) + return s.repoManager.Vtxos().GetSpendableVtxosWithPubkey(ctx, pk) } func (s *service) GetEventsChannel(ctx context.Context) <-chan domain.RoundEvent { @@ -175,36 +189,16 @@ func (s *service) GetRoundByTxid(ctx context.Context, poolTxid string) (*domain. } func (s *service) GetPubkey(ctx context.Context) (string, error) { - if s.pubkey == "" { - pubkey, err := s.wallet.GetPubkey(ctx) - if err != nil { - return "", err - } - serializedPubkey, err := common.EncodePubKey(s.network.PubKey, pubkey) - if err != nil { - return "", err - } - s.pubkey = serializedPubkey + pubkey, err := common.EncodePubKey(s.network.PubKey, s.pubkey) + if err != nil { + return "", err } - return s.pubkey, nil + return pubkey, nil } func (s *service) start() error { - startImmediately := true - finalizationInterval := int64(s.roundInterval / 2) - if err := s.scheduler.ScheduleTask( - s.roundInterval, startImmediately, s.startRound, - ); err != nil { - return err - } - if err := s.scheduler.ScheduleTask( - finalizationInterval, !startImmediately, s.startFinalization, - ); err != nil { - return err - } - return s.scheduler.ScheduleTask( - s.roundInterval-1, !startImmediately, s.finalizeRound, - ) + s.startRound() + return nil } func (s *service) startRound() { @@ -217,6 +211,11 @@ func (s *service) startRound() { return } + defer func() { + time.Sleep(time.Duration(s.roundInterval/2) * time.Second) + s.startFinalization() + }() + log.Debugf("started registration stage for new round: %s", round.Id) } @@ -227,6 +226,16 @@ func (s *service) startFinalization() { log.WithError(err).Warn("failed to retrieve current round") return } + + defer func() { + if round.IsFailed() { + s.startRound() + return + } + time.Sleep(time.Duration((s.roundInterval/2)-1) * time.Second) + s.finalizeRound() + }() + if round.IsFailed() { return } @@ -251,29 +260,33 @@ func (s *service) startFinalization() { num = paymentsThreshold } payments := s.paymentRequests.pop(num) - changes, _ = round.RegisterPayments(payments) + changes, err = round.RegisterPayments(payments) + if err != nil { + changes = round.Fail(fmt.Errorf("failed to register payments: %s", err)) + log.WithError(err).Warn("failed to register payments") + return + } - signedPoolTx, err := s.builder.BuildPoolTx(s.wallet, payments) + signedPoolTx, err := s.builder.BuildPoolTx(s.pubkey, s.wallet, payments) if err != nil { changes = round.Fail(fmt.Errorf("failed to create pool tx: %s", err)) log.WithError(err).Warn("failed to create pool tx") return } - tree, err := s.builder.BuildCongestionTree(signedPoolTx, payments) + tree, err := s.builder.BuildCongestionTree(s.pubkey, signedPoolTx, payments) if err != nil { changes = round.Fail(fmt.Errorf("failed to create congestion tree: %s", err)) log.WithError(err).Warn("failed to create congestion tree") return } - connectors, forfeitTxs, err := s.builder.BuildForfeitTxs(signedPoolTx, payments) + connectors, forfeitTxs, err := s.builder.BuildForfeitTxs(s.pubkey, signedPoolTx, payments) if err != nil { changes = round.Fail(fmt.Errorf("failed to create connectors and forfeit txs: %s", err)) log.WithError(err).Warn("failed to create connectors and forfeit txs") return } - events, _ := round.StartFinalization(connectors, tree, signedPoolTx) changes = append(changes, events...) @@ -283,6 +296,8 @@ func (s *service) startFinalization() { } func (s *service) finalizeRound() { + defer s.startRound() + ctx := context.Background() round, err := s.repoManager.Rounds().GetCurrentRound(ctx) if err != nil { @@ -293,27 +308,30 @@ func (s *service) finalizeRound() { return } + var changes []domain.RoundEvent + defer func() { + if err := s.repoManager.Events().Save(ctx, round.Id, changes...); err != nil { + log.WithError(err).Warn("failed to store new round events") + return + } + }() + forfeitTxs, leftUnsigned := s.forfeitTxs.pop() if len(leftUnsigned) > 0 { err := fmt.Errorf("%d forfeit txs left to sign", len(leftUnsigned)) - round.Fail(fmt.Errorf("failed to finalize round: %s", err)) + changes = round.Fail(fmt.Errorf("failed to finalize round: %s", err)) log.WithError(err).Warn("failed to finalize round") return } txid, err := s.wallet.BroadcastTransaction(ctx, round.TxHex) if err != nil { - round.Fail(fmt.Errorf("failed to broadcast pool tx: %s", err)) + changes = round.Fail(fmt.Errorf("failed to broadcast pool tx: %s", err)) log.WithError(err).Warn("failed to broadcast pool tx") return } - changes, _ := round.EndFinalization(forfeitTxs, txid) - if err := s.repoManager.Events().Save(ctx, round.Id, changes...); err != nil { - log.WithError(err).Warn("failed to store new round events") - return - } - + changes, _ = round.EndFinalization(forfeitTxs, txid) log.Debugf("finalized round %s with pool tx %s", round.Id, round.Txid) } @@ -331,6 +349,7 @@ func (s *service) updateProjectionStore(round *domain.Round) { time.Sleep(100 * time.Millisecond) continue } + log.Debugf("spent %d vtxos", len(spentVtxos)) break } } @@ -342,6 +361,7 @@ func (s *service) updateProjectionStore(round *domain.Round) { time.Sleep(100 * time.Millisecond) continue } + log.Debugf("added %d new vtxos", len(newVtxos)) break } } @@ -359,7 +379,16 @@ func (s *service) updateProjectionStore(round *domain.Round) { func (s *service) propagateEvents(round *domain.Round) { lastEvent := round.Events()[len(round.Events())-1] switch e := lastEvent.(type) { - case domain.RoundFinalizationStarted, domain.RoundFinalized: + case domain.RoundFinalizationStarted: + forfeitTxs := s.forfeitTxs.view() + s.eventsCh <- domain.RoundFinalizationStarted{ + Id: e.Id, + CongestionTree: e.CongestionTree, + Connectors: e.Connectors, + PoolTx: e.PoolTx, + UnsignedForfeitTxs: forfeitTxs, + } + case domain.RoundFinalized: s.eventsCh <- e } } @@ -375,13 +404,13 @@ func getNewVtxos(net network.Network, round *domain.Round) []domain.Vtxo { found := false for _, r := range p.Receivers { buf, _ := hex.DecodeString(r.Pubkey) - pk, _ := btcec.ParsePubKey(buf) + pk, _ := secp256k1.ParsePubKey(buf) p2wpkh := payment.FromPublicKey(pk, &net, nil) addr, _ := p2wpkh.WitnessPubKeyHash() script, _ := address.ToOutputScript(addr) if bytes.Equal(script, out.Script) { found = true - pubkey = hex.EncodeToString(pk.SerializeCompressed()) + pubkey = r.Pubkey break } } diff --git a/asp/internal/core/application/utils.go b/asp/internal/core/application/utils.go index 8551193..d61bdb7 100644 --- a/asp/internal/core/application/utils.go +++ b/asp/internal/core/application/utils.go @@ -91,6 +91,7 @@ func (m *paymentsMap) update(payment domain.Payment) error { } p.Payment = payment + return nil } @@ -182,3 +183,14 @@ func (m *forfeitTxsMap) pop() (signed, unsigned []string) { m.forfeitTxs = make(map[string]*signedTx) return signed, unsigned } + +func (m *forfeitTxsMap) view() []string { + m.lock.RLock() + defer m.lock.RUnlock() + + txs := make([]string, 0, len(m.forfeitTxs)) + for _, tx := range m.forfeitTxs { + txs = append(txs, tx.tx) + } + return txs +} diff --git a/asp/internal/core/domain/congestion_tree.go b/asp/internal/core/domain/congestion_tree.go index d28dbbc..c7be516 100644 --- a/asp/internal/core/domain/congestion_tree.go +++ b/asp/internal/core/domain/congestion_tree.go @@ -4,17 +4,22 @@ type Node struct { Txid string Tx string ParentTxid string + Leaf bool } type CongestionTree [][]Node func (c CongestionTree) Leaves() []Node { - length := len(c) - if length == 0 { - return nil + leaves := c[len(c)-1] + for _, level := range c[:len(c)-1] { + for _, node := range level { + if node.Leaf { + leaves = append(leaves, node) + } + } } - return c[length-1] + return leaves } func (c CongestionTree) NumberOfNodes() int { diff --git a/asp/internal/core/domain/events.go b/asp/internal/core/domain/events.go index ad3c4a3..5426301 100644 --- a/asp/internal/core/domain/events.go +++ b/asp/internal/core/domain/events.go @@ -16,10 +16,11 @@ type RoundStarted struct { } type RoundFinalizationStarted struct { - Id string - CongestionTree CongestionTree - Connectors []string - PoolTx string + Id string + CongestionTree CongestionTree + Connectors []string + UnsignedForfeitTxs []string + PoolTx string } type RoundFinalized struct { @@ -31,7 +32,7 @@ type RoundFinalized struct { type RoundFailed struct { Id string - Err error + Err string Timestamp int64 } diff --git a/asp/internal/core/domain/round.go b/asp/internal/core/domain/round.go index bc77d0b..2ccd35b 100644 --- a/asp/internal/core/domain/round.go +++ b/asp/internal/core/domain/round.go @@ -201,7 +201,7 @@ func (r *Round) Fail(err error) []RoundEvent { } event := RoundFailed{ Id: r.Id, - Err: err, + Err: err.Error(), Timestamp: time.Now().Unix(), } r.raise(event) diff --git a/asp/internal/core/domain/round_test.go b/asp/internal/core/domain/round_test.go index ffc4276..ced4528 100644 --- a/asp/internal/core/domain/round_test.go +++ b/asp/internal/core/domain/round_test.go @@ -508,8 +508,8 @@ func testFail(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, events) - reason := "some valid reason" - events = round.Fail(fmt.Errorf(reason)) + reason := fmt.Errorf("some valid reason") + events = round.Fail(reason) require.Len(t, events, 1) require.False(t, round.IsStarted()) require.False(t, round.IsEnded()) @@ -519,9 +519,9 @@ func testFail(t *testing.T) { require.True(t, ok) require.Exactly(t, round.Id, event.Id) require.Exactly(t, round.EndingTimestamp, event.Timestamp) - require.EqualError(t, event.Err, reason) + require.EqualError(t, reason, event.Err) - events = round.Fail(fmt.Errorf(reason)) + events = round.Fail(reason) require.Empty(t, events) }) }) diff --git a/asp/internal/core/ports/tx_builder.go b/asp/internal/core/ports/tx_builder.go index 26ba393..9adfb95 100644 --- a/asp/internal/core/ports/tx_builder.go +++ b/asp/internal/core/ports/tx_builder.go @@ -1,9 +1,18 @@ package ports -import "github.com/ark-network/ark/internal/core/domain" +import ( + "github.com/ark-network/ark/internal/core/domain" + "github.com/decred/dcrd/dcrec/secp256k1/v4" +) type TxBuilder interface { - BuildPoolTx(wallet WalletService, payments []domain.Payment) (poolTx string, err error) - BuildCongestionTree(poolTx string, payments []domain.Payment) (congestionTree domain.CongestionTree, err error) - BuildForfeitTxs(poolTx string, payments []domain.Payment) (connectors []string, forfeitTxs []string, err error) + BuildPoolTx( + aspPubkey *secp256k1.PublicKey, wallet WalletService, payments []domain.Payment, + ) (poolTx string, err error) + BuildCongestionTree( + aspPubkey *secp256k1.PublicKey, poolTx string, payments []domain.Payment, + ) (congestionTree domain.CongestionTree, err error) + BuildForfeitTxs( + aspPubkey *secp256k1.PublicKey, poolTx string, payments []domain.Payment, + ) (connectors []string, forfeitTxs []string, err error) } diff --git a/asp/internal/core/ports/wallet.go b/asp/internal/core/ports/wallet.go index 515b5a2..9ea1021 100644 --- a/asp/internal/core/ports/wallet.go +++ b/asp/internal/core/ports/wallet.go @@ -15,6 +15,7 @@ type WalletService interface { ) (string, error) Transfer(ctx context.Context, outs []TxOutput) (string, error) BroadcastTransaction(ctx context.Context, txHex string) (string, error) + Close() } type WalletStatus interface { @@ -33,5 +34,6 @@ type TxInput interface { type TxOutput interface { GetAmount() uint64 + GetAsset() string GetScript() string } diff --git a/asp/internal/infrastructure/db/badger/round_repo.go b/asp/internal/infrastructure/db/badger/round_repo.go index fc0a48e..fec9d51 100644 --- a/asp/internal/infrastructure/db/badger/round_repo.go +++ b/asp/internal/infrastructure/db/badger/round_repo.go @@ -11,6 +11,8 @@ import ( "github.com/timshannon/badgerhold/v4" ) +const roundStoreDir = "rounds" + type roundRepository struct { store *badgerhold.Store } @@ -33,7 +35,7 @@ func NewRoundRepository(config ...interface{}) (dbtypes.RoundStore, error) { var dir string if len(baseDir) > 0 { - dir = filepath.Join(baseDir, eventStoreDir) + dir = filepath.Join(baseDir, roundStoreDir) } store, err := createDB(dir, logger) if err != nil { @@ -58,7 +60,7 @@ func (r *roundRepository) GetCurrentRound( return nil, err } if len(rounds) <= 0 { - return nil, nil + return nil, fmt.Errorf("ongoing round not found") } return &rounds[0], nil } diff --git a/asp/internal/infrastructure/db/badger/utils.go b/asp/internal/infrastructure/db/badger/utils.go index e2e173d..0dee5e7 100644 --- a/asp/internal/infrastructure/db/badger/utils.go +++ b/asp/internal/infrastructure/db/badger/utils.go @@ -82,36 +82,32 @@ func serializeEvent(event domain.RoundEvent) ([]byte, error) { func deserializeEvent(buf []byte) (domain.RoundEvent, error) { { - var event = domain.RoundStarted{} - if err := json.Unmarshal(buf, &event); err == nil { + var event = domain.RoundFailed{} + if err := json.Unmarshal(buf, &event); err == nil && len(event.Err) > 0 { return event, nil } } - - { - var event = domain.RoundFinalizationStarted{} - if err := json.Unmarshal(buf, &event); err == nil { - return event, nil - } - } - { var event = domain.RoundFinalized{} - if err := json.Unmarshal(buf, &event); err == nil { + if err := json.Unmarshal(buf, &event); err == nil && len(event.Txid) > 0 { return event, nil } } - { - var event = domain.RoundFailed{} - if err := json.Unmarshal(buf, &event); err == nil { + var event = domain.RoundFinalizationStarted{} + if err := json.Unmarshal(buf, &event); err == nil && len(event.CongestionTree) > 0 { return event, nil } } - { var event = domain.PaymentsRegistered{} - if err := json.Unmarshal(buf, &event); err == nil { + if err := json.Unmarshal(buf, &event); err == nil && len(event.Payments) > 0 { + return event, nil + } + } + { + var event = domain.RoundStarted{} + if err := json.Unmarshal(buf, &event); err == nil && event.Timestamp > 0 { return event, nil } } diff --git a/asp/internal/infrastructure/db/badger/vtxo_repo.go b/asp/internal/infrastructure/db/badger/vtxo_repo.go index 0b14fed..038b6ee 100644 --- a/asp/internal/infrastructure/db/badger/vtxo_repo.go +++ b/asp/internal/infrastructure/db/badger/vtxo_repo.go @@ -11,6 +11,8 @@ import ( "github.com/timshannon/badgerhold/v4" ) +const vtxoStoreDir = "vtxos" + type vtxoRepository struct { store *badgerhold.Store } @@ -33,7 +35,7 @@ func NewVtxoRepository(config ...interface{}) (dbtypes.VtxoStore, error) { var dir string if len(baseDir) > 0 { - dir = filepath.Join(baseDir, eventStoreDir) + dir = filepath.Join(baseDir, vtxoStoreDir) } store, err := createDB(dir, logger) if err != nil { diff --git a/asp/internal/infrastructure/db/service_test.go b/asp/internal/infrastructure/db/service_test.go index 2224717..3e41625 100644 --- a/asp/internal/infrastructure/db/service_test.go +++ b/asp/internal/infrastructure/db/service_test.go @@ -138,7 +138,8 @@ func testRoundEventRepository(t *testing.T, svc ports.RepoManager) { handler: func(round *domain.Round) { require.NotNil(t, round) require.Len(t, round.Events(), 2) - require.Len(t, round.CongestionTree, 7) + require.Len(t, round.CongestionTree, 3) + require.Equal(t, round.CongestionTree.NumberOfNodes(), 7) require.Len(t, round.Connectors, 2) }, }, @@ -274,7 +275,7 @@ func testRoundRepository(t *testing.T, svc ports.RepoManager) { require.NoError(t, err) currentRound, err = svc.Rounds().GetCurrentRound(ctx) - require.NoError(t, err) + require.Error(t, err) require.Nil(t, currentRound) roundById, err = svc.Rounds().GetRoundWithId(ctx, roundId) diff --git a/asp/internal/infrastructure/ocean-wallet/transaction.go b/asp/internal/infrastructure/ocean-wallet/transaction.go index cf843bf..8253532 100644 --- a/asp/internal/infrastructure/ocean-wallet/transaction.go +++ b/asp/internal/infrastructure/ocean-wallet/transaction.go @@ -68,6 +68,7 @@ func (l outputList) toProto() []*pb.Output { list = append(list, &pb.Output{ Amount: out.GetAmount(), Script: out.GetScript(), + Asset: out.GetAsset(), }) } return list diff --git a/asp/internal/infrastructure/scheduler/gocron/service.go b/asp/internal/infrastructure/scheduler/gocron/service.go index 5161e14..391ef8e 100644 --- a/asp/internal/infrastructure/scheduler/gocron/service.go +++ b/asp/internal/infrastructure/scheduler/gocron/service.go @@ -26,9 +26,9 @@ func (s *service) Stop() { func (s *service) ScheduleTask(interval int64, immediate bool, task func()) error { if immediate { - _, err := s.scheduler.Every(interval).Seconds().Do(task) + _, err := s.scheduler.Every(int(interval)).Seconds().Do(task) return err } - _, err := s.scheduler.Every(interval).Seconds().WaitForSchedule().Do(task) + _, err := s.scheduler.Every(int(interval)).Seconds().WaitForSchedule().Do(task) return err } diff --git a/asp/internal/infrastructure/tx-builder/dummy/builder.go b/asp/internal/infrastructure/tx-builder/dummy/builder.go index 2aafbfc..36529f3 100644 --- a/asp/internal/infrastructure/tx-builder/dummy/builder.go +++ b/asp/internal/infrastructure/tx-builder/dummy/builder.go @@ -4,12 +4,12 @@ import ( "context" "encoding/hex" - "github.com/ark-network/ark/common" "github.com/ark-network/ark/internal/core/domain" "github.com/ark-network/ark/internal/core/ports" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/vulpemventures/go-elements/network" "github.com/vulpemventures/go-elements/psetv2" + "github.com/vulpemventures/go-elements/transaction" ) const ( @@ -17,31 +17,18 @@ const ( ) type txBuilder struct { - net *network.Network - aspPublicKey *secp256k1.PublicKey + net network.Network } -func toElementsNetwork(net common.Network) *network.Network { - switch net { - case common.MainNet: - return &network.Liquid - case common.TestNet: - return &network.Testnet - default: - return nil - } -} - -func NewTxBuilder(aspPublicKey *secp256k1.PublicKey, net common.Network) ports.TxBuilder { - return &txBuilder{ - aspPublicKey: aspPublicKey, - net: toElementsNetwork(net), - } +func NewTxBuilder(net network.Network) ports.TxBuilder { + return &txBuilder{net} } // BuildCongestionTree implements ports.TxBuilder. -func (b *txBuilder) BuildCongestionTree(poolTx string, payments []domain.Payment) (congestionTree domain.CongestionTree, err error) { - poolTxID, err := getTxID(poolTx) +func (b *txBuilder) BuildCongestionTree( + aspPubkey *secp256k1.PublicKey, poolTx string, payments []domain.Payment, +) (congestionTree domain.CongestionTree, err error) { + poolTxID, err := getTxid(poolTx) if err != nil { return nil, err } @@ -49,7 +36,7 @@ func (b *txBuilder) BuildCongestionTree(poolTx string, payments []domain.Payment receivers := receiversFromPayments(payments) return buildCongestionTree( - newOutputScriptFactory(b.aspPublicKey, b.net), + newOutputScriptFactory(aspPubkey, b.net), b.net, poolTxID, receivers, @@ -57,13 +44,15 @@ func (b *txBuilder) BuildCongestionTree(poolTx string, payments []domain.Payment } // BuildForfeitTxs implements ports.TxBuilder. -func (b *txBuilder) BuildForfeitTxs(poolTx string, payments []domain.Payment) (connectors []string, forfeitTxs []string, err error) { - poolTxID, err := getTxID(poolTx) +func (b *txBuilder) BuildForfeitTxs( + aspPubkey *secp256k1.PublicKey, poolTx string, payments []domain.Payment, +) (connectors []string, forfeitTxs []string, err error) { + poolTxID, err := getTxid(poolTx) if err != nil { return nil, nil, err } - aspScript, err := p2wpkhScript(b.aspPublicKey, b.net) + aspScript, err := p2wpkhScript(aspPubkey, b.net) if err != nil { return nil, nil, err } @@ -117,8 +106,10 @@ func (b *txBuilder) BuildForfeitTxs(poolTx string, payments []domain.Payment) (c } // BuildPoolTx implements ports.TxBuilder. -func (b *txBuilder) BuildPoolTx(wallet ports.WalletService, payments []domain.Payment) (poolTx string, err error) { - aspScriptBytes, err := p2wpkhScript(b.aspPublicKey, b.net) +func (b *txBuilder) BuildPoolTx( + aspPubkey *secp256k1.PublicKey, wallet ports.WalletService, payments []domain.Payment, +) (poolTx string, err error) { + aspScriptBytes, err := p2wpkhScript(aspPubkey, b.net) if err != nil { return "", err } @@ -134,40 +125,44 @@ func (b *txBuilder) BuildPoolTx(wallet ports.WalletService, payments []domain.Pa ctx := context.Background() return wallet.Transfer(ctx, []ports.TxOutput{ - newOutput(aspScript, sharedOutputAmount), - newOutput(aspScript, connectorOutputAmount), + newOutput(aspScript, sharedOutputAmount, b.net.AssetID), + newOutput(aspScript, connectorOutputAmount, b.net.AssetID), }) } func connectorsToInputArgs(connectors []string) ([]psetv2.InputArgs, error) { inputs := make([]psetv2.InputArgs, 0, len(connectors)+1) for i, psetb64 := range connectors { - txID, err := getTxID(psetb64) + tx, err := psetv2.NewPsetFromBase64(psetb64) if err != nil { return nil, err } - - input := psetv2.InputArgs{ - Txid: txID, - TxIndex: 0, + utx, err := tx.UnsignedTx() + if err != nil { + return nil, err } - inputs = append(inputs, input) - - if i == len(connectors)-1 { - input := psetv2.InputArgs{ - Txid: txID, - TxIndex: 1, + txid := utx.TxHash().String() + for j := range tx.Outputs { + inputs = append(inputs, psetv2.InputArgs{ + Txid: txid, + TxIndex: uint32(j), + }) + if i != len(connectors)-1 { + break } - inputs = append(inputs, input) } } return inputs, nil } -func getTxID(psetBase64 string) (string, error) { - pset, err := psetv2.NewPsetFromBase64(psetBase64) +func getTxid(txStr string) (string, error) { + pset, err := psetv2.NewPsetFromBase64(txStr) if err != nil { - return "", err + tx, err := transaction.NewTxFromHex(txStr) + if err != nil { + return "", err + } + return tx.TxHash().String(), nil } utx, err := pset.UnsignedTx() @@ -205,12 +200,14 @@ func sumReceivers(receivers []domain.Receiver) uint64 { type output struct { script string amount uint64 + asset string } -func newOutput(script string, amount uint64) ports.TxOutput { +func newOutput(script string, amount uint64, asset string) ports.TxOutput { return &output{ script: script, amount: amount, + asset: asset, } } @@ -218,6 +215,10 @@ func (o *output) GetAmount() uint64 { return o.amount } +func (o *output) GetAsset() string { + return o.asset +} + func (o *output) GetScript() string { return o.script } diff --git a/asp/internal/infrastructure/tx-builder/dummy/builder_test.go b/asp/internal/infrastructure/tx-builder/dummy/builder_test.go index 0d5517e..0580f46 100644 --- a/asp/internal/infrastructure/tx-builder/dummy/builder_test.go +++ b/asp/internal/infrastructure/tx-builder/dummy/builder_test.go @@ -9,7 +9,6 @@ import ( txbuilder "github.com/ark-network/ark/internal/infrastructure/tx-builder/dummy" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/stretchr/testify/require" - "github.com/vulpemventures/go-elements/address" "github.com/vulpemventures/go-elements/network" "github.com/vulpemventures/go-elements/payment" "github.com/vulpemventures/go-elements/psetv2" @@ -20,12 +19,7 @@ const ( ) func createTestTxBuilder() (ports.TxBuilder, error) { - _, key, err := common.DecodePubKey(testingKey) - if err != nil { - return nil, err - } - - return txbuilder.NewTxBuilder(key, common.MainNet), nil + return txbuilder.NewTxBuilder(network.Liquid), nil } func createTestPoolTx(sharedOutputAmount, numberOfInputs uint64) (string, error) { @@ -34,16 +28,8 @@ func createTestPoolTx(sharedOutputAmount, numberOfInputs uint64) (string, error) return "", err } - payment := payment.FromPublicKey(key, &network.Regtest, nil) - addr, err := payment.WitnessPubKeyHash() - if err != nil { - return "", err - } - - script, err := address.ToOutputScript(addr) - if err != nil { - return "", err - } + payment := payment.FromPublicKey(key, &network.Testnet, nil) + script := payment.WitnessScript pset, err := psetv2.New(nil, nil, nil) if err != nil { @@ -106,8 +92,9 @@ func TestBuildCongestionTree(t *testing.T) { poolTxID := poolTxUnsigned.TxHash().String() fixtures := []struct { - payments []domain.Payment - expectedNodesNum int // 2*len(receivers)-1 + payments []domain.Payment + expectedNodesNum int // 2*len(receivers)-1 + expectedLeavesNum int }{ { payments: []domain.Payment{ @@ -120,24 +107,25 @@ func TestBuildCongestionTree(t *testing.T) { VOut: 0, }, Receiver: domain.Receiver{ - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, }, }, Receivers: []domain.Receiver{ { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 400, }, }, }, }, - expectedNodesNum: 3, + expectedNodesNum: 3, + expectedLeavesNum: 2, }, { payments: []domain.Payment{ @@ -150,18 +138,18 @@ func TestBuildCongestionTree(t *testing.T) { VOut: 0, }, Receiver: domain.Receiver{ - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, }, }, Receivers: []domain.Receiver{ { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 400, }, }, @@ -175,18 +163,18 @@ func TestBuildCongestionTree(t *testing.T) { VOut: 0, }, Receiver: domain.Receiver{ - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, }, }, Receivers: []domain.Receiver{ { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 400, }, }, @@ -200,31 +188,37 @@ func TestBuildCongestionTree(t *testing.T) { VOut: 0, }, Receiver: domain.Receiver{ - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, }, }, Receivers: []domain.Receiver{ { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 400, }, }, }, }, - expectedNodesNum: 11, + expectedNodesNum: 11, + expectedLeavesNum: 6, }, } + _, key, err := common.DecodePubKey(testingKey) + require.NoError(t, err) + require.NotNil(t, key) + for _, f := range fixtures { - tree, err := builder.BuildCongestionTree(poolTx, f.payments) + tree, err := builder.BuildCongestionTree(key, poolTx, f.payments) require.NoError(t, err) require.Equal(t, f.expectedNodesNum, tree.NumberOfNodes()) + require.Len(t, tree.Leaves(), f.expectedLeavesNum) // check the root require.Len(t, tree[0], 1) @@ -298,7 +292,7 @@ func TestBuildForfeitTxs(t *testing.T) { VOut: 0, }, Receiver: domain.Receiver{ - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, }, @@ -308,18 +302,18 @@ func TestBuildForfeitTxs(t *testing.T) { VOut: 1, }, Receiver: domain.Receiver{ - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 400, }, }, }, Receivers: []domain.Receiver{ { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 600, }, { - Pubkey: "apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x", + Pubkey: "020000000000000000000000000000000000000000000000000000000000000002", Amount: 400, }, }, @@ -330,10 +324,15 @@ func TestBuildForfeitTxs(t *testing.T) { }, } - for _, f := range fixtures { - connectors, forfeitTxs, err := builder.BuildForfeitTxs(poolTx, f.payments) - require.NoError(t, err) + _, key, err := common.DecodePubKey(testingKey) + require.NoError(t, err) + require.NotNil(t, key) + for _, f := range fixtures { + connectors, forfeitTxs, err := builder.BuildForfeitTxs( + key, poolTx, f.payments, + ) + require.NoError(t, err) require.Len(t, connectors, f.expectedNumOfConnectors) require.Len(t, forfeitTxs, f.expectedNumOfForfeitTxs) diff --git a/asp/internal/infrastructure/tx-builder/dummy/connectors.go b/asp/internal/infrastructure/tx-builder/dummy/connectors.go index f56d1b8..8008295 100644 --- a/asp/internal/infrastructure/tx-builder/dummy/connectors.go +++ b/asp/internal/infrastructure/tx-builder/dummy/connectors.go @@ -16,6 +16,34 @@ func createConnectors( TxIndex: connectorOutputIndex, } + if numberOfConnectors == 1 { + pset, err := psetv2.New(nil, nil, nil) + if err != nil { + return nil, err + } + updater, err := psetv2.NewUpdater(pset) + if err != nil { + return nil, err + } + + err = updater.AddInputs([]psetv2.InputArgs{previousInput}) + if err != nil { + return nil, err + } + + err = updater.AddOutputs([]psetv2.OutputArgs{connectorOutput}) + if err != nil { + return nil, err + } + + base64, err := pset.ToBase64() + if err != nil { + return nil, err + } + + return []string{base64}, nil + } + // compute the initial amount of the connectors output in pool transaction remainingAmount := connectorAmount * numberOfConnectors diff --git a/asp/internal/infrastructure/tx-builder/dummy/forfeit.go b/asp/internal/infrastructure/tx-builder/dummy/forfeit.go index 6db4749..ff15c68 100644 --- a/asp/internal/infrastructure/tx-builder/dummy/forfeit.go +++ b/asp/internal/infrastructure/tx-builder/dummy/forfeit.go @@ -10,7 +10,7 @@ func createForfeitTx( vtxoInput psetv2.InputArgs, vtxoAmount uint64, aspScript []byte, - net *network.Network, + net network.Network, ) (forfeitTx string, err error) { pset, err := psetv2.New(nil, nil, nil) if err != nil { diff --git a/asp/internal/infrastructure/tx-builder/dummy/tree.go b/asp/internal/infrastructure/tx-builder/dummy/tree.go index aeaab3b..0ac3b52 100644 --- a/asp/internal/infrastructure/tx-builder/dummy/tree.go +++ b/asp/internal/infrastructure/tx-builder/dummy/tree.go @@ -1,7 +1,8 @@ package txbuilder import ( - "github.com/ark-network/ark/common" + "encoding/hex" + "github.com/ark-network/ark/internal/core/domain" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/decred/dcrd/dcrec/secp256k1/v4" @@ -17,8 +18,8 @@ const ( type outputScriptFactory func(leaves []domain.Receiver) ([]byte, error) -func p2wpkhScript(publicKey *secp256k1.PublicKey, net *network.Network) ([]byte, error) { - payment := payment.FromPublicKey(publicKey, net, nil) +func p2wpkhScript(publicKey *secp256k1.PublicKey, net network.Network) ([]byte, error) { + payment := payment.FromPublicKey(publicKey, &net, nil) addr, err := payment.WitnessPubKeyHash() if err != nil { return nil, err @@ -28,7 +29,7 @@ func p2wpkhScript(publicKey *secp256k1.PublicKey, net *network.Network) ([]byte, } // newOtputScriptFactory returns an output script factory func that lock funds using the ASP public key only on all branches psbt. The leaves are instead locked by the leaf public key. -func newOutputScriptFactory(aspPublicKey *secp256k1.PublicKey, net *network.Network) outputScriptFactory { +func newOutputScriptFactory(aspPublicKey *secp256k1.PublicKey, net network.Network) outputScriptFactory { return func(leaves []domain.Receiver) ([]byte, error) { aspScript, err := p2wpkhScript(aspPublicKey, net) if err != nil { @@ -39,7 +40,11 @@ func newOutputScriptFactory(aspPublicKey *secp256k1.PublicKey, net *network.Netw case 0: return nil, nil case 1: // it's a leaf - _, key, err := common.DecodePubKey(leaves[0].Pubkey) + buf, err := hex.DecodeString(leaves[0].Pubkey) + if err != nil { + return nil, err + } + key, err := secp256k1.ParsePubKey(buf) if err != nil { return nil, err } @@ -55,7 +60,7 @@ func newOutputScriptFactory(aspPublicKey *secp256k1.PublicKey, net *network.Netw // it also expect createOutputScript func managing the output script creation and the network to use (mainly for L-BTC asset id) func buildCongestionTree( createOutputScript outputScriptFactory, - net *network.Network, + net network.Network, poolTxID string, receivers []domain.Receiver, ) (congestionTree domain.CongestionTree, err error) { @@ -108,6 +113,7 @@ func buildCongestionTree( Txid: txid, Tx: psetB64, ParentTxid: parentTxid, + Leaf: psetWithLevel.leaf, }) } @@ -138,13 +144,13 @@ type node struct { left *node right *node createOutputScript outputScriptFactory - network *network.Network + network network.Network } // create a node from a single receiver func newLeaf( createOutputScript outputScriptFactory, - network *network.Network, + network network.Network, receiver domain.Receiver, ) *node { return &node{ @@ -172,7 +178,7 @@ func newBranch( // is it the final node of the tree func (n *node) isLeaf() bool { - return len(n.receivers) == 1 + return n.left == nil && n.right == nil } // compute the output amount of a node @@ -256,6 +262,7 @@ func (n *node) pset(input psetv2.InputArgs) (*psetv2.Pset, error) { type psetWithLevel struct { pset *psetv2.Pset level int + leaf bool } // create the node pset and all the psets of its children recursively, updating the input arg at each step @@ -267,7 +274,7 @@ func (n *node) psets(input psetv2.InputArgs, level int) ([]psetWithLevel, error) } nodeResult := []psetWithLevel{ - {pset, level}, + {pset, level, n.isLeaf()}, } if n.isLeaf() { diff --git a/asp/internal/interface/grpc/config.go b/asp/internal/interface/grpc/config.go new file mode 100644 index 0000000..ef21062 --- /dev/null +++ b/asp/internal/interface/grpc/config.go @@ -0,0 +1,46 @@ +package grpcservice + +import ( + "crypto/tls" + "fmt" + "net" +) + +type Config struct { + Port uint32 + NoTLS bool +} + +func (c Config) Validate() error { + lis, err := net.Listen("tcp", c.address()) + if err != nil { + return fmt.Errorf("invalid port: %s", err) + } + defer lis.Close() + + if !c.NoTLS { + return fmt.Errorf("tls termination not supported yet") + } + return nil +} + +func (c Config) insecure() bool { + return c.NoTLS +} + +func (c Config) address() string { + return fmt.Sprintf(":%d", c.Port) +} + +func (c Config) listener() net.Listener { + lis, _ := net.Listen("tcp", c.address()) + + if c.insecure() { + return lis + } + return tls.NewListener(lis, c.tlsConfig()) +} + +func (c Config) tlsConfig() *tls.Config { + return nil +} diff --git a/asp/internal/interface/grpc/handlers/arkservice.go b/asp/internal/interface/grpc/handlers/arkservice.go index ddef8d8..21ac4e9 100644 --- a/asp/internal/interface/grpc/handlers/arkservice.go +++ b/asp/internal/interface/grpc/handlers/arkservice.go @@ -7,7 +7,6 @@ import ( arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" "github.com/ark-network/ark/internal/core/application" "github.com/ark-network/ark/internal/core/domain" - "github.com/ark-network/ark/internal/core/ports" "github.com/google/uuid" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -25,7 +24,7 @@ type handler struct { listeners []*listener } -func NewHandler(service application.Service, repoManager ports.RepoManager) arkv1.ArkServiceServer { +func NewHandler(service application.Service) arkv1.ArkServiceServer { h := &handler{ svc: service, listenersLock: &sync.Mutex{}, @@ -154,6 +153,9 @@ func (h *handler) GetEventStream(_ *arkv1.GetEventStreamRequest, stream arkv1.Ar switch ev.Event.(type) { case *arkv1.GetEventStreamResponse_RoundFinalized, *arkv1.GetEventStreamResponse_RoundFailed: + if err := stream.Send(ev); err != nil { + return err + } return nil } } @@ -220,7 +222,7 @@ func (h *handler) listenToEvents() { Id: e.Id, PoolPartialTx: e.PoolTx, CongestionTree: castCongestionTree(e.CongestionTree), - ForfeitTxs: nil, // TODO: add forfeit txs + ForfeitTxs: e.UnsignedForfeitTxs, }, }, } @@ -238,7 +240,7 @@ func (h *handler) listenToEvents() { Event: &arkv1.GetEventStreamResponse_RoundFailed{ RoundFailed: &arkv1.RoundFailed{ Id: e.Id, - Reason: e.Err.Error(), + Reason: e.Err, }, }, } diff --git a/asp/internal/interface/grpc/handlers/utils.go b/asp/internal/interface/grpc/handlers/utils.go index 798d96e..69e7e50 100644 --- a/asp/internal/interface/grpc/handlers/utils.go +++ b/asp/internal/interface/grpc/handlers/utils.go @@ -1,10 +1,10 @@ package handlers import ( - "encoding/hex" "fmt" "github.com/ark-network/ark/common" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/vulpemventures/go-elements/psetv2" ) @@ -20,14 +20,13 @@ func parseTxs(txs []string) ([]string, error) { return txs, nil } -func parseAddress(addr string) (string, error) { +func parseAddress(addr string) (*secp256k1.PublicKey, error) { if len(addr) <= 0 { - return "", fmt.Errorf("missing address") + return nil, fmt.Errorf("missing address") } _, userPubkey, _, err := common.DecodeAddress(addr) if err != nil { - return "", fmt.Errorf("invalid address: %s", err) + return nil, fmt.Errorf("invalid address: %s", err) } - pubkey := hex.EncodeToString(userPubkey.SerializeCompressed()) - return pubkey, nil + return userPubkey, nil } diff --git a/asp/internal/interface/grpc/interceptors/.gitkeep b/asp/internal/interface/grpc/interceptors/.gitkeep deleted file mode 100755 index e69de29..0000000 diff --git a/asp/internal/interface/grpc/interceptors/interceptor.go b/asp/internal/interface/grpc/interceptors/interceptor.go new file mode 100644 index 0000000..c41729c --- /dev/null +++ b/asp/internal/interface/grpc/interceptors/interceptor.go @@ -0,0 +1,16 @@ +package interceptors + +import ( + middleware "github.com/grpc-ecosystem/go-grpc-middleware" + "google.golang.org/grpc" +) + +// UnaryInterceptor returns the unary interceptor +func UnaryInterceptor() grpc.ServerOption { + return grpc.UnaryInterceptor(middleware.ChainUnaryServer(unaryLogger)) +} + +// StreamInterceptor returns the stream interceptor with a logrus log +func StreamInterceptor() grpc.ServerOption { + return grpc.StreamInterceptor(middleware.ChainStreamServer(streamLogger)) +} diff --git a/asp/internal/interface/grpc/interceptors/logger.go b/asp/internal/interface/grpc/interceptors/logger.go new file mode 100644 index 0000000..13244f7 --- /dev/null +++ b/asp/internal/interface/grpc/interceptors/logger.go @@ -0,0 +1,28 @@ +package interceptors + +import ( + "context" + + log "github.com/sirupsen/logrus" + "google.golang.org/grpc" +) + +func unaryLogger( + ctx context.Context, + req interface{}, + info *grpc.UnaryServerInfo, + handler grpc.UnaryHandler, +) (interface{}, error) { + log.Debugf("gRPC method: %s", info.FullMethod) + return handler(ctx, req) +} + +func streamLogger( + srv interface{}, + stream grpc.ServerStream, + info *grpc.StreamServerInfo, + handler grpc.StreamHandler, +) error { + log.Debugf("gRPC method: %s", info.FullMethod) + return handler(srv, stream) +} diff --git a/asp/internal/interface/grpc/service.go b/asp/internal/interface/grpc/service.go new file mode 100644 index 0000000..3f29952 --- /dev/null +++ b/asp/internal/interface/grpc/service.go @@ -0,0 +1,63 @@ +package grpcservice + +import ( + "fmt" + + arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" + appconfig "github.com/ark-network/ark/internal/app-config" + interfaces "github.com/ark-network/ark/internal/interface" + "github.com/ark-network/ark/internal/interface/grpc/handlers" + "github.com/ark-network/ark/internal/interface/grpc/interceptors" + log "github.com/sirupsen/logrus" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +type service struct { + config Config + appConfig *appconfig.Config + server *grpc.Server +} + +func NewService( + svcConfig Config, appConfig *appconfig.Config, +) (interfaces.Service, error) { + if err := svcConfig.Validate(); err != nil { + return nil, fmt.Errorf("invalid service config: %s", err) + } + if err := appConfig.Validate(); err != nil { + return nil, fmt.Errorf("invalid app config: %s", err) + } + + grpcConfig := []grpc.ServerOption{ + interceptors.UnaryInterceptor(), interceptors.StreamInterceptor(), + } + if !svcConfig.NoTLS { + return nil, fmt.Errorf("tls termination not supported yet") + } + creds := insecure.NewCredentials() + grpcConfig = append(grpcConfig, grpc.Creds(creds)) + server := grpc.NewServer(grpcConfig...) + handler := handlers.NewHandler(appConfig.AppService()) + arkv1.RegisterArkServiceServer(server, handler) + return &service{svcConfig, appConfig, server}, nil +} + +func (s *service) Start() error { + // nolint:all + go s.server.Serve(s.config.listener()) + log.Infof("started listening at %s", s.config.address()) + + if err := s.appConfig.AppService().Start(); err != nil { + return fmt.Errorf("failed to start app service: %s", err) + } + log.Info("started app service") + return nil +} + +func (s *service) Stop() { + s.server.Stop() + log.Info("stopped grpc server") + s.appConfig.AppService().Stop() + log.Info("stopped app service") +} diff --git a/asp/internal/interface/service.go b/asp/internal/interface/service.go index a2fe8ad..1f7536e 100755 --- a/asp/internal/interface/service.go +++ b/asp/internal/interface/service.go @@ -1,49 +1,6 @@ package interfaces -import ( - arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" - "github.com/ark-network/ark/internal/core/application" - "github.com/ark-network/ark/internal/core/ports" - "github.com/ark-network/ark/internal/interface/grpc/handlers" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -// TODO: Edit this file to something more meaningful for your application. type Service interface { Start() error Stop() } - -type service struct { - grpcService arkv1.ArkServiceServer - grpcServer *grpc.Server -} - -type Options struct { - applicationService application.Service - repositoryManager ports.RepoManager -} - -func NewService(opts Options) (Service, error) { - return &service{ - grpcService: handlers.NewHandler(opts.applicationService, opts.repositoryManager), - }, nil -} - -// Start implements Service. -func (s *service) Start() error { - creds := insecure.NewCredentials() - serverOpts := grpc.Creds(creds) - server := grpc.NewServer(serverOpts) - - arkv1.RegisterArkServiceServer(server, s.grpcService) - - s.grpcServer = server - return nil -} - -// Stop implements Service. -func (s *service) Stop() { - s.grpcServer.Stop() -} diff --git a/noah/client.go b/noah/client.go index ccc88e9..4a2c7b8 100644 --- a/noah/client.go +++ b/noah/client.go @@ -66,9 +66,9 @@ func getConn(ctx *cli.Context) (*grpc.ClientConn, error) { return nil, err } - rpcUrl, ok := state["rpc_url"] + rpcUrl, ok := state["ark_url"] if !ok { - return nil, fmt.Errorf("missing rpc_url") + return nil, fmt.Errorf("missing ark_url") } conn, err := grpc.Dial(rpcUrl, grpc.WithTransportCredentials(insecure.NewCredentials())) diff --git a/noah/faucet.go b/noah/faucet.go index 6814a3e..50193ae 100644 --- a/noah/faucet.go +++ b/noah/faucet.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "io" @@ -47,6 +48,14 @@ func faucetAction(ctx *cli.Context) error { return err } + if event.GetRoundFinalization() != nil { + if _, err := client.FinalizePayment(context.Background(), &arkv1.FinalizePaymentRequest{ + SignedForfeitTxs: event.GetRoundFinalization().GetForfeitTxs(), + }); err != nil { + return err + } + } + if event.GetRoundFailed() != nil { return fmt.Errorf("faucet failed: %s", event.GetRoundFailed().GetReason()) } diff --git a/noah/go.mod b/noah/go.mod index ce4c0af..9dfa15d 100644 --- a/noah/go.mod +++ b/noah/go.mod @@ -28,7 +28,6 @@ require ( require ( github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/noah/go.sum b/noah/go.sum index 1b19bc8..8a6c52c 100644 --- a/noah/go.sum +++ b/noah/go.sum @@ -44,8 +44,6 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3 github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -69,8 +67,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -101,30 +97,19 @@ github.com/vulpemventures/go-secp256k1-zkp v1.1.6 h1:BmsrmXRLUibwa75Qkk8yELjpzCz 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.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -134,7 +119,6 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= @@ -145,11 +129,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4 h1:W12Pwm4urIbRdGhMEg2NM9O3TWKjNcxQhs46V0ypf/k= diff --git a/noah/send.go b/noah/send.go index 3b07c69..8a6a568 100644 --- a/noah/send.go +++ b/noah/send.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "encoding/hex" "encoding/json" "fmt" "io" @@ -16,7 +17,7 @@ import ( type receiver struct { To string `json:"to"` - Amount int64 `json:"amount"` + Amount uint64 `json:"amount"` } var ( @@ -55,7 +56,6 @@ func sendAction(ctx *cli.Context) error { receiversOutput := make([]*arkv1.Output, 0) sumOfReceivers := uint64(0) - net := getNetwork() for _, receiver := range receiversJSON { _, userKey, aspKey, err := common.DecodeAddress(receiver.To) @@ -71,15 +71,12 @@ func sendAction(ctx *cli.Context) error { return fmt.Errorf("invalid amount: %d", receiver.Amount) } - encodedKey, err := common.EncodePubKey(net.PubKey, userKey) - if err != nil { - return err - } - + encodedKey := hex.EncodeToString(userKey.SerializeCompressed()) receiversOutput = append(receiversOutput, &arkv1.Output{ Pubkey: encodedKey, Amount: uint64(receiver.Amount), }) + sumOfReceivers += receiver.Amount } client, close, err := getArkClient(ctx) if err != nil { @@ -104,10 +101,7 @@ func sendAction(ctx *cli.Context) error { } walletPubKey := walletPrvKey.PubKey() - encodedPubKey, err := common.EncodePubKey(net.PubKey, walletPubKey) - if err != nil { - return err - } + encodedPubKey := hex.EncodeToString(walletPubKey.SerializeCompressed()) changeReceiver := &arkv1.Output{ Pubkey: encodedPubKey,