From 82b9729474247c772f8e4f854dbf64b73097e4b1 Mon Sep 17 00:00:00 2001 From: mattfoley8 Date: Fri, 7 Apr 2023 13:32:07 -0400 Subject: [PATCH 01/99] Test backend CI against core with relic dependency. --- test.Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test.Dockerfile b/test.Dockerfile index d078d61c..94369939 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -2,7 +2,7 @@ FROM alpine:latest AS backend RUN apk update RUN apk upgrade -RUN apk add --update go gcc g++ vips-dev git +RUN apk add --update bash cmake git go gcc g++ make vips-dev WORKDIR /deso/src @@ -17,6 +17,7 @@ COPY go.mod . COPY go.sum . RUN go mod download +RUN /deso/src/core/scripts/install-relic.sh # include backend src COPY apis apis @@ -30,4 +31,4 @@ COPY main.go . # build backend RUN GOOS=linux go build -mod=mod -a -installsuffix cgo -o bin/backend main.go -ENTRYPOINT ["go", "test", "-v", "github.com/deso-protocol/backend/routes"] +ENTRYPOINT ["go", "test", "-tags", "relic", "-v", "github.com/deso-protocol/backend/routes"] From 6834066c530c1b001f8ed9506d9165303f1a99d2 Mon Sep 17 00:00:00 2001 From: mattfoley8 Date: Fri, 7 Apr 2023 13:34:03 -0400 Subject: [PATCH 02/99] Checkout specific branch just for testing purposes. --- test.Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.Dockerfile b/test.Dockerfile index 94369939..78e65790 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -2,14 +2,14 @@ FROM alpine:latest AS backend RUN apk update RUN apk upgrade -RUN apk add --update bash cmake git go gcc g++ make vips-dev +RUN apk add --update bash cmake go gcc g++ make vips-dev git WORKDIR /deso/src RUN git clone https://github.com/deso-protocol/core.git WORKDIR /deso/src/core -RUN git pull +RUN git checkout mf/add-bls-signature-utils && git pull origin mf/add-bls-signature-utils WORKDIR /deso/src/backend From 6a6576656806a393de7b08310693e88824ef807a Mon Sep 17 00:00:00 2001 From: mattfoley8 Date: Thu, 1 Jun 2023 09:55:33 -0400 Subject: [PATCH 03/99] Update test Dockerfile. --- test.Dockerfile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test.Dockerfile b/test.Dockerfile index 78e65790..ce28ac59 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -2,14 +2,21 @@ FROM alpine:latest AS backend RUN apk update RUN apk upgrade -RUN apk add --update bash cmake go gcc g++ make vips-dev git +RUN apk add --update bash cmake gcc g++ make vips-dev git + +COPY --from=golang:1.20-alpine /usr/local/go/ /usr/local/go/ +ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /deso/src RUN git clone https://github.com/deso-protocol/core.git WORKDIR /deso/src/core -RUN git checkout mf/add-bls-signature-utils && git pull origin mf/add-bls-signature-utils +RUN git checkout mf/add-bls-signature-utils && \ + git pull origin mf/add-bls-signature-utils # TODO: Revert to `git pull` once core PR is merged. + +RUN go mod download +RUN ./scripts/install-relic.sh WORKDIR /deso/src/backend @@ -17,7 +24,6 @@ COPY go.mod . COPY go.sum . RUN go mod download -RUN /deso/src/core/scripts/install-relic.sh # include backend src COPY apis apis From 5428fa79b69fbdc225bc09a016e86223e12e4687 Mon Sep 17 00:00:00 2001 From: mattfoley8 Date: Fri, 2 Jun 2023 12:40:05 -0400 Subject: [PATCH 04/99] Fix failing build stages. --- Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index d06304f6..d7fec234 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,10 +25,11 @@ COPY backend/countries countries COPY backend/main.go . # include core src +COPY core/bls ../core/bls COPY core/desohash ../core/desohash -COPY core/cmd ../core/cmd -COPY core/lib ../core/lib -COPY core/migrate ../core/migrate +COPY core/cmd ../core/cmd +COPY core/lib ../core/lib +COPY core/migrate ../core/migrate # build backend RUN GOOS=linux go build -mod=mod -a -installsuffix cgo -o bin/backend main.go From cc557618b65717f473a7f481f0fb7c1f8eb1f4a6 Mon Sep 17 00:00:00 2001 From: mattfoley8 Date: Mon, 12 Jun 2023 10:55:44 -0400 Subject: [PATCH 05/99] Add new deps. --- go.mod | 2 ++ go.sum | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/go.mod b/go.mod index cdcecd6d..b4b79c8d 100644 --- a/go.mod +++ b/go.mod @@ -41,6 +41,7 @@ require ( cloud.google.com/go v0.81.0 // indirect github.com/DataDog/datadog-go v4.5.0+incompatible // indirect github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/bwesterb/go-ristretto v1.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect @@ -82,6 +83,7 @@ require ( github.com/mattn/goveralls v0.0.6 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/oleiade/lane v1.0.1 // indirect + github.com/onflow/flow-go/crypto v0.24.7 // indirect github.com/pelletier/go-toml v1.7.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/philhofer/fwd v1.1.1 // indirect diff --git a/go.sum b/go.sum index 00904dfa..3dbb5e5e 100644 --- a/go.sum +++ b/go.sum @@ -86,6 +86,8 @@ github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnC github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= +github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -372,6 +374,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -433,6 +436,8 @@ github.com/oleiade/lane v1.0.1 h1:hXofkn7GEOubzTwNpeL9MaNy8WxolCYb9cInAIeqShU= github.com/oleiade/lane v1.0.1/go.mod h1:IyTkraa4maLfjq/GmHR+Dxb4kCMtEGeb+qmhlrQ5Mk4= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onflow/flow-go/crypto v0.24.7 h1:RCLuB83At4z5wkAyUCF7MYEnPoIIOHghJaODuJyEoW0= +github.com/onflow/flow-go/crypto v0.24.7/go.mod h1:fqCzkIBBMRRkciVrvW21rECKq1oD7Q6u+bCI78lfNX0= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -498,6 +503,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= @@ -541,6 +547,7 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/supranational/blst v0.3.10 h1:CMciDZ/h4pXDDXQASe8ZGTNKUiVNxVVA5hpci2Uuhuk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= @@ -1018,6 +1025,7 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w= mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ= +pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From 06c8c36049bff657f43eb953d95d2c0c66e1a1d6 Mon Sep 17 00:00:00 2001 From: Matt Foley <100429827+mattfoley8@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:41:33 -0400 Subject: [PATCH 06/99] Allow ParamUpdater to update PoS consensus params (#499) * Allow ParamUpdater to update PoS GlobalParams. * Add epoch number to get pos params call. * Change core branch in test Dockerfile. * Add test for updating global params. * Fix bugs in testing updating global params. * Checkout correct core branch. * Change core branch. --- routes/admin_transaction.go | 84 +++++++++++++++++-- routes/admin_transaction_test.go | 137 +++++++++++++++++++++++++++++++ test.Dockerfile | 5 +- 3 files changed, 219 insertions(+), 7 deletions(-) create mode 100644 routes/admin_transaction_test.go diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index eea78f06..3643e759 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -31,6 +31,26 @@ type GetGlobalParamsResponse struct { // The maximum number of copies a single NFT can have. MaxCopiesPerNFT uint64 `safeForLogging:"true"` + + // StakeLockupEpochDuration is the number of epochs that a + // user must wait before unlocking their unstaked stake. + StakeLockupEpochDuration uint64 `safeForLogging:"true"` + + // ValidatorJailEpochDuration is the number of epochs that a validator must + // wait after being jailed before submitting an UnjailValidator txn. + ValidatorJailEpochDuration uint64 `safeForLogging:"true"` + + // LeaderScheduleMaxNumValidators is the maximum number of validators that + // are included when generating a new Proof-of-Stake leader schedule. + LeaderScheduleMaxNumValidators uint64 `safeForLogging:"true"` + + // EpochDurationNumBlocks is the number of blocks included in one epoch. + EpochDurationNumBlocks uint64 `safeForLogging:"true"` + + // JailInactiveValidatorGracePeriodEpochs is the number of epochs we + // allow a validator to be inactive for (neither voting nor proposing + // blocks) before they are jailed. + JailInactiveValidatorGracePeriodEpochs uint64 `safeForLogging:"true"` } func (fes *APIServer) GetGlobalParams(ww http.ResponseWriter, req *http.Request) { @@ -50,11 +70,16 @@ func (fes *APIServer) GetGlobalParams(ww http.ResponseWriter, req *http.Request) globalParamsEntry := utxoView.GlobalParamsEntry // Return all the data associated with the transaction in the response res := GetGlobalParamsResponse{ - USDCentsPerBitcoin: globalParamsEntry.USDCentsPerBitcoin, - CreateProfileFeeNanos: globalParamsEntry.CreateProfileFeeNanos, - MinimumNetworkFeeNanosPerKB: globalParamsEntry.MinimumNetworkFeeNanosPerKB, - CreateNFTFeeNanos: globalParamsEntry.CreateNFTFeeNanos, - MaxCopiesPerNFT: globalParamsEntry.MaxCopiesPerNFT, + USDCentsPerBitcoin: globalParamsEntry.USDCentsPerBitcoin, + CreateProfileFeeNanos: globalParamsEntry.CreateProfileFeeNanos, + MinimumNetworkFeeNanosPerKB: globalParamsEntry.MinimumNetworkFeeNanosPerKB, + CreateNFTFeeNanos: globalParamsEntry.CreateNFTFeeNanos, + MaxCopiesPerNFT: globalParamsEntry.MaxCopiesPerNFT, + StakeLockupEpochDuration: utxoView.GetCurrentGlobalParam(lib.StakeLockupEpochDuration), + ValidatorJailEpochDuration: utxoView.GetCurrentGlobalParam(lib.ValidatorJailEpochDuration), + LeaderScheduleMaxNumValidators: utxoView.GetCurrentGlobalParam(lib.LeaderScheduleMaxNumValidators), + EpochDurationNumBlocks: utxoView.GetCurrentGlobalParam(lib.EpochDurationNumBlocks), + JailInactiveValidatorGracePeriodEpochs: utxoView.GetCurrentGlobalParam(lib.JailInactiveValidatorGracePeriodEpochs), } if err := json.NewEncoder(ww).Encode(res); err != nil { _AddBadRequestError(ww, fmt.Sprintf("GetGlobalParams: Problem encoding response as JSON: %v", err)) @@ -84,6 +109,26 @@ type UpdateGlobalParamsRequest struct { // heights on nonces. MaxNonceExpirationBlockHeightOffset int64 `safeForLogging:"true"` + // StakeLockupEpochDuration is the number of epochs that a + // user must wait before unlocking their unstaked stake. + StakeLockupEpochDuration uint64 `safeForLogging:"true"` + + // ValidatorJailEpochDuration is the number of epochs that a validator must + // wait after being jailed before submitting an UnjailValidator txn. + ValidatorJailEpochDuration uint64 `safeForLogging:"true"` + + // LeaderScheduleMaxNumValidators is the maximum number of validators that + // are included when generating a new Proof-of-Stake leader schedule. + LeaderScheduleMaxNumValidators uint64 `safeForLogging:"true"` + + // EpochDurationNumBlocks is the number of blocks included in one epoch. + EpochDurationNumBlocks uint64 `safeForLogging:"true"` + + // JailInactiveValidatorGracePeriodEpochs is the number of epochs we + // allow a validator to be inactive for (neither voting nor proposing + // blocks) before they are jailed. + JailInactiveValidatorGracePeriodEpochs uint64 `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` // No need to specify ProfileEntryResponse in each TransactionFee @@ -172,6 +217,34 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque maxNonceExpirationBlockHeightOffset = requestData.MaxNonceExpirationBlockHeightOffset } + extraData := make(map[string][]byte) + + // Update Proof of Stake consensus related global params if they have changed. + if requestData.StakeLockupEpochDuration > 0 && + requestData.StakeLockupEpochDuration != utxoView.GetCurrentGlobalParam(lib.StakeLockupEpochDuration) { + extraData[lib.StakeLockupEpochDuration.ToString()] = lib.UintToBuf(requestData.StakeLockupEpochDuration) + } + + if requestData.ValidatorJailEpochDuration > 0 && + requestData.ValidatorJailEpochDuration != utxoView.GetCurrentGlobalParam(lib.ValidatorJailEpochDuration) { + extraData[lib.ValidatorJailEpochDuration.ToString()] = lib.UintToBuf(requestData.ValidatorJailEpochDuration) + } + + if requestData.LeaderScheduleMaxNumValidators > 0 && + requestData.LeaderScheduleMaxNumValidators != utxoView.GetCurrentGlobalParam(lib.LeaderScheduleMaxNumValidators) { + extraData[lib.LeaderScheduleMaxNumValidators.ToString()] = lib.UintToBuf(requestData.LeaderScheduleMaxNumValidators) + } + + if requestData.EpochDurationNumBlocks > 0 && + requestData.EpochDurationNumBlocks != utxoView.GetCurrentGlobalParam(lib.EpochDurationNumBlocks) { + extraData[lib.EpochDurationNumBlocks.ToString()] = lib.UintToBuf(requestData.EpochDurationNumBlocks) + } + + if requestData.JailInactiveValidatorGracePeriodEpochs > 0 && + requestData.JailInactiveValidatorGracePeriodEpochs != utxoView.GetCurrentGlobalParam(lib.JailInactiveValidatorGracePeriodEpochs) { + extraData[lib.JailInactiveValidatorGracePeriodEpochs.ToString()] = lib.UintToBuf(requestData.JailInactiveValidatorGracePeriodEpochs) + } + // Try and create the update txn for the user. txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateUpdateGlobalParamsTxn( updaterPkBytes, @@ -182,6 +255,7 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque minimumNetworkFeeNanosPerKb, []byte{}, maxNonceExpirationBlockHeightOffset, + extraData, requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { diff --git a/routes/admin_transaction_test.go b/routes/admin_transaction_test.go new file mode 100644 index 00000000..06d67f7f --- /dev/null +++ b/routes/admin_transaction_test.go @@ -0,0 +1,137 @@ +package routes + +import ( + "bytes" + "encoding/json" + "github.com/deso-protocol/core/lib" + "github.com/stretchr/testify/require" + "io" + "net/http" + "net/http/httptest" + "testing" +) + +func TestUpdateGlobalParams(t *testing.T) { + // Hard-coded test constants + adminPublicKeyBase58Check := "tBCKWVydPvhXyxSVhntXCw7wUev2fUx64h84FLAfz4JStsdBAq4v9r" + adminJWT := "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NDQ3MDU1Mzh9.LXA2uT8tm-6DXDwTXaCRyqqbFNa96jLl_02LXyAwq58PbVPe28hrICP3P-D5g9mktPJolSVXK_UebRcL5oYCWg" + + // Init api server + apiServer := newTestApiServer(t) + apiServer.Config.SuperAdminPublicKeys = []string{adminPublicKeyBase58Check} + senderPkBytes, _, err := lib.Base58CheckDecode(senderPkString) + require.NoError(t, err) + apiServer.Params.ExtraRegtestParamUpdaterKeys[lib.MakePkMapKey(senderPkBytes)] = true + + // Helper utils + getGlobalParams := func() *GetGlobalParamsResponse { + // Send POST request. + body := GetGlobalParamsRequest{} + bodyJSON, err := json.Marshal(body) + require.NoError(t, err) + request, _ := http.NewRequest("POST", RoutePathGetGlobalParams, bytes.NewBuffer(bodyJSON)) + request.Header.Set("Content-Type", "application/json") + response := httptest.NewRecorder() + apiServer.router.ServeHTTP(response, request) + require.NotContains(t, string(response.Body.Bytes()), "error") + + // Decode response. + decoder := json.NewDecoder(io.LimitReader(response.Body, MaxRequestBodySizeBytes)) + globalParams := GetGlobalParamsResponse{} + err = decoder.Decode(&globalParams) + return &globalParams + } + + updateGlobalParams := func(body *UpdateGlobalParamsRequest) { + // Add JWT auth to body of request. + type MergedBody struct { + AdminRequest + UpdateGlobalParamsRequest + } + mergedBody := MergedBody{ + AdminRequest: AdminRequest{ + JWT: adminJWT, AdminPublicKey: adminPublicKeyBase58Check, + }, + UpdateGlobalParamsRequest: *body, + } + + // Send POST request. + bodyJSON, err := json.Marshal(mergedBody) + require.NoError(t, err) + request, _ := http.NewRequest("POST", RoutePathUpdateGlobalParams, bytes.NewBuffer(bodyJSON)) + request.Header.Set("Content-Type", "application/json") + response := httptest.NewRecorder() + apiServer.router.ServeHTTP(response, request) + require.NotContains(t, string(response.Body.Bytes()), "error") + + // Decode response. + decoder := json.NewDecoder(io.LimitReader(response.Body, MaxRequestBodySizeBytes)) + updateGlobalParamsResponse := UpdateGlobalParamsResponse{} + err = decoder.Decode(&updateGlobalParamsResponse) + require.NoError(t, err) + txn := updateGlobalParamsResponse.Transaction + + // Sign txn. + require.Nil(t, txn.Signature.Sign) + signTxn(t, txn, senderPrivString) + require.NotNil(t, txn.Signature.Sign) + + // Submit txn. + _, err = submitTxn(t, apiServer, txn) + require.NoError(t, err) + } + + // Tests + { + // Confirm default GlobalParams. + globalParams := getGlobalParams() + require.Zero(t, globalParams.MinimumNetworkFeeNanosPerKB) + require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(3)) + require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(3)) + require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(100)) + require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(3600)) + require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(48)) + } + { + // Update all GlobalParam fields. + updateGlobalParams(&UpdateGlobalParamsRequest{ + UpdaterPublicKeyBase58Check: senderPkString, + MinimumNetworkFeeNanosPerKB: 99, + StakeLockupEpochDuration: 4, + ValidatorJailEpochDuration: 4, + LeaderScheduleMaxNumValidators: 101, + EpochDurationNumBlocks: 3601, + JailInactiveValidatorGracePeriodEpochs: 49, + MinFeeRateNanosPerKB: 99, + }) + } + { + // Verify all updated GlobalParam fields. + globalParams := getGlobalParams() + require.Equal(t, globalParams.MinimumNetworkFeeNanosPerKB, uint64(99)) + require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(4)) + require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(4)) + require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(101)) + require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(3601)) + require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(49)) + } + { + // Update only one GlobalParam field. + updateGlobalParams(&UpdateGlobalParamsRequest{ + UpdaterPublicKeyBase58Check: senderPkString, + MinimumNetworkFeeNanosPerKB: 99, + JailInactiveValidatorGracePeriodEpochs: 50, + MinFeeRateNanosPerKB: 99, + }) + } + { + // Verify updated GlobalParam field. And other fields retain old values. + globalParams := getGlobalParams() + require.Equal(t, globalParams.MinimumNetworkFeeNanosPerKB, uint64(99)) + require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(4)) + require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(4)) + require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(101)) + require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(3601)) + require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(50)) + } +} diff --git a/test.Dockerfile b/test.Dockerfile index ce28ac59..19d7e5ad 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -12,8 +12,9 @@ WORKDIR /deso/src RUN git clone https://github.com/deso-protocol/core.git WORKDIR /deso/src/core -RUN git checkout mf/add-bls-signature-utils && \ - git pull origin mf/add-bls-signature-utils # TODO: Revert to `git pull` once core PR is merged. +RUN git pull && \ + git checkout mf/pos-merge-20230605 && \ + git pull origin mf/pos-merge-20230605 # TODO: Revert to `git pull` once core PR is merged. RUN go mod download RUN ./scripts/install-relic.sh From 898b8aabddd34171607c2707b82961bd566275cd Mon Sep 17 00:00:00 2001 From: Matt Foley <100429827+mattfoley8@users.noreply.github.com> Date: Tue, 13 Jun 2023 11:55:41 -0400 Subject: [PATCH 07/99] Mf/add validator registration endpoints (#500) * Add validator registration endpoints. * Allow ExtraData to be logged. --- routes/server.go | 17 +++ routes/validators.go | 212 ++++++++++++++++++++++++++++++++++++++ routes/validators_test.go | 124 ++++++++++++++++++++++ 3 files changed, 353 insertions(+) create mode 100644 routes/validators.go create mode 100644 routes/validators_test.go diff --git a/routes/server.go b/routes/server.go index cc6208ec..9dca3ef8 100644 --- a/routes/server.go +++ b/routes/server.go @@ -311,6 +311,9 @@ const ( // snapshot.go RoutePathSnapshotEpochMetadata = "/api/v0/snapshot-epoch-metadata" RoutePathStateChecksum = "/api/v0/state-checksum" + + // validators.go + RoutePathValidators = "/api/v0/validators" ) // APIServer provides the interface between the blockchain and things like the @@ -1270,6 +1273,20 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.CountPostAssociationsByValue, PublicAccess, }, + { + "RegisterAsValidator", + []string{"POST", "OPTIONS"}, + RoutePathValidators + "/register", + fes.RegisterAsValidator, + PublicAccess, + }, + { + "UnregisterAsValidator", + []string{"POST", "OPTIONS"}, + RoutePathValidators + "/unregister", + fes.UnregisterAsValidator, + PublicAccess, + }, // Jumio Routes { "JumioBegin", diff --git a/routes/validators.go b/routes/validators.go new file mode 100644 index 00000000..e013ab35 --- /dev/null +++ b/routes/validators.go @@ -0,0 +1,212 @@ +package routes + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "github.com/deso-protocol/core/bls" + "github.com/deso-protocol/core/lib" + "io" + "net/http" +) + +type RegisterAsValidatorRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + Domains []string `safeForLogging:"true"` + DisableDelegatedStake bool `safeForLogging:"true"` + VotingPublicKey string `safeForLogging:"true"` + VotingPublicKeySignature string `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type UnregisterAsValidatorRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type ValidatorTxnResponse struct { + SpendAmountNanos uint64 + TotalInputNanos uint64 + ChangeAmountNanos uint64 + FeeNanos uint64 + Transaction *lib.MsgDeSoTxn + TransactionHex string + TxnHashHex string +} + +func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := RegisterAsValidatorRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, "RegisterAsValidator: problem parsing request body") + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes. + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, "RegisterAsValidator: must provide a TransactorPublicKeyBase58Check") + return + } + transactorPublicKeyBytes, err := GetPubKeyBytesFromBase58Check(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddInternalServerError(ww, "RegisterAsValidator: problem getting public key for the transactor") + return + } + + // Convert Domains from []string to [][]byte. + var domains [][]byte + for _, domain := range requestData.Domains { + domains = append(domains, []byte(domain)) + } + + // Convert VotingPublicKeyString to VotingPublicKey. + votingPublicKey, err := (&bls.PublicKey{}).FromString(requestData.VotingPublicKey) + if err != nil { + _AddBadRequestError(ww, "RegisterAsValidator: problem parsing VotingPublicKey") + return + } + + // Convert VotingPublicKeySignatureString to VotingPublicKeySignature. + votingPublicKeySignature, err := (&bls.Signature{}).FromString(requestData.VotingPublicKeySignature) + if err != nil { + _AddBadRequestError(ww, "RegisterAsValidator: problem parsing VotingPublicKeySignature") + return + } + + // Parse ExtraData. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, "RegisterAsValidator: invalid ExtraData provided") + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeRegisterAsValidator, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, "RegisterAsValidator: specified TransactionFees are invalid") + return + } + + // Create transaction. + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateRegisterAsValidatorTxn( + transactorPublicKeyBytes, + &lib.RegisterAsValidatorMetadata{ + Domains: domains, + DisableDelegatedStake: requestData.DisableDelegatedStake, + VotingPublicKey: votingPublicKey, + VotingPublicKeySignature: votingPublicKeySignature, + }, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("RegisterAsValidator: problem creating txn: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, "RegisterAsValidator: problem encoding txn to bytes") + return + } + res := ValidatorTxnResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "RegisterAsValidator: problem encoding response as JSON") + return + } +} + +func (fes *APIServer) UnregisterAsValidator(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := UnregisterAsValidatorRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, "UnregisterAsValidator: problem parsing request body") + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes. + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, "UnregisterAsValidator: must provide a TransactorPublicKeyBase58Check") + return + } + transactorPublicKeyBytes, err := GetPubKeyBytesFromBase58Check(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddInternalServerError(ww, "UnregisterAsValidator: problem getting public key for the transactor") + return + } + + // Parse ExtraData. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, "UnregisterAsValidator: invalid ExtraData provided") + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeRegisterAsValidator, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, "UnregisterAsValidator: specified TransactionFees are invalid") + return + } + + // Create transaction. + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateUnregisterAsValidatorTxn( + transactorPublicKeyBytes, + &lib.UnregisterAsValidatorMetadata{}, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("UnregisterAsValidator: problem creating txn: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, "UnregisterAsValidator: problem encoding txn to bytes") + return + } + res := ValidatorTxnResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "UnregisterAsValidator: problem encoding response as JSON") + return + } +} diff --git a/routes/validators_test.go b/routes/validators_test.go new file mode 100644 index 00000000..9a56850e --- /dev/null +++ b/routes/validators_test.go @@ -0,0 +1,124 @@ +//go:build relic + +package routes + +import ( + "bytes" + "encoding/json" + "github.com/deso-protocol/core/bls" + "github.com/deso-protocol/core/lib" + "github.com/stretchr/testify/require" + "io" + "net/http" + "net/http/httptest" + "testing" +) + +func TestValidatorRegistration(t *testing.T) { + apiServer := newTestApiServer(t) + + // Convert senderPkString to senderPkBytes. + senderPkBytes, _, err := lib.Base58CheckDecode(senderPkString) + require.NoError(t, err) + + { + // sender registers as a validator. + + // Send POST request. + votingPublicKey, votingSignature := _generateVotingPublicKeyAndSignature(t, senderPkBytes) + extraData := map[string]string{"Foo": "Bar"} + body := &RegisterAsValidatorRequest{ + TransactorPublicKeyBase58Check: senderPkString, + Domains: []string{"https://sender-001.deso.com", "https://sender-002.deso.com"}, + DisableDelegatedStake: false, + VotingPublicKey: votingPublicKey.ToString(), + VotingPublicKeySignature: votingSignature.ToString(), + ExtraData: extraData, + MinFeeRateNanosPerKB: apiServer.MinFeeRateNanosPerKB, + TransactionFees: []TransactionFee{}, + } + bodyJSON, err := json.Marshal(body) + require.NoError(t, err) + request, _ := http.NewRequest("POST", RoutePathValidators+"/register", bytes.NewBuffer(bodyJSON)) + request.Header.Set("Content-Type", "application/json") + response := httptest.NewRecorder() + apiServer.router.ServeHTTP(response, request) + require.NotContains(t, string(response.Body.Bytes()), "error") + + // Decode response. + decoder := json.NewDecoder(io.LimitReader(response.Body, MaxRequestBodySizeBytes)) + txnResponse := ValidatorTxnResponse{} + err = decoder.Decode(&txnResponse) + require.NoError(t, err) + + // Test response fields. + txn := txnResponse.Transaction + require.Equal(t, txn.PublicKey, senderPkBytes) + txnMeta := txn.TxnMeta.(*lib.RegisterAsValidatorMetadata) + require.Len(t, txnMeta.Domains, 2) + require.Equal(t, txnMeta.Domains[0], []byte("https://sender-001.deso.com")) + require.Equal(t, txnMeta.Domains[1], []byte("https://sender-002.deso.com")) + require.False(t, txnMeta.DisableDelegatedStake) + require.True(t, txnMeta.VotingPublicKey.Eq(votingPublicKey)) + require.True(t, txnMeta.VotingPublicKeySignature.Eq(votingSignature)) + extraDataEncoded, err := EncodeExtraDataMap(extraData) + require.NoError(t, err) + require.Equal(t, txn.ExtraData, extraDataEncoded) + + // Sign txn. + require.Nil(t, txn.Signature.Sign) + signTxn(t, txn, senderPrivString) + require.NotNil(t, txn.Signature.Sign) + + // Submit txn. + _, err = submitTxn(t, apiServer, txn) + require.NoError(t, err) + } + { + // sender unregisters as a validator. + + // Send POST request. + body := &UnregisterAsValidatorRequest{ + TransactorPublicKeyBase58Check: senderPkString, + ExtraData: map[string]string{}, + MinFeeRateNanosPerKB: apiServer.MinFeeRateNanosPerKB, + TransactionFees: []TransactionFee{}, + } + bodyJSON, err := json.Marshal(body) + require.NoError(t, err) + request, _ := http.NewRequest("POST", RoutePathValidators+"/unregister", bytes.NewBuffer(bodyJSON)) + request.Header.Set("Content-Type", "application/json") + response := httptest.NewRecorder() + apiServer.router.ServeHTTP(response, request) + require.NotContains(t, string(response.Body.Bytes()), "error") + + // Decode response. + decoder := json.NewDecoder(io.LimitReader(response.Body, MaxRequestBodySizeBytes)) + txnResponse := ValidatorTxnResponse{} + err = decoder.Decode(&txnResponse) + require.NoError(t, err) + + // Test response fields. + txn := txnResponse.Transaction + require.Equal(t, txn.PublicKey, senderPkBytes) + + // Sign txn. + require.Nil(t, txn.Signature.Sign) + signTxn(t, txn, senderPrivString) + require.NotNil(t, txn.Signature.Sign) + + // Submit txn. + _, err = submitTxn(t, apiServer, txn) + require.NoError(t, err) + } +} + +func _generateVotingPublicKeyAndSignature(t *testing.T, transactorPkBytes []byte) (*bls.PublicKey, *bls.Signature) { + blsPrivateKey, err := bls.NewPrivateKey() + require.NoError(t, err) + votingPublicKey := blsPrivateKey.PublicKey() + signaturePayload := lib.CreateValidatorVotingSignaturePayload(transactorPkBytes) + votingSignature, err := blsPrivateKey.Sign(signaturePayload) + require.NoError(t, err) + return votingPublicKey, votingSignature +} From cf62ed014d04ba40ae62a586b39fe2119872c9f3 Mon Sep 17 00:00:00 2001 From: mattfoley8 Date: Wed, 14 Jun 2023 12:30:03 -0400 Subject: [PATCH 08/99] Add relic dependency to prod dockerfile. --- Dockerfile | 12 +++++++++--- test.Dockerfile | 5 +++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index d7fec234..6c105e91 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,10 @@ FROM alpine:latest AS backend RUN apk update RUN apk upgrade -RUN apk add --update go gcc g++ vips-dev +RUN apk add --update bash cmake g++ gcc git make vips-dev + +COPY --from=golang:1.20-alpine /usr/local/go/ /usr/local/go/ +ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /deso/src @@ -26,13 +29,16 @@ COPY backend/main.go . # include core src COPY core/bls ../core/bls -COPY core/desohash ../core/desohash COPY core/cmd ../core/cmd +COPY core/desohash ../core/desohash COPY core/lib ../core/lib COPY core/migrate ../core/migrate +COPY core/scripts ../core/scripts + +RUN ../core/scripts/install-relic.sh # build backend -RUN GOOS=linux go build -mod=mod -a -installsuffix cgo -o bin/backend main.go +RUN GOOS=linux go build -mod=mod -a -installsuffix cgo -o bin/backend -tags=relic main.go # create tiny image FROM alpine:latest diff --git a/test.Dockerfile b/test.Dockerfile index ce28ac59..785601c9 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -2,7 +2,7 @@ FROM alpine:latest AS backend RUN apk update RUN apk upgrade -RUN apk add --update bash cmake gcc g++ make vips-dev git +RUN apk add --update bash cmake g++ gcc git make vips-dev COPY --from=golang:1.20-alpine /usr/local/go/ /usr/local/go/ ENV PATH="/usr/local/go/bin:${PATH}" @@ -12,7 +12,8 @@ WORKDIR /deso/src RUN git clone https://github.com/deso-protocol/core.git WORKDIR /deso/src/core -RUN git checkout mf/add-bls-signature-utils && \ +RUN git pull && \ + git checkout mf/add-bls-signature-utils && \ git pull origin mf/add-bls-signature-utils # TODO: Revert to `git pull` once core PR is merged. RUN go mod download From 32e6c56e3ced3e9582f8a45b338000e80d21dde8 Mon Sep 17 00:00:00 2001 From: Matt Foley <100429827+mattfoley8@users.noreply.github.com> Date: Wed, 14 Jun 2023 17:22:37 -0400 Subject: [PATCH 09/99] Mf/add get validator by public key endpoint (#501) * Add get validator by PublicKey route. * Address PR review feedback. --- routes/server.go | 7 +++ routes/validators.go | 91 +++++++++++++++++++++++++++++++++++++++ routes/validators_test.go | 59 +++++++++++++++++++++---- 3 files changed, 149 insertions(+), 8 deletions(-) diff --git a/routes/server.go b/routes/server.go index 9dca3ef8..2aba5c9b 100644 --- a/routes/server.go +++ b/routes/server.go @@ -1287,6 +1287,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.UnregisterAsValidator, PublicAccess, }, + { + "GetValidatorByPublicKeyBase58Check", + []string{"GET"}, + RoutePathValidators + "/{publicKeyBase58Check:t?BC[1-9A-HJ-NP-Za-km-z]{51,53}}", + fes.GetValidatorByPublicKeyBase58Check, + PublicAccess, + }, // Jumio Routes { "JumioBegin", diff --git a/routes/validators.go b/routes/validators.go index e013ab35..c11d1280 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -6,6 +6,8 @@ import ( "fmt" "github.com/deso-protocol/core/bls" "github.com/deso-protocol/core/lib" + "github.com/gorilla/mux" + "github.com/holiman/uint256" "io" "net/http" ) @@ -38,6 +40,19 @@ type ValidatorTxnResponse struct { TxnHashHex string } +type ValidatorResponse struct { + ValidatorPublicKeyBase58Check string + Domains []string + DisableDelegatedStake bool + VotingPublicKey string + VotingPublicKeySignature string + TotalStakeAmountNanos *uint256.Int + Status string + LastActiveAtEpochNumber uint64 + JailedAtEpochNumber uint64 + ExtraData map[string]string +} + func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Request) { // Decode request body. decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) @@ -210,3 +225,79 @@ func (fes *APIServer) UnregisterAsValidator(ww http.ResponseWriter, req *http.Re return } } + +func (fes *APIServer) GetValidatorByPublicKeyBase58Check(ww http.ResponseWriter, req *http.Request) { + // Parse ValidatorPublicKeyBase58Check from URL. + vars := mux.Vars(req) + validatorPublicKeyBase58Check, exists := vars["publicKeyBase58Check"] + if !exists { + _AddBadRequestError(ww, "GetValidatorByPublicKeyBase58Check: must provide a ValidatorPublicKeyBase58Check") + return + } + + // Create UTXO view. + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddInternalServerError(ww, "GetValidatorByPublicKeyBase58Check: problem getting UTXO view") + return + } + + // Convert ValidatorPublicKeyBase58Check to ValidatorPKID. + validatorPKID, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, validatorPublicKeyBase58Check) + if err != nil || validatorPKID == nil { + _AddInternalServerError(ww, "GetValidatorByPublicKeyBase58Check: problem retrieving validator PKID") + return + } + + // Get validator by PKID. + validatorEntry, err := utxoView.GetValidatorByPKID(validatorPKID) + if err != nil { + _AddInternalServerError(ww, "GetValidatorByPublicKeyBase58Check: problem retrieving validator") + return + } + if validatorEntry == nil { + _AddNotFoundError(ww, "GetValidatorByPublicKeyBase58Check: validator not found") + return + } + + // Encode response. + validatorResponse := _convertValidatorEntryToResponse(utxoView, validatorEntry, fes.Params) + if err = json.NewEncoder(ww).Encode(validatorResponse); err != nil { + _AddInternalServerError(ww, "GetValidatorByPublicKeyBase58Check: problem encoding response as JSON") + return + } +} + +func _convertValidatorEntryToResponse( + utxoView *lib.UtxoView, validatorEntry *lib.ValidatorEntry, params *lib.DeSoParams, +) *ValidatorResponse { + // Nil check: this should never happen but just to be safe. + if validatorEntry == nil { + return &ValidatorResponse{} + } + + // Convert ValidatorPKID to ValidatorPublicKeyBase58Check. + validatorPublicKeyBase58Check := lib.Base58CheckEncode( + utxoView.GetPublicKeyForPKID(validatorEntry.ValidatorPKID), false, params, + ) + + // Convert Domains [][]byte to []string. + var domains []string + for _, domain := range validatorEntry.Domains { + domains = append(domains, string(domain)) + } + + // Convert ValidatorEntry to ValidatorResponse. + return &ValidatorResponse{ + ValidatorPublicKeyBase58Check: validatorPublicKeyBase58Check, + Domains: domains, + DisableDelegatedStake: validatorEntry.DisableDelegatedStake, + VotingPublicKey: validatorEntry.VotingPublicKey.ToString(), + VotingPublicKeySignature: validatorEntry.VotingPublicKeySignature.ToString(), + TotalStakeAmountNanos: validatorEntry.TotalStakeAmountNanos.Clone(), + Status: validatorEntry.Status().ToString(), + LastActiveAtEpochNumber: validatorEntry.LastActiveAtEpochNumber, + JailedAtEpochNumber: validatorEntry.JailedAtEpochNumber, + ExtraData: DecodeExtraDataMap(params, utxoView, validatorEntry.ExtraData), + } +} diff --git a/routes/validators_test.go b/routes/validators_test.go index 9a56850e..8c99282c 100644 --- a/routes/validators_test.go +++ b/routes/validators_test.go @@ -21,19 +21,20 @@ func TestValidatorRegistration(t *testing.T) { senderPkBytes, _, err := lib.Base58CheckDecode(senderPkString) require.NoError(t, err) + // sender creates a VotingPublicKey and VotingSignature. + votingPublicKey, votingSignature := _generateVotingPublicKeyAndSignature(t, senderPkBytes) + { // sender registers as a validator. // Send POST request. - votingPublicKey, votingSignature := _generateVotingPublicKeyAndSignature(t, senderPkBytes) - extraData := map[string]string{"Foo": "Bar"} body := &RegisterAsValidatorRequest{ TransactorPublicKeyBase58Check: senderPkString, Domains: []string{"https://sender-001.deso.com", "https://sender-002.deso.com"}, DisableDelegatedStake: false, VotingPublicKey: votingPublicKey.ToString(), VotingPublicKeySignature: votingSignature.ToString(), - ExtraData: extraData, + ExtraData: map[string]string{"Foo": "Bar"}, MinFeeRateNanosPerKB: apiServer.MinFeeRateNanosPerKB, TransactionFees: []TransactionFee{}, } @@ -51,7 +52,7 @@ func TestValidatorRegistration(t *testing.T) { err = decoder.Decode(&txnResponse) require.NoError(t, err) - // Test response fields. + // Verify response fields. txn := txnResponse.Transaction require.Equal(t, txn.PublicKey, senderPkBytes) txnMeta := txn.TxnMeta.(*lib.RegisterAsValidatorMetadata) @@ -61,9 +62,8 @@ func TestValidatorRegistration(t *testing.T) { require.False(t, txnMeta.DisableDelegatedStake) require.True(t, txnMeta.VotingPublicKey.Eq(votingPublicKey)) require.True(t, txnMeta.VotingPublicKeySignature.Eq(votingSignature)) - extraDataEncoded, err := EncodeExtraDataMap(extraData) - require.NoError(t, err) - require.Equal(t, txn.ExtraData, extraDataEncoded) + require.NotNil(t, txn.ExtraData) + require.Equal(t, txn.ExtraData["Foo"], []byte("Bar")) // Sign txn. require.Nil(t, txn.Signature.Sign) @@ -74,6 +74,36 @@ func TestValidatorRegistration(t *testing.T) { _, err = submitTxn(t, apiServer, txn) require.NoError(t, err) } + { + // get sender validator by PublicKeyBase58Check + + // Send GET request. + request, _ := http.NewRequest("GET", RoutePathValidators+"/"+senderPkString, nil) + response := httptest.NewRecorder() + apiServer.router.ServeHTTP(response, request) + require.NotContains(t, string(response.Body.Bytes()), "error") + + // Decode response. + decoder := json.NewDecoder(io.LimitReader(response.Body, MaxRequestBodySizeBytes)) + validatorResponse := ValidatorResponse{} + err := decoder.Decode(&validatorResponse) + require.NoError(t, err) + + // Verify response fields. + require.Equal(t, validatorResponse.ValidatorPublicKeyBase58Check, senderPkString) + require.Len(t, validatorResponse.Domains, 2) + require.Equal(t, validatorResponse.Domains[0], "https://sender-001.deso.com") + require.Equal(t, validatorResponse.Domains[1], "https://sender-002.deso.com") + require.False(t, validatorResponse.DisableDelegatedStake) + require.Equal(t, validatorResponse.VotingPublicKey, votingPublicKey.ToString()) + require.Equal(t, validatorResponse.VotingPublicKeySignature, votingSignature.ToString()) + require.Equal(t, validatorResponse.TotalStakeAmountNanos.Uint64(), uint64(0)) + require.Equal(t, validatorResponse.Status, "Active") + require.Equal(t, validatorResponse.LastActiveAtEpochNumber, uint64(0)) + require.Equal(t, validatorResponse.JailedAtEpochNumber, uint64(0)) + require.NotNil(t, validatorResponse.ExtraData) + require.Equal(t, validatorResponse.ExtraData["Foo"], "Bar") + } { // sender unregisters as a validator. @@ -98,7 +128,7 @@ func TestValidatorRegistration(t *testing.T) { err = decoder.Decode(&txnResponse) require.NoError(t, err) - // Test response fields. + // Verify response fields. txn := txnResponse.Transaction require.Equal(t, txn.PublicKey, senderPkBytes) @@ -111,6 +141,19 @@ func TestValidatorRegistration(t *testing.T) { _, err = submitTxn(t, apiServer, txn) require.NoError(t, err) } + { + // get sender validator by PublicKeyBase58Check + + // Send GET request. + request, _ := http.NewRequest("GET", RoutePathValidators+"/"+senderPkString, nil) + response := httptest.NewRecorder() + apiServer.router.ServeHTTP(response, request) + responseBody := string(response.Body.Bytes()) + + // errors: doesn't exist + require.Contains(t, responseBody, "error") + require.Contains(t, responseBody, "validator not found") + } } func _generateVotingPublicKeyAndSignature(t *testing.T, transactorPkBytes []byte) (*bls.PublicKey, *bls.Signature) { From 1f88c5275bf03e1ea924cde7a2328ab10b47b416 Mon Sep 17 00:00:00 2001 From: Matt Foley <100429827+mattfoley8@users.noreply.github.com> Date: Thu, 15 Jun 2023 12:22:53 -0400 Subject: [PATCH 10/99] Rename VotingPublicKeySignature to VotingAuthorization. (#502) * Rename VotingPublicKeySignature to VotingAuthorization. * Checkout corresponding core branch. * Change core branch in test CI. --- routes/validators.go | 20 ++++++++++---------- routes/validators_test.go | 18 +++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/routes/validators.go b/routes/validators.go index c11d1280..687a668d 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -17,7 +17,7 @@ type RegisterAsValidatorRequest struct { Domains []string `safeForLogging:"true"` DisableDelegatedStake bool `safeForLogging:"true"` VotingPublicKey string `safeForLogging:"true"` - VotingPublicKeySignature string `safeForLogging:"true"` + VotingAuthorization string `safeForLogging:"true"` ExtraData map[string]string `safeForLogging:"true"` MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` TransactionFees []TransactionFee `safeForLogging:"true"` @@ -45,7 +45,7 @@ type ValidatorResponse struct { Domains []string DisableDelegatedStake bool VotingPublicKey string - VotingPublicKeySignature string + VotingAuthorization string TotalStakeAmountNanos *uint256.Int Status string LastActiveAtEpochNumber uint64 @@ -86,10 +86,10 @@ func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Requ return } - // Convert VotingPublicKeySignatureString to VotingPublicKeySignature. - votingPublicKeySignature, err := (&bls.Signature{}).FromString(requestData.VotingPublicKeySignature) + // Convert VotingAuthorizationString to VotingAuthorization. + votingAuthorization, err := (&bls.Signature{}).FromString(requestData.VotingAuthorization) if err != nil { - _AddBadRequestError(ww, "RegisterAsValidator: problem parsing VotingPublicKeySignature") + _AddBadRequestError(ww, "RegisterAsValidator: problem parsing VotingAuthorization") return } @@ -116,10 +116,10 @@ func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Requ txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateRegisterAsValidatorTxn( transactorPublicKeyBytes, &lib.RegisterAsValidatorMetadata{ - Domains: domains, - DisableDelegatedStake: requestData.DisableDelegatedStake, - VotingPublicKey: votingPublicKey, - VotingPublicKeySignature: votingPublicKeySignature, + Domains: domains, + DisableDelegatedStake: requestData.DisableDelegatedStake, + VotingPublicKey: votingPublicKey, + VotingAuthorization: votingAuthorization, }, extraData, requestData.MinFeeRateNanosPerKB, @@ -293,7 +293,7 @@ func _convertValidatorEntryToResponse( Domains: domains, DisableDelegatedStake: validatorEntry.DisableDelegatedStake, VotingPublicKey: validatorEntry.VotingPublicKey.ToString(), - VotingPublicKeySignature: validatorEntry.VotingPublicKeySignature.ToString(), + VotingAuthorization: validatorEntry.VotingAuthorization.ToString(), TotalStakeAmountNanos: validatorEntry.TotalStakeAmountNanos.Clone(), Status: validatorEntry.Status().ToString(), LastActiveAtEpochNumber: validatorEntry.LastActiveAtEpochNumber, diff --git a/routes/validators_test.go b/routes/validators_test.go index 8c99282c..be7188b8 100644 --- a/routes/validators_test.go +++ b/routes/validators_test.go @@ -21,8 +21,8 @@ func TestValidatorRegistration(t *testing.T) { senderPkBytes, _, err := lib.Base58CheckDecode(senderPkString) require.NoError(t, err) - // sender creates a VotingPublicKey and VotingSignature. - votingPublicKey, votingSignature := _generateVotingPublicKeyAndSignature(t, senderPkBytes) + // sender creates a VotingPublicKey and VotingAuthorization. + votingPublicKey, votingAuthorization := _generateVotingPublicKeyAndAuthorization(t, senderPkBytes) { // sender registers as a validator. @@ -33,7 +33,7 @@ func TestValidatorRegistration(t *testing.T) { Domains: []string{"https://sender-001.deso.com", "https://sender-002.deso.com"}, DisableDelegatedStake: false, VotingPublicKey: votingPublicKey.ToString(), - VotingPublicKeySignature: votingSignature.ToString(), + VotingAuthorization: votingAuthorization.ToString(), ExtraData: map[string]string{"Foo": "Bar"}, MinFeeRateNanosPerKB: apiServer.MinFeeRateNanosPerKB, TransactionFees: []TransactionFee{}, @@ -61,7 +61,7 @@ func TestValidatorRegistration(t *testing.T) { require.Equal(t, txnMeta.Domains[1], []byte("https://sender-002.deso.com")) require.False(t, txnMeta.DisableDelegatedStake) require.True(t, txnMeta.VotingPublicKey.Eq(votingPublicKey)) - require.True(t, txnMeta.VotingPublicKeySignature.Eq(votingSignature)) + require.True(t, txnMeta.VotingAuthorization.Eq(votingAuthorization)) require.NotNil(t, txn.ExtraData) require.Equal(t, txn.ExtraData["Foo"], []byte("Bar")) @@ -96,7 +96,7 @@ func TestValidatorRegistration(t *testing.T) { require.Equal(t, validatorResponse.Domains[1], "https://sender-002.deso.com") require.False(t, validatorResponse.DisableDelegatedStake) require.Equal(t, validatorResponse.VotingPublicKey, votingPublicKey.ToString()) - require.Equal(t, validatorResponse.VotingPublicKeySignature, votingSignature.ToString()) + require.Equal(t, validatorResponse.VotingAuthorization, votingAuthorization.ToString()) require.Equal(t, validatorResponse.TotalStakeAmountNanos.Uint64(), uint64(0)) require.Equal(t, validatorResponse.Status, "Active") require.Equal(t, validatorResponse.LastActiveAtEpochNumber, uint64(0)) @@ -156,12 +156,12 @@ func TestValidatorRegistration(t *testing.T) { } } -func _generateVotingPublicKeyAndSignature(t *testing.T, transactorPkBytes []byte) (*bls.PublicKey, *bls.Signature) { +func _generateVotingPublicKeyAndAuthorization(t *testing.T, transactorPkBytes []byte) (*bls.PublicKey, *bls.Signature) { blsPrivateKey, err := bls.NewPrivateKey() require.NoError(t, err) votingPublicKey := blsPrivateKey.PublicKey() - signaturePayload := lib.CreateValidatorVotingSignaturePayload(transactorPkBytes) - votingSignature, err := blsPrivateKey.Sign(signaturePayload) + votingAuthorizationPayload := lib.CreateValidatorVotingAuthorizationPayload(transactorPkBytes) + votingAuthorization, err := blsPrivateKey.Sign(votingAuthorizationPayload) require.NoError(t, err) - return votingPublicKey, votingSignature + return votingPublicKey, votingAuthorization } From a64baa625c1ecdb24e40aff8aecacc571fc34c59 Mon Sep 17 00:00:00 2001 From: Matt Foley <100429827+mattfoley8@users.noreply.github.com> Date: Mon, 19 Jun 2023 10:36:31 -0400 Subject: [PATCH 11/99] Refactor merging GlobalParamsEntry defaults. (#503) * Refactor merging GlobalParamsEntry defaults. * Change core branch in test dockerfile. --- routes/admin_transaction.go | 46 +++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index 3643e759..0ae1d3ab 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -67,7 +67,7 @@ func (fes *APIServer) GetGlobalParams(ww http.ResponseWriter, req *http.Request) _AddBadRequestError(ww, fmt.Sprintf("GetGlobalParams: Error getting utxoView: %v", err)) return } - globalParamsEntry := utxoView.GlobalParamsEntry + globalParamsEntry := utxoView.GetCurrentGlobalParamsEntry() // Return all the data associated with the transaction in the response res := GetGlobalParamsResponse{ USDCentsPerBitcoin: globalParamsEntry.USDCentsPerBitcoin, @@ -75,11 +75,11 @@ func (fes *APIServer) GetGlobalParams(ww http.ResponseWriter, req *http.Request) MinimumNetworkFeeNanosPerKB: globalParamsEntry.MinimumNetworkFeeNanosPerKB, CreateNFTFeeNanos: globalParamsEntry.CreateNFTFeeNanos, MaxCopiesPerNFT: globalParamsEntry.MaxCopiesPerNFT, - StakeLockupEpochDuration: utxoView.GetCurrentGlobalParam(lib.StakeLockupEpochDuration), - ValidatorJailEpochDuration: utxoView.GetCurrentGlobalParam(lib.ValidatorJailEpochDuration), - LeaderScheduleMaxNumValidators: utxoView.GetCurrentGlobalParam(lib.LeaderScheduleMaxNumValidators), - EpochDurationNumBlocks: utxoView.GetCurrentGlobalParam(lib.EpochDurationNumBlocks), - JailInactiveValidatorGracePeriodEpochs: utxoView.GetCurrentGlobalParam(lib.JailInactiveValidatorGracePeriodEpochs), + StakeLockupEpochDuration: globalParamsEntry.StakeLockupEpochDuration, + ValidatorJailEpochDuration: globalParamsEntry.ValidatorJailEpochDuration, + LeaderScheduleMaxNumValidators: globalParamsEntry.LeaderScheduleMaxNumValidators, + EpochDurationNumBlocks: globalParamsEntry.EpochDurationNumBlocks, + JailInactiveValidatorGracePeriodEpochs: globalParamsEntry.JailInactiveValidatorGracePeriodEpochs, } if err := json.NewEncoder(ww).Encode(res); err != nil { _AddBadRequestError(ww, fmt.Sprintf("GetGlobalParams: Problem encoding response as JSON: %v", err)) @@ -190,30 +190,32 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque } // Only update values if they have changed. Values less than 0 are excluded from the transaction + globalParamsEntry := utxoView.GetCurrentGlobalParamsEntry() + usdCentsPerBitcoin := int64(-1) - if requestData.USDCentsPerBitcoin >= 0 && uint64(requestData.USDCentsPerBitcoin) != utxoView.GlobalParamsEntry.USDCentsPerBitcoin { + if requestData.USDCentsPerBitcoin >= 0 && uint64(requestData.USDCentsPerBitcoin) != globalParamsEntry.USDCentsPerBitcoin { usdCentsPerBitcoin = requestData.USDCentsPerBitcoin } createProfileFeeNanos := int64(-1) - if requestData.CreateProfileFeeNanos >= 0 && uint64(requestData.CreateProfileFeeNanos) != utxoView.GlobalParamsEntry.CreateProfileFeeNanos { + if requestData.CreateProfileFeeNanos >= 0 && uint64(requestData.CreateProfileFeeNanos) != globalParamsEntry.CreateProfileFeeNanos { createProfileFeeNanos = requestData.CreateProfileFeeNanos } createNFTFeeNanos := int64(-1) - if requestData.CreateNFTFeeNanos >= 0 && uint64(requestData.CreateNFTFeeNanos) != utxoView.GlobalParamsEntry.CreateNFTFeeNanos { + if requestData.CreateNFTFeeNanos >= 0 && uint64(requestData.CreateNFTFeeNanos) != globalParamsEntry.CreateNFTFeeNanos { createNFTFeeNanos = requestData.CreateNFTFeeNanos } minimumNetworkFeeNanosPerKb := int64(-1) - if requestData.MinimumNetworkFeeNanosPerKB >= 0 && uint64(requestData.MinimumNetworkFeeNanosPerKB) != utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB { + if requestData.MinimumNetworkFeeNanosPerKB >= 0 && uint64(requestData.MinimumNetworkFeeNanosPerKB) != globalParamsEntry.MinimumNetworkFeeNanosPerKB { minimumNetworkFeeNanosPerKb = requestData.MinimumNetworkFeeNanosPerKB } maxCopiesPerNFT := int64(-1) - if requestData.MaxCopiesPerNFT >= 0 && uint64(requestData.MaxCopiesPerNFT) != utxoView.GlobalParamsEntry.MaxCopiesPerNFT { + if requestData.MaxCopiesPerNFT >= 0 && uint64(requestData.MaxCopiesPerNFT) != globalParamsEntry.MaxCopiesPerNFT { maxCopiesPerNFT = requestData.MaxCopiesPerNFT } maxNonceExpirationBlockHeightOffset := int64(-1) - if requestData.MaxNonceExpirationBlockHeightOffset >= 0 && uint64(requestData.MaxNonceExpirationBlockHeightOffset) != utxoView.GlobalParamsEntry.MaxNonceExpirationBlockHeightOffset { + if requestData.MaxNonceExpirationBlockHeightOffset >= 0 && uint64(requestData.MaxNonceExpirationBlockHeightOffset) != globalParamsEntry.MaxNonceExpirationBlockHeightOffset { maxNonceExpirationBlockHeightOffset = requestData.MaxNonceExpirationBlockHeightOffset } @@ -221,28 +223,28 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque // Update Proof of Stake consensus related global params if they have changed. if requestData.StakeLockupEpochDuration > 0 && - requestData.StakeLockupEpochDuration != utxoView.GetCurrentGlobalParam(lib.StakeLockupEpochDuration) { - extraData[lib.StakeLockupEpochDuration.ToString()] = lib.UintToBuf(requestData.StakeLockupEpochDuration) + requestData.StakeLockupEpochDuration != globalParamsEntry.StakeLockupEpochDuration { + extraData[lib.StakeLockupEpochDurationKey] = lib.UintToBuf(requestData.StakeLockupEpochDuration) } if requestData.ValidatorJailEpochDuration > 0 && - requestData.ValidatorJailEpochDuration != utxoView.GetCurrentGlobalParam(lib.ValidatorJailEpochDuration) { - extraData[lib.ValidatorJailEpochDuration.ToString()] = lib.UintToBuf(requestData.ValidatorJailEpochDuration) + requestData.ValidatorJailEpochDuration != globalParamsEntry.ValidatorJailEpochDuration { + extraData[lib.ValidatorJailEpochDurationKey] = lib.UintToBuf(requestData.ValidatorJailEpochDuration) } if requestData.LeaderScheduleMaxNumValidators > 0 && - requestData.LeaderScheduleMaxNumValidators != utxoView.GetCurrentGlobalParam(lib.LeaderScheduleMaxNumValidators) { - extraData[lib.LeaderScheduleMaxNumValidators.ToString()] = lib.UintToBuf(requestData.LeaderScheduleMaxNumValidators) + requestData.LeaderScheduleMaxNumValidators != globalParamsEntry.LeaderScheduleMaxNumValidators { + extraData[lib.LeaderScheduleMaxNumValidatorsKey] = lib.UintToBuf(requestData.LeaderScheduleMaxNumValidators) } if requestData.EpochDurationNumBlocks > 0 && - requestData.EpochDurationNumBlocks != utxoView.GetCurrentGlobalParam(lib.EpochDurationNumBlocks) { - extraData[lib.EpochDurationNumBlocks.ToString()] = lib.UintToBuf(requestData.EpochDurationNumBlocks) + requestData.EpochDurationNumBlocks != globalParamsEntry.EpochDurationNumBlocks { + extraData[lib.EpochDurationNumBlocksKey] = lib.UintToBuf(requestData.EpochDurationNumBlocks) } if requestData.JailInactiveValidatorGracePeriodEpochs > 0 && - requestData.JailInactiveValidatorGracePeriodEpochs != utxoView.GetCurrentGlobalParam(lib.JailInactiveValidatorGracePeriodEpochs) { - extraData[lib.JailInactiveValidatorGracePeriodEpochs.ToString()] = lib.UintToBuf(requestData.JailInactiveValidatorGracePeriodEpochs) + requestData.JailInactiveValidatorGracePeriodEpochs != globalParamsEntry.JailInactiveValidatorGracePeriodEpochs { + extraData[lib.JailInactiveValidatorGracePeriodEpochsKey] = lib.UintToBuf(requestData.JailInactiveValidatorGracePeriodEpochs) } // Try and create the update txn for the user. From ea9c5d5ff0657d4cc01ec10e9476928de57700be Mon Sep 17 00:00:00 2001 From: Matt Foley <100429827+mattfoley8@users.noreply.github.com> Date: Mon, 26 Jun 2023 14:46:48 -0400 Subject: [PATCH 12/99] Update test.Dockerfile core branch. (#504) --- test.Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.Dockerfile b/test.Dockerfile index 37a281c3..a1ed5cd2 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -13,8 +13,8 @@ RUN git clone https://github.com/deso-protocol/core.git WORKDIR /deso/src/core RUN git pull && \ - git checkout mf/pos-merge-20230605 && \ - git pull origin mf/pos-merge-20230605 # TODO: Revert to `git pull` once core PR is merged. + git checkout feature/proof-of-stake && \ + git pull origin feature/proof-of-stake # TODO: Revert to `git pull` once core PR is merged. RUN go mod download RUN ./scripts/install-relic.sh From c40453c849f93a55c6ee48f59372eabb245fabf7 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:10:44 -0500 Subject: [PATCH 13/99] Initial backend updates to conform to new function signatures in core (#512) Co-authored-by: Lazy Nina <> --- Dockerfile | 14 ++-- go.mod | 1 + go.sum | 2 + routes/access_group_test.go | 2 +- routes/admin_node.go | 4 +- routes/admin_transaction.go | 14 ++++ routes/admin_transaction_test.go | 3 + routes/exchange.go | 4 +- routes/exchange_test.go | 112 ++----------------------------- routes/global_state_test.go | 6 +- routes/miner.go | 2 +- routes/transaction.go | 1 + 12 files changed, 43 insertions(+), 122 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6c105e91..24721308 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,12 +28,14 @@ COPY backend/countries countries COPY backend/main.go . # include core src -COPY core/bls ../core/bls -COPY core/cmd ../core/cmd -COPY core/desohash ../core/desohash -COPY core/lib ../core/lib -COPY core/migrate ../core/migrate -COPY core/scripts ../core/scripts +COPY core/bls ../core/bls +COPY core/cmd ../core/cmd +COPY core/collections ../core/collections +COPY core/consensus ../core/consensus +COPY core/desohash ../core/desohash +COPY core/lib ../core/lib +COPY core/migrate ../core/migrate +COPY core/scripts ../core/scripts RUN ../core/scripts/install-relic.sh diff --git a/go.mod b/go.mod index b4b79c8d..1c351627 100644 --- a/go.mod +++ b/go.mod @@ -53,6 +53,7 @@ require ( github.com/deso-protocol/go-merkle-tree v1.0.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/ethereum/go-ethereum v1.9.25 // indirect github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect diff --git a/go.sum b/go.sum index 3dbb5e5e..75f51c55 100644 --- a/go.sum +++ b/go.sum @@ -164,6 +164,8 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= diff --git a/routes/access_group_test.go b/routes/access_group_test.go index 11d5d535..ef058388 100644 --- a/routes/access_group_test.go +++ b/routes/access_group_test.go @@ -97,7 +97,7 @@ func ExecuteRequest(t *testing.T, apiServer *APIServer, routePath string, reques func TestAPIAccessGroupBaseGroupMembership(t *testing.T) { assert := assert.New(t) - apiServer, _, _ := newTestAPIServer(t, "" /*globalStateRemoteNode*/) + apiServer, _, _ := newTestAPIServer(t, "" /*globalStateRemoteNode*/, false) // form the request for RoutePathGetAllUserAccessGroups values := GetAccessGroupsRequest{PublicKeyBase58Check: senderPkString} diff --git a/routes/admin_node.go b/routes/admin_node.go index f1ebc32f..473c26dd 100644 --- a/routes/admin_node.go +++ b/routes/admin_node.go @@ -109,13 +109,13 @@ func (fes *APIServer) _handleNodeControlGetInfo( { desoNodeStatus.LatestHeaderHeight = desoHeaderTip.Height desoNodeStatus.LatestHeaderHash = hex.EncodeToString(desoHeaderTip.Hash[:]) - desoNodeStatus.LatestHeaderTstampSecs = uint32(desoHeaderTip.Header.TstampSecs) + desoNodeStatus.LatestHeaderTstampSecs = uint32(desoHeaderTip.Header.GetTstampSecs()) } // Main block chain fields { desoNodeStatus.LatestBlockHeight = desoBlockTip.Height desoNodeStatus.LatestBlockHash = hex.EncodeToString(desoBlockTip.Hash[:]) - desoNodeStatus.LatestBlockTstampSecs = uint32(desoBlockTip.Header.TstampSecs) + desoNodeStatus.LatestBlockTstampSecs = uint32(desoBlockTip.Header.GetTstampSecs()) } if fes.TXIndex != nil { // TxIndex status diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index 0ae1d3ab..4f6bbceb 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -44,6 +44,10 @@ type GetGlobalParamsResponse struct { // are included when generating a new Proof-of-Stake leader schedule. LeaderScheduleMaxNumValidators uint64 `safeForLogging:"true"` + // ValidatorSetMaxNumValidators is the maximum number of validators that + // are included when generating a new Proof-of-Stake validator set. + ValidatorSetMaxNumValidators uint64 `safeForLogging:"true"` + // EpochDurationNumBlocks is the number of blocks included in one epoch. EpochDurationNumBlocks uint64 `safeForLogging:"true"` @@ -78,6 +82,7 @@ func (fes *APIServer) GetGlobalParams(ww http.ResponseWriter, req *http.Request) StakeLockupEpochDuration: globalParamsEntry.StakeLockupEpochDuration, ValidatorJailEpochDuration: globalParamsEntry.ValidatorJailEpochDuration, LeaderScheduleMaxNumValidators: globalParamsEntry.LeaderScheduleMaxNumValidators, + ValidatorSetMaxNumValidators: globalParamsEntry.ValidatorSetMaxNumValidators, EpochDurationNumBlocks: globalParamsEntry.EpochDurationNumBlocks, JailInactiveValidatorGracePeriodEpochs: globalParamsEntry.JailInactiveValidatorGracePeriodEpochs, } @@ -121,6 +126,10 @@ type UpdateGlobalParamsRequest struct { // are included when generating a new Proof-of-Stake leader schedule. LeaderScheduleMaxNumValidators uint64 `safeForLogging:"true"` + // ValidatorSetMaxNumValidators is the maximum number of validators that + // are included when generating a new Proof-of-Stake validator set. + ValidatorSetMaxNumValidators uint64 `safeForLogging:"true"` + // EpochDurationNumBlocks is the number of blocks included in one epoch. EpochDurationNumBlocks uint64 `safeForLogging:"true"` @@ -237,6 +246,11 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque extraData[lib.LeaderScheduleMaxNumValidatorsKey] = lib.UintToBuf(requestData.LeaderScheduleMaxNumValidators) } + if requestData.ValidatorSetMaxNumValidators > 0 && + requestData.ValidatorSetMaxNumValidators != globalParamsEntry.ValidatorSetMaxNumValidators { + extraData[lib.ValidatorSetMaxNumValidatorsKey] = lib.UintToBuf(requestData.ValidatorSetMaxNumValidators) + } + if requestData.EpochDurationNumBlocks > 0 && requestData.EpochDurationNumBlocks != globalParamsEntry.EpochDurationNumBlocks { extraData[lib.EpochDurationNumBlocksKey] = lib.UintToBuf(requestData.EpochDurationNumBlocks) diff --git a/routes/admin_transaction_test.go b/routes/admin_transaction_test.go index 06d67f7f..0d195822 100644 --- a/routes/admin_transaction_test.go +++ b/routes/admin_transaction_test.go @@ -100,6 +100,7 @@ func TestUpdateGlobalParams(t *testing.T) { StakeLockupEpochDuration: 4, ValidatorJailEpochDuration: 4, LeaderScheduleMaxNumValidators: 101, + ValidatorSetMaxNumValidators: 102, EpochDurationNumBlocks: 3601, JailInactiveValidatorGracePeriodEpochs: 49, MinFeeRateNanosPerKB: 99, @@ -112,6 +113,7 @@ func TestUpdateGlobalParams(t *testing.T) { require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(4)) require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(4)) require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(101)) + require.Equal(t, globalParams.ValidatorSetMaxNumValidators, uint64(102)) require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(3601)) require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(49)) } @@ -131,6 +133,7 @@ func TestUpdateGlobalParams(t *testing.T) { require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(4)) require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(4)) require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(101)) + require.Equal(t, globalParams.ValidatorSetMaxNumValidators, uint64(102)) require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(3601)) require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(50)) } diff --git a/routes/exchange.go b/routes/exchange.go index 89eba7f5..30f54311 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -132,7 +132,7 @@ func _headerToResponse(header *lib.MsgDeSoHeader, hash string) *HeaderResponse { Version: header.Version, PrevBlockHashHex: header.PrevBlockHash.String(), TransactionMerkleRootHex: header.TransactionMerkleRoot.String(), - TstampSecs: header.TstampSecs, + TstampSecs: header.GetTstampSecs(), Height: header.Height, Nonce: header.Nonce, ExtraNonce: header.ExtraNonce, @@ -666,7 +666,7 @@ func APITransactionToResponse( if block != nil && block.Header != nil { ret.BlockInfo = &TransactionBlockInfo{ Height: block.Header.Height, - TimestampSecs: block.Header.TstampSecs, + TimestampSecs: block.Header.GetTstampSecs(), } } diff --git a/routes/exchange_test.go b/routes/exchange_test.go index 663ce57c..2756e059 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -4,8 +4,9 @@ import ( "bytes" "encoding/hex" "encoding/json" - chainlib "github.com/btcsuite/btcd/blockchain" + "github.com/deso-protocol/backend/config" coreCmd "github.com/deso-protocol/core/cmd" + "github.com/deso-protocol/core/lib" "github.com/google/uuid" "io" "io/ioutil" @@ -14,10 +15,6 @@ import ( "net/http/httptest" "os" "testing" - "time" - - "github.com/deso-protocol/backend/config" - "github.com/deso-protocol/core/lib" "github.com/dgraph-io/badger/v3" @@ -78,106 +75,7 @@ func GetTestBadgerDb(t *testing.T) (_db *badger.DB, _dir string) { return db, dir } -func NewLowDifficultyBlockchain(t *testing.T) (*lib.Blockchain, *lib.DeSoParams, *badger.DB, string) { - - // Set the number of txns per view regeneration to one while creating the txns - lib.ReadOnlyUtxoViewRegenerationIntervalTxns = 1 - - return NewLowDifficultyBlockchainWithParams(t, &lib.DeSoTestnetParams) -} - -func NewLowDifficultyBlockchainWithParams(t *testing.T, params *lib.DeSoParams) ( - *lib.Blockchain, *lib.DeSoParams, *badger.DB, string) { - - // Set the number of txns per view regeneration to one while creating the txns - lib.ReadOnlyUtxoViewRegenerationIntervalTxns = 1 - - db, dir := GetTestBadgerDb(t) - timesource := chainlib.NewMedianTime() - - // Set some special parameters for testing. If the blocks above are changed - // these values should be updated to reflect the latest testnet values. - paramsCopy := *params - paramsCopy.GenesisBlock = &lib.MsgDeSoBlock{ - Header: &lib.MsgDeSoHeader{ - Version: 0, - PrevBlockHash: lib.MustDecodeHexBlockHash("0000000000000000000000000000000000000000000000000000000000000000"), - TransactionMerkleRoot: lib.MustDecodeHexBlockHash("097158f0d27e6d10565c4dc696c784652c3380e0ff8382d3599a4d18b782e965"), - TstampSecs: uint64(1560735050), - Height: uint64(0), - Nonce: uint64(0), - // No ExtraNonce is set in the genesis block - }, - Txns: []*lib.MsgDeSoTxn{ - { - TxInputs: []*lib.DeSoInput{}, - TxOutputs: []*lib.DeSoOutput{}, - TxnMeta: &lib.BlockRewardMetadataa{ - ExtraData: []byte("They came here, to the new world. World 2.0, version 1776."), - }, - // A signature is not required for BLOCK_REWARD transactions since they - // don't spend anything. - }, - }, - } - paramsCopy.MinDifficultyTargetHex = "999999948931e5874cf66a74c0fda790dd8c7458243d400324511a4c71f54faa" - paramsCopy.MinChainWorkHex = "0000000000000000000000000000000000000000000000000000000000000000" - paramsCopy.MiningIterationsPerCycle = 500 - // Set maturity to 2 blocks so we can test spending on short chains. The - // tests rely on the maturity equaling exactly two blocks (i.e. being - // two times the time between blocks). - paramsCopy.TimeBetweenBlocks = 2 * time.Second - paramsCopy.BlockRewardMaturity = time.Second * 4 - paramsCopy.TimeBetweenDifficultyRetargets = 100 * time.Second - paramsCopy.MaxDifficultyRetargetFactor = 2 - paramsCopy.SeedBalances = []*lib.DeSoOutput{ - { - PublicKey: lib.MustBase58CheckDecode(moneyPkString), - AmountNanos: uint64(2000000 * lib.NanosPerUnit), - }, - } - - // Temporarily modify the seed balances to make a specific public - // key have some DeSo - chain, err := lib.NewBlockchain([]string{blockSignerPk}, 0, 0, - ¶msCopy, timesource, db, nil, nil, nil, false) - if err != nil { - log.Fatal(err) - } - - return chain, ¶msCopy, db, dir -} - -func NewTestMiner(t *testing.T, chain *lib.Blockchain, params *lib.DeSoParams, isSender bool) (*lib.DeSoMempool, *lib.DeSoMiner) { - assert := assert.New(t) - require := require.New(t) - _ = assert - _ = require - - mempool := lib.NewDeSoMempool( - chain, 0, /* rateLimitFeeRateNanosPerKB */ - 0 /* minFeeRateNanosPerKB */, "", true, - "" /*dataDir*/, "") - minerPubKeys := []string{} - if isSender { - minerPubKeys = append(minerPubKeys, senderPkString) - } else { - minerPubKeys = append(minerPubKeys, recipientPkString) - } - - blockProducer, err := lib.NewDeSoBlockProducer( - 0, 1, - blockSignerSeed, - mempool, chain, - params, nil) - require.NoError(err) - - newMiner, err := lib.NewDeSoMiner(minerPubKeys, 1 /*numThreads*/, blockProducer, params) - require.NoError(err) - return mempool, newMiner -} - -func newTestAPIServer(t *testing.T, globalStateRemoteNode string) (*APIServer, *APIServer, *lib.DeSoMiner) { +func newTestAPIServer(t *testing.T, globalStateRemoteNode string, txindex bool) (*APIServer, *APIServer, *lib.DeSoMiner) { assert := assert.New(t) require := require.New(t) _, _ = assert, require @@ -202,7 +100,7 @@ func newTestAPIServer(t *testing.T, globalStateRemoteNode string) (*APIServer, * coreConfig := coreCmd.LoadConfig() coreConfig.Params = &lib.DeSoTestnetParams coreConfig.DataDirectory = badgerDir - coreConfig.TXIndex = true + coreConfig.TXIndex = txindex coreConfig.MinerPublicKeys = []string{senderPkString} coreConfig.NumMiningThreads = 1 coreConfig.HyperSync = false @@ -257,7 +155,7 @@ func TestAPI(t *testing.T) { require := require.New(t) _, _ = assert, require - apiServer, _, miner := newTestAPIServer(t, "" /*globalStateRemoteNode*/) + apiServer, _, miner := newTestAPIServer(t, "" /*globalStateRemoteNode*/, false) { request, _ := http.NewRequest("GET", RoutePathAPIBase, nil) diff --git a/routes/global_state_test.go b/routes/global_state_test.go index 235b829c..cea0e1c8 100644 --- a/routes/global_state_test.go +++ b/routes/global_state_test.go @@ -18,7 +18,7 @@ func TestGlobalStateServicePutGetDeleteWithDB(t *testing.T) { _, _ = assert, require apiServer, _, _ := newTestAPIServer( - t, "" /*globalStateRemoteNode*/) + t, "" /*globalStateRemoteNode*/, false) // Getting when no value is present should return nil without an // error. @@ -62,7 +62,7 @@ func TestGlobalStateServicePutGetDeleteWithRemoteNode(t *testing.T) { _, _ = assert, require apiServer, _, _ := newTestAPIServer( - t, "" /*globalStateRemoteNode*/) + t, "" /*globalStateRemoteNode*/, false) // Getting when no value is present should return nil without an // error. @@ -189,7 +189,7 @@ func TestGlobalStateServiceURLCreation(t *testing.T) { _, _ = assert, require apiServer, _, _ := newTestAPIServer( - t, "https://deso.com:17001" /*globalStateRemoteNode*/) + t, "https://deso.com:17001" /*globalStateRemoteNode*/, false) { url, _, err := apiServer.GlobalState.CreateGetRequest([]byte("woo")) diff --git a/routes/miner.go b/routes/miner.go index 4f046bc9..752b5655 100644 --- a/routes/miner.go +++ b/routes/miner.go @@ -187,7 +187,7 @@ func (fes *APIServer) SubmitBlock(ww http.ResponseWriter, req *http.Request) { // TODO: Signature checking slows things down because it acquires the ChainLock. // The optimal solution is to check signatures in a way that doesn't acquire the // ChainLock, which is what Bitcoin Core does. - isMainChain, isOrphan, err := fes.blockchain.ProcessBlock( + isMainChain, isOrphan, _, err := fes.blockchain.ProcessBlock( blockFound, true /*verifySignatures*/) glog.V(1).Infof("Called ProcessBlock: isMainChain=(%v), isOrphan=(%v), err=(%v)", isMainChain, isOrphan, err) diff --git a/routes/transaction.go b/routes/transaction.go index 43ee242a..6405f370 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -3953,6 +3953,7 @@ func (fes *APIServer) simulateSubmitTransaction(utxoView *lib.UtxoView, txn *lib txn.Hash(), 0, bestHeight, + 0, false, false, ) From f045518391941afef30bfa3645d771f5587a12e0 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:40:34 -0500 Subject: [PATCH 14/99] Update backend to use BackendMempool interface instead of DeSoMempool (#513) Co-authored-by: Lazy Nina <> --- go.mod | 2 +- routes/exchange.go | 18 +++++++----------- routes/exchange_test.go | 14 ++++++-------- routes/hot_feed.go | 2 +- routes/server.go | 4 ++-- routes/user.go | 5 +---- 6 files changed, 18 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 1c351627..4c9a0578 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/fatih/structs v1.1.0 github.com/golang-jwt/jwt/v4 v4.1.0 github.com/golang/glog v1.0.0 - github.com/google/uuid v1.2.0 github.com/gorilla/mux v1.8.0 github.com/h2non/bimg v1.1.5 github.com/holiman/uint256 v1.1.1 @@ -68,6 +67,7 @@ require ( github.com/golang/snappy v0.0.3 // indirect github.com/google/flatbuffers v2.0.0+incompatible // indirect github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 // indirect + github.com/google/uuid v1.2.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.8 // indirect diff --git a/routes/exchange.go b/routes/exchange.go index 30f54311..a5f0259d 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -133,6 +133,7 @@ func _headerToResponse(header *lib.MsgDeSoHeader, hash string) *HeaderResponse { PrevBlockHashHex: header.PrevBlockHash.String(), TransactionMerkleRootHex: header.TransactionMerkleRoot.String(), TstampSecs: header.GetTstampSecs(), + TstampNanoSecs: header.TstampNanoSecs, Height: header.Height, Nonce: header.Nonce, ExtraNonce: header.ExtraNonce, @@ -968,11 +969,7 @@ func (fes *APIServer) APITransactionInfo(ww http.ResponseWriter, rr *http.Reques // IsMempool means we should just return all of the transactions that are currently in the mempool. if transactionInfoRequest.IsMempool { // Get all the txns from the mempool. - poolTxns, _, err := fes.mempool.GetTransactionsOrderedByTimeAdded() - if err != nil { - APIAddError(ww, fmt.Sprintf("APITransactionInfo: Error getting txns from mempool: %v", err)) - return - } + poolTxns := fes.mempool.GetOrderedTransactions() res := &APITransactionInfoResponse{} res.Transactions = []*TransactionResponse{} @@ -1039,7 +1036,7 @@ func (fes *APIServer) APITransactionInfo(ww http.ResponseWriter, rr *http.Reques if txn == nil { // Try to look the transaction up in the mempool before giving up. - txnInPool := fes.mempool.GetTransaction(txID) + txnInPool := fes.mempool.GetMempoolTx(txID) if txnInPool == nil { APIAddError(ww, fmt.Sprintf("APITransactionInfo: Could not find transaction with TransactionIDBase58Check = %s", transactionInfoRequest.TransactionIDBase58Check)) @@ -1154,11 +1151,7 @@ func (fes *APIServer) APITransactionInfo(ww http.ResponseWriter, rr *http.Reques if transactionInfoRequest.LastPublicKeyTransactionIndex <= 0 { // Start with the mempool - poolTxns, _, err := fes.mempool.GetTransactionsOrderedByTimeAdded() - if err != nil { - APIAddError(ww, fmt.Sprintf("APITransactionInfo: Error getting txns from mempool: %v", err)) - return - } + poolTxns := fes.mempool.GetOrderedTransactions() // Go from most recent to least recent // TODO: Support pagination for mempool transactions @@ -1270,6 +1263,9 @@ type HeaderResponse struct { // The unix timestamp (in seconds) specifying when this block was // mined. TstampSecs uint64 + // The unix timestamp (in nanoseconds) specifying when this block was + // mined. + TstampNanoSecs uint64 // The height of the block this header corresponds to. Height uint64 diff --git a/routes/exchange_test.go b/routes/exchange_test.go index 2756e059..94518e99 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -7,9 +7,7 @@ import ( "github.com/deso-protocol/backend/config" coreCmd "github.com/deso-protocol/core/cmd" "github.com/deso-protocol/core/lib" - "github.com/google/uuid" "io" - "io/ioutil" "log" "net/http" "net/http/httptest" @@ -54,7 +52,7 @@ func CleanUpBadger(db *badger.DB) { } func GetTestBadgerDb(t *testing.T) (_db *badger.DB, _dir string) { - dir, err := ioutil.TempDir("", "badgerdb-"+uuid.New().String()) + dir, err := os.MkdirTemp("", "badgerdb") if err != nil { log.Fatal(err) } @@ -135,9 +133,9 @@ func newTestAPIServer(t *testing.T, globalStateRemoteNode string, txindex bool) privateApiServer.initState() miner := node.Server.GetMiner() - _, err = miner.MineAndProcessSingleBlock(0, node.Server.GetMempool()) + _, err = miner.MineAndProcessSingleBlock(0, node.Server.GetMempool().(*lib.DeSoMempool)) require.NoError(err) - _, err = miner.MineAndProcessSingleBlock(0, node.Server.GetMempool()) + _, err = miner.MineAndProcessSingleBlock(0, node.Server.GetMempool().(*lib.DeSoMempool)) require.NoError(err) t.Cleanup(func() { @@ -664,7 +662,7 @@ func TestAPI(t *testing.T) { txn1 := &lib.MsgDeSoTxn{} txn1Bytes, _ := hex.DecodeString(txn1Hex) _ = txn1.FromBytes(txn1Bytes) - _, err := apiServer.mempool.ProcessTransaction( + _, err := apiServer.mempool.(*lib.DeSoMempool).ProcessTransaction( txn1, false /*allowOrphan*/, true /*rateLimit*/, 0, /*peerID*/ true /*verifySignatures*/) require.NoError(err) @@ -779,7 +777,7 @@ func TestAPI(t *testing.T) { txn2 := &lib.MsgDeSoTxn{} txn2Bytes, _ := hex.DecodeString(txn2Hex) _ = txn2.FromBytes(txn2Bytes) - apiServer.mempool.ProcessTransaction( + apiServer.mempool.(*lib.DeSoMempool).ProcessTransaction( txn2, false /*allowOrphan*/, true /*rateLimit*/, 0, /*peerID*/ true /*verifySignatures*/) { @@ -961,7 +959,7 @@ func TestAPI(t *testing.T) { } // Mine a block and check the balances. - block3, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, apiServer.mempool) + block3, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, apiServer.mempool.(*lib.DeSoMempool)) require.NoError(err) balSum := int64(0) { diff --git a/routes/hot_feed.go b/routes/hot_feed.go index 0f058b2e..853cfc87 100644 --- a/routes/hot_feed.go +++ b/routes/hot_feed.go @@ -446,7 +446,7 @@ func (fes *APIServer) UpdateHotFeedOrderedList( // Create new "block" for mempool txns, give it a block age of 1 greater than the current tip // First get all MempoolTxns from mempool. - mempoolTxnsOrderedByTime, _, err := fes.backendServer.GetMempool().GetTransactionsOrderedByTimeAdded() + mempoolTxnsOrderedByTime := fes.backendServer.GetMempool().GetOrderedTransactions() // Extract MsgDesoTxn from each MempoolTxn var txnsFromMempoolOrderedByTime []*lib.MsgDeSoTxn for _, mempoolTxn := range mempoolTxnsOrderedByTime { diff --git a/routes/server.go b/routes/server.go index 2aba5c9b..7c46af86 100644 --- a/routes/server.go +++ b/routes/server.go @@ -321,7 +321,7 @@ const ( // frontend cares about, from posts to profiles to purchasing DeSo with Bitcoin. type APIServer struct { backendServer *lib.Server - mempool *lib.DeSoMempool + mempool lib.Mempool blockchain *lib.Blockchain blockProducer *lib.DeSoBlockProducer Params *lib.DeSoParams @@ -475,7 +475,7 @@ type LastTradePriceHistoryItem struct { // NewAPIServer ... func NewAPIServer( _backendServer *lib.Server, - _mempool *lib.DeSoMempool, + _mempool lib.Mempool, _blockchain *lib.Blockchain, _blockProducer *lib.DeSoBlockProducer, txIndex *lib.TXIndex, diff --git a/routes/user.go b/routes/user.go index 5e6863aa..a38ec364 100644 --- a/routes/user.go +++ b/routes/user.go @@ -2535,10 +2535,7 @@ func (fes *APIServer) _getMempoolNotifications(request *GetNotificationsRequest, // // TODO(performance): This could get slow if the mempool gets big. Fix is to organize everything // in the mempool by public key and only look up transactions that are relevant to this public key. - poolTxns, _, err := fes.mempool.GetTransactionsOrderedByTimeAdded() - if err != nil { - return nil, errors.Errorf("APITransactionInfo: Error getting txns from mempool: %v", err) - } + poolTxns := fes.mempool.GetOrderedTransactions() mempoolTxnMetadata := []*TransactionMetadataResponse{} for _, poolTx := range poolTxns { From f3932da21612f2333ab01e0581e43f0f11d24592 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Wed, 13 Dec 2023 12:51:10 -0500 Subject: [PATCH 15/99] Add fee estimator arg to all txn construction calls (#514) Co-authored-by: Lazy Nina <> --- routes/access_group.go | 6 ++++-- routes/admin_transaction.go | 4 ++-- routes/associations.go | 4 ++++ routes/exchange.go | 4 ++-- routes/message.go | 6 ++++-- routes/new_message.go | 11 ++++++----- routes/nft.go | 21 +++++++++++++------- routes/shared.go | 3 ++- routes/transaction.go | 39 ++++++++++++++++++++++++------------- routes/validators.go | 2 ++ 10 files changed, 66 insertions(+), 34 deletions(-) diff --git a/routes/access_group.go b/routes/access_group.go index 6a5b7278..873f3d01 100644 --- a/routes/access_group.go +++ b/routes/access_group.go @@ -117,7 +117,8 @@ func (fes *APIServer) accessGroupHandler( accessGroupOwnerPkBytes, accessGroupPkBytes, accessGroupKeyNameBytes, accessGroupOperationType, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { return fmt.Errorf("problem creating transaction: %v", err) } @@ -397,7 +398,8 @@ func (fes *APIServer) accessGroupMemberHandler( accessGroupOwnerPkBytes, accessGroupKeyNameBytes, accessGroupMembers, accessGroupMemberOperationType, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { return fmt.Errorf("problem creating transaction: %v", err) } diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index 4f6bbceb..7b2f5277 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -273,7 +273,7 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque maxNonceExpirationBlockHeightOffset, extraData, requestData.MinFeeRateNanosPerKB, - fes.backendServer.GetMempool(), additionalOutputs) + fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateGlobalParams: Problem creating transaction: %v", err)) return @@ -401,7 +401,7 @@ func (fes *APIServer) SwapIdentity(ww http.ResponseWriter, req *http.Request) { toPublicKey, requestData.MinFeeRateNanosPerKB, - fes.backendServer.GetMempool(), additionalOutputs) + fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SwapIdentity: Problem creating transaction: %v", err)) return diff --git a/routes/associations.go b/routes/associations.go index 14c9f9b7..23f88b5e 100644 --- a/routes/associations.go +++ b/routes/associations.go @@ -252,6 +252,7 @@ func (fes *APIServer) CreateUserAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("CreateUserAssociation: problem creating txn: %v", err)) @@ -337,6 +338,7 @@ func (fes *APIServer) DeleteUserAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("DeleteUserAssociation: problem creating txn: %v", err)) @@ -804,6 +806,7 @@ func (fes *APIServer) CreatePostAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("CreatePostAssociation: problem creating txn: %v", err)) @@ -889,6 +892,7 @@ func (fes *APIServer) DeletePostAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("DeletePostAssociation: problem creating txn: %v", err)) diff --git a/routes/exchange.go b/routes/exchange.go index a5f0259d..84a99649 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -766,7 +766,7 @@ func (fes *APIServer) APITransferDeSo(ww http.ResponseWriter, rr *http.Request) txnn, totalInputt, spendAmountt, feeNanoss, err = fes.blockchain.CreateMaxSpend( senderPublicKeyBytes, recipientPub.SerializeCompressed(), uint64(minFeeRateNanosPerKB), - fes.backendServer.GetMempool(), additionalOutputs) + fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) if err != nil { APIAddError(ww, fmt.Sprintf("APITransferDeSo: Error processing MAX transaction: %v", err)) return @@ -1423,7 +1423,7 @@ func (fes *APIServer) _augmentAndProcessTransactionWithSubsidyWithKey( // return an error. totalInput, spendAmount, changeAmount, fees, err := fes.blockchain.AddInputsAndChangeToTransactionWithSubsidy(txn, minFeeRateNanosPerKB, - inputSubsidy, fes.mempool, 0) + inputSubsidy, fes.mempool, 0, fes.backendServer.GetFeeEstimator()) if err != nil { return 0, 0, 0, 0, fmt.Errorf("_augmentAndProcessTransactionWithKey: Problem adding inputs and "+ "change to transaction %v: %v", txn, err) diff --git a/routes/message.go b/routes/message.go index e30f75a8..8f150d4b 100644 --- a/routes/message.go +++ b/routes/message.go @@ -714,7 +714,8 @@ func (fes *APIServer) SendMessageStateless(ww http.ResponseWriter, req *http.Req senderMessagingPublicKey, senderMessagingGroupKeyNameBytes, recipientMessagingPublicKey, recipientMessagingGroupKeyNameBytes, tstamp, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendMessageStateless: Problem creating transaction: %v", err)) return @@ -973,7 +974,8 @@ func (fes *APIServer) RegisterMessagingGroupKey(ww http.ResponseWriter, req *htt txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateMessagingKeyTxn( ownerPkBytes, messagingPkBytes, messagingKeyNameBytes, messagingKeySignature, []*lib.MessagingGroupMember{}, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("RegisterMessagingGroupKey: Problem creating transaction: %v", err)) return diff --git a/routes/new_message.go b/routes/new_message.go index f33d09f5..c428c382 100644 --- a/routes/new_message.go +++ b/routes/new_message.go @@ -372,11 +372,12 @@ func (fes *APIServer) sendMessageHandler( // Call CreateNewMessageTxn the core lib to construct the transaction to send a group chat message. // The message type must be lib.NewMessageTypeGroupChat, and operation type is lib.NewMessageOperationCreate. txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateNewMessageTxn( - senderGroupOwnerPkBytes, *lib.NewPublicKey(senderGroupOwnerPkBytes), *lib.NewGroupKeyName(senderGroupKeyNameBytes), *lib.NewPublicKey(senderAccessGroupPkbytes), - *lib.NewPublicKey(recipientGroupOwnerPkBytes), *lib.NewGroupKeyName(recipientGroupKeyNameBytes), *lib.NewPublicKey(recipientAccessGroupPkbytes), - hexDecodedEncryptedMessageBytes, tstamp, - newMessageType, newMessageOperationType, - extraData, requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + senderGroupOwnerPkBytes, *lib.NewPublicKey(senderGroupOwnerPkBytes), + *lib.NewGroupKeyName(senderGroupKeyNameBytes), *lib.NewPublicKey(senderAccessGroupPkbytes), + *lib.NewPublicKey(recipientGroupOwnerPkBytes), *lib.NewGroupKeyName(recipientGroupKeyNameBytes), + *lib.NewPublicKey(recipientAccessGroupPkbytes), hexDecodedEncryptedMessageBytes, tstamp, + newMessageType, newMessageOperationType, extraData, requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) if err != nil { return errors.Wrapf(err, "Problem creating transaction: ") } diff --git a/routes/nft.go b/routes/nft.go index c6affae5..d730d16b 100644 --- a/routes/nft.go +++ b/routes/nft.go @@ -262,7 +262,8 @@ func (fes *APIServer) CreateNFT(ww http.ResponseWriter, req *http.Request) { additionalDESORoyaltiesPubKeyMap, additionalCoinRoyaltiesPubKeyMap, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateNFT: Problem creating transaction: %v", err)) return @@ -411,7 +412,8 @@ func (fes *APIServer) UpdateNFT(ww http.ResponseWriter, req *http.Request) { uint64(requestData.MinBidAmountNanos), requestData.IsBuyNow, requestData.BuyNowPriceNanos, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateNFT: Problem creating transaction: %v", err)) return @@ -568,7 +570,8 @@ func (fes *APIServer) CreateNFTBid(ww http.ResponseWriter, req *http.Request) { nftPostHash, uint64(requestData.SerialNumber), uint64(requestData.BidAmountNanos), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateNFTBid: Problem creating transaction: %v", err)) return @@ -731,7 +734,8 @@ func (fes *APIServer) AcceptNFTBid(ww http.ResponseWriter, req *http.Request) { bidderPKID.PKID, uint64(requestData.BidAmountNanos), encryptedUnlockableTextBytes, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AcceptNFTBid: Problem creating transaction: %v", err)) return @@ -1649,7 +1653,8 @@ func (fes *APIServer) TransferNFT(ww http.ResponseWriter, req *http.Request) { nftPostHash, uint64(requestData.SerialNumber), []byte(requestData.EncryptedUnlockableText), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferNFT: Problem creating transaction: %v", err)) return @@ -1789,7 +1794,8 @@ func (fes *APIServer) AcceptNFTTransfer(ww http.ResponseWriter, req *http.Reques updaterPublicKeyBytes, nftPostHash, uint64(requestData.SerialNumber), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AcceptNFTTransfer: Problem creating transaction: %v", err)) return @@ -1928,7 +1934,8 @@ func (fes *APIServer) BurnNFT(ww http.ResponseWriter, req *http.Request) { updaterPublicKeyBytes, nftPostHash, uint64(requestData.SerialNumber), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("BurnNFT: Problem creating transaction: %v", err)) return diff --git a/routes/shared.go b/routes/shared.go index c050007c..2a82de51 100644 --- a/routes/shared.go +++ b/routes/shared.go @@ -397,7 +397,8 @@ func (fes *APIServer) SendSeedDeSo(recipientPkBytes []byte, amountNanos uint64, if utxoView.GlobalParamsEntry != nil && utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB > 0 { minFee = utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB } - _, _, _, _, err = fes.blockchain.AddInputsAndChangeToTransaction(txn, minFee, fes.mempool) + _, _, _, _, err = fes.blockchain.AddInputsAndChangeToTransaction(txn, minFee, fes.mempool, + fes.backendServer.GetFeeEstimator()) if err != nil { return nil, fmt.Errorf("SendSeedDeSo: Error adding inputs for seed DeSo: %v", err) } diff --git a/routes/transaction.go b/routes/transaction.go index 6405f370..b3355b50 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -409,7 +409,8 @@ func (fes *APIServer) UpdateProfile(ww http.ResponseWriter, req *http.Request) { requestData.IsHidden, additionalFees, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Problem creating transaction: %v", err)) return @@ -1069,7 +1070,7 @@ func (fes *APIServer) SendDeSo(ww http.ResponseWriter, req *http.Request) { // Create a MAX transaction txnn, totalInputt, spendAmountt, feeNanoss, err = fes.blockchain.CreateMaxSpend( senderPkBytes, recipientPkBytes, requestData.MinFeeRateNanosPerKB, - fes.backendServer.GetMempool(), additionalOutputs) + fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDeSo: Error processing MAX transaction: %v", err)) return @@ -1103,7 +1104,8 @@ func (fes *APIServer) SendDeSo(ww http.ResponseWriter, req *http.Request) { // depending on what the user requested. totalInputt, spendAmountt, changeAmountt, feeNanoss, err = fes.blockchain.AddInputsAndChangeToTransaction( - txnn, requestData.MinFeeRateNanosPerKB, fes.mempool) + txnn, requestData.MinFeeRateNanosPerKB, fes.mempool, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDeSo: Error processing transaction: %v", err)) return @@ -1212,7 +1214,8 @@ func (fes *APIServer) CreateLikeStateless(ww http.ResponseWriter, req *http.Requ // Try and create the message for the user. txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateLikeTxn( readerPkBytes, postHash, requestData.IsUnlike, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateLikeStateless: Problem creating transaction: %v", err)) return @@ -1462,7 +1465,8 @@ func (fes *APIServer) SubmitPost(ww http.ResponseWriter, req *http.Request) { tstamp, postExtraData, requestData.IsHidden, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SubmitPost: Problem creating transaction: %v", err)) return @@ -1615,7 +1619,8 @@ func (fes *APIServer) CreateFollowTxnStateless(ww http.ResponseWriter, req *http // Try and create the follow for the user. txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateFollowTxn( followerPkBytes, followedPkBytes, requestData.IsUnfollow, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateFollowTxnStateless: Problem creating transaction: %v", err)) return @@ -1789,7 +1794,8 @@ func (fes *APIServer) BuyOrSellCreatorCoin(ww http.ResponseWriter, req *http.Req requestData.MinDeSoExpectedNanos, requestData.MinCreatorCoinExpectedNanos, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("BuyOrSellCreatorCoin: Problem adding inputs and change transaction: %v", err)) return @@ -2053,7 +2059,8 @@ func (fes *APIServer) TransferCreatorCoin(ww http.ResponseWriter, req *http.Requ requestData.CreatorCoinToTransferNanos, receiverPublicKeyBytes, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferCreatorCoin: Problem creating transaction: %v", err)) return @@ -2195,7 +2202,8 @@ func (fes *APIServer) SendDiamonds(ww http.ResponseWriter, req *http.Request) { diamondPostHash, requestData.DiamondLevel, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDiamonds: Problem creating transaction: %v", err)) return @@ -2214,7 +2222,8 @@ func (fes *APIServer) SendDiamonds(ww http.ResponseWriter, req *http.Request) { diamondPostHash, requestData.DiamondLevel, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDiamonds: Problem creating transaction: %v", err)) return @@ -2436,7 +2445,8 @@ func (fes *APIServer) DAOCoin(ww http.ResponseWriter, req *http.Request) { TransferRestrictionStatus: transferRestrictionStatus, }, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("DAOCoin: Problem adding inputs and change transaction: %v", err)) return @@ -2571,7 +2581,8 @@ func (fes *APIServer) TransferDAOCoin(ww http.ResponseWriter, req *http.Request) DAOCoinToTransferNanos: requestData.DAOCoinToTransferNanos, }, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferDAOCoin: Problem creating transaction: %v", err)) return @@ -3126,6 +3137,7 @@ func (fes *APIServer) createDAOCoinLimitOrderResponse( minFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator(), ) if err != nil { @@ -3372,7 +3384,8 @@ func (fes *APIServer) AuthorizeDerivedKey(ww http.ResponseWriter, req *http.Requ memo, requestData.TransactionSpendingLimitHex, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AuthorizeDerivedKey: Problem creating transaction: %v", err)) return diff --git a/routes/validators.go b/routes/validators.go index 687a668d..5ac46603 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -125,6 +125,7 @@ func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Requ requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("RegisterAsValidator: problem creating txn: %v", err)) @@ -199,6 +200,7 @@ func (fes *APIServer) UnregisterAsValidator(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, + fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("UnregisterAsValidator: problem creating txn: %v", err)) From 4bf1f10f7f6ad730a711e393d5fc601b33604424 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:30:00 -0500 Subject: [PATCH 16/99] merge main into feature pos (#519) * [stable] Release 3.4.4 * add node version endpoint (#505) Co-authored-by: Lazy Nina <> * [stable] Release 3.4.5 * hotfix to exchange test * Add captcha verification (#509) * Updates to captcha verification * Updates to backend * Updates to captcha verify * Update captcha verification * Cleanup logs * Add routes to store reward amount in global state, track usage via data dog * Update verify captcha validation ordering, add back comp profile config bool * Update badger sync settings to optimize memory usage during hypersync (#506) * Update hypersync to use default badger settings, switch to performance settings once hypersync completes * Update test dockerfile to accept core branch name as parameter * Blank commit to trigger build * ln/fix-transaction-info-mempool (#510) Co-authored-by: Lazy Nina <> * ln/no-comp-when-0-create-profile-fee (#511) Co-authored-by: Lazy Nina <> * Empty commit to trigger build (#515) * Add extra data to basic transfer and diamond txn construction endpoints (#516) * trigger build (#517) Co-authored-by: Lazy Nina <> * trigger build * Add RWLock around AllCountryLevelSignUpBonuses (#518) Co-authored-by: Lazy Nina <> --------- Co-authored-by: Lazy Nina <> Co-authored-by: superzordon <88362450+superzordon@users.noreply.github.com> --- cmd/run.go | 1 + config/config.go | 6 + routes/admin_jumio.go | 6 + routes/base.go | 7 + routes/exchange.go | 30 +++- routes/exchange_test.go | 101 ++++++++++- routes/global_state.go | 17 +- routes/hot_feed.go | 24 ++- routes/server.go | 44 ++++- routes/supply.go | 5 + routes/transaction.go | 56 ++++-- routes/verify.go | 210 ++++++++++++++++++++++- scripts/nodes/n0 | 1 + scripts/nodes/n0_test | 3 +- scripts/tools/clear_ancestral_records.go | 2 +- test.Dockerfile | 6 + 16 files changed, 489 insertions(+), 30 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index aeac0335..02486a57 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -177,6 +177,7 @@ func init() { runCmd.PersistentFlags().String("metamask-airdrop-eth-minimum", "100000000000000", "In Wei, amount of Eth required to receive an airdrop during Metamask signup.") runCmd.PersistentFlags().Uint64("metamask-airdrop-deso-nanos-amount", 0, "Amount of DESO in nanos to send to metamask users as an airdrop") + runCmd.PersistentFlags().String("hcaptcha-secret", "", "Secret key for hcaptcha service. Used to verify captcha token verifications.") runCmd.PersistentFlags().VisitAll(func(flag *pflag.Flag) { viper.BindPFlag(flag.Name, flag) }) diff --git a/config/config.go b/config/config.go index 55ecc326..81b9b47a 100644 --- a/config/config.go +++ b/config/config.go @@ -94,6 +94,9 @@ type Config struct { MetamaskAirdropEthMinimum *uint256.Int // Amount of DESO in nanos metamask users receive as an airdrop MetamaskAirdropDESONanosAmount uint64 + + // Secret used to validate hCaptcha tokens. + HCaptchaSecret string } func LoadConfig(coreConfig *coreCmd.Config) *Config { @@ -194,6 +197,9 @@ func LoadConfig(coreConfig *coreCmd.Config) *Config { // Node source ID config.NodeSource = viper.GetUint64("node-source") + // hCaptcha secret + config.HCaptchaSecret = viper.GetString("hcaptcha-secret") + // Public keys that need their balances monitored. Map of Label to Public key labelsToPublicKeys := viper.GetString("public-key-balances-to-monitor") if len(labelsToPublicKeys) > 0 { diff --git a/routes/admin_jumio.go b/routes/admin_jumio.go index adfe40dc..cab84dbf 100644 --- a/routes/admin_jumio.go +++ b/routes/admin_jumio.go @@ -341,6 +341,8 @@ type GetAllCountryLevelSignUpBonusResponse struct { } func (fes *APIServer) AdminGetAllCountryLevelSignUpBonuses(ww http.ResponseWriter, req *http.Request) { + fes.allCountryLevelSignUpBonusesLock.RLock() + defer fes.allCountryLevelSignUpBonusesLock.RUnlock() res := GetAllCountryLevelSignUpBonusResponse{ SignUpBonusMetadata: fes.AllCountryLevelSignUpBonuses, DefaultSignUpBonusMetadata: fes.GetDefaultJumioCountrySignUpBonus(), @@ -373,6 +375,8 @@ func (fes *APIServer) SetAllCountrySignUpBonusMetadata() { // SetSingleCountrySignUpBonus sets the sign up bonus configuration for a given country in the cached map. func (fes *APIServer) SetSingleCountrySignUpBonus(countryDetails countries.Alpha3CountryCodeDetails, signUpBonus CountryLevelSignUpBonus) { + fes.allCountryLevelSignUpBonusesLock.Lock() + defer fes.allCountryLevelSignUpBonusesLock.Unlock() fes.AllCountryLevelSignUpBonuses[countryDetails.Name] = CountrySignUpBonusResponse{ CountryLevelSignUpBonus: signUpBonus, CountryCodeDetails: countryDetails, @@ -385,6 +389,8 @@ func (fes *APIServer) GetSingleCountrySignUpBonus(countryCode string) CountryLev countryCodeDetails := countries.Alpha3CountryCodes[strings.ToUpper(countryCode)] // If we can't find the signup bonus from the map, return the default. Else, return the sign up bonus we found in // the map. + fes.allCountryLevelSignUpBonusesLock.RLock() + defer fes.allCountryLevelSignUpBonusesLock.RUnlock() if countrySignUpBonusResponse, exists := fes.AllCountryLevelSignUpBonuses[countryCodeDetails.Name]; !exists { return fes.GetDefaultJumioCountrySignUpBonus() } else { diff --git a/routes/base.go b/routes/base.go index 8649c30e..59d6555e 100644 --- a/routes/base.go +++ b/routes/base.go @@ -358,6 +358,7 @@ type GetAppStateResponse struct { JumioKickbackUSDCents uint64 // CountrySignUpBonus is the sign-up bonus configuration for the country inferred from a request's IP address. CountrySignUpBonus CountryLevelSignUpBonus + CaptchaDeSoNanos uint64 DefaultFeeRateNanosPerKB uint64 TransactionFeeMap map[string][]TransactionFee @@ -394,6 +395,11 @@ func (fes *APIServer) GetAppState(ww http.ResponseWriter, req *http.Request) { defaultFeeRateNanosPerKB = globalParams.MinimumNetworkFeeNanosPerKB } + captchaDesoNanos, err := fes.getCaptchaRewardNanosFromGlobalState() + if err != nil { + captchaDesoNanos = 0 + } + res := &GetAppStateResponse{ MinSatoshisBurnedForProfileCreation: fes.Config.MinSatoshisForProfile, BlockHeight: fes.backendServer.GetBlockchain().BlockTip().Height, @@ -417,6 +423,7 @@ func (fes *APIServer) GetAppState(ww http.ResponseWriter, req *http.Request) { TransactionFeeMap: fes.TxnFeeMapToResponse(true), BuyETHAddress: fes.Config.BuyDESOETHAddress, Nodes: lib.NODES, + CaptchaDeSoNanos: captchaDesoNanos, // Deprecated USDCentsPerBitCloutExchangeRate: fes.GetExchangeDeSoPrice(), diff --git a/routes/exchange.go b/routes/exchange.go index 84a99649..a65cdb88 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -31,6 +31,8 @@ var ( IsBlacklisted = []byte{1} ) +const NodeVersion = "3.4.5" + const ( // RoutePathAPIBase ... RoutePathAPIBase = "/api/v1" @@ -46,6 +48,8 @@ const ( RoutePathAPINodeInfo = "/api/v1/node-info" // RoutePathAPIBlock ... RoutePathAPIBlock = "/api/v1/block" + // RoutePathAPINodeVersion ... + RoutePathAPINodeVersion = "/api/v1/node-version" ) // APIRoutes returns the routes for the public-facing API. @@ -100,6 +104,13 @@ func (fes *APIServer) APIRoutes() []Route { fes.APIBlock, PublicAccess, }, + { + "APINodeVersion", + []string{"GET"}, + RoutePathAPINodeVersion, + fes.APINodeVersion, + PublicAccess, + }, } return APIRoutes @@ -764,7 +775,7 @@ func (fes *APIServer) APITransferDeSo(ww http.ResponseWriter, rr *http.Request) if transferDeSoRequest.AmountNanos < 0 { // Create a MAX transaction txnn, totalInputt, spendAmountt, feeNanoss, err = fes.blockchain.CreateMaxSpend( - senderPublicKeyBytes, recipientPub.SerializeCompressed(), + senderPublicKeyBytes, recipientPub.SerializeCompressed(), nil, uint64(minFeeRateNanosPerKB), fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) if err != nil { @@ -1169,7 +1180,7 @@ func (fes *APIServer) APITransactionInfo(ww http.ResponseWriter, rr *http.Reques } // Skip irrelevant transactions - if !isRelevantTxn { + if !isRelevantTxn && txnMeta.TransactorPublicKeyBase58Check != transactionInfoRequest.PublicKeyBase58Check { continue } @@ -1369,6 +1380,21 @@ func (fes *APIServer) APIBlock(ww http.ResponseWriter, rr *http.Request) { } } +type APINodeVersionResponse struct { + Version string +} + +// APINodeVersion returns the version of the node. +func (fes *APIServer) APINodeVersion(ww http.ResponseWriter, rr *http.Request) { + if err := json.NewEncoder(ww).Encode(&APINodeVersionResponse{ + Version: NodeVersion, + }); err != nil { + APIAddError(ww, fmt.Sprintf("APINodeVersion: Problem encoding response "+ + "as JSON: %v", err)) + return + } +} + // TODO: This is a somewhat redundant version of processTransaction It exists // because the API needed to cut out the derivation of the public key from the // user object, among other things. diff --git a/routes/exchange_test.go b/routes/exchange_test.go index 94518e99..c14592cd 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -73,7 +73,106 @@ func GetTestBadgerDb(t *testing.T) (_db *badger.DB, _dir string) { return db, dir } -func newTestAPIServer(t *testing.T, globalStateRemoteNode string, txindex bool) (*APIServer, *APIServer, *lib.DeSoMiner) { +func NewLowDifficultyBlockchain(t *testing.T) (*lib.Blockchain, *lib.DeSoParams, *badger.DB, string) { + + // Set the number of txns per view regeneration to one while creating the txns + lib.ReadOnlyUtxoViewRegenerationIntervalTxns = 1 + + return NewLowDifficultyBlockchainWithParams(t, &lib.DeSoTestnetParams) +} + +func NewLowDifficultyBlockchainWithParams(t *testing.T, params *lib.DeSoParams) ( + *lib.Blockchain, *lib.DeSoParams, *badger.DB, string) { + + // Set the number of txns per view regeneration to one while creating the txns + lib.ReadOnlyUtxoViewRegenerationIntervalTxns = 1 + + db, dir := GetTestBadgerDb(t) + timesource := chainlib.NewMedianTime() + + // Set some special parameters for testing. If the blocks above are changed + // these values should be updated to reflect the latest testnet values. + paramsCopy := *params + paramsCopy.GenesisBlock = &lib.MsgDeSoBlock{ + Header: &lib.MsgDeSoHeader{ + Version: 0, + PrevBlockHash: lib.MustDecodeHexBlockHash("0000000000000000000000000000000000000000000000000000000000000000"), + TransactionMerkleRoot: lib.MustDecodeHexBlockHash("097158f0d27e6d10565c4dc696c784652c3380e0ff8382d3599a4d18b782e965"), + TstampSecs: uint64(1560735050), + Height: uint64(0), + Nonce: uint64(0), + // No ExtraNonce is set in the genesis block + }, + Txns: []*lib.MsgDeSoTxn{ + { + TxInputs: []*lib.DeSoInput{}, + TxOutputs: []*lib.DeSoOutput{}, + TxnMeta: &lib.BlockRewardMetadataa{ + ExtraData: []byte("They came here, to the new world. World 2.0, version 1776."), + }, + // A signature is not required for BLOCK_REWARD transactions since they + // don't spend anything. + }, + }, + } + paramsCopy.MinDifficultyTargetHex = "999999948931e5874cf66a74c0fda790dd8c7458243d400324511a4c71f54faa" + paramsCopy.MinChainWorkHex = "0000000000000000000000000000000000000000000000000000000000000000" + paramsCopy.MiningIterationsPerCycle = 500 + // Set maturity to 2 blocks so we can test spending on short chains. The + // tests rely on the maturity equaling exactly two blocks (i.e. being + // two times the time between blocks). + paramsCopy.TimeBetweenBlocks = 2 * time.Second + paramsCopy.BlockRewardMaturity = time.Second * 4 + paramsCopy.TimeBetweenDifficultyRetargets = 100 * time.Second + paramsCopy.MaxDifficultyRetargetFactor = 2 + paramsCopy.SeedBalances = []*lib.DeSoOutput{ + { + PublicKey: lib.MustBase58CheckDecode(moneyPkString), + AmountNanos: uint64(2000000 * lib.NanosPerUnit), + }, + } + + // Temporarily modify the seed balances to make a specific public + // key have some DeSo + chain, err := lib.NewBlockchain([]string{blockSignerPk}, 0, 0, + ¶msCopy, timesource, db, nil, nil, nil, false) + if err != nil { + log.Fatal(err) + } + + return chain, ¶msCopy, db, dir +} + +func NewTestMiner(t *testing.T, chain *lib.Blockchain, params *lib.DeSoParams, isSender bool) (*lib.DeSoMempool, *lib.DeSoMiner) { + assert := assert.New(t) + require := require.New(t) + _ = assert + _ = require + + mempool := lib.NewDeSoMempool( + chain, 0, /* rateLimitFeeRateNanosPerKB */ + 0 /* minFeeRateNanosPerKB */, "", true, + "" /*dataDir*/, "", true) + minerPubKeys := []string{} + if isSender { + minerPubKeys = append(minerPubKeys, senderPkString) + } else { + minerPubKeys = append(minerPubKeys, recipientPkString) + } + + blockProducer, err := lib.NewDeSoBlockProducer( + 0, 1, + blockSignerSeed, + mempool, chain, + params, nil) + require.NoError(err) + + newMiner, err := lib.NewDeSoMiner(minerPubKeys, 1 /*numThreads*/, blockProducer, params) + require.NoError(err) + return mempool, newMiner +} + +func newTestAPIServer(t *testing.T, globalStateRemoteNode string) (*APIServer, *APIServer, *lib.DeSoMiner) { assert := assert.New(t) require := require.New(t) _, _ = assert, require diff --git a/routes/global_state.go b/routes/global_state.go index 88c88acc..c478695c 100644 --- a/routes/global_state.go +++ b/routes/global_state.go @@ -240,8 +240,11 @@ var ( // -> _GlobalStatePrefixUsernameToBlacklistState = []byte{47} - // NEXT_TAG: 48 + // The prefix for modifying the starter nanos reward for solving a captcha on signup. + // -> + _GlobalStatePrefixToCaptchaReward = []byte{48} + // NEXT_TAG: 49 ) type HotFeedApprovedPostOp struct { @@ -389,6 +392,12 @@ type UserMetadata struct { UnreadNotifications uint64 // The most recently scanned notification transaction index in the database. Stored in order to prevent unnecessary re-scanning. LatestUnreadNotificationIndex int64 + + // The last block height that the user has submitted hcaptcha verification for. + LastHcaptchaBlockHeight uint32 + // HcaptchaShouldCompProfileCreation = True if we should comp the create profile fee because the user went through the + // Captcha flow. + HcaptchaShouldCompProfileCreation bool } type TutorialStatus string @@ -673,6 +682,12 @@ func GlobalStateKeyForBlacklistedProfileByUsername(username string) []byte { return key } +// Key for accessing the captcha reward amount. +func GlobalStateKeyForCaptchaRewardAmountNanos() []byte { + key := append([]byte{}, _GlobalStatePrefixToCaptchaReward...) + return key +} + // Key for accessing the blacklist audit logs associated with a user. func GlobalStateKeyForBlacklistAuditLogs(username string) []byte { key := append([]byte{}, _GlobalStatePrefixBlacklistAuditLog...) diff --git a/routes/hot_feed.go b/routes/hot_feed.go index 853cfc87..9a884efa 100644 --- a/routes/hot_feed.go +++ b/routes/hot_feed.go @@ -83,13 +83,23 @@ func (fes *APIServer) StartHotFeedRoutine() { for { select { case <-time.After(30 * time.Second): - resetCache := false - if cacheResetCounter >= ResetCachesIterationLimit { - resetCache = true - cacheResetCounter = 0 - } - fes.UpdateHotFeed(resetCache) - cacheResetCounter += 1 + // Use an inner function to unlock the mutex with a defer statement. + func() { + // If we're syncing a snapshot, we need to lock the DB mutex before updating the hot feed. + // This is because at the end of a snapshot sync, we re-start the DB, which will cause + // the hot feed routine to panic if it's in the middle of updating the hot feed. + if fes.backendServer.GetBlockchain().ChainState() == lib.SyncStateSyncingSnapshot { + fes.backendServer.DbMutex.Lock() + defer fes.backendServer.DbMutex.Unlock() + } + resetCache := false + if cacheResetCounter >= ResetCachesIterationLimit { + resetCache = true + cacheResetCounter = 0 + } + fes.UpdateHotFeed(resetCache) + cacheResetCounter += 1 + }() case <-fes.quit: break out } diff --git a/routes/server.go b/routes/server.go index 7c46af86..710a0d4c 100644 --- a/routes/server.go +++ b/routes/server.go @@ -155,10 +155,12 @@ const ( RoutePathSubmitPhoneNumberVerificationCode = "/api/v0/submit-phone-number-verification-code" RoutePathResendVerifyEmail = "/api/v0/resend-verify-email" RoutePathVerifyEmail = "/api/v0/verify-email" + RoutePathVerifyCaptcha = "/api/v0/verify-captcha" RoutePathJumioBegin = "/api/v0/jumio-begin" RoutePathJumioCallback = "/api/v0/jumio-callback" RoutePathJumioFlowFinished = "/api/v0/jumio-flow-finished" RoutePathGetJumioStatusForPublicKey = "/api/v0/get-jumio-status-for-public-key" + RoutePathAdminSetCaptchaRewardNanos = "/api/v0/admin/set-captcha-reward-nanos" // tutorial.go RoutePathGetTutorialCreators = "/api/v0/get-tutorial-creators" @@ -452,7 +454,8 @@ type APIServer struct { CountKeysWithDESO uint64 // map of country name to sign up bonus data - AllCountryLevelSignUpBonuses map[string]CountrySignUpBonusResponse + allCountryLevelSignUpBonusesLock sync.RWMutex + AllCountryLevelSignUpBonuses map[string]CountrySignUpBonusResponse // Frequently accessed data from global state USDCentsToDESOReserveExchangeRate uint64 @@ -1112,6 +1115,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.VerifyEmail, PublicAccess, }, + { + "VerifyCaptcha", + []string{"POST", "OPTIONS"}, + RoutePathVerifyCaptcha, + fes.HandleCaptchaVerificationRequest, + PublicAccess, + }, { "GetUserDerivedKeys", []string{"POST", "OPTIONS"}, @@ -1753,6 +1763,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.AdminResetPhoneNumber, SuperAdminAccess, }, + { + "SetCaptchaRewardNanos", + []string{"POST", "OPTIONS"}, + RoutePathAdminSetCaptchaRewardNanos, + fes.AdminSetCaptchaRewardNanos, + SuperAdminAccess, + }, // End all /admin routes // GET endpoints for managing parameters related to Buying DeSo { @@ -2607,11 +2624,20 @@ func (fes *APIServer) StartSeedBalancesMonitoring() { return } tags := []string{} - fes.logBalanceForSeed(fes.Config.StarterDESOSeed, "STARTER_DESO", tags) - fes.logBalanceForSeed(fes.Config.BuyDESOSeed, "BUY_DESO", tags) - for label, publicKey := range fes.Config.PublicKeyBalancesToMonitor { - fes.logBalanceForPublicKey(publicKey, label, tags) - } + // Use an inner function to unlock the mutex with a defer statement. + func() { + // If we're syncing a snapshot, we need to lock the DB in case the DB is restarted. This happens + // at the end of the snapshot sync. + if fes.backendServer.GetBlockchain().ChainState() == lib.SyncStateSyncingSnapshot { + fes.backendServer.DbMutex.Lock() + defer fes.backendServer.DbMutex.Unlock() + } + fes.logBalanceForSeed(fes.Config.StarterDESOSeed, "STARTER_DESO", tags) + fes.logBalanceForSeed(fes.Config.BuyDESOSeed, "BUY_DESO", tags) + for label, publicKey := range fes.Config.PublicKeyBalancesToMonitor { + fes.logBalanceForPublicKey(publicKey, label, tags) + } + }() case <-fes.quit: break out } @@ -2692,6 +2718,12 @@ func (fes *APIServer) SetGlobalStateCache() { if fes.backendServer == nil { return } + // If we're syncing a snapshot, we need to lock the DB in case the DB is restarted. This happens at + // the end of the snapshot sync. + if fes.backendServer.GetBlockchain().ChainState() == lib.SyncStateSyncingSnapshot { + fes.backendServer.DbMutex.Lock() + defer fes.backendServer.DbMutex.Unlock() + } utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { glog.Errorf("SetGlobalStateCache: problem with GetAugmentedUniversalView: %v", err) diff --git a/routes/supply.go b/routes/supply.go index 83743504..f6114dd4 100644 --- a/routes/supply.go +++ b/routes/supply.go @@ -44,6 +44,11 @@ func (fes *APIServer) StartSupplyMonitoring() { } func (fes *APIServer) UpdateSupplyStats() { + // Prevent access to the DB while it's reset. This only happens when we're syncing a snapshot. + if fes.backendServer.GetBlockchain().ChainState() == lib.SyncStateSyncingSnapshot { + fes.backendServer.DbMutex.Lock() + defer fes.backendServer.DbMutex.Unlock() + } totalSupply := uint64(0) totalKeysWithDESO := uint64(0) // Get all the balances from the DB diff --git a/routes/transaction.go b/routes/transaction.go index b3355b50..11667c73 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -25,7 +25,7 @@ import ( ) type GetTxnRequest struct { - // TxnHash to fetch. + // TxnHashHex to fetch. TxnHashHex string `safeForLogging:"true"` } @@ -459,14 +459,16 @@ func (fes *APIServer) CompProfileCreation(profilePublicKey []byte, userMetadata } // Additional fee is set to the create profile fee when we are creating a profile additionalFees := utxoView.GlobalParamsEntry.CreateProfileFeeNanos - + if additionalFees == 0 { + return 0, nil, nil + } existingMetamaskAirdropMetadata, err := fes.GetMetamaskAirdropMetadata(profilePublicKey) if err != nil { return 0, nil, fmt.Errorf("Error geting metamask airdrop metadata from global state: %v", err) } // Only comp create profile fee if frontend server has both twilio and starter deso seed configured and the user // has verified their profile. - if !fes.Config.CompProfileCreation || fes.Config.StarterDESOSeed == "" || fes.Twilio == nil || (userMetadata.PhoneNumber == "" && !userMetadata.JumioVerified && existingMetamaskAirdropMetadata == nil) { + if !fes.Config.CompProfileCreation || fes.Config.StarterDESOSeed == "" || (fes.Config.HCaptchaSecret == "" && fes.Twilio == nil) || (userMetadata.PhoneNumber == "" && !userMetadata.JumioVerified && existingMetamaskAirdropMetadata == nil && userMetadata.LastHcaptchaBlockHeight == 0) { return additionalFees, nil, nil } var currentBalanceNanos uint64 @@ -507,11 +509,16 @@ func (fes *APIServer) CompProfileCreation(profilePublicKey []byte, userMetadata return additionalFees, nil, nil } updateMetamaskAirdropMetadata = true - } else { + } else if userMetadata.JumioVerified { // User has been Jumio verified but should comp profile creation is false, just return if !userMetadata.JumioShouldCompProfileCreation { return additionalFees, nil, nil } + } else if userMetadata.LastHcaptchaBlockHeight != 0 { + // User has been captcha verified but should comp profile creation is false, just return + if !userMetadata.HcaptchaShouldCompProfileCreation { + return additionalFees, nil, nil + } } // Find the minimum starter bit deso amount @@ -530,6 +537,10 @@ func (fes *APIServer) CompProfileCreation(profilePublicKey []byte, userMetadata // We comp the create profile fee minus the minimum starter deso amount divided by 2. // This discourages botting while covering users who verify a phone number. compAmount := createProfileFeeNanos - (minStarterDESONanos / 2) + if (minStarterDESONanos / 2) > createProfileFeeNanos { + compAmount = createProfileFeeNanos + } + // If the user won't have enough deso to cover the fee, this is an error. if currentBalanceNanos+compAmount < createProfileFeeNanos { return 0, nil, fmt.Errorf("Creating a profile requires DeSo. Please purchase some to create a profile.") @@ -547,6 +558,11 @@ func (fes *APIServer) CompProfileCreation(profilePublicKey []byte, userMetadata if err = fes.putPhoneNumberMetadataInGlobalState(newPhoneNumberMetadata, userMetadata.PhoneNumber); err != nil { return 0, nil, fmt.Errorf("UpdateProfile: Error setting ShouldComp to false for phone number metadata: %v", err) } + } else if userMetadata.LastHcaptchaBlockHeight != 0 { + userMetadata.HcaptchaShouldCompProfileCreation = false + if err = fes.putUserMetadataInGlobalState(userMetadata); err != nil { + return 0, nil, fmt.Errorf("UpdateProfile: Error setting ShouldComp to false for jumio user metadata: %v", err) + } } else { // Set JumioShouldCompProfileCreation to false so we don't continue to comp profile creation. userMetadata.JumioShouldCompProfileCreation = false @@ -978,10 +994,11 @@ func (fes *APIServer) ExceedsDeSoBalance(nanosPurchased uint64, seed string) (bo // SendDeSoRequest ... type SendDeSoRequest struct { - SenderPublicKeyBase58Check string `safeForLogging:"true"` - RecipientPublicKeyOrUsername string `safeForLogging:"true"` - AmountNanos int64 `safeForLogging:"true"` - MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + SenderPublicKeyBase58Check string `safeForLogging:"true"` + RecipientPublicKeyOrUsername string `safeForLogging:"true"` + AmountNanos int64 `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` @@ -1059,6 +1076,12 @@ func (fes *APIServer) SendDeSo(ww http.ResponseWriter, req *http.Request) { return } + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("SendDeSo: Problem encoding ExtraData: %v", err)) + return + } + // If the AmountNanos is less than zero then we have a special case where we create // a transaction with the maximum spend. var txnn *lib.MsgDeSoTxn @@ -1069,8 +1092,8 @@ func (fes *APIServer) SendDeSo(ww http.ResponseWriter, req *http.Request) { if requestData.AmountNanos < 0 { // Create a MAX transaction txnn, totalInputt, spendAmountt, feeNanoss, err = fes.blockchain.CreateMaxSpend( - senderPkBytes, recipientPkBytes, requestData.MinFeeRateNanosPerKB, - fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) + senderPkBytes, recipientPkBytes, extraData, requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDeSo: Error processing MAX transaction: %v", err)) return @@ -1100,6 +1123,10 @@ func (fes *APIServer) SendDeSo(ww http.ResponseWriter, req *http.Request) { // inputs and change. } + if len(extraData) > 0 { + txnn.ExtraData = extraData + } + // Add inputs to the transaction and do signing, validation, and broadcast // depending on what the user requested. totalInputt, spendAmountt, changeAmountt, feeNanoss, err = @@ -2107,6 +2134,8 @@ type SendDiamondsRequest struct { MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` @@ -2182,6 +2211,12 @@ func (fes *APIServer) SendDiamonds(ww http.ResponseWriter, req *http.Request) { return } + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("SendDiamonds: Problem encoding extra data: %v", err)) + return + } + // Try and create the transfer with diamonds for the user. // We give diamonds in DESO if we're past the corresponding block height. blockHeight := fes.blockchain.BlockTip().Height + 1 @@ -2201,6 +2236,7 @@ func (fes *APIServer) SendDiamonds(ww http.ResponseWriter, req *http.Request) { senderPublicKeyBytes, diamondPostHash, requestData.DiamondLevel, + extraData, // Standard transaction fields requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) diff --git a/routes/verify.go b/routes/verify.go index 97237d85..e668b593 100644 --- a/routes/verify.go +++ b/routes/verify.go @@ -141,8 +141,9 @@ func (fes *APIServer) canUserCreateProfile(userMetadata *UserMetadata, utxoView return false, err } // User can create a profile if they have a phone number or if they have enough DeSo to cover the create profile fee. + // User can also create a profile if they've successfully filled out a captcha. // The PhoneNumber is only set if the user has passed phone number verification. - if userMetadata.PhoneNumber != "" || totalBalanceNanos >= utxoView.GlobalParamsEntry.CreateProfileFeeNanos { + if userMetadata.PhoneNumber != "" || totalBalanceNanos >= utxoView.GlobalParamsEntry.CreateProfileFeeNanos || userMetadata.LastHcaptchaBlockHeight > 0 { return true, nil } @@ -251,6 +252,213 @@ func (fes *APIServer) validatePhoneNumberNotAlreadyInUse(phoneNumber string, use return nil } +type SubmitCaptchaVerificationRequest struct { + Token string + JWT string + PublicKeyBase58Check string +} + +type SubmitCaptchaVerificationResponse struct { + Success bool + TxnHashHex string +} + +func (fes *APIServer) HandleCaptchaVerificationRequest(ww http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := SubmitCaptchaVerificationRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("HandleCaptchaVerificationRequest: Problem parsing request body: %v", err)) + return + } + + // Validate their permissions + isValid, err := fes.ValidateJWT(requestData.PublicKeyBase58Check, requestData.JWT) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("HandleCaptchaVerificationRequest: Error validating JWT: %v", err)) + } + if !isValid { + _AddBadRequestError(ww, fmt.Sprintf("HandleCaptchaVerificationRequest: Invalid token: %v", err)) + return + } + + txnHashHex, err := fes.verifyHCaptchaTokenAndSendStarterDESO(requestData.Token, requestData.PublicKeyBase58Check) + + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("HandleCaptchaVerificationRequest: Error verifying captcha: %v", err)) + return + } + + res := SubmitCaptchaVerificationResponse{ + Success: true, + TxnHashHex: txnHashHex, + } + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("HandleCaptchaVerificationRequest: Problem encoding response: %v", err)) + return + } +} + +type AdminUpdateCaptchaRewardRequest struct { + // Amount of nanos to reward for a successful captcha. + RewardNanos uint64 +} + +type AdminUpdateCaptchaRewardResponse struct { + // Amount of nanos to reward for a successful captcha. + RewardNanos uint64 +} + +// HandleAdminUpdateCaptchaRewardRequest allows an admin to update the captcha reward amount. +func (fes *APIServer) AdminSetCaptchaRewardNanos(ww http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := AdminUpdateCaptchaRewardRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("HandleAdminUpdateCaptchaRewardRequest: Problem parsing request body: %v", err)) + return + } + + // Ensure that the reward amount is not greater than the starter deso amount flag. + if requestData.RewardNanos > fes.Config.StarterDESONanos { + _AddBadRequestError(ww, fmt.Sprintf("HandleAdminUpdateCaptchaRewardRequest: Reward amount %v exceeds starter deso amount %v", requestData.RewardNanos, fes.Config.StarterDESONanos)) + return + } + + if err := fes.putCaptchaRewardNanosInGlobalState(requestData.RewardNanos); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("HandleAdminUpdateCaptchaRewardRequest: Error putting captcha reward in global state: %v", err)) + return + } + + res := AdminUpdateCaptchaRewardResponse{ + RewardNanos: requestData.RewardNanos, + } + if err := json.NewEncoder(ww).Encode(res); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("HandleAdminUpdateCaptchaRewardRequest: Problem encoding response: %v", err)) + return + } +} + +// getCaptchaRewardNanosFromGlobalState returns the amount of nanos to reward for a successful captcha from global state. +func (fes *APIServer) getCaptchaRewardNanosFromGlobalState() (uint64, error) { + dbKey := GlobalStateKeyForCaptchaRewardAmountNanos() + + rewardNanosBytes, err := fes.GlobalState.Get(dbKey) + if err != nil { + return 0, fmt.Errorf( + "getCaptchaRewardNanosFromGlobalState: Problem with Get: %v", err) + } + + rewardNanos, err := lib.ReadUvarint(bytes.NewReader(rewardNanosBytes)) + + return rewardNanos, nil +} + +// putCaptchaRewardNanosInGlobalState puts the amount of nanos to reward for a successful captcha in global state. +func (fes *APIServer) putCaptchaRewardNanosInGlobalState(rewardNanos uint64) error { + dbKey := GlobalStateKeyForCaptchaRewardAmountNanos() + + rewardNanosBytes := lib.UintToBuf(rewardNanos) + + if err := fes.GlobalState.Put(dbKey, rewardNanosBytes); err != nil { + return fmt.Errorf( + "putCaptchaRewardNanosInGlobalState: Problem with Put: %v", err) + } + + return nil +} + +// verifyHCaptchaTokenAndSendStarterDESO verifies the captcha token and sends the starter DESO to the user. +func (fes *APIServer) verifyHCaptchaTokenAndSendStarterDESO(token string, publicKeyBase58Check string) (txnHashHex string, err error) { + if fes.Config.StarterDESOSeed == "" { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Starter DESO seed not set") + } + + // Retrieve the amount of nanos to reward for a successful captcha. + amountToSendNanos, err := fes.getCaptchaRewardNanosFromGlobalState() + if err != nil { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Problem with getCaptchaRewardNanosFromGlobalState: %v", err) + } + + // Decode the public key. + publicKeyBytes, _, err := lib.Base58CheckDecode(publicKeyBase58Check) + if err != nil { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Problem decoding public key: %v", err) + } + + // Ensure the user has not already received the starter DESO for submitting a successful captcha. + userMetadata, err := fes.getUserMetadataFromGlobalState(publicKeyBase58Check) + if err != nil { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Problem with getUserMetadataFromGlobalState: %v", err) + } + + if userMetadata.LastHcaptchaBlockHeight != 0 { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: LastHcaptchaBlockHeight is already set") + } + + // Verify the token with hCaptcha. + verificationSuccess, err := fes.verifyHCaptchaToken(token) + + if err != nil { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Error verifying captcha: %v", err) + } + + if !verificationSuccess { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Captcha verification failed") + } + + // Update the user's metadata to indicate that they have received the starter DESO. + lastBlockheight := fes.blockchain.BlockTip().Height + userMetadata.LastHcaptchaBlockHeight = lastBlockheight + userMetadata.HcaptchaShouldCompProfileCreation = true + + if err = fes.putUserMetadataInGlobalState(userMetadata); err != nil { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Problem with putUserMetadataInGlobalState: %v", err) + } + + // Send the starter DESO to the user. + var txnHash *lib.BlockHash + txnHash, err = fes.SendSeedDeSo(publicKeyBytes, amountToSendNanos, false) + if err != nil { + return "", fmt.Errorf("HandleCaptchaVerificationRequest: Error sending seed DeSo: %v", err) + } + + // Log the transaction to datadog. + if fes.backendServer.GetStatsdClient() != nil { + fes.backendServer.GetStatsdClient().Incr("SEND_STARTER_DESO_CAPTCHA", nil, 1) + } + + return txnHash.String(), nil +} + +type VerificationResponse struct { + Success bool `json:"success"` + ErrorCodes []string `json:"error-codes"` +} + +const VERIFY_URL = "https://hcaptcha.com/siteverify" + +// verifyHCaptchaToken verifies the captcha token via the hCaptcha API. +func (fes *APIServer) verifyHCaptchaToken(token string) (bool, error) { + // Construct and send the request to hcaptcha. + data := url.Values{} + data.Set("secret", fes.Config.HCaptchaSecret) + data.Set("response", token) + + resp, err := http.PostForm(VERIFY_URL, data) + if err != nil { + return false, err + } + defer resp.Body.Close() + + // Parse the response and return the result. + var verificationResponse VerificationResponse + err = json.NewDecoder(resp.Body).Decode(&verificationResponse) + if err != nil { + return false, err + } + + return verificationResponse.Success, nil +} + type SubmitPhoneNumberVerificationCodeRequest struct { JWT string PublicKeyBase58Check string diff --git a/scripts/nodes/n0 b/scripts/nodes/n0 index 84289258..a80aa764 100755 --- a/scripts/nodes/n0 +++ b/scripts/nodes/n0 @@ -18,6 +18,7 @@ rm /tmp/main.*.log --block-cypher-api-key=092dae962ea44b02809a4c74408b42a1 \ --min-satoshis-for-profile=0 \ --connect-ips=deso-seed-2.io:17000 \ + --hypersync-max-queue-size=10 \ --run-hot-feed-routine=true ) diff --git a/scripts/nodes/n0_test b/scripts/nodes/n0_test index fb9f8855..b12c2682 100755 --- a/scripts/nodes/n0_test +++ b/scripts/nodes/n0_test @@ -36,11 +36,12 @@ rm /tmp/main.*.log --block-producer-seed='essence camp ghost remove document vault ladder swim pupil index apart ring' \ --starter-deso-seed='road congress client market couple bid risk escape artwork rookie artwork food' \ --data-dir=/tmp/n0_test_00000 \ - --access-control-allow-origins=http://localhost:4200,http://localhost:80,http://localhost:18002,http://localhost:4201,http://localhost:18001 \ + --access-control-allow-origins=http://localhost:4200,http://localhost:80,http://localhost:18002,http://localhost:4201,http://localhost:18001,http://localhost:3000,localhost:3000 \ --secure-header-allow-hosts=localhost:4200 \ --secure-header-development=true \ --block-cypher-api-key=092dae962ea44b02809a4c74408b42a1 \ --min-satoshis-for-profile=0 \ --expose-global-state=true \ --show-processing-spinners=true \ + --comp-profile-creation=true \ --metamask-airdrop-deso-nanos-amount=1000 ) diff --git a/scripts/tools/clear_ancestral_records.go b/scripts/tools/clear_ancestral_records.go index cf7a9edb..7f862488 100644 --- a/scripts/tools/clear_ancestral_records.go +++ b/scripts/tools/clear_ancestral_records.go @@ -16,7 +16,7 @@ func main() { fmt.Printf("Error reading db1 err: %v", err) return } - snap, err, _ := lib.NewSnapshot(db, dbDir, lib.SnapshotBlockHeightPeriod, false, false, &lib.DeSoMainnetParams, false) + snap, err, _ := lib.NewSnapshot(db, dbDir, lib.SnapshotBlockHeightPeriod, false, false, &lib.DeSoMainnetParams, false, lib.HypersyncDefaultMaxQueueSize) if err != nil { fmt.Printf("Error reading snap err: %v", err) return diff --git a/test.Dockerfile b/test.Dockerfile index a1ed5cd2..a7970f17 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -7,6 +7,9 @@ RUN apk add --update bash cmake g++ gcc git make vips-dev COPY --from=golang:1.20-alpine /usr/local/go/ /usr/local/go/ ENV PATH="/usr/local/go/bin:${PATH}" +# Declare an ARG for the branch name with a default value of "main" +ARG BRANCH_NAME=main + WORKDIR /deso/src RUN git clone https://github.com/deso-protocol/core.git @@ -19,6 +22,9 @@ RUN git pull && \ RUN go mod download RUN ./scripts/install-relic.sh +# Try to checkout to the specified branch. If it fails, checkout main. +RUN git checkout ${BRANCH_NAME} || (echo "Branch ${BRANCH_NAME} not found. Falling back to main." && git checkout main) + WORKDIR /deso/src/backend COPY go.mod . From e392f7f008943d5416df75c1e1ea8fb2e99577c9 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:31:55 -0500 Subject: [PATCH 17/99] Remove fee estimator from txn construction calls (#520) Co-authored-by: Lazy Nina <> --- routes/access_group.go | 6 ++---- routes/admin_transaction.go | 4 ++-- routes/associations.go | 4 ---- routes/exchange.go | 15 +++++++------- routes/message.go | 6 ++---- routes/new_message.go | 2 +- routes/nft.go | 21 +++++++------------ routes/server.go | 2 +- routes/shared.go | 3 +-- routes/transaction.go | 41 +++++++++++++------------------------ routes/user.go | 6 +++--- routes/validators.go | 2 -- 12 files changed, 41 insertions(+), 71 deletions(-) diff --git a/routes/access_group.go b/routes/access_group.go index 873f3d01..6a5b7278 100644 --- a/routes/access_group.go +++ b/routes/access_group.go @@ -117,8 +117,7 @@ func (fes *APIServer) accessGroupHandler( accessGroupOwnerPkBytes, accessGroupPkBytes, accessGroupKeyNameBytes, accessGroupOperationType, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { return fmt.Errorf("problem creating transaction: %v", err) } @@ -398,8 +397,7 @@ func (fes *APIServer) accessGroupMemberHandler( accessGroupOwnerPkBytes, accessGroupKeyNameBytes, accessGroupMembers, accessGroupMemberOperationType, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { return fmt.Errorf("problem creating transaction: %v", err) } diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index 7b2f5277..4f6bbceb 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -273,7 +273,7 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque maxNonceExpirationBlockHeightOffset, extraData, requestData.MinFeeRateNanosPerKB, - fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) + fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateGlobalParams: Problem creating transaction: %v", err)) return @@ -401,7 +401,7 @@ func (fes *APIServer) SwapIdentity(ww http.ResponseWriter, req *http.Request) { toPublicKey, requestData.MinFeeRateNanosPerKB, - fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) + fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SwapIdentity: Problem creating transaction: %v", err)) return diff --git a/routes/associations.go b/routes/associations.go index 23f88b5e..14c9f9b7 100644 --- a/routes/associations.go +++ b/routes/associations.go @@ -252,7 +252,6 @@ func (fes *APIServer) CreateUserAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("CreateUserAssociation: problem creating txn: %v", err)) @@ -338,7 +337,6 @@ func (fes *APIServer) DeleteUserAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("DeleteUserAssociation: problem creating txn: %v", err)) @@ -806,7 +804,6 @@ func (fes *APIServer) CreatePostAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("CreatePostAssociation: problem creating txn: %v", err)) @@ -892,7 +889,6 @@ func (fes *APIServer) DeletePostAssociation(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("DeletePostAssociation: problem creating txn: %v", err)) diff --git a/routes/exchange.go b/routes/exchange.go index a65cdb88..a75cade4 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -378,7 +378,7 @@ func (fes *APIServer) APIBalance(ww http.ResponseWriter, rr *http.Request) { } // Get all the UTXOs for the public key. - utxoView, err := fes.mempool.GetAugmentedUtxoViewForPublicKey(publicKeyBytes, nil) + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUtxoViewForPublicKey(publicKeyBytes, nil) if err != nil { APIAddError(ww, fmt.Sprintf("APIBalanceRequest: Problem getting UTXOs for public key: %v", err)) return @@ -776,8 +776,7 @@ func (fes *APIServer) APITransferDeSo(ww http.ResponseWriter, rr *http.Request) // Create a MAX transaction txnn, totalInputt, spendAmountt, feeNanoss, err = fes.blockchain.CreateMaxSpend( senderPublicKeyBytes, recipientPub.SerializeCompressed(), nil, - uint64(minFeeRateNanosPerKB), - fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) + uint64(minFeeRateNanosPerKB), fes.backendServer.GetMempool(), additionalOutputs) if err != nil { APIAddError(ww, fmt.Sprintf("APITransferDeSo: Error processing MAX transaction: %v", err)) return @@ -980,7 +979,7 @@ func (fes *APIServer) APITransactionInfo(ww http.ResponseWriter, rr *http.Reques // IsMempool means we should just return all of the transactions that are currently in the mempool. if transactionInfoRequest.IsMempool { // Get all the txns from the mempool. - poolTxns := fes.mempool.GetOrderedTransactions() + poolTxns := fes.backendServer.GetMempool().GetOrderedTransactions() res := &APITransactionInfoResponse{} res.Transactions = []*TransactionResponse{} @@ -1047,7 +1046,7 @@ func (fes *APIServer) APITransactionInfo(ww http.ResponseWriter, rr *http.Reques if txn == nil { // Try to look the transaction up in the mempool before giving up. - txnInPool := fes.mempool.GetMempoolTx(txID) + txnInPool := fes.backendServer.GetMempool().GetMempoolTx(txID) if txnInPool == nil { APIAddError(ww, fmt.Sprintf("APITransactionInfo: Could not find transaction with TransactionIDBase58Check = %s", transactionInfoRequest.TransactionIDBase58Check)) @@ -1162,7 +1161,7 @@ func (fes *APIServer) APITransactionInfo(ww http.ResponseWriter, rr *http.Reques if transactionInfoRequest.LastPublicKeyTransactionIndex <= 0 { // Start with the mempool - poolTxns := fes.mempool.GetOrderedTransactions() + poolTxns := fes.backendServer.GetMempool().GetOrderedTransactions() // Go from most recent to least recent // TODO: Support pagination for mempool transactions @@ -1416,6 +1415,8 @@ func (fes *APIServer) _processTransactionWithKey( // transaction will be mined at the earliest. blockHeight+1, true, + // TODO: Do we want to use fes.backendServer.GetMempool here? + // There are probably other updates we need to make here for PoS as well. fes.mempool) if err != nil { return fmt.Errorf("_processTransactionWithKey: Problem validating txn: %v", err) @@ -1449,7 +1450,7 @@ func (fes *APIServer) _augmentAndProcessTransactionWithSubsidyWithKey( // return an error. totalInput, spendAmount, changeAmount, fees, err := fes.blockchain.AddInputsAndChangeToTransactionWithSubsidy(txn, minFeeRateNanosPerKB, - inputSubsidy, fes.mempool, 0, fes.backendServer.GetFeeEstimator()) + inputSubsidy, fes.backendServer.GetMempool(), 0) if err != nil { return 0, 0, 0, 0, fmt.Errorf("_augmentAndProcessTransactionWithKey: Problem adding inputs and "+ "change to transaction %v: %v", txn, err) diff --git a/routes/message.go b/routes/message.go index 8f150d4b..e30f75a8 100644 --- a/routes/message.go +++ b/routes/message.go @@ -714,8 +714,7 @@ func (fes *APIServer) SendMessageStateless(ww http.ResponseWriter, req *http.Req senderMessagingPublicKey, senderMessagingGroupKeyNameBytes, recipientMessagingPublicKey, recipientMessagingGroupKeyNameBytes, tstamp, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendMessageStateless: Problem creating transaction: %v", err)) return @@ -974,8 +973,7 @@ func (fes *APIServer) RegisterMessagingGroupKey(ww http.ResponseWriter, req *htt txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateMessagingKeyTxn( ownerPkBytes, messagingPkBytes, messagingKeyNameBytes, messagingKeySignature, []*lib.MessagingGroupMember{}, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("RegisterMessagingGroupKey: Problem creating transaction: %v", err)) return diff --git a/routes/new_message.go b/routes/new_message.go index c428c382..67ed7f27 100644 --- a/routes/new_message.go +++ b/routes/new_message.go @@ -377,7 +377,7 @@ func (fes *APIServer) sendMessageHandler( *lib.NewPublicKey(recipientGroupOwnerPkBytes), *lib.NewGroupKeyName(recipientGroupKeyNameBytes), *lib.NewPublicKey(recipientAccessGroupPkbytes), hexDecodedEncryptedMessageBytes, tstamp, newMessageType, newMessageOperationType, extraData, requestData.MinFeeRateNanosPerKB, - fes.backendServer.GetMempool(), additionalOutputs, fes.backendServer.GetFeeEstimator()) + fes.backendServer.GetMempool(), additionalOutputs) if err != nil { return errors.Wrapf(err, "Problem creating transaction: ") } diff --git a/routes/nft.go b/routes/nft.go index d730d16b..c6affae5 100644 --- a/routes/nft.go +++ b/routes/nft.go @@ -262,8 +262,7 @@ func (fes *APIServer) CreateNFT(ww http.ResponseWriter, req *http.Request) { additionalDESORoyaltiesPubKeyMap, additionalCoinRoyaltiesPubKeyMap, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateNFT: Problem creating transaction: %v", err)) return @@ -412,8 +411,7 @@ func (fes *APIServer) UpdateNFT(ww http.ResponseWriter, req *http.Request) { uint64(requestData.MinBidAmountNanos), requestData.IsBuyNow, requestData.BuyNowPriceNanos, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateNFT: Problem creating transaction: %v", err)) return @@ -570,8 +568,7 @@ func (fes *APIServer) CreateNFTBid(ww http.ResponseWriter, req *http.Request) { nftPostHash, uint64(requestData.SerialNumber), uint64(requestData.BidAmountNanos), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateNFTBid: Problem creating transaction: %v", err)) return @@ -734,8 +731,7 @@ func (fes *APIServer) AcceptNFTBid(ww http.ResponseWriter, req *http.Request) { bidderPKID.PKID, uint64(requestData.BidAmountNanos), encryptedUnlockableTextBytes, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AcceptNFTBid: Problem creating transaction: %v", err)) return @@ -1653,8 +1649,7 @@ func (fes *APIServer) TransferNFT(ww http.ResponseWriter, req *http.Request) { nftPostHash, uint64(requestData.SerialNumber), []byte(requestData.EncryptedUnlockableText), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferNFT: Problem creating transaction: %v", err)) return @@ -1794,8 +1789,7 @@ func (fes *APIServer) AcceptNFTTransfer(ww http.ResponseWriter, req *http.Reques updaterPublicKeyBytes, nftPostHash, uint64(requestData.SerialNumber), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AcceptNFTTransfer: Problem creating transaction: %v", err)) return @@ -1934,8 +1928,7 @@ func (fes *APIServer) BurnNFT(ww http.ResponseWriter, req *http.Request) { updaterPublicKeyBytes, nftPostHash, uint64(requestData.SerialNumber), - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("BurnNFT: Problem creating transaction: %v", err)) return diff --git a/routes/server.go b/routes/server.go index 710a0d4c..9d5f0877 100644 --- a/routes/server.go +++ b/routes/server.go @@ -2490,7 +2490,7 @@ func (fes *APIServer) ValidateJWT(publicKey string, jwtToken string) (bool, erro return nil, errors.Wrapf(err, "Problem parsing derived public key bytes") } // Validate the derived public key. - utxoView, err := fes.mempool.GetAugmentedUniversalView() + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { return nil, errors.Wrapf(err, "Problem getting utxoView") } diff --git a/routes/shared.go b/routes/shared.go index 2a82de51..d5a67200 100644 --- a/routes/shared.go +++ b/routes/shared.go @@ -397,8 +397,7 @@ func (fes *APIServer) SendSeedDeSo(recipientPkBytes []byte, amountNanos uint64, if utxoView.GlobalParamsEntry != nil && utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB > 0 { minFee = utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB } - _, _, _, _, err = fes.blockchain.AddInputsAndChangeToTransaction(txn, minFee, fes.mempool, - fes.backendServer.GetFeeEstimator()) + _, _, _, _, err = fes.blockchain.AddInputsAndChangeToTransaction(txn, minFee, fes.backendServer.GetMempool()) if err != nil { return nil, fmt.Errorf("SendSeedDeSo: Error adding inputs for seed DeSo: %v", err) } diff --git a/routes/transaction.go b/routes/transaction.go index 11667c73..d1eea6ec 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -57,7 +57,7 @@ func (fes *APIServer) GetTxn(ww http.ResponseWriter, req *http.Request) { copy(txnHash[:], txnHashBytes) } - txnFound := fes.mempool.IsTransactionInPool(txnHash) + txnFound := fes.backendServer.GetMempool().IsTransactionInPool(txnHash) if !txnFound { txnFound = lib.DbCheckTxnExistence(fes.TXIndex.TXIndexChain.DB(), nil, txnHash) } @@ -409,8 +409,7 @@ func (fes *APIServer) UpdateProfile(ww http.ResponseWriter, req *http.Request) { requestData.IsHidden, additionalFees, extraData, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Problem creating transaction: %v", err)) return @@ -1131,8 +1130,7 @@ func (fes *APIServer) SendDeSo(ww http.ResponseWriter, req *http.Request) { // depending on what the user requested. totalInputt, spendAmountt, changeAmountt, feeNanoss, err = fes.blockchain.AddInputsAndChangeToTransaction( - txnn, requestData.MinFeeRateNanosPerKB, fes.mempool, - fes.backendServer.GetFeeEstimator()) + txnn, requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDeSo: Error processing transaction: %v", err)) return @@ -1241,8 +1239,7 @@ func (fes *APIServer) CreateLikeStateless(ww http.ResponseWriter, req *http.Requ // Try and create the message for the user. txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateLikeTxn( readerPkBytes, postHash, requestData.IsUnlike, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateLikeStateless: Problem creating transaction: %v", err)) return @@ -1492,8 +1489,7 @@ func (fes *APIServer) SubmitPost(ww http.ResponseWriter, req *http.Request) { tstamp, postExtraData, requestData.IsHidden, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SubmitPost: Problem creating transaction: %v", err)) return @@ -1646,8 +1642,7 @@ func (fes *APIServer) CreateFollowTxnStateless(ww http.ResponseWriter, req *http // Try and create the follow for the user. txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateFollowTxn( followerPkBytes, followedPkBytes, requestData.IsUnfollow, - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateFollowTxnStateless: Problem creating transaction: %v", err)) return @@ -1821,8 +1816,7 @@ func (fes *APIServer) BuyOrSellCreatorCoin(ww http.ResponseWriter, req *http.Req requestData.MinDeSoExpectedNanos, requestData.MinCreatorCoinExpectedNanos, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("BuyOrSellCreatorCoin: Problem adding inputs and change transaction: %v", err)) return @@ -1831,7 +1825,7 @@ func (fes *APIServer) BuyOrSellCreatorCoin(ww http.ResponseWriter, req *http.Req // Add node source to txn metadata fes.AddNodeSourceToTxnMetadata(txn) - utxoView, err := fes.mempool.GetAugmentedUtxoViewForPublicKey(updaterPublicKeyBytes, txn) + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUtxoViewForPublicKey(updaterPublicKeyBytes, txn) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("BuyOrSellCreatorCoin: Problem computing view for transaction: %v", err)) return @@ -2086,8 +2080,7 @@ func (fes *APIServer) TransferCreatorCoin(ww http.ResponseWriter, req *http.Requ requestData.CreatorCoinToTransferNanos, receiverPublicKeyBytes, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferCreatorCoin: Problem creating transaction: %v", err)) return @@ -2238,8 +2231,7 @@ func (fes *APIServer) SendDiamonds(ww http.ResponseWriter, req *http.Request) { requestData.DiamondLevel, extraData, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDiamonds: Problem creating transaction: %v", err)) return @@ -2258,8 +2250,7 @@ func (fes *APIServer) SendDiamonds(ww http.ResponseWriter, req *http.Request) { diamondPostHash, requestData.DiamondLevel, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDiamonds: Problem creating transaction: %v", err)) return @@ -2481,8 +2472,7 @@ func (fes *APIServer) DAOCoin(ww http.ResponseWriter, req *http.Request) { TransferRestrictionStatus: transferRestrictionStatus, }, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("DAOCoin: Problem adding inputs and change transaction: %v", err)) return @@ -2617,8 +2607,7 @@ func (fes *APIServer) TransferDAOCoin(ww http.ResponseWriter, req *http.Request) DAOCoinToTransferNanos: requestData.DAOCoinToTransferNanos, }, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferDAOCoin: Problem creating transaction: %v", err)) return @@ -3173,7 +3162,6 @@ func (fes *APIServer) createDAOCoinLimitOrderResponse( minFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator(), ) if err != nil { @@ -3420,8 +3408,7 @@ func (fes *APIServer) AuthorizeDerivedKey(ww http.ResponseWriter, req *http.Requ memo, requestData.TransactionSpendingLimitHex, // Standard transaction fields - requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator()) + requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AuthorizeDerivedKey: Problem creating transaction: %v", err)) return diff --git a/routes/user.go b/routes/user.go index a38ec364..62a2e24d 100644 --- a/routes/user.go +++ b/routes/user.go @@ -2535,7 +2535,7 @@ func (fes *APIServer) _getMempoolNotifications(request *GetNotificationsRequest, // // TODO(performance): This could get slow if the mempool gets big. Fix is to organize everything // in the mempool by public key and only look up transactions that are relevant to this public key. - poolTxns := fes.mempool.GetOrderedTransactions() + poolTxns := fes.backendServer.GetMempool().GetOrderedTransactions() mempoolTxnMetadata := []*TransactionMetadataResponse{} for _, poolTx := range poolTxns { @@ -2631,7 +2631,7 @@ func (fes *APIServer) _getNotificationsCount(request *GetNotificationsRequest) ( // A valid mempool object is used to compute the TransactionMetadata for the mempool // and to allow for things like: filtering notifications for a hidden post. - utxoView, err := fes.mempool.GetAugmentedUniversalView() + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { return 0, 0, errors.Errorf("GetNotifications: Problem getting view: %v", err) } @@ -2685,7 +2685,7 @@ func (fes *APIServer) _getNotifications(request *GetNotificationsRequest) ([]*Tr // A valid mempool object is used to compute the TransactionMetadata for the mempool // and to allow for things like: filtering notifications for a hidden post. - utxoView, err := fes.mempool.GetAugmentedUniversalView() + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { return nil, nil, errors.Errorf("GetNotifications: Problem getting view: %v", err) } diff --git a/routes/validators.go b/routes/validators.go index 5ac46603..687a668d 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -125,7 +125,6 @@ func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Requ requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("RegisterAsValidator: problem creating txn: %v", err)) @@ -200,7 +199,6 @@ func (fes *APIServer) UnregisterAsValidator(ww http.ResponseWriter, req *http.Re requestData.MinFeeRateNanosPerKB, fes.backendServer.GetMempool(), additionalOutputs, - fes.backendServer.GetFeeEstimator(), ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("UnregisterAsValidator: problem creating txn: %v", err)) From c70fa5c9a58dfcb0755ed88b5b70797ca7829de2 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:11:57 -0500 Subject: [PATCH 18/99] Fix compilation errors (#521) Co-authored-by: Lazy Nina <> --- routes/exchange_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/routes/exchange_test.go b/routes/exchange_test.go index c14592cd..d5c71937 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/hex" "encoding/json" + chainlib "github.com/btcsuite/btcd/blockchain" "github.com/deso-protocol/backend/config" coreCmd "github.com/deso-protocol/core/cmd" "github.com/deso-protocol/core/lib" @@ -13,6 +14,7 @@ import ( "net/http/httptest" "os" "testing" + "time" "github.com/dgraph-io/badger/v3" @@ -98,7 +100,7 @@ func NewLowDifficultyBlockchainWithParams(t *testing.T, params *lib.DeSoParams) Version: 0, PrevBlockHash: lib.MustDecodeHexBlockHash("0000000000000000000000000000000000000000000000000000000000000000"), TransactionMerkleRoot: lib.MustDecodeHexBlockHash("097158f0d27e6d10565c4dc696c784652c3380e0ff8382d3599a4d18b782e965"), - TstampSecs: uint64(1560735050), + TstampNanoSecs: uint64(1560735050), Height: uint64(0), Nonce: uint64(0), // No ExtraNonce is set in the genesis block @@ -172,7 +174,7 @@ func NewTestMiner(t *testing.T, chain *lib.Blockchain, params *lib.DeSoParams, i return mempool, newMiner } -func newTestAPIServer(t *testing.T, globalStateRemoteNode string) (*APIServer, *APIServer, *lib.DeSoMiner) { +func newTestAPIServer(t *testing.T, globalStateRemoteNode string, txindex bool) (*APIServer, *APIServer, *lib.DeSoMiner) { assert := assert.New(t) require := require.New(t) _, _ = assert, require From 753f14d16208c7a9ef0ad0e972994ae5b6b144a3 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:37:01 -0500 Subject: [PATCH 19/99] Fix validator test (#522) Co-authored-by: Lazy Nina <> --- routes/validators_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/validators_test.go b/routes/validators_test.go index be7188b8..151b2f36 100644 --- a/routes/validators_test.go +++ b/routes/validators_test.go @@ -99,7 +99,7 @@ func TestValidatorRegistration(t *testing.T) { require.Equal(t, validatorResponse.VotingAuthorization, votingAuthorization.ToString()) require.Equal(t, validatorResponse.TotalStakeAmountNanos.Uint64(), uint64(0)) require.Equal(t, validatorResponse.Status, "Active") - require.Equal(t, validatorResponse.LastActiveAtEpochNumber, uint64(0)) + require.Equal(t, validatorResponse.LastActiveAtEpochNumber, uint64(1)) require.Equal(t, validatorResponse.JailedAtEpochNumber, uint64(0)) require.NotNil(t, validatorResponse.ExtraData) require.Equal(t, validatorResponse.ExtraData["Foo"], "Bar") From 43493e3388efbe5f2266d9e95668ef2fee18458f Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:59:26 -0500 Subject: [PATCH 20/99] Add DelegatedStakeCommissionBasisPoints to RegisterAsValidator txn construction endpoint (#523) Co-authored-by: Lazy Nina <> --- routes/validators.go | 68 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/routes/validators.go b/routes/validators.go index 687a668d..c86e0afb 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -13,14 +13,15 @@ import ( ) type RegisterAsValidatorRequest struct { - TransactorPublicKeyBase58Check string `safeForLogging:"true"` - Domains []string `safeForLogging:"true"` - DisableDelegatedStake bool `safeForLogging:"true"` - VotingPublicKey string `safeForLogging:"true"` - VotingAuthorization string `safeForLogging:"true"` - ExtraData map[string]string `safeForLogging:"true"` - MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` - TransactionFees []TransactionFee `safeForLogging:"true"` + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + Domains []string `safeForLogging:"true"` + DisableDelegatedStake bool `safeForLogging:"true"` + DelegatedStakeCommissionBasisPoints uint64 `safeForLogging:"true"` + VotingPublicKey string `safeForLogging:"true"` + VotingAuthorization string `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` } type UnregisterAsValidatorRequest struct { @@ -41,16 +42,17 @@ type ValidatorTxnResponse struct { } type ValidatorResponse struct { - ValidatorPublicKeyBase58Check string - Domains []string - DisableDelegatedStake bool - VotingPublicKey string - VotingAuthorization string - TotalStakeAmountNanos *uint256.Int - Status string - LastActiveAtEpochNumber uint64 - JailedAtEpochNumber uint64 - ExtraData map[string]string + ValidatorPublicKeyBase58Check string + Domains []string + DisableDelegatedStake bool + DelegatedStakeCommissionBasisPoints uint64 + VotingPublicKey string + VotingAuthorization string + TotalStakeAmountNanos *uint256.Int + Status string + LastActiveAtEpochNumber uint64 + JailedAtEpochNumber uint64 + ExtraData map[string]string } func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Request) { @@ -116,10 +118,11 @@ func (fes *APIServer) RegisterAsValidator(ww http.ResponseWriter, req *http.Requ txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateRegisterAsValidatorTxn( transactorPublicKeyBytes, &lib.RegisterAsValidatorMetadata{ - Domains: domains, - DisableDelegatedStake: requestData.DisableDelegatedStake, - VotingPublicKey: votingPublicKey, - VotingAuthorization: votingAuthorization, + Domains: domains, + DisableDelegatedStake: requestData.DisableDelegatedStake, + DelegatedStakeCommissionBasisPoints: requestData.DelegatedStakeCommissionBasisPoints, + VotingPublicKey: votingPublicKey, + VotingAuthorization: votingAuthorization, }, extraData, requestData.MinFeeRateNanosPerKB, @@ -289,15 +292,16 @@ func _convertValidatorEntryToResponse( // Convert ValidatorEntry to ValidatorResponse. return &ValidatorResponse{ - ValidatorPublicKeyBase58Check: validatorPublicKeyBase58Check, - Domains: domains, - DisableDelegatedStake: validatorEntry.DisableDelegatedStake, - VotingPublicKey: validatorEntry.VotingPublicKey.ToString(), - VotingAuthorization: validatorEntry.VotingAuthorization.ToString(), - TotalStakeAmountNanos: validatorEntry.TotalStakeAmountNanos.Clone(), - Status: validatorEntry.Status().ToString(), - LastActiveAtEpochNumber: validatorEntry.LastActiveAtEpochNumber, - JailedAtEpochNumber: validatorEntry.JailedAtEpochNumber, - ExtraData: DecodeExtraDataMap(params, utxoView, validatorEntry.ExtraData), + ValidatorPublicKeyBase58Check: validatorPublicKeyBase58Check, + Domains: domains, + DisableDelegatedStake: validatorEntry.DisableDelegatedStake, + DelegatedStakeCommissionBasisPoints: validatorEntry.DelegatedStakeCommissionBasisPoints, + VotingPublicKey: validatorEntry.VotingPublicKey.ToString(), + VotingAuthorization: validatorEntry.VotingAuthorization.ToString(), + TotalStakeAmountNanos: validatorEntry.TotalStakeAmountNanos.Clone(), + Status: validatorEntry.Status().ToString(), + LastActiveAtEpochNumber: validatorEntry.LastActiveAtEpochNumber, + JailedAtEpochNumber: validatorEntry.JailedAtEpochNumber, + ExtraData: DecodeExtraDataMap(params, utxoView, validatorEntry.ExtraData), } } From c5f420c77bc6a2300b5d20d4afdabfc987c5440f Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:42:45 -0500 Subject: [PATCH 21/99] Add stake, unstake, and unlock stake txn construction endpoints (#524) * Add stake, unstake, and unlock stake txn construction endpoints * Add stake, unstake, and unlock stake txn construction endpoints --------- Co-authored-by: Lazy Nina <> --- .gitignore | 1 + routes/server.go | 26 +++ routes/stake.go | 417 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 444 insertions(+) create mode 100644 routes/stake.go diff --git a/.gitignore b/.gitignore index ca6db9b9..5851a585 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ local_scripts/* backend .idea +mem.log \ No newline at end of file diff --git a/routes/server.go b/routes/server.go index 9d5f0877..8cf6cb16 100644 --- a/routes/server.go +++ b/routes/server.go @@ -316,6 +316,11 @@ const ( // validators.go RoutePathValidators = "/api/v0/validators" + + // stake.go + RoutePathStake = "/api/v0/stake" + RoutePathUnstake = "/api/v0/unstake" + RoutePathUnlockStake = "/api/v0/unlock-stake" ) // APIServer provides the interface between the blockchain and things like the @@ -1304,6 +1309,27 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.GetValidatorByPublicKeyBase58Check, PublicAccess, }, + { + "CreateStakeTxn", + []string{"POST", "OPTIONS"}, + RoutePathStake, + fes.CreateStakeTxn, + PublicAccess, + }, + { + "CreateUnstakeTxn", + []string{"POST", "OPTIONS"}, + RoutePathUnstake, + fes.CreateUnstakeTxn, + PublicAccess, + }, + { + "CreateUnlockStakeTxn", + []string{"POST", "OPTIONS"}, + RoutePathUnlockStake, + fes.CreateUnlockStakeTxn, + PublicAccess, + }, // Jumio Routes { "JumioBegin", diff --git a/routes/stake.go b/routes/stake.go new file mode 100644 index 00000000..8b1d3aa9 --- /dev/null +++ b/routes/stake.go @@ -0,0 +1,417 @@ +package routes + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "github.com/deso-protocol/core/lib" + "github.com/holiman/uint256" + "io" + "net/http" +) + +type StakeRewardMethod string + +const ( + PayToBalance StakeRewardMethod = "PAY_TO_BALANCE" + Restake StakeRewardMethod = "RESTAKE" +) + +type StakeRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ValidatorPublicKeyBase58Check string `safeForLogging:"true"` + RewardMethod StakeRewardMethod `safeForLogging:"true"` + StakeAmountNanos *uint256.Int `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type UnstakeRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ValidatorPublicKeyBase58Check string `safeForLogging:"true"` + UnstakeAmountNanos *uint256.Int `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type UnlockStakeRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ValidatorPublicKeyBase58Check string `safeForLogging:"true"` + StartEpochNumber uint64 `safeForLogging:"true"` + EndEpochNumber uint64 `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type StakeTxnResponse struct { + SpendAmountNanos uint64 + TotalInputNanos uint64 + ChangeAmountNanos uint64 + FeeNanos uint64 + Transaction *lib.MsgDeSoTxn + TransactionHex string + TxnHashHex string +} + +type StakeEntryResponse struct { + StakerPublicKeyBase58Check string + ValidatorPublicKeyBase58Check string + RewardMethod StakeRewardMethod + StakeAmountNanos *uint256.Int + ExtraData map[string]string +} + +type LockedStakeEntryResponse struct { + StakerPublicKeyBase58Check string + ValidatorPublicKeyBase58Check string + LockedAmountNanos *uint256.Int + LockedAtEpochNumber uint64 + ExtraData map[string]string +} + +func (fes *APIServer) CreateStakeTxn(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := StakeRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem parsing request body: %v", err)) + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CreateStakeTxn: TransactorPublicKeyBase58Check is required")) + return + } + transactorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem decoding TransactorPublicKeyBase58Check %s: %v", + requestData.TransactorPublicKeyBase58Check, err)) + return + } + + // Convert ValidatorPublicKeyBase58Check to ValidatorPublicKeyBytes + if requestData.ValidatorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CreateStakeTxn: ValidatorPublicKeyBase58Check is required")) + return + } + validatorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.ValidatorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem decoding ValidatorPublicKeyBase58Check %s: %v", + requestData.ValidatorPublicKeyBase58Check, err)) + return + } + + // Convert reward method string to enum. + var rewardMethod lib.StakingRewardMethod + switch requestData.RewardMethod { + case PayToBalance: + rewardMethod = lib.StakingRewardMethodPayToBalance + break + case Restake: + rewardMethod = lib.StakingRewardMethodRestake + break + default: + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Invalid RewardMethod %s", requestData.RewardMethod)) + return + } + + // Validate stake amount + if !requestData.StakeAmountNanos.IsUint64() { + _AddBadRequestError(ww, fmt.Sprint("CreateStakeTxn: StakeAmountNanos must be a uint64")) + return + } + stakeAmountNanosUint64 := requestData.StakeAmountNanos.Uint64() + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem fetching utxoView: %v", err)) + return + } + balance, err := utxoView.GetDeSoBalanceNanosForPublicKey(transactorPublicKeyBytes) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem fetching balance: %v", err)) + return + } + if stakeAmountNanosUint64 > balance { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Insufficient balance: %d", balance)) + return + } + + // Parse ExtraData. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem parsing ExtraData: %v", err)) + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeStake, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprint("CreateStakeTxn: specified TransactionFees are invalid")) + return + } + + // Create transaction. + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateStakeTxn( + transactorPublicKeyBytes, + &lib.StakeMetadata{ + ValidatorPublicKey: lib.NewPublicKey(validatorPublicKeyBytes), + RewardMethod: rewardMethod, + StakeAmountNanos: requestData.StakeAmountNanos, + }, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem creating transaction: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CreateStakeTxn: Problem serializing transaction: %v", err)) + return + } + + // TODO: do we need to specify the stake amount in the spend amount nanos? + res := StakeTxnResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "CreateStakeTxn: Problem encoding response as JSON") + return + } +} + +func (fes *APIServer) CreateUnstakeTxn(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := UnstakeRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem parsing request body: %v", err)) + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CreateUnstakeTxn: TransactorPublicKeyBase58Check is required")) + return + } + transactorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem decoding TransactorPublicKeyBase58Check %s: %v", + requestData.TransactorPublicKeyBase58Check, err)) + return + } + + // Convert ValidatorPublicKeyBase58Check to ValidatorPublicKeyBytes + if requestData.ValidatorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CreateUnstakeTxn: ValidatorPublicKeyBase58Check is required")) + return + } + validatorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.ValidatorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem decoding ValidatorPublicKeyBase58Check %s: %v", + requestData.ValidatorPublicKeyBase58Check, err)) + return + } + + // Validate unstake amount nanos + if !requestData.UnstakeAmountNanos.IsUint64() { + _AddBadRequestError(ww, fmt.Sprint("CreateUnstakeTxn: UnstakeAmountNanos must be a uint64")) + return + } + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem fetching utxoView: %v", err)) + return + } + // Get staker and validator PKIDs + stakerPKID := utxoView.GetPKIDForPublicKey(transactorPublicKeyBytes) + validatorPKID := utxoView.GetPKIDForPublicKey(validatorPublicKeyBytes) + stakeEntry, err := utxoView.GetStakeEntry(validatorPKID.PKID, stakerPKID.PKID) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem fetching stake entry: %v", err)) + return + } + if requestData.UnstakeAmountNanos.Gt(stakeEntry.StakeAmountNanos) { + _AddBadRequestError(ww, fmt.Sprint("CreateUnstakeTxn: UnstakeAmountNanos cannot be greater than the current stake "+ + "amount")) + return + } + + // Parse ExtraData. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem parsing ExtraData: %v", err)) + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeUnstake, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprint("CreateUnstakeTxn: specified TransactionFees are invalid")) + return + } + + // Create the transaction. + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateUnstakeTxn( + transactorPublicKeyBytes, + &lib.UnstakeMetadata{ + ValidatorPublicKey: lib.NewPublicKey(validatorPublicKeyBytes), + UnstakeAmountNanos: requestData.UnstakeAmountNanos, + }, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem serializing transaction: %v", err)) + return + } + + res := StakeTxnResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "CreateUnstakeTxn: Problem encoding response as JSON") + return + } +} + +func (fes *APIServer) CreateUnlockStakeTxn(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := UnlockStakeRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnlockStakeTxn: Problem parsing request body: %v", err)) + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CreateUnlockStakeTxn: TransactorPublicKeyBase58Check is required")) + return + } + transactorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnlockStakeTxn: Problem decoding TransactorPublicKeyBase58Check %s: %v", + requestData.TransactorPublicKeyBase58Check, err)) + return + } + + // Convert ValidatorPublicKeyBase58Check to ValidatorPublicKeyBytes + if requestData.ValidatorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CreateUnlockStakeTxn: ValidatorPublicKeyBase58Check is required")) + return + } + validatorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.ValidatorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnlockStakeTxn: Problem decoding ValidatorPublicKeyBase58Check %s: %v", + requestData.ValidatorPublicKeyBase58Check, err)) + return + } + + // Validate start and end epoch + if requestData.StartEpochNumber > requestData.EndEpochNumber { + _AddBadRequestError(ww, fmt.Sprint("CreateUnlockStakeTxn: StartEpochNumber cannot be greater than EndEpochNumber")) + return + } + + // Parse ExtraData. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateUnlockStakeTxn: Problem parsing ExtraData: %v", err)) + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeUnlockStake, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprint("CreateUnlockStakeTxn: specified TransactionFees are invalid")) + return + } + + // Create the transaction. + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateUnlockStakeTxn( + transactorPublicKeyBytes, + &lib.UnlockStakeMetadata{ + ValidatorPublicKey: lib.NewPublicKey(validatorPublicKeyBytes), + StartEpochNumber: requestData.StartEpochNumber, + EndEpochNumber: requestData.EndEpochNumber, + }, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CreateUnlockStakeTxn: Problem serializing transaction: %v", err)) + return + } + + res := StakeTxnResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "CreateUnlockStakeTxn: Problem encoding response as JSON") + return + } +} + +// TODO: Implement the following GET endpoints: +// 1. GET stake entry given validator pub key & staker pub key +// 2. GET all stake entries given validator pub key +// 3. GET all stake entries given staker pub key +// 4. GET locked stake entry given validator pub key & staker pub key & locked at epoch number +// 5. GET all locked stake entries given validator pub key & staker pub key & optionally start and end epochs + +// Other functions to implement. +// 1. _convertStakeEntryToResponse() helper function to convert a StakeEntry to a StakeEntryResponse. +// 2. _convertLockedStakeEntryToResponse() helper function to convert a LockedStakeEntry to a LockedStakeEntryResponse. From 6b5ddf3a7336c0fef191e71daa8b210f636b387f Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:45:54 -0500 Subject: [PATCH 22/99] Add GET endpoints for stake and locked stake entries (#525) Co-authored-by: Lazy Nina <> --- routes/constants.go | 1 + routes/server.go | 30 +++++ routes/stake.go | 321 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 331 insertions(+), 21 deletions(-) create mode 100644 routes/constants.go diff --git a/routes/constants.go b/routes/constants.go new file mode 100644 index 00000000..0db51ae5 --- /dev/null +++ b/routes/constants.go @@ -0,0 +1 @@ +package routes diff --git a/routes/server.go b/routes/server.go index 8cf6cb16..1d17ece5 100644 --- a/routes/server.go +++ b/routes/server.go @@ -321,6 +321,7 @@ const ( RoutePathStake = "/api/v0/stake" RoutePathUnstake = "/api/v0/unstake" RoutePathUnlockStake = "/api/v0/unlock-stake" + RoutePathLockedStake = "/api/v0/locked-stake" ) // APIServer provides the interface between the blockchain and things like the @@ -1330,6 +1331,29 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.CreateUnlockStakeTxn, PublicAccess, }, + { + "GetStakeForValidatorAndStaker", + []string{"GET"}, + RoutePathStake + "/" + makePublicKeyParamRegex(validatorPublicKeyBase58CheckKey) + "/" + + makePublicKeyParamRegex(stakerPublicKeyBase58CheckKey), + fes.GetStakeForValidatorAndStaker, + PublicAccess, + }, + { + "GetStakesForValidator", + []string{"GET"}, + RoutePathStake + "/validator/" + makePublicKeyParamRegex(validatorPublicKeyBase58CheckKey), + fes.GetStakesForValidator, + PublicAccess, + }, + { + "GetLockedStakeForValidatorAndStaker", + []string{"GET"}, + RoutePathLockedStake + "/" + makePublicKeyParamRegex(validatorPublicKeyBase58CheckKey) + "/" + + makePublicKeyParamRegex(stakerPublicKeyBase58CheckKey), + fes.GetLockedStakesForValidatorAndStaker, + PublicAccess, + }, // Jumio Routes { "JumioBegin", @@ -2842,3 +2866,9 @@ func (fes *APIServer) makePKIDMapJSONEncodable(restrictedKeysMap map[lib.PKID][] } return outputMap } + +const publicKeyParamRegex = "t?BC[1-9A-HJ-NP-Za-km-z]{51,53}" + +func makePublicKeyParamRegex(paramName string) string { + return fmt.Sprintf("{%s:%s}", paramName, publicKeyParamRegex) +} diff --git a/routes/stake.go b/routes/stake.go index 8b1d3aa9..583280b2 100644 --- a/routes/stake.go +++ b/routes/stake.go @@ -5,18 +5,48 @@ import ( "encoding/json" "fmt" "github.com/deso-protocol/core/lib" + "github.com/gorilla/mux" "github.com/holiman/uint256" "io" + "math" "net/http" + "strconv" ) type StakeRewardMethod string const ( - PayToBalance StakeRewardMethod = "PAY_TO_BALANCE" - Restake StakeRewardMethod = "RESTAKE" + PayToBalance StakeRewardMethod = "PAY_TO_BALANCE" + Restake StakeRewardMethod = "RESTAKE" + UnknownStakeRewardMethod StakeRewardMethod = "UNKNOWN_STAKE_REWARD_METHOD" ) +func (stakeRewardMethod StakeRewardMethod) String() string { + return string(stakeRewardMethod) +} + +func (stakeRewardMethod StakeRewardMethod) ToStakeRewardMethod() lib.StakingRewardMethod { + switch stakeRewardMethod { + case PayToBalance: + return lib.StakingRewardMethodPayToBalance + case Restake: + return lib.StakingRewardMethodRestake + default: + return lib.StakingRewardMethodUnknown + } +} + +func FromLibStakeRewardMethod(stakeRewardMethod lib.StakingRewardMethod) StakeRewardMethod { + switch stakeRewardMethod { + case lib.StakingRewardMethodPayToBalance: + return PayToBalance + case lib.StakingRewardMethodRestake: + return Restake + default: + return UnknownStakeRewardMethod + } +} + type StakeRequest struct { TransactorPublicKeyBase58Check string `safeForLogging:"true"` ValidatorPublicKeyBase58Check string `safeForLogging:"true"` @@ -59,7 +89,7 @@ type StakeTxnResponse struct { type StakeEntryResponse struct { StakerPublicKeyBase58Check string ValidatorPublicKeyBase58Check string - RewardMethod StakeRewardMethod + RewardMethod string StakeAmountNanos *uint256.Int ExtraData map[string]string } @@ -72,6 +102,16 @@ type LockedStakeEntryResponse struct { ExtraData map[string]string } +// Constants for query params +const ( + validatorPublicKeyBase58CheckKey = "validatorPublicKeyBase58Check" + stakerPublicKeyBase58CheckKey = "stakerPublicKeyBase58Check" + lockedAtEpochNumberKey = "lockedAtEpochNumber" + startEpochNumberKey = "startEpochNumber" + endEpochNumberKey = "endEpochNumber" +) + +// Stake constructs a transaction that stakes a given amount of DeSo. func (fes *APIServer) CreateStakeTxn(ww http.ResponseWriter, req *http.Request) { // Decode request body. decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) @@ -106,15 +146,8 @@ func (fes *APIServer) CreateStakeTxn(ww http.ResponseWriter, req *http.Request) } // Convert reward method string to enum. - var rewardMethod lib.StakingRewardMethod - switch requestData.RewardMethod { - case PayToBalance: - rewardMethod = lib.StakingRewardMethodPayToBalance - break - case Restake: - rewardMethod = lib.StakingRewardMethodRestake - break - default: + rewardMethod := requestData.RewardMethod.ToStakeRewardMethod() + if rewardMethod == lib.StakingRewardMethodUnknown { _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Invalid RewardMethod %s", requestData.RewardMethod)) return } @@ -200,6 +233,7 @@ func (fes *APIServer) CreateStakeTxn(ww http.ResponseWriter, req *http.Request) } } +// Unstake constructs a transaction that unstakes a staked entry. func (fes *APIServer) CreateUnstakeTxn(ww http.ResponseWriter, req *http.Request) { // Decode request body. decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) @@ -311,6 +345,7 @@ func (fes *APIServer) CreateUnstakeTxn(ww http.ResponseWriter, req *http.Request } } +// UnlockStake constructs a transaction that unlocks a locked stake entry. func (fes *APIServer) CreateUnlockStakeTxn(ww http.ResponseWriter, req *http.Request) { // Decode request body. decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) @@ -405,13 +440,257 @@ func (fes *APIServer) CreateUnlockStakeTxn(ww http.ResponseWriter, req *http.Req } } -// TODO: Implement the following GET endpoints: -// 1. GET stake entry given validator pub key & staker pub key -// 2. GET all stake entries given validator pub key -// 3. GET all stake entries given staker pub key -// 4. GET locked stake entry given validator pub key & staker pub key & locked at epoch number -// 5. GET all locked stake entries given validator pub key & staker pub key & optionally start and end epochs +// _stakeEntryToResponse converts the core lib.StakeEntry to a StakeEntryResponse +func _stakeEntryToResponse( + stakeEntry *lib.StakeEntry, params *lib.DeSoParams, utxoView *lib.UtxoView) *StakeEntryResponse { + stakerPublicKey := utxoView.GetPublicKeyForPKID(stakeEntry.StakerPKID) + validatorPublicKey := utxoView.GetPublicKeyForPKID(stakeEntry.ValidatorPKID) + return &StakeEntryResponse{ + StakerPublicKeyBase58Check: lib.Base58CheckEncode(stakerPublicKey, false, params), + ValidatorPublicKeyBase58Check: lib.Base58CheckEncode(validatorPublicKey, false, params), + RewardMethod: FromLibStakeRewardMethod(stakeEntry.RewardMethod).String(), + StakeAmountNanos: stakeEntry.StakeAmountNanos, + ExtraData: DecodeExtraDataMap(params, utxoView, stakeEntry.ExtraData), + } +} + +// GetStakeForValidatorAndStaker returns the stake entry for a given validator and staker +func (fes *APIServer) GetStakeForValidatorAndStaker(ww http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + validatorPublicKeyBase58Check, validatorExists := vars[validatorPublicKeyBase58CheckKey] + if !validatorExists { + _AddBadRequestError(ww, fmt.Sprint("GetStakeForValidatorAndStaker: validatorPublicKeyBase58Check is required")) + return + } + stakerPublicKeyBase58Check, stakerExists := vars[stakerPublicKeyBase58CheckKey] + if !stakerExists { + _AddBadRequestError(ww, fmt.Sprint("GetStakeForValidatorAndStaker: stakerPublicKeyBase58Check is required")) + return + } + + // Create UTXO View + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("GetStakeForValidatorAndStaker: Problem fetching utxoView: %v", err)) + return + } + + // Convert validator public key to bytes + validatorPKID, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, validatorPublicKeyBase58Check) + if err != nil || validatorPKID == nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetStakeForValidatorAndStaker: Problem decoding validator public key: %v", err)) + return + } + + // Convert staker public key to bytes + stakerPKID, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, stakerPublicKeyBase58Check) + if err != nil || stakerPKID == nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetStakeForValidatorAndStaker: Problem decoding staker public key: %v", err)) + return + } + + // Get the stake entry + stakeEntry, err := utxoView.GetStakeEntry(validatorPKID, stakerPKID) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("GetStakeForValidatorAndStaker: Problem fetching stake entry: %v", err)) + return + } + if stakeEntry == nil { + _AddNotFoundError(ww, fmt.Sprint("GetStakeForValidatorAndStaker: No stake entry found")) + return + } + + if err = json.NewEncoder(ww).Encode(_stakeEntryToResponse(stakeEntry, fes.Params, utxoView)); err != nil { + _AddInternalServerError(ww, "GetStakeForValidatorAndStaker: Problem encoding response as JSON") + return + } +} -// Other functions to implement. -// 1. _convertStakeEntryToResponse() helper function to convert a StakeEntry to a StakeEntryResponse. -// 2. _convertLockedStakeEntryToResponse() helper function to convert a LockedStakeEntry to a LockedStakeEntryResponse. +// GetStakesForValidator returns all stake entries for a given validator +func (fes *APIServer) GetStakesForValidator(ww http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + validatorPublicKeyBase58Check, validatorExists := vars[validatorPublicKeyBase58CheckKey] + if !validatorExists { + _AddBadRequestError(ww, fmt.Sprint("GetStakesForValidator: validatorPublicKeyBase58Check is required")) + return + } + + // Create UTXO View + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("GetStakesForValidator: Problem fetching utxoView: %v", err)) + return + } + + // Convert validator public key to bytes + validatorPKID, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, validatorPublicKeyBase58Check) + if err != nil || validatorPKID == nil { + _AddBadRequestError(ww, fmt.Sprintf("GetStakesForValidator: Problem decoding validator public key: %v", err)) + return + } + + // Get the stake entries + stakeEntries, err := utxoView.GetStakeEntriesForValidatorPKID(validatorPKID) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("GetStakesForValidator: Problem fetching stake entries: %v", err)) + return + } + + // Convert to stake entry responses + var stakeEntryResponses []*StakeEntryResponse + for _, stakeEntry := range stakeEntries { + stakeEntryResponses = append(stakeEntryResponses, _stakeEntryToResponse(stakeEntry, fes.Params, utxoView)) + } + + // Encode response. + if err = json.NewEncoder(ww).Encode(stakeEntryResponses); err != nil { + _AddInternalServerError(ww, "GetStakesForValidator: Problem encoding response as JSON") + return + } +} + +// GetLockedStakesForValidatorAndStaker returns all locked stake entries for a given validator and staker +// If lockedAtEpochNumber is specified, only the locked stake entry that was locked at that epoch number is returned +// If startEpochNumber and endEpochNumber are specified, all locked stake entries that were locked between those. +// If none are provided, all locked stake entries are returned. +func (fes *APIServer) GetLockedStakesForValidatorAndStaker(ww http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + validatorPublicKeyBase58Check, validatorExists := vars[validatorPublicKeyBase58CheckKey] + if !validatorExists { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: validatorPublicKeyBase58Check is required")) + return + } + stakerPublicKeyBase58Check, stakerExists := vars[stakerPublicKeyBase58CheckKey] + if !stakerExists { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: stakerPublicKeyBase58Check is required")) + return + } + + // Create UTXO View + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem fetching utxoView: %v", err)) + return + } + + // Convert validator public key to bytes + validatorPKID, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, validatorPublicKeyBase58Check) + if err != nil || validatorPKID == nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem decoding validator public key: %v", err)) + return + } + + // Convert staker public key to bytes + stakerPKID, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, stakerPublicKeyBase58Check) + if err != nil || stakerPKID == nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem decoding staker public key: %v", err)) + return + } + + queryParamBytes, err := json.Marshal(req.URL.Query()) + + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem parsing query params: %v", err)) + return + } + + queryParams := make(map[string][]string) + + if err = json.Unmarshal(queryParamBytes, &queryParams); err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem parsing query params: %v", err)) + return + } + + var lockedStakeEntries []*lib.LockedStakeEntry + // First check for lockedAtEpochNumber + if len(queryParams[lockedAtEpochNumberKey]) != 0 { + lockedAtEpochNumber, err := strconv.ParseUint(queryParams[lockedAtEpochNumberKey][0], 10, 64) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem parsing lockedAtEpochNumber: %v", err)) + return + } + lockedStakeEntry, err := utxoView.GetLockedStakeEntry(validatorPKID, stakerPKID, lockedAtEpochNumber) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem fetching locked stake entry: %v", err)) + return + } + if lockedStakeEntry == nil { + _AddNotFoundError(ww, fmt.Sprint("GetLockedStakesForValidatorAndStaker: No locked stake entry found")) + return + } + lockedStakeEntries = append(lockedStakeEntries, lockedStakeEntry) + } else { + startEpochNumber := uint64(0) + endEpochNumber := uint64(math.MaxUint64) + if len(queryParams[startEpochNumberKey]) != 0 { + startEpochNumber, err = strconv.ParseUint(queryParams[startEpochNumberKey][0], 10, 64) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem parsing startEpochNumber: %v", err)) + return + } + } + if len(queryParams[endEpochNumberKey]) != 0 { + endEpochNumber, err = strconv.ParseUint(queryParams[endEpochNumberKey][0], 10, 64) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem parsing endEpochNumber: %v", err)) + return + } + } + if startEpochNumber > endEpochNumber { + _AddBadRequestError(ww, fmt.Sprint( + "GetLockedStakesForValidatorAndStaker: startEpochNumber cannot be greater than endEpochNumber")) + return + } + lockedStakeEntries, err = utxoView.GetLockedStakeEntriesInRange( + validatorPKID, stakerPKID, startEpochNumber, endEpochNumber) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetLockedStakesForValidatorAndStaker: Problem fetching locked stake entries: %v", err)) + return + } + if len(lockedStakeEntries) == 0 { + _AddNotFoundError(ww, fmt.Sprint("GetLockedStakesForValidatorAndStaker: No locked stake entries found")) + return + } + } + + // Convert locked stake entries to responses + var lockedStakeEntryResponses []*LockedStakeEntryResponse + for _, lockedStakeEntry := range lockedStakeEntries { + lockedStakeEntryResponses = append(lockedStakeEntryResponses, _lockedStakeEntryToResponse( + lockedStakeEntry, fes.Params, utxoView)) + } + + // Encode response. + if err = json.NewEncoder(ww).Encode(lockedStakeEntryResponses); err != nil { + _AddInternalServerError(ww, "GetLockedStakesForValidatorAndStaker: Problem encoding response as JSON") + return + } +} + +// _lockedStakeEntryToResponse converts the core lib.LockedStakeEntry to a LockedStakeEntryResponse +func _lockedStakeEntryToResponse( + lockedStakeEntry *lib.LockedStakeEntry, params *lib.DeSoParams, utxoView *lib.UtxoView) *LockedStakeEntryResponse { + stakerPublicKey := utxoView.GetPublicKeyForPKID(lockedStakeEntry.StakerPKID) + validatorPublicKey := utxoView.GetPublicKeyForPKID(lockedStakeEntry.ValidatorPKID) + return &LockedStakeEntryResponse{ + StakerPublicKeyBase58Check: lib.Base58CheckEncode(stakerPublicKey, false, params), + ValidatorPublicKeyBase58Check: lib.Base58CheckEncode(validatorPublicKey, false, params), + LockedAmountNanos: lockedStakeEntry.LockedAmountNanos, + LockedAtEpochNumber: lockedStakeEntry.LockedAtEpochNumber, + ExtraData: DecodeExtraDataMap(params, utxoView, lockedStakeEntry.ExtraData), + } +} From 91b9b8c3486f88fc33e3d2755042ec84089a0b22 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Wed, 24 Jan 2024 11:07:55 -0500 Subject: [PATCH 23/99] Add spending limits backend support for stake, unstake, unlock stake (#529) --- routes/transaction.go | 114 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/routes/transaction.go b/routes/transaction.go index d1eea6ec..a23dda95 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -3234,6 +3234,21 @@ type AccessGroupMemberLimitMapItem struct { OpCount uint64 } +type StakeLimitMapItem struct { + ValidatorPublicKeyBase58Check string + StakeLimit *uint256.Int +} + +type UnstakeLimitMapItem struct { + ValidatorPublicKeyBase58Check string + UnstakeLimit *uint256.Int +} + +type UnlockStakeLimitMapItem struct { + ValidatorPublicKeyBase58Check string + OpCount uint64 +} + // TransactionSpendingLimitResponse is a backend struct used to describe the TransactionSpendingLimit for a Derived key // in a way that can be JSON encoded/decoded. type TransactionSpendingLimitResponse struct { @@ -3265,6 +3280,12 @@ type TransactionSpendingLimitResponse struct { AccessGroupLimitMap []AccessGroupLimitMapItem // AccessGroupMemberLimitMap is a slice of AccessGroupMemberLimitMapItems. AccessGroupMemberLimitMap []AccessGroupMemberLimitMapItem + // StakeLimitMap is a slice of StakeLimitMapItems + StakeLimitMap []StakeLimitMapItem + // UnstakeLimitMap is a slice of UnstakeLimitMapItems + UnstakeLimitMap []UnstakeLimitMapItem + // UnlockStakeLimitMap is a slice of UnlockStakeLimitMapItems + UnlockStakeLimitMap []UnlockStakeLimitMapItem // ===== ENCODER MIGRATION lib.UnlimitedDerivedKeysMigration ===== // IsUnlimited determines whether this derived key is unlimited. An unlimited derived key can perform all transactions @@ -3614,6 +3635,54 @@ func TransactionSpendingLimitToResponse( } } + if len(transactionSpendingLimit.StakeLimitMap) > 0 { + for stakeLimitKey, stakeLimit := range transactionSpendingLimit.StakeLimitMap { + validatorPublicKey := utxoView.GetPublicKeyForPKID(&stakeLimitKey.ValidatorPKID) + validatorPublicKeyBase58Check := lib.Base58CheckEncode( + validatorPublicKey, false, params, + ) + transactionSpendingLimitResponse.StakeLimitMap = append( + transactionSpendingLimitResponse.StakeLimitMap, + StakeLimitMapItem{ + ValidatorPublicKeyBase58Check: validatorPublicKeyBase58Check, + StakeLimit: stakeLimit.Clone(), + }, + ) + } + } + + if len(transactionSpendingLimit.UnstakeLimitMap) > 0 { + for unstakeLimitKey, unstakeLimit := range transactionSpendingLimit.UnstakeLimitMap { + validatorPublicKey := utxoView.GetPublicKeyForPKID(&unstakeLimitKey.ValidatorPKID) + validatorPublicKeyBase58Check := lib.Base58CheckEncode( + validatorPublicKey, false, params, + ) + transactionSpendingLimitResponse.UnstakeLimitMap = append( + transactionSpendingLimitResponse.UnstakeLimitMap, + UnstakeLimitMapItem{ + ValidatorPublicKeyBase58Check: validatorPublicKeyBase58Check, + UnstakeLimit: unstakeLimit.Clone(), + }, + ) + } + } + + if len(transactionSpendingLimit.UnlockStakeLimitMap) > 0 { + for unlockStakeLimitKey, opCount := range transactionSpendingLimit.UnlockStakeLimitMap { + validatorPublicKey := utxoView.GetPublicKeyForPKID(&unlockStakeLimitKey.ValidatorPKID) + validatorPublicKeyBase58Check := lib.Base58CheckEncode( + validatorPublicKey, false, params, + ) + transactionSpendingLimitResponse.UnlockStakeLimitMap = append( + transactionSpendingLimitResponse.UnlockStakeLimitMap, + UnlockStakeLimitMapItem{ + ValidatorPublicKeyBase58Check: validatorPublicKeyBase58Check, + OpCount: opCount, + }, + ) + } + } + return transactionSpendingLimitResponse } @@ -3777,6 +3846,51 @@ func (fes *APIServer) TransactionSpendingLimitFromResponse( } } + if len(transactionSpendingLimitResponse.StakeLimitMap) > 0 { + transactionSpendingLimit.StakeLimitMap = make(map[lib.StakeLimitKey]*uint256.Int) + for _, stakeLimitMapItem := range transactionSpendingLimitResponse.StakeLimitMap { + validatorPublicKey, _, err := lib.Base58CheckDecode(stakeLimitMapItem.ValidatorPublicKeyBase58Check) + if err != nil { + return nil, err + } + validatorPKID := utxoView.GetPKIDForPublicKey(validatorPublicKey) + stakeLimitKey := lib.MakeStakeLimitKey( + validatorPKID.PKID, + ) + transactionSpendingLimit.StakeLimitMap[stakeLimitKey] = stakeLimitMapItem.StakeLimit.Clone() + } + } + + if len(transactionSpendingLimitResponse.UnstakeLimitMap) > 0 { + transactionSpendingLimit.UnstakeLimitMap = make(map[lib.StakeLimitKey]*uint256.Int) + for _, unstakeLimitMapItem := range transactionSpendingLimitResponse.UnstakeLimitMap { + validatorPublicKey, _, err := lib.Base58CheckDecode(unstakeLimitMapItem.ValidatorPublicKeyBase58Check) + if err != nil { + return nil, err + } + validatorPKID := utxoView.GetPKIDForPublicKey(validatorPublicKey) + unstakeLimitKey := lib.MakeStakeLimitKey( + validatorPKID.PKID, + ) + transactionSpendingLimit.UnstakeLimitMap[unstakeLimitKey] = unstakeLimitMapItem.UnstakeLimit.Clone() + } + } + + if len(transactionSpendingLimitResponse.UnlockStakeLimitMap) > 0 { + transactionSpendingLimit.UnlockStakeLimitMap = make(map[lib.StakeLimitKey]uint64) + for _, unlockStakeLimitMapItem := range transactionSpendingLimitResponse.UnlockStakeLimitMap { + validatorPublicKey, _, err := lib.Base58CheckDecode(unlockStakeLimitMapItem.ValidatorPublicKeyBase58Check) + if err != nil { + return nil, err + } + validatorPKID := utxoView.GetPKIDForPublicKey(validatorPublicKey) + unlockStakeLimitKey := lib.MakeStakeLimitKey( + validatorPKID.PKID, + ) + transactionSpendingLimit.UnlockStakeLimitMap[unlockStakeLimitKey] = unlockStakeLimitMapItem.OpCount + } + } + return transactionSpendingLimit, nil } From 0cf96c15c21c83b074a26f10790b37c908fe1ea6 Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:39:04 -0500 Subject: [PATCH 24/99] Update Block Header Timestamps to int64 (#535) --- routes/exchange.go | 6 +++--- routes/exchange_test.go | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/routes/exchange.go b/routes/exchange.go index a75cade4..5f035dbb 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -678,7 +678,7 @@ func APITransactionToResponse( if block != nil && block.Header != nil { ret.BlockInfo = &TransactionBlockInfo{ Height: block.Header.Height, - TimestampSecs: block.Header.GetTstampSecs(), + TimestampSecs: uint64(block.Header.GetTstampSecs()), } } @@ -1272,10 +1272,10 @@ type HeaderResponse struct { TransactionMerkleRootHex string // The unix timestamp (in seconds) specifying when this block was // mined. - TstampSecs uint64 + TstampSecs int64 // The unix timestamp (in nanoseconds) specifying when this block was // mined. - TstampNanoSecs uint64 + TstampNanoSecs int64 // The height of the block this header corresponds to. Height uint64 diff --git a/routes/exchange_test.go b/routes/exchange_test.go index d5c71937..c5f87556 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -4,10 +4,6 @@ import ( "bytes" "encoding/hex" "encoding/json" - chainlib "github.com/btcsuite/btcd/blockchain" - "github.com/deso-protocol/backend/config" - coreCmd "github.com/deso-protocol/core/cmd" - "github.com/deso-protocol/core/lib" "io" "log" "net/http" @@ -16,6 +12,11 @@ import ( "testing" "time" + chainlib "github.com/btcsuite/btcd/blockchain" + "github.com/deso-protocol/backend/config" + coreCmd "github.com/deso-protocol/core/cmd" + "github.com/deso-protocol/core/lib" + "github.com/dgraph-io/badger/v3" "github.com/stretchr/testify/assert" @@ -100,7 +101,7 @@ func NewLowDifficultyBlockchainWithParams(t *testing.T, params *lib.DeSoParams) Version: 0, PrevBlockHash: lib.MustDecodeHexBlockHash("0000000000000000000000000000000000000000000000000000000000000000"), TransactionMerkleRoot: lib.MustDecodeHexBlockHash("097158f0d27e6d10565c4dc696c784652c3380e0ff8382d3599a4d18b782e965"), - TstampNanoSecs: uint64(1560735050), + TstampNanoSecs: int64(1560735050), Height: uint64(0), Nonce: uint64(0), // No ExtraNonce is set in the genesis block From c11ca20fe3c285779aa1c6376c2d300b6b6d029c Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Fri, 2 Feb 2024 11:58:46 -0500 Subject: [PATCH 25/99] Fix Backend To Run With Regtest PoS Node (#536) --- routes/exchange_test.go | 2 +- routes/transaction.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/routes/exchange_test.go b/routes/exchange_test.go index c5f87556..ad159f5f 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -101,7 +101,7 @@ func NewLowDifficultyBlockchainWithParams(t *testing.T, params *lib.DeSoParams) Version: 0, PrevBlockHash: lib.MustDecodeHexBlockHash("0000000000000000000000000000000000000000000000000000000000000000"), TransactionMerkleRoot: lib.MustDecodeHexBlockHash("097158f0d27e6d10565c4dc696c784652c3380e0ff8382d3599a4d18b782e965"), - TstampNanoSecs: int64(1560735050), + TstampNanoSecs: 1560735050, Height: uint64(0), Nonce: uint64(0), // No ExtraNonce is set in the genesis block diff --git a/routes/transaction.go b/routes/transaction.go index a23dda95..070af111 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4101,7 +4101,6 @@ func (fes *APIServer) simulateSubmitTransaction(utxoView *lib.UtxoView, txn *lib return utxoView.ConnectTransaction( txn, txn.Hash(), - 0, bestHeight, 0, false, From 734d12efcfcf2d0fb2cb61f396a31010903a8297 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 2 Feb 2024 15:41:14 -0500 Subject: [PATCH 26/99] Add txn construction and get endpoints for lockups (#526) * Add spending limits backend support for stake, unstake, unlock stake * Add txn construction and get endpoints for lockups * Add additional sanity checks to lockup endpoint. * Add txn construction and get endpoints for lockups * Add additional sanity checks to lockup endpoint. * Remove redundant profile entry response from LockedBalanceEntryResponse. * Add proper timestamp to simulateSubmitTransaction. * Apply suggestions from code review --------- Co-authored-by: Lazy Nina <> Co-authored-by: Jon Pollock --- routes/lockups.go | 733 ++++++++++++++++++++++++++++++++++++++++++ routes/server.go | 50 +++ routes/stake.go | 1 + routes/transaction.go | 42 ++- routes/user.go | 11 +- 5 files changed, 832 insertions(+), 5 deletions(-) create mode 100644 routes/lockups.go diff --git a/routes/lockups.go b/routes/lockups.go new file mode 100644 index 00000000..45d7f08f --- /dev/null +++ b/routes/lockups.go @@ -0,0 +1,733 @@ +package routes + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "github.com/deso-protocol/core/collections" + "github.com/deso-protocol/core/lib" + "github.com/gorilla/mux" + "github.com/holiman/uint256" + "io" + "net/http" + "reflect" + "time" +) + +type CumulativeLockedBalanceEntryResponse struct { + HODLerPublicKeyBase58Check string + ProfilePublicKeyBase58Check string + TotalLockedBaseUnits uint256.Int + UnlockableBaseUnits uint256.Int + UnvestedLockedBalanceEntries []*LockedBalanceEntryResponse + VestedLockedBalanceEntries []*LockedBalanceEntryResponse + ProfileEntryResponse *ProfileEntryResponse +} + +type LockedBalanceEntryResponse struct { + HODLerPublicKeyBase58Check string + ProfilePublicKeyBase58Check string + UnlockTimestampNanoSecs int64 + VestingEndTimestampNanoSecs int64 + BalanceBaseUnits uint256.Int +} + +func (fes *APIServer) _lockedBalanceEntryToResponse( + lockedBalanceEntry *lib.LockedBalanceEntry, utxoView *lib.UtxoView, params *lib.DeSoParams, +) *LockedBalanceEntryResponse { + hodlerPublicKey := utxoView.GetPublicKeyForPKID(lockedBalanceEntry.HODLerPKID) + profilePublicKey := utxoView.GetPublicKeyForPKID(lockedBalanceEntry.ProfilePKID) + return &LockedBalanceEntryResponse{ + HODLerPublicKeyBase58Check: lib.PkToString(hodlerPublicKey, params), + ProfilePublicKeyBase58Check: lib.PkToString(profilePublicKey, params), + UnlockTimestampNanoSecs: lockedBalanceEntry.UnlockTimestampNanoSecs, + VestingEndTimestampNanoSecs: lockedBalanceEntry.VestingEndTimestampNanoSecs, + BalanceBaseUnits: lockedBalanceEntry.BalanceBaseUnits, + } +} + +type LockupYieldCurvePointResponse struct { + ProfilePublicKeyBase58Check string + LockupDurationNanoSecs int64 + LockupYieldAPYBasisPoints uint64 + ProfileEntryResponse *ProfileEntryResponse +} + +func (fes *APIServer) _lockupYieldCurvePointToResponse( + lockupYieldCurvePoint *lib.LockupYieldCurvePoint, utxoView *lib.UtxoView, params *lib.DeSoParams, +) *LockupYieldCurvePointResponse { + profilePublicKey := utxoView.GetPublicKeyForPKID(lockupYieldCurvePoint.ProfilePKID) + profileEntry := utxoView.GetProfileEntryForPKID(lockupYieldCurvePoint.ProfilePKID) + profileEntryResponse := fes._profileEntryToResponse(profileEntry, utxoView) + return &LockupYieldCurvePointResponse{ + ProfilePublicKeyBase58Check: lib.PkToString(profilePublicKey, params), + LockupDurationNanoSecs: lockupYieldCurvePoint.LockupDurationNanoSecs, + LockupYieldAPYBasisPoints: lockupYieldCurvePoint.LockupYieldAPYBasisPoints, + ProfileEntryResponse: profileEntryResponse, + } +} + +type CoinLockupRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ProfilePublicKeyBase58Check string `safeForLogging:"true"` + RecipientPublicKeyBase58Check string `safeForLogging:"true"` + UnlockTimestampNanoSecs int64 `safeForLogging:"true"` + VestingEndTimestampNanoSecs int64 `safeForLogging:"true"` + LockupAmountBaseUnits *uint256.Int `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type UpdateCoinLockupParamsRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + LockupYieldDurationNanoSecs int64 `safeForLogging:"true"` + LockupYieldAPYBasisPoints uint64 `safeForLogging:"true"` + RemoveYieldCurvePoint bool `safeForLogging:"true"` + NewLockupTransferRestrictions bool `safeForLogging:"true"` + LockupTransferRestrictionStatus TransferRestrictionStatusString `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type CoinLockupTransferRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ProfilePublicKeyBase58Check string `safeForLogging:"true"` + RecipientPublicKeyBase58Check string `safeForLogging:"true"` + UnlockTimestampNanoSecs int64 `safeForLogging:"true"` + LockedCoinsToTransferBaseUnits *uint256.Int `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type CoinUnlockRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ProfilePublicKeyBase58Check string `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + +type CoinLockResponse struct { + SpendAmountNanos uint64 + TotalInputNanos uint64 + ChangeAmountNanos uint64 + FeeNanos uint64 + Transaction *lib.MsgDeSoTxn + TransactionHex string + TxnHashHex string +} + +func (fes *APIServer) CoinLockup(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := CoinLockupRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Problem parsing request body: %v", err)) + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CoinLockup: TransactorPublicKeyBase58Check is required")) + return + } + transactorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Problem decoding TransactorPublicKeyBase58Check %s: %v", + requestData.TransactorPublicKeyBase58Check, err)) + return + } + + // Convert ProfilePublicKeyBase58Check to ProfilePublicKeyBytes + if requestData.ProfilePublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CoinLockup: ProfilePublicKeyBase58Check is required")) + return + } + profilePublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.ProfilePublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Problem decoding ProfilePublicKeyBase58Check %s: %v", + requestData.ProfilePublicKeyBase58Check, err)) + return + + } + + // Convert RecipientPublicKeyBase58Check to RecipientPublicKeyBytes if it exists + var recipientPublicKeyBytes []byte + if requestData.RecipientPublicKeyBase58Check != "" { + recipientPublicKeyBytes, _, err = lib.Base58CheckDecode(requestData.RecipientPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Problem decoding RecipientPublicKeyBase58Check %s: %v", + requestData.RecipientPublicKeyBase58Check, err)) + return + } + } + + // Sanity check that the lockup appears to occur in the future. + currentTimestampNanoSecs := time.Now().UnixNano() + if requestData.UnlockTimestampNanoSecs < currentTimestampNanoSecs { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: The unlock timestamp cannot be in the past "+ + "(unlock timestamp: %d, current timestamp: %d)\n", + requestData.UnlockTimestampNanoSecs, currentTimestampNanoSecs)) + return + } + + // Sanity check that the vested lockup does not go into the past. + if requestData.UnlockTimestampNanoSecs > requestData.VestingEndTimestampNanoSecs { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Vested lockups cannot vest into the past "+ + "(unlock timestamp: %d, vesting end timestamp: %d\n", + requestData.UnlockTimestampNanoSecs, requestData.VestingEndTimestampNanoSecs)) + return + } + + // Sanity check that the lockup request amount is non-zero. + if requestData.LockupAmountBaseUnits.IsZero() { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Cannot lockup an amount of zero\n")) + return + } + + // Encode the extra data. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Problem encoding ExtraData: %v", err)) + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeCoinLockup, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: specified TransactionFees are invalid: %v", err)) + return + } + + // Create transaction + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateCoinLockupTxn( + transactorPublicKeyBytes, + profilePublicKeyBytes, + recipientPublicKeyBytes, + requestData.UnlockTimestampNanoSecs, + requestData.VestingEndTimestampNanoSecs, + requestData.LockupAmountBaseUnits, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockup: Problem creating txn: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CoinLockup: Problem serializing txn: %v", err)) + return + } + + res := CoinLockResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CoinLockup: Problem encoding response as JSON: %v", err)) + return + } +} + +func (fes *APIServer) UpdateCoinLockupParams(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := UpdateCoinLockupParamsRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("UpdateCoinLockupParams: Problem parsing request body: %v", err)) + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("UpdateCoinLockupParams: TransactorPublicKeyBase58Check is required")) + return + } + transactorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("UpdateCoinLockupParams: Problem decoding TransactorPublicKeyBase58Check %s: %v", + requestData.TransactorPublicKeyBase58Check, err)) + return + } + + var transferRestrictionStatus lib.TransferRestrictionStatus + if requestData.NewLockupTransferRestrictions { + switch requestData.LockupTransferRestrictionStatus { + case TransferRestrictionStatusStringUnrestricted: + transferRestrictionStatus = lib.TransferRestrictionStatusUnrestricted + case TransferRestrictionStatusStringProfileOwnerOnly: + transferRestrictionStatus = lib.TransferRestrictionStatusProfileOwnerOnly + case TransferRestrictionStatusStringDAOMembersOnly: + transferRestrictionStatus = lib.TransferRestrictionStatusDAOMembersOnly + case TransferRestrictionStatusStringPermanentlyUnrestricted: + transferRestrictionStatus = lib.TransferRestrictionStatusPermanentlyUnrestricted + default: + _AddBadRequestError(ww, fmt.Sprintf( + "UpdateCoinLockupParams: TransferRestrictionStatus \"%v\" not supported", + requestData.LockupTransferRestrictionStatus)) + return + } + } + + // Parse extra data. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("UpdateCoinLockupParams: Problem encoding ExtraData: %v", err)) + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeUpdateCoinLockupParams, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("UpdateCoinLockupParams: specified TransactionFees are invalid: %v", err)) + return + } + + // Create transaction + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateUpdateCoinLockupParamsTxn( + transactorPublicKeyBytes, + requestData.LockupYieldDurationNanoSecs, + requestData.LockupYieldAPYBasisPoints, + requestData.RemoveYieldCurvePoint, + requestData.NewLockupTransferRestrictions, + transferRestrictionStatus, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("UpdateCoinLockupParams: Problem creating txn: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("UpdateCoinLockupParams: Problem serializing txn: %v", err)) + return + } + + res := CoinLockResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, fmt.Sprintf("UpdateCoinLockupParams: Problem encoding response as JSON: %v", err)) + return + } +} + +func (fes *APIServer) CoinLockupTransfer(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := CoinLockupTransferRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockupTransfer: Problem parsing request body: %v", err)) + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CoinLockupTransfer: TransactorPublicKeyBase58Check is required")) + return + } + transactorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "CoinLockupTransfer: Problem decoding TransactorPublicKeyBase58Check %s: %v", + requestData.TransactorPublicKeyBase58Check, err)) + return + } + + // Convert ProfilePublicKeyBase58Check to ProfilePublicKeyBytes + if requestData.ProfilePublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CoinLockupTransfer: ProfilePublicKeyBase58Check is required")) + return + } + profilePublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.ProfilePublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockupTransfer: Problem decoding ProfilePublicKeyBase58Check %s: %v", + requestData.ProfilePublicKeyBase58Check, err)) + return + } + + // Convert RecipientPublicKeyBase58Check to RecipientPublicKeyBytes + if requestData.RecipientPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CoinLockupTransfer: RecipientPublicKeyBase58Check is required")) + return + } + recipientPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.RecipientPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockupTransfer: Problem decoding RecipientPublicKeyBase58Check %s: %v", + requestData.RecipientPublicKeyBase58Check, err)) + return + } + + // Check to ensure the recipient is different than the sender. + if reflect.DeepEqual(recipientPublicKeyBytes, transactorPublicKeyBytes) { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockupTransfer: Sender cannot be receiver of a transfer")) + return + } + + // Parse extra data. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockupTransfer: Problem encoding ExtraData: %v", err)) + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeCoinLockupTransfer, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockupTransfer: specified TransactionFees are invalid: %v", err)) + return + } + + // Create transaction + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateCoinLockupTransferTxn( + transactorPublicKeyBytes, + recipientPublicKeyBytes, + profilePublicKeyBytes, + requestData.UnlockTimestampNanoSecs, + requestData.LockedCoinsToTransferBaseUnits, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinLockupTransfer: Problem creating txn: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CoinLockupTransfer: Problem serializing txn: %v", err)) + return + } + + res := CoinLockResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CoinLockupTransfer: Problem encoding response as JSON: %v", err)) + return + } +} + +func (fes *APIServer) CoinUnlock(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := CoinUnlockRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinUnlock: Problem parsing request body: %v", err)) + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CoinUnlock: TransactorPublicKeyBase58Check is required")) + return + } + transactorPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinUnlock: Problem decoding TransactorPublicKeyBase58Check %s: %v", + requestData.TransactorPublicKeyBase58Check, err)) + return + } + + // Convert ProfilePublicKeyBase58Check to ProfilePublicKeyBytes + if requestData.ProfilePublicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprint("CoinUnlock: ProfilePublicKeyBase58Check is required")) + return + } + profilePublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.ProfilePublicKeyBase58Check) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinUnlock: Problem decoding ProfilePublicKeyBase58Check %s: %v", + requestData.ProfilePublicKeyBase58Check, err)) + return + } + + // Parse extra data. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinUnlock: Problem encoding ExtraData: %v", err)) + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeCoinUnlock, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinUnlock: specified TransactionFees are invalid: %v", err)) + return + } + + // Create transaction + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateCoinUnlockTxn( + transactorPublicKeyBytes, + profilePublicKeyBytes, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CoinUnlock: Problem creating txn: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CoinUnlock: Problem serializing txn: %v", err)) + return + } + + res := CoinLockResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, fmt.Sprintf("CoinUnlock: Problem encoding response as JSON: %v", err)) + return + } +} + +// GET lockup yield curve points for a profile by public key +func (fes *APIServer) LockedYieldCurvePoints(ww http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + publicKeyBase58Check := vars[publicKeyBase58CheckKey] + + if publicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprintf("LockedYieldCurvePoints: PublicKeyBase58Check is required")) + return + } + + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("LockedYieldCurvePoints: Problem getting utxoView: %v", err)) + return + } + + // Decode public key + pkid, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, publicKeyBase58Check) + if err != nil || pkid == nil { + _AddBadRequestError(ww, fmt.Sprintf("LockedYieldCurvePoints: Problem decoding public key: %v", err)) + return + } + + // Get locked yield curve points + yieldCurvePointsMap, err := utxoView.GetAllYieldCurvePoints(pkid) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("LockedYieldCurvePoints: Problem getting yield curve points: %v", err)) + return + } + + var allYieldCurvePoints []*LockupYieldCurvePointResponse + for _, yieldCurvePoint := range yieldCurvePointsMap { + if yieldCurvePoint.IsDeleted() { + continue + } + allYieldCurvePoints = append(allYieldCurvePoints, + fes._lockupYieldCurvePointToResponse(yieldCurvePoint, utxoView, fes.Params)) + } + + sortedYieldCurvePoints := collections.SortStable(allYieldCurvePoints, + func(ii *LockupYieldCurvePointResponse, jj *LockupYieldCurvePointResponse) bool { + return ii.LockupDurationNanoSecs < jj.LockupDurationNanoSecs + }) + + if err = json.NewEncoder(ww).Encode(sortedYieldCurvePoints); err != nil { + _AddInternalServerError(ww, fmt.Sprintf("LockedYieldCurvePoints: Problem encoding response as JSON: %v", err)) + return + } +} + +// GET all locked balance entries held by a HODLer public key +func (fes *APIServer) LockedBalanceEntries(ww http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + publicKeyBase58Check := vars[publicKeyBase58CheckKey] + + if publicKeyBase58Check == "" { + _AddBadRequestError(ww, fmt.Sprintf("LockedBalanceEntriesHeldByPublicKey: PublicKeyBase58Check is required")) + return + } + + // Create an augmented UTXO view to include uncomitted transactions. + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("LockedBalanceEntriesHeldByPublicKey: Problem getting utxoView: %v", err)) + return + } + + // Decode public key + pkid, err := fes.getPKIDFromPublicKeyBase58Check(utxoView, publicKeyBase58Check) + if err != nil || pkid == nil { + _AddBadRequestError(ww, fmt.Sprintf("LockedBalanceEntriesHeldByPublicKey: Problem decoding public key: %v", err)) + return + } + + // Get all locked balance entries for a user. + lockedBalanceEntries, err := utxoView.GetAllLockedBalanceEntriesForHodlerPKID(pkid) + if err != nil { + _AddBadRequestError(ww, + fmt.Sprintf("LockedBalanceEntries: Problem getting locked balance entries: %v", err)) + return + } + + // Split the locked balance entries based on the creator. + creatorPKIDToCumulativeLockedBalanceEntryResponse := make(map[lib.PKID]*CumulativeLockedBalanceEntryResponse) + currentTimestampNanoSecs := time.Now().UnixNano() + for _, lockedBalanceEntry := range lockedBalanceEntries { + // Check if we need to initialize the cumulative response. + if _, exists := creatorPKIDToCumulativeLockedBalanceEntryResponse[*lockedBalanceEntry.ProfilePKID]; !exists { + hodlerPublicKey := utxoView.GetPublicKeyForPKID(lockedBalanceEntry.HODLerPKID) + profilePublicKey := utxoView.GetPublicKeyForPKID(lockedBalanceEntry.ProfilePKID) + profileEntry := utxoView.GetProfileEntryForPKID(lockedBalanceEntry.ProfilePKID) + profileEntryResponse := fes._profileEntryToResponse(profileEntry, utxoView) + + creatorPKIDToCumulativeLockedBalanceEntryResponse[*lockedBalanceEntry.ProfilePKID] = + &CumulativeLockedBalanceEntryResponse{ + HODLerPublicKeyBase58Check: lib.PkToString(hodlerPublicKey, fes.Params), + ProfilePublicKeyBase58Check: lib.PkToString(profilePublicKey, fes.Params), + TotalLockedBaseUnits: uint256.Int{}, + UnlockableBaseUnits: uint256.Int{}, + UnvestedLockedBalanceEntries: []*LockedBalanceEntryResponse{}, + VestedLockedBalanceEntries: []*LockedBalanceEntryResponse{}, + ProfileEntryResponse: profileEntryResponse, + } + } + + // Get the existing cumulative response. + cumulativeResponse := creatorPKIDToCumulativeLockedBalanceEntryResponse[*lockedBalanceEntry.ProfilePKID] + + // Update the total locked base units. + // NOTE: It's possible to create multiple locked balance entries that are impossible to unlock due to overflow. + // As such, if the addition triggers an overflow we will just ignore adding more and use the max Uint256. + var newTotalLockedBaseUnits *uint256.Int + if uint256.NewInt().Sub( + lib.MaxUint256, + &cumulativeResponse.TotalLockedBaseUnits).Lt(&lockedBalanceEntry.BalanceBaseUnits) { + newTotalLockedBaseUnits = lib.MaxUint256 + } else { + newTotalLockedBaseUnits = uint256.NewInt().Add( + &cumulativeResponse.TotalLockedBaseUnits, + &lockedBalanceEntry.BalanceBaseUnits) + } + + // Compute how much (if any) is unlockable in the give entry. + unlockableBaseUnitsFromEntry := uint256.NewInt() + newTotalUnlockableBaseUnits := uint256.NewInt() + if lockedBalanceEntry.UnlockTimestampNanoSecs < currentTimestampNanoSecs { + // Check if the locked balance entry is unvested or vested. + if lockedBalanceEntry.UnlockTimestampNanoSecs == lockedBalanceEntry.VestingEndTimestampNanoSecs { + unlockableBaseUnitsFromEntry = &lockedBalanceEntry.BalanceBaseUnits + } else { + unlockableBaseUnitsFromEntry, err = + lib.CalculateVestedEarnings(lockedBalanceEntry, currentTimestampNanoSecs) + if err != nil { + _AddBadRequestError(ww, + fmt.Sprintf("LockedBalanceEntries: Problem computing vested earnings: %v", err)) + return + } + } + } + if uint256.NewInt().Sub( + lib.MaxUint256, + &cumulativeResponse.UnlockableBaseUnits).Lt(unlockableBaseUnitsFromEntry) { + newTotalUnlockableBaseUnits = lib.MaxUint256 + } else { + newTotalUnlockableBaseUnits = uint256.NewInt().Add( + &cumulativeResponse.UnlockableBaseUnits, + unlockableBaseUnitsFromEntry) + } + + // Update the cumulative response. + cumulativeResponse.TotalLockedBaseUnits = *newTotalLockedBaseUnits + cumulativeResponse.UnlockableBaseUnits = *newTotalUnlockableBaseUnits + if lockedBalanceEntry.UnlockTimestampNanoSecs == lockedBalanceEntry.VestingEndTimestampNanoSecs { + cumulativeResponse.UnvestedLockedBalanceEntries = append( + cumulativeResponse.UnvestedLockedBalanceEntries, + fes._lockedBalanceEntryToResponse(lockedBalanceEntry, utxoView, fes.Params)) + } else { + cumulativeResponse.VestedLockedBalanceEntries = append( + cumulativeResponse.VestedLockedBalanceEntries, + fes._lockedBalanceEntryToResponse(lockedBalanceEntry, utxoView, fes.Params)) + } + } + + // Create a list of the cumulative locked balance entries and sort based on amount locked. + var cumulativeLockedBalanceEntryResponses []*CumulativeLockedBalanceEntryResponse + for _, cumulativeResponse := range creatorPKIDToCumulativeLockedBalanceEntryResponse { + cumulativeLockedBalanceEntryResponses = append( + cumulativeLockedBalanceEntryResponses, cumulativeResponse) + } + + // Sort the response based on the amount locked. + sortedCumulativeResponses := collections.SortStable(cumulativeLockedBalanceEntryResponses, + func(ii *CumulativeLockedBalanceEntryResponse, jj *CumulativeLockedBalanceEntryResponse) bool { + return ii.TotalLockedBaseUnits.Lt(&jj.TotalLockedBaseUnits) + }) + + // Encode and return the responses. + if err = json.NewEncoder(ww).Encode(sortedCumulativeResponses); err != nil { + _AddInternalServerError(ww, + fmt.Sprintf("LockedBalanceEntries: Problem encoding response as JSON: %v", err)) + return + } +} diff --git a/routes/server.go b/routes/server.go index 1d17ece5..77eddf69 100644 --- a/routes/server.go +++ b/routes/server.go @@ -322,6 +322,14 @@ const ( RoutePathUnstake = "/api/v0/unstake" RoutePathUnlockStake = "/api/v0/unlock-stake" RoutePathLockedStake = "/api/v0/locked-stake" + + // lockups.go + RoutePathCoinLockup = "/api/v0/coin-lockup" + RoutePathUpdateCoinLockupParams = "/api/v0/update-coin-lockup-params" + RoutePathCoinLockupTransfer = "/api/v0/coin-lockup-transfer" + RoutePathCoinUnlock = "/api/v0/coin-unlock" + RoutePathLockupYieldCurvePoints = "/api/v0/lockup-yield-curve-points" + RoutePathLockedBalanceEntries = "/api/v0/locked-balance-entries" ) // APIServer provides the interface between the blockchain and things like the @@ -1354,6 +1362,48 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.GetLockedStakesForValidatorAndStaker, PublicAccess, }, + { + "CoinLockup", + []string{"POST", "OPTIONS"}, + RoutePathCoinLockup, + fes.CoinLockup, + PublicAccess, + }, + { + "UpdateCoinLockupParams", + []string{"POST", "OPTIONS"}, + RoutePathUpdateCoinLockupParams, + fes.UpdateCoinLockupParams, + PublicAccess, + }, + { + "CoinLockupTransfer", + []string{"POST", "OPTIONS"}, + RoutePathCoinLockupTransfer, + fes.CoinLockupTransfer, + PublicAccess, + }, + { + "CoinUnlock", + []string{"POST", "OPTIONS"}, + RoutePathCoinUnlock, + fes.CoinUnlock, + PublicAccess, + }, + { + "LockedYieldCurvePoints", + []string{"GET"}, + RoutePathLockupYieldCurvePoints + "/" + makePublicKeyParamRegex(publicKeyBase58CheckKey), + fes.LockedYieldCurvePoints, + PublicAccess, + }, + { + "LockedBalanceEntries", + []string{"GET"}, + RoutePathLockedBalanceEntries + "/" + makePublicKeyParamRegex(publicKeyBase58CheckKey), + fes.LockedBalanceEntries, + PublicAccess, + }, // Jumio Routes { "JumioBegin", diff --git a/routes/stake.go b/routes/stake.go index 583280b2..891d9c74 100644 --- a/routes/stake.go +++ b/routes/stake.go @@ -109,6 +109,7 @@ const ( lockedAtEpochNumberKey = "lockedAtEpochNumber" startEpochNumberKey = "startEpochNumber" endEpochNumberKey = "endEpochNumber" + publicKeyBase58CheckKey = "publicKeyBase58Check" ) // Stake constructs a transaction that stakes a given amount of DeSo. diff --git a/routes/transaction.go b/routes/transaction.go index 070af111..797401ac 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -3249,6 +3249,13 @@ type UnlockStakeLimitMapItem struct { OpCount uint64 } +type LockupLimitMapItem struct { + ProfilePublicKeyBase58Check string + ScopeType lib.LockupLimitScopeTypeString + Operation lib.LockupLimitOperationString + OpCount uint64 +} + // TransactionSpendingLimitResponse is a backend struct used to describe the TransactionSpendingLimit for a Derived key // in a way that can be JSON encoded/decoded. type TransactionSpendingLimitResponse struct { @@ -3286,6 +3293,8 @@ type TransactionSpendingLimitResponse struct { UnstakeLimitMap []UnstakeLimitMapItem // UnlockStakeLimitMap is a slice of UnlockStakeLimitMapItems UnlockStakeLimitMap []UnlockStakeLimitMapItem + // LockupLimitMap is a slice of LockupLimitMapItems + LockupLimitMap []LockupLimitMapItem // ===== ENCODER MIGRATION lib.UnlimitedDerivedKeysMigration ===== // IsUnlimited determines whether this derived key is unlimited. An unlimited derived key can perform all transactions @@ -3683,6 +3692,21 @@ func TransactionSpendingLimitToResponse( } } + if len(transactionSpendingLimit.LockupLimitMap) > 0 { + for lockupLimitKey, opCount := range transactionSpendingLimit.LockupLimitMap { + publicKeyBytes := utxoView.GetPublicKeyForPKID(&lockupLimitKey.ProfilePKID) + publicKeyBase58Check := lib.Base58CheckEncode(publicKeyBytes, false, params) + transactionSpendingLimitResponse.LockupLimitMap = append( + transactionSpendingLimitResponse.LockupLimitMap, + LockupLimitMapItem{ + ProfilePublicKeyBase58Check: publicKeyBase58Check, + ScopeType: lockupLimitKey.ScopeType.ToScopeString(), + Operation: lockupLimitKey.Operation.ToOperationString(), + OpCount: opCount, + }) + } + } + return transactionSpendingLimitResponse } @@ -3890,6 +3914,21 @@ func (fes *APIServer) TransactionSpendingLimitFromResponse( transactionSpendingLimit.UnlockStakeLimitMap[unlockStakeLimitKey] = unlockStakeLimitMapItem.OpCount } } + if len(transactionSpendingLimitResponse.LockupLimitMap) > 0 { + transactionSpendingLimit.LockupLimitMap = make(map[lib.LockupLimitKey]uint64) + for _, lockupLimitMapItem := range transactionSpendingLimitResponse.LockupLimitMap { + profilePublicKey, _, err := lib.Base58CheckDecode(lockupLimitMapItem.ProfilePublicKeyBase58Check) + if err != nil { + return nil, err + } + pkidEntry := utxoView.GetPKIDForPublicKey(profilePublicKey) + transactionSpendingLimit.LockupLimitMap[lib.MakeLockupLimitKey( + *pkidEntry.PKID, + lockupLimitMapItem.ScopeType.ToScopeType(), + lockupLimitMapItem.Operation.ToOperationType(), + )] = lockupLimitMapItem.OpCount + } + } return transactionSpendingLimit, nil } @@ -4098,11 +4137,12 @@ func (fes *APIServer) GetTransactionSpending(ww http.ResponseWriter, req *http.R func (fes *APIServer) simulateSubmitTransaction(utxoView *lib.UtxoView, txn *lib.MsgDeSoTxn) (_utxoOperations []*lib.UtxoOperation, _totalInput uint64, _totalOutput uint64, _fees uint64, _err error) { bestHeight := fes.blockchain.BlockTip().Height + 1 + bytes, _ := txn.ToBytes(false) return utxoView.ConnectTransaction( txn, txn.Hash(), bestHeight, - 0, + time.Now().UnixNano(), false, false, ) diff --git a/routes/user.go b/routes/user.go index 62a2e24d..410a94d2 100644 --- a/routes/user.go +++ b/routes/user.go @@ -641,10 +641,11 @@ type CoinEntryResponse struct { } type DAOCoinEntryResponse struct { - NumberOfHolders uint64 - CoinsInCirculationNanos uint256.Int - MintingDisabled bool - TransferRestrictionStatus TransferRestrictionStatusString + NumberOfHolders uint64 + CoinsInCirculationNanos uint256.Int + MintingDisabled bool + TransferRestrictionStatus TransferRestrictionStatusString + LockupTransferRestrictionStatus TransferRestrictionStatusString } // GetProfiles ... @@ -1060,6 +1061,8 @@ func (fes *APIServer) _profileEntryToResponse(profileEntry *lib.ProfileEntry, ut MintingDisabled: profileEntry.DAOCoinEntry.MintingDisabled, TransferRestrictionStatus: getTransferRestrictionStatusStringFromTransferRestrictionStatus( profileEntry.DAOCoinEntry.TransferRestrictionStatus), + LockupTransferRestrictionStatus: getTransferRestrictionStatusStringFromTransferRestrictionStatus( + profileEntry.DAOCoinEntry.LockupTransferRestrictionStatus), }, CoinPriceDeSoNanos: coinPriceDeSoNanos, CoinPriceBitCloutNanos: coinPriceDeSoNanos, From 7151d337fa506610aa8d7295f340c4c4f0fc4d19 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 2 Feb 2024 15:42:32 -0500 Subject: [PATCH 27/99] Add Unjail Validator endpoint (#532) --- routes/server.go | 7 ++++ routes/validators.go | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/routes/server.go b/routes/server.go index 77eddf69..e5531599 100644 --- a/routes/server.go +++ b/routes/server.go @@ -1311,6 +1311,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.UnregisterAsValidator, PublicAccess, }, + { + "UnjailValidator", + []string{"POST", "OPTIONS"}, + RoutePathValidators + "/unjail", + fes.UnjailValidator, + PublicAccess, + }, { "GetValidatorByPublicKeyBase58Check", []string{"GET"}, diff --git a/routes/validators.go b/routes/validators.go index c86e0afb..8b447ebf 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -31,6 +31,13 @@ type UnregisterAsValidatorRequest struct { TransactionFees []TransactionFee `safeForLogging:"true"` } +type UnjailValidatorRequest struct { + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + ExtraData map[string]string `safeForLogging:"true"` + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` + TransactionFees []TransactionFee `safeForLogging:"true"` +} + type ValidatorTxnResponse struct { SpendAmountNanos uint64 TotalInputNanos uint64 @@ -229,6 +236,80 @@ func (fes *APIServer) UnregisterAsValidator(ww http.ResponseWriter, req *http.Re } } +func (fes *APIServer) UnjailValidator(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := UnjailValidatorRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, "UnjailValidator: problem parsing request body") + return + } + + // Convert TransactorPublicKeyBase58Check to TransactorPublicKeyBytes. + if requestData.TransactorPublicKeyBase58Check == "" { + _AddBadRequestError(ww, "UnjailValidator: must provide a TransactorPublicKeyBase58Check") + return + } + transactorPublicKeyBytes, err := GetPubKeyBytesFromBase58Check(requestData.TransactorPublicKeyBase58Check) + if err != nil { + _AddInternalServerError(ww, "UnjailValidator: problem getting public key for the transactor") + return + } + + // Parse ExtraData. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, "UnjailValidator: invalid ExtraData provided") + return + } + + // Compute the additional transaction fees as specified + // by the request body and the node-level fees. + additionalOutputs, err := fes.getTransactionFee( + lib.TxnTypeUnjailValidator, + transactorPublicKeyBytes, + requestData.TransactionFees, + ) + if err != nil { + _AddBadRequestError(ww, "UnjailValidator: specified TransactionFees are invalid") + return + } + + // Create transaction. + txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateUnjailValidatorTxn( + transactorPublicKeyBytes, + &lib.UnjailValidatorMetadata{}, + extraData, + requestData.MinFeeRateNanosPerKB, + fes.backendServer.GetMempool(), + additionalOutputs, + ) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("UnjailValidator: problem creating txn: %v", err)) + return + } + + // Construct response. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddInternalServerError(ww, "UnjailValidator: problem encoding txn to bytes") + return + } + res := ValidatorTxnResponse{ + SpendAmountNanos: totalInput - changeAmount - fees, + TotalInputNanos: totalInput, + ChangeAmountNanos: changeAmount, + FeeNanos: fees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + TxnHashHex: txn.Hash().String(), + } + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "UnjailValidator: problem encoding response as JSON") + return + } +} + func (fes *APIServer) GetValidatorByPublicKeyBase58Check(ww http.ResponseWriter, req *http.Request) { // Parse ValidatorPublicKeyBase58Check from URL. vars := mux.Vars(req) From 698a0bf523420a5c81c29d609a6e33044a341a73 Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:57:45 -0500 Subject: [PATCH 28/99] feature/pos-syncing-and-steady-state (#537) * Regtest PoS Validator Support * Fix n0_test script --- .gitignore | 3 ++- scripts/nodes/n0_test | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5851a585..0ff977e4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ local_scripts/* backend .idea -mem.log \ No newline at end of file +.vscode +mem.log diff --git a/scripts/nodes/n0_test b/scripts/nodes/n0_test index b12c2682..2da232ad 100755 --- a/scripts/nodes/n0_test +++ b/scripts/nodes/n0_test @@ -13,6 +13,7 @@ DATE=`date +%Y%m%d-%H:%M:%S-%N` # * 13UkvpJXdLWE4p68n4MAK6zQntQ1RHixyM rm /tmp/main.*.log +rm -rf /tmp/n0_test_00000 # "-gcflags=”all=-N -l" was added to get GoLand debugger (Delve) to work, see # https://blog.jetbrains.com/go/2019/02/06/debugging-with-goland-getting-started/ @@ -20,7 +21,7 @@ rm /tmp/main.*.log # "If you are running with Go 1.10 or newer, you need to add ` -gcflags=”all=-N -l” ` # to the ` go build ` command." -(cd ../../ && go build -o backend -gcflags="all=-N -l" main.go && ./backend run \ +(cd ../../ && go build -o backend -gcflags="all=-N -l" -tags="relic" main.go && ./backend run \ --glog-v=0 \ --glog-vmodule="*api*=0,*bitcoin_manager*=2,*balance*=0,*frontend*=0,*peer*=0,*addr*=0,*network*=0,*utils*=0,*connection*=0,*main*=0,server*=0,*mempool*=0,*miner*=0,*blockchain*=0,*block_producer*=1" \ --add-ips=localhost:19000 \ @@ -33,7 +34,8 @@ rm /tmp/main.*.log --super-admin-public-keys=* \ --num-mining-threads=1 \ --miner-public-keys=BC1YLg7Bk5sq9iNY17bAwoAYiChLYpmWEi6nY6q5gnA1UQV6xixHjfV \ - --block-producer-seed='essence camp ghost remove document vault ladder swim pupil index apart ring' \ + --block-producer-seed='verb find card ship another until version devote guilt strong lemon six' \ + --pos-validator-seed='verb find card ship another until version devote guilt strong lemon six' \ --starter-deso-seed='road congress client market couple bid risk escape artwork rookie artwork food' \ --data-dir=/tmp/n0_test_00000 \ --access-control-allow-origins=http://localhost:4200,http://localhost:80,http://localhost:18002,http://localhost:4201,http://localhost:18001,http://localhost:3000,localhost:3000 \ From e3d9a48d950f0085e89aadafdbe6e6e23b3f1404 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 7 Feb 2024 16:59:16 -0500 Subject: [PATCH 29/99] Fix compile error --- routes/transaction.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routes/transaction.go b/routes/transaction.go index 797401ac..9c4ca3e9 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4137,7 +4137,6 @@ func (fes *APIServer) GetTransactionSpending(ww http.ResponseWriter, req *http.R func (fes *APIServer) simulateSubmitTransaction(utxoView *lib.UtxoView, txn *lib.MsgDeSoTxn) (_utxoOperations []*lib.UtxoOperation, _totalInput uint64, _totalOutput uint64, _fees uint64, _err error) { bestHeight := fes.blockchain.BlockTip().Height + 1 - bytes, _ := txn.ToBytes(false) return utxoView.ConnectTransaction( txn, txn.Hash(), From 8bf9ca743550b78e0b2bc1d657095526a6d5fece Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:52:32 -0500 Subject: [PATCH 30/99] Fix CI (#540) --- routes/admin_transaction_test.go | 7 ++++--- routes/validators_test.go | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/routes/admin_transaction_test.go b/routes/admin_transaction_test.go index 0d195822..869a182d 100644 --- a/routes/admin_transaction_test.go +++ b/routes/admin_transaction_test.go @@ -3,12 +3,13 @@ package routes import ( "bytes" "encoding/json" - "github.com/deso-protocol/core/lib" - "github.com/stretchr/testify/require" "io" "net/http" "net/http/httptest" "testing" + + "github.com/deso-protocol/core/lib" + "github.com/stretchr/testify/require" ) func TestUpdateGlobalParams(t *testing.T) { @@ -89,7 +90,7 @@ func TestUpdateGlobalParams(t *testing.T) { require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(3)) require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(3)) require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(100)) - require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(3600)) + require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(10)) require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(48)) } { diff --git a/routes/validators_test.go b/routes/validators_test.go index 151b2f36..e2f61459 100644 --- a/routes/validators_test.go +++ b/routes/validators_test.go @@ -5,13 +5,14 @@ package routes import ( "bytes" "encoding/json" - "github.com/deso-protocol/core/bls" - "github.com/deso-protocol/core/lib" - "github.com/stretchr/testify/require" "io" "net/http" "net/http/httptest" "testing" + + "github.com/deso-protocol/core/bls" + "github.com/deso-protocol/core/lib" + "github.com/stretchr/testify/require" ) func TestValidatorRegistration(t *testing.T) { @@ -99,7 +100,6 @@ func TestValidatorRegistration(t *testing.T) { require.Equal(t, validatorResponse.VotingAuthorization, votingAuthorization.ToString()) require.Equal(t, validatorResponse.TotalStakeAmountNanos.Uint64(), uint64(0)) require.Equal(t, validatorResponse.Status, "Active") - require.Equal(t, validatorResponse.LastActiveAtEpochNumber, uint64(1)) require.Equal(t, validatorResponse.JailedAtEpochNumber, uint64(0)) require.NotNil(t, validatorResponse.ExtraData) require.Equal(t, validatorResponse.ExtraData["Foo"], "Bar") From e7363610420572df5f0e757c6b0f047d313b054a Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:54:42 -0500 Subject: [PATCH 31/99] Only set public keys if not the zero pkid (#533) --- routes/transaction.go | 94 +++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/routes/transaction.go b/routes/transaction.go index 9c4ca3e9..7bf7c1e8 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -3646,10 +3646,13 @@ func TransactionSpendingLimitToResponse( if len(transactionSpendingLimit.StakeLimitMap) > 0 { for stakeLimitKey, stakeLimit := range transactionSpendingLimit.StakeLimitMap { - validatorPublicKey := utxoView.GetPublicKeyForPKID(&stakeLimitKey.ValidatorPKID) - validatorPublicKeyBase58Check := lib.Base58CheckEncode( - validatorPublicKey, false, params, - ) + var validatorPublicKeyBase58Check string + if !stakeLimitKey.ValidatorPKID.IsZeroPKID() { + validatorPublicKey := utxoView.GetPublicKeyForPKID(&stakeLimitKey.ValidatorPKID) + validatorPublicKeyBase58Check = lib.Base58CheckEncode( + validatorPublicKey, false, params, + ) + } transactionSpendingLimitResponse.StakeLimitMap = append( transactionSpendingLimitResponse.StakeLimitMap, StakeLimitMapItem{ @@ -3662,10 +3665,13 @@ func TransactionSpendingLimitToResponse( if len(transactionSpendingLimit.UnstakeLimitMap) > 0 { for unstakeLimitKey, unstakeLimit := range transactionSpendingLimit.UnstakeLimitMap { - validatorPublicKey := utxoView.GetPublicKeyForPKID(&unstakeLimitKey.ValidatorPKID) - validatorPublicKeyBase58Check := lib.Base58CheckEncode( - validatorPublicKey, false, params, - ) + var validatorPublicKeyBase58Check string + if !unstakeLimitKey.ValidatorPKID.IsZeroPKID() { + validatorPublicKey := utxoView.GetPublicKeyForPKID(&unstakeLimitKey.ValidatorPKID) + validatorPublicKeyBase58Check = lib.Base58CheckEncode( + validatorPublicKey, false, params, + ) + } transactionSpendingLimitResponse.UnstakeLimitMap = append( transactionSpendingLimitResponse.UnstakeLimitMap, UnstakeLimitMapItem{ @@ -3678,10 +3684,13 @@ func TransactionSpendingLimitToResponse( if len(transactionSpendingLimit.UnlockStakeLimitMap) > 0 { for unlockStakeLimitKey, opCount := range transactionSpendingLimit.UnlockStakeLimitMap { - validatorPublicKey := utxoView.GetPublicKeyForPKID(&unlockStakeLimitKey.ValidatorPKID) - validatorPublicKeyBase58Check := lib.Base58CheckEncode( - validatorPublicKey, false, params, - ) + var validatorPublicKeyBase58Check string + if !unlockStakeLimitKey.ValidatorPKID.IsZeroPKID() { + validatorPublicKey := utxoView.GetPublicKeyForPKID(&unlockStakeLimitKey.ValidatorPKID) + validatorPublicKeyBase58Check = lib.Base58CheckEncode( + validatorPublicKey, false, params, + ) + } transactionSpendingLimitResponse.UnlockStakeLimitMap = append( transactionSpendingLimitResponse.UnlockStakeLimitMap, UnlockStakeLimitMapItem{ @@ -3694,8 +3703,11 @@ func TransactionSpendingLimitToResponse( if len(transactionSpendingLimit.LockupLimitMap) > 0 { for lockupLimitKey, opCount := range transactionSpendingLimit.LockupLimitMap { - publicKeyBytes := utxoView.GetPublicKeyForPKID(&lockupLimitKey.ProfilePKID) - publicKeyBase58Check := lib.Base58CheckEncode(publicKeyBytes, false, params) + var publicKeyBase58Check string + if !lockupLimitKey.ProfilePKID.IsZeroPKID() { + publicKeyBytes := utxoView.GetPublicKeyForPKID(&lockupLimitKey.ProfilePKID) + publicKeyBase58Check = lib.Base58CheckEncode(publicKeyBytes, false, params) + } transactionSpendingLimitResponse.LockupLimitMap = append( transactionSpendingLimitResponse.LockupLimitMap, LockupLimitMapItem{ @@ -3873,14 +3885,14 @@ func (fes *APIServer) TransactionSpendingLimitFromResponse( if len(transactionSpendingLimitResponse.StakeLimitMap) > 0 { transactionSpendingLimit.StakeLimitMap = make(map[lib.StakeLimitKey]*uint256.Int) for _, stakeLimitMapItem := range transactionSpendingLimitResponse.StakeLimitMap { - validatorPublicKey, _, err := lib.Base58CheckDecode(stakeLimitMapItem.ValidatorPublicKeyBase58Check) - if err != nil { - return nil, err + validatorPKID := &lib.ZeroPKID + if stakeLimitMapItem.ValidatorPublicKeyBase58Check != "" { + validatorPKID, err = getCreatorPKIDForBase58Check(stakeLimitMapItem.ValidatorPublicKeyBase58Check) + if err != nil { + return nil, err + } } - validatorPKID := utxoView.GetPKIDForPublicKey(validatorPublicKey) - stakeLimitKey := lib.MakeStakeLimitKey( - validatorPKID.PKID, - ) + stakeLimitKey := lib.MakeStakeLimitKey(validatorPKID) transactionSpendingLimit.StakeLimitMap[stakeLimitKey] = stakeLimitMapItem.StakeLimit.Clone() } } @@ -3888,14 +3900,14 @@ func (fes *APIServer) TransactionSpendingLimitFromResponse( if len(transactionSpendingLimitResponse.UnstakeLimitMap) > 0 { transactionSpendingLimit.UnstakeLimitMap = make(map[lib.StakeLimitKey]*uint256.Int) for _, unstakeLimitMapItem := range transactionSpendingLimitResponse.UnstakeLimitMap { - validatorPublicKey, _, err := lib.Base58CheckDecode(unstakeLimitMapItem.ValidatorPublicKeyBase58Check) - if err != nil { - return nil, err + validatorPKID := &lib.ZeroPKID + if unstakeLimitMapItem.ValidatorPublicKeyBase58Check != "" { + validatorPKID, err = getCreatorPKIDForBase58Check(unstakeLimitMapItem.ValidatorPublicKeyBase58Check) + if err != nil { + return nil, err + } } - validatorPKID := utxoView.GetPKIDForPublicKey(validatorPublicKey) - unstakeLimitKey := lib.MakeStakeLimitKey( - validatorPKID.PKID, - ) + unstakeLimitKey := lib.MakeStakeLimitKey(validatorPKID) transactionSpendingLimit.UnstakeLimitMap[unstakeLimitKey] = unstakeLimitMapItem.UnstakeLimit.Clone() } } @@ -3903,27 +3915,29 @@ func (fes *APIServer) TransactionSpendingLimitFromResponse( if len(transactionSpendingLimitResponse.UnlockStakeLimitMap) > 0 { transactionSpendingLimit.UnlockStakeLimitMap = make(map[lib.StakeLimitKey]uint64) for _, unlockStakeLimitMapItem := range transactionSpendingLimitResponse.UnlockStakeLimitMap { - validatorPublicKey, _, err := lib.Base58CheckDecode(unlockStakeLimitMapItem.ValidatorPublicKeyBase58Check) - if err != nil { - return nil, err + validatorPKID := &lib.ZeroPKID + if unlockStakeLimitMapItem.ValidatorPublicKeyBase58Check != "" { + validatorPKID, err = getCreatorPKIDForBase58Check(unlockStakeLimitMapItem.ValidatorPublicKeyBase58Check) + if err != nil { + return nil, err + } } - validatorPKID := utxoView.GetPKIDForPublicKey(validatorPublicKey) - unlockStakeLimitKey := lib.MakeStakeLimitKey( - validatorPKID.PKID, - ) + unlockStakeLimitKey := lib.MakeStakeLimitKey(validatorPKID) transactionSpendingLimit.UnlockStakeLimitMap[unlockStakeLimitKey] = unlockStakeLimitMapItem.OpCount } } if len(transactionSpendingLimitResponse.LockupLimitMap) > 0 { transactionSpendingLimit.LockupLimitMap = make(map[lib.LockupLimitKey]uint64) for _, lockupLimitMapItem := range transactionSpendingLimitResponse.LockupLimitMap { - profilePublicKey, _, err := lib.Base58CheckDecode(lockupLimitMapItem.ProfilePublicKeyBase58Check) - if err != nil { - return nil, err + profilePKID := &lib.ZeroPKID + if lockupLimitMapItem.ProfilePublicKeyBase58Check != "" { + profilePKID, err = getCreatorPKIDForBase58Check(lockupLimitMapItem.ProfilePublicKeyBase58Check) + if err != nil { + return nil, err + } } - pkidEntry := utxoView.GetPKIDForPublicKey(profilePublicKey) transactionSpendingLimit.LockupLimitMap[lib.MakeLockupLimitKey( - *pkidEntry.PKID, + *profilePKID, lockupLimitMapItem.ScopeType.ToScopeType(), lockupLimitMapItem.Operation.ToOperationType(), )] = lockupLimitMapItem.OpCount From b33a0aba7013465eed3b32cb402ffe16d826e349 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 13 Feb 2024 11:50:30 -0500 Subject: [PATCH 32/99] Level 2 glog for price fetching logic (#541) --- routes/base.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/routes/base.go b/routes/base.go index 59d6555e..fa72279c 100644 --- a/routes/base.go +++ b/routes/base.go @@ -182,7 +182,7 @@ func (fes *APIServer) GetBlockchainDotComExchangeRate() (_exchangeRate float64, glog.Errorf("GetBlockchainDotComExchangeRate: Problem getting max from list of float64s: %v", err) return 0, err } - glog.Infof("Blockchain exchange rate: %v %v", blockchainDotComExchangeRate, exchangeRatesFetched) + glog.V(2).Infof("Blockchain exchange rate: %v %v", blockchainDotComExchangeRate, exchangeRatesFetched) if fes.backendServer != nil && fes.backendServer.GetStatsdClient() != nil { if err = fes.backendServer.GetStatsdClient().Gauge("BLOCKCHAIN_LAST_TRADE_PRICE", blockchainDotComExchangeRate, []string{}, 1); err != nil { glog.Errorf("GetBlockchainDotComExchangeRate: Error logging Last Trade Price of %f to datadog: %v", blockchainDotComExchangeRate, err) @@ -243,18 +243,18 @@ func (fes *APIServer) GetCoinbaseExchangeRate() (_exchangeRate float64, _err err // UpdateUSDCentsToDeSoExchangeRate updates app state's USD Cents per DeSo value func (fes *APIServer) UpdateUSDCentsToDeSoExchangeRate() { - glog.Infof("Refreshing exchange rate...") + glog.V(2).Info("Refreshing exchange rate...") // Fetch price from blockchain.com blockchainDotComPrice, err := fes.GetBlockchainDotComExchangeRate() - glog.Infof("Blockchain.com price (USD cents): %v", blockchainDotComPrice) + glog.V(2).Infof("Blockchain.com price (USD cents): %v", blockchainDotComPrice) if err != nil { glog.Errorf("UpdateUSDCentsToDeSoExchangeRate: Error fetching exchange rate from blockchain.com: %v", err) } // Fetch price from coinbase coinbasePrice, err := fes.GetCoinbaseExchangeRate() - glog.Infof("Coinbase price (USD Cents): %v", coinbasePrice) + glog.V(2).Infof("Coinbase price (USD Cents): %v", coinbasePrice) if err != nil { glog.Errorf("UpdateUSDCentsToDeSoExchangeRate: Error fetching exchange rate from coinbase: %v", err) } @@ -283,29 +283,29 @@ func (fes *APIServer) UpdateUSDCentsToDeSoExchangeRate() { fes.UsdCentsPerDeSoExchangeRate = maxPrice } - glog.Infof("Final exchange rate: %v", fes.UsdCentsPerDeSoExchangeRate) + glog.V(2).Infof("Final exchange rate: %v", fes.UsdCentsPerDeSoExchangeRate) } func (fes *APIServer) UpdateUSDToBTCPrice() { - glog.Info("Refreshing USD to BTC exchange rate") + glog.V(2).Info("Refreshing USD to BTC exchange rate") btcExchangeRate, err := GetUSDToBTCPrice() if err != nil { glog.Errorf("Error getting BTC price: %v", err) return } fes.UsdCentsPerBitCoinExchangeRate = btcExchangeRate * 100 - glog.Infof("New USD to BTC exchange rate: %f", fes.UsdCentsPerBitCoinExchangeRate/100) + glog.V(2).Infof("New USD to BTC exchange rate: %f", fes.UsdCentsPerBitCoinExchangeRate/100) } func (fes *APIServer) UpdateUSDToETHPrice() { - glog.Info("Refreshing USD to ETH exchange rate") + glog.V(2).Info("Refreshing USD to ETH exchange rate") ethExchangeRate, err := apis.GetUSDToETHPrice() if err != nil { glog.Errorf("Error getting ETH price: %v", err) return } fes.UsdCentsPerETHExchangeRate = uint64(ethExchangeRate * 100) - glog.Infof("New USD to ETH exchange rate: %f", float64(fes.UsdCentsPerETHExchangeRate)/100) + glog.V(2).Infof("New USD to ETH exchange rate: %f", float64(fes.UsdCentsPerETHExchangeRate)/100) } // getMaxPriceFromHistoryAndCull removes elements that are outside of the lookback window and return the max price From e0fe7550465e8f1e370426fcb7b762f51bfc87fd Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 13 Feb 2024 19:39:07 -0500 Subject: [PATCH 33/99] Remove datadir deletion from n0_test --- scripts/nodes/n0_test | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/nodes/n0_test b/scripts/nodes/n0_test index 2da232ad..f2e03236 100755 --- a/scripts/nodes/n0_test +++ b/scripts/nodes/n0_test @@ -13,7 +13,6 @@ DATE=`date +%Y%m%d-%H:%M:%S-%N` # * 13UkvpJXdLWE4p68n4MAK6zQntQ1RHixyM rm /tmp/main.*.log -rm -rf /tmp/n0_test_00000 # "-gcflags=”all=-N -l" was added to get GoLand debugger (Delve) to work, see # https://blog.jetbrains.com/go/2019/02/06/debugging-with-goland-getting-started/ From 91f7302b3b138f6507f12f1d89ad7a676b52a34d Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 15 Feb 2024 16:35:21 -0500 Subject: [PATCH 34/99] Update miner to pass params into RecomputeBlockRewardWithBlockRewardOutputPublicKey (#542) --- routes/miner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/miner.go b/routes/miner.go index 752b5655..5c2addb5 100644 --- a/routes/miner.go +++ b/routes/miner.go @@ -162,7 +162,7 @@ func (fes *APIServer) SubmitBlock(ww http.ResponseWriter, req *http.Request) { blockFound.Txns[0].TxOutputs[0].PublicKey = pkBytes blockFound.Txns[0].TxnMeta.(*lib.BlockRewardMetadataa).ExtraData = lib.UintToBuf(requestData.ExtraData) - blockFound, err = lib.RecomputeBlockRewardWithBlockRewardOutputPublicKey(blockFound, pkBytes) + blockFound, err = lib.RecomputeBlockRewardWithBlockRewardOutputPublicKey(blockFound, pkBytes, fes.Params) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SubmitBlock: Problem recomputing block reward: %v", err)) return From 0345c2e83c593069ca3cdee775afc4f215a25700 Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:08:16 -0400 Subject: [PATCH 35/99] feature/pos-networking-and-syncing (#556) * Fix Compile Errors For Networking (#543) * Fix broken unit test (#546) * Add endpoint to get fee rate and block height for local txn construction (#544) * Fix NetworkManager Access (#550) * Reduce logging (#547) * Validator Registration Script (#552) * Validator Registration Script * Fix validator domain * Update flow crypto dependency (#554) --------- Co-authored-by: Lazy Nina <81658138+lazynina@users.noreply.github.com> --- Dockerfile | 5 +- README.md | 12 ++ apis/eth_price.go | 15 +- go.mod | 4 +- go.sum | 26 +++- routes/admin_fees.go | 2 +- routes/admin_node.go | 18 +-- routes/admin_transaction_test.go | 2 +- routes/base.go | 10 +- routes/bitcoin_price.go | 15 +- routes/hot_feed.go | 8 +- routes/server.go | 8 ++ routes/transaction.go | 71 +++++++++ routes/verify.go | 6 + scripts/pos/validator_registration.go | 198 ++++++++++++++++++++++++++ test.Dockerfile | 3 +- 16 files changed, 359 insertions(+), 44 deletions(-) create mode 100644 scripts/pos/validator_registration.go diff --git a/Dockerfile b/Dockerfile index 24721308..26b104bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,12 +35,9 @@ COPY core/consensus ../core/consensus COPY core/desohash ../core/desohash COPY core/lib ../core/lib COPY core/migrate ../core/migrate -COPY core/scripts ../core/scripts - -RUN ../core/scripts/install-relic.sh # build backend -RUN GOOS=linux go build -mod=mod -a -installsuffix cgo -o bin/backend -tags=relic main.go +RUN GOOS=linux go build -mod=mod -a -installsuffix cgo -o bin/backend main.go # create tiny image FROM alpine:latest diff --git a/README.md b/README.md index caa33659..63d552d6 100644 --- a/README.md +++ b/README.md @@ -71,3 +71,15 @@ go build github.com/h2non/bimg: invalid flag in pkg-config --cflags: -Xpreproces ``` export CGO_CFLAGS_ALLOW="-Xpreprocessor" ``` + +#### Error +``` +ld: library not found for -lvips +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` + +#### Solution + +``` +go clean -cache +``` \ No newline at end of file diff --git a/apis/eth_price.go b/apis/eth_price.go index ffd8c1eb..f7e82947 100644 --- a/apis/eth_price.go +++ b/apis/eth_price.go @@ -4,11 +4,12 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/golang/glog" - "github.com/montanaflynn/stats" "io/ioutil" "net/http" "strconv" + + "github.com/golang/glog" + "github.com/montanaflynn/stats" ) type CoinbaseResponse struct { @@ -194,7 +195,7 @@ func GetUSDToETHPrice() (float64, error) { amount, err := getCoinbasePrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Coinbase price: %v", err) + glog.V(2).Infof("Error fetching Coinbase price: %v", err) } if amount != 0 { @@ -205,7 +206,7 @@ func GetUSDToETHPrice() (float64, error) { amount, err := getCoingeckoPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Coingecko price: %v", err) + glog.V(2).Infof("Error fetching Coingecko price: %v", err) } if amount != 0 { @@ -216,7 +217,7 @@ func GetUSDToETHPrice() (float64, error) { amount, err := getBlockchainDotcomPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching blockchain.com price: %v", err) + glog.V(2).Infof("Error fetching blockchain.com price: %v", err) } if amount != 0 { @@ -227,7 +228,7 @@ func GetUSDToETHPrice() (float64, error) { amount, err := getGeminiPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Gemini price: %v", err) + glog.V(2).Infof("Error fetching Gemini price: %v", err) } if amount != 0 { @@ -238,7 +239,7 @@ func GetUSDToETHPrice() (float64, error) { amount, err := getKrakenPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Kraken price: %v", err) + glog.V(2).Infof("Error fetching Kraken price: %v", err) } if amount != 0 { diff --git a/go.mod b/go.mod index 4c9a0578..eb46ff87 100644 --- a/go.mod +++ b/go.mod @@ -69,6 +69,7 @@ require ( github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 // indirect github.com/google/uuid v1.2.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.8 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -84,7 +85,7 @@ require ( github.com/mattn/goveralls v0.0.6 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/oleiade/lane v1.0.1 // indirect - github.com/onflow/flow-go/crypto v0.24.7 // indirect + github.com/onflow/crypto v0.25.0 // indirect github.com/pelletier/go-toml v1.7.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/philhofer/fwd v1.1.1 // indirect @@ -119,6 +120,7 @@ require ( golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect golang.org/x/tools v0.1.5 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + gonum.org/v1/gonum v0.6.1 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab // indirect google.golang.org/grpc v1.37.0 // indirect diff --git a/go.sum b/go.sum index 75f51c55..aab30020 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,7 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= @@ -183,6 +184,7 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fergusstrange/embedded-postgres v1.19.0 h1:NqDufJHeA03U7biULlPHZ0pZ10/mDOMKPILEpT50Fyk= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -214,6 +216,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= @@ -324,6 +327,9 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -361,6 +367,7 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= @@ -438,8 +445,8 @@ github.com/oleiade/lane v1.0.1 h1:hXofkn7GEOubzTwNpeL9MaNy8WxolCYb9cInAIeqShU= github.com/oleiade/lane v1.0.1/go.mod h1:IyTkraa4maLfjq/GmHR+Dxb4kCMtEGeb+qmhlrQ5Mk4= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onflow/flow-go/crypto v0.24.7 h1:RCLuB83At4z5wkAyUCF7MYEnPoIIOHghJaODuJyEoW0= -github.com/onflow/flow-go/crypto v0.24.7/go.mod h1:fqCzkIBBMRRkciVrvW21rECKq1oD7Q6u+bCI78lfNX0= +github.com/onflow/crypto v0.25.0 h1:BeWbLsh3ZD13Ej+Uky6kg1PL1ZIVBDVX+2MVBNwqddg= +github.com/onflow/crypto v0.25.0/go.mod h1:C8FbaX0x8y+FxWjbkHy0Q4EASCDR9bSPWZqlpCLYyVI= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -549,7 +556,6 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/supranational/blst v0.3.10 h1:CMciDZ/h4pXDDXQASe8ZGTNKUiVNxVVA5hpci2Uuhuk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= @@ -625,7 +631,10 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= @@ -635,7 +644,9 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -817,8 +828,10 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -876,6 +889,12 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.6.1 h1:/LSrTrgZtpbXyAR6+0e152SROCkJJSh7goYWVmdPFGc= +gonum.org/v1/gonum v0.6.1/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1029,5 +1048,6 @@ mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w= mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ= pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/routes/admin_fees.go b/routes/admin_fees.go index 52eebe7f..d8c64829 100644 --- a/routes/admin_fees.go +++ b/routes/admin_fees.go @@ -255,7 +255,7 @@ func (fes *APIServer) GetTransactionFeeMapFromGlobalState() map[lib.TxnType][]*l var feeOutputs []*lib.DeSoOutput // Decode the bytes into the slice of DeSoOutputs if err = gob.NewDecoder(bytes.NewReader(desoOutputBytes)).Decode(&feeOutputs); err != nil { - glog.Infof("Error decoding desoOutputBytes to slice of DeSoOutputs: %v - default to no additional fees", err) + glog.V(2).Infof("Error decoding desoOutputBytes to slice of DeSoOutputs: %v - default to no additional fees", err) // Default to an empty slice. transactionFeeMap[txnType] = []*lib.DeSoOutput{} } else { diff --git a/routes/admin_node.go b/routes/admin_node.go index 473c26dd..21692b7c 100644 --- a/routes/admin_node.go +++ b/routes/admin_node.go @@ -167,7 +167,7 @@ func (fes *APIServer) _handleNodeControlGetInfo( existingDeSoPeers[currentPeerRes.IP+fmt.Sprintf(":%d", currentPeerRes.ProtocolPort)] = true } // Return some deso addrs from the addr manager. - desoAddrs := fes.backendServer.GetConnectionManager().GetAddrManager().AddressCache() + desoAddrs := fes.backendServer.AddrMgr.AddressCache() sort.Slice(desoAddrs, func(ii, jj int) bool { // Use a hash to get a random but deterministic ordering. hashI := string(lib.Sha256DoubleHash([]byte(desoAddrs[ii].IP.String() + fmt.Sprintf(":%d", desoAddrs[ii].Port)))[:]) @@ -239,12 +239,12 @@ func (fes *APIServer) _handleConnectDeSoNode( // increasing retry delay, but we should still clean it up at some point. connectPeerDone := make(chan bool) go func() { - netAddr, err := fes.backendServer.GetConnectionManager().GetAddrManager().HostToNetAddress(ip, protocolPort, 0) + netAddr, err := fes.backendServer.AddrMgr.HostToNetAddress(ip, protocolPort, 0) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("_handleConnectDeSoNode: Cannot connect to node %s:%d: %v", ip, protocolPort, err)) return } - fes.backendServer.GetConnectionManager().ConnectPeer(nil, netAddr) + fes.backendServer.GetNetworkManager().CreateNonValidatorOutboundConnection(ip) // Spin until the peer shows up in the connection manager or until 100 iterations. // Note the pause between each iteration. @@ -274,7 +274,7 @@ func (fes *APIServer) _handleConnectDeSoNode( // At this point the peer shoud be connected. Add their address to the addrmgr // in case the user wants to connect again in the future. Set the source to be // the address itself since we don't have anything else. - fes.backendServer.GetConnectionManager().GetAddrManager().AddAddress(netAddr, netAddr) + fes.backendServer.AddrMgr.AddAddress(netAddr, netAddr) connectPeerDone <- true return @@ -320,13 +320,13 @@ func (fes *APIServer) _handleDisconnectDeSoNode( // Manually remove the peer from the connection manager and mark it as such // so that the connection manager won't reconnect to it or replace it. - fes.backendServer.GetConnectionManager().RemovePeer(peerFound) - peerFound.PeerManuallyRemovedFromConnectionManager = true - - peerFound.Disconnect() + remoteNode := fes.backendServer.GetNetworkManager().GetRemoteNodeFromPeer(peerFound) + if remoteNode != nil { + fes.backendServer.GetNetworkManager().Disconnect(remoteNode) + } res := NodeControlResponse{ - // Return an empty response, which indicates we set the peer up to be connected. + // Return an empty response, which indicates we set the peer up to be disconnected. } if err := json.NewEncoder(ww).Encode(res); err != nil { _AddBadRequestError(ww, fmt.Sprintf("NodeControl: Problem encoding response as JSON: %v", err)) diff --git a/routes/admin_transaction_test.go b/routes/admin_transaction_test.go index 869a182d..20ecfd4d 100644 --- a/routes/admin_transaction_test.go +++ b/routes/admin_transaction_test.go @@ -91,7 +91,7 @@ func TestUpdateGlobalParams(t *testing.T) { require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(3)) require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(100)) require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(10)) - require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(48)) + require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(3)) } { // Update all GlobalParam fields. diff --git a/routes/base.go b/routes/base.go index fa72279c..ce0359a0 100644 --- a/routes/base.go +++ b/routes/base.go @@ -150,14 +150,14 @@ func (fes *APIServer) GetBlockchainDotComExchangeRate() (_exchangeRate float64, url := "https://api.blockchain.com/v3/exchange/tickers/CLOUT-USD" req, err := http.NewRequest("GET", url, nil) if err != nil { - glog.Errorf("GetBlockchainDotComExchangeRate: Problem creating request: %v", err) + glog.V(2).Infof("GetBlockchainDotComExchangeRate: Problem creating request: %v", err) continue } req.Header.Set("Content-Type", "application/json") resp, err := httpClient.Do(req) if err != nil { - glog.Errorf("GetBlockchainDotComExchangeRate: Problem with HTTP request %s: %v", url, err) + glog.V(2).Infof("GetBlockchainDotComExchangeRate: Problem with HTTP request %s: %v", url, err) continue } defer resp.Body.Close() @@ -167,7 +167,7 @@ func (fes *APIServer) GetBlockchainDotComExchangeRate() (_exchangeRate float64, responseData := &BlockchainDeSoTickerResponse{} decoder := json.NewDecoder(bytes.NewReader(body)) if err = decoder.Decode(responseData); err != nil { - glog.Errorf("GetBlockchainDotComExchangeRate: Problem decoding response JSON into "+ + glog.V(2).Infof("GetBlockchainDotComExchangeRate: Problem decoding response JSON into "+ "interface %v, response: %v, error: %v", responseData, resp, err) continue } @@ -179,13 +179,13 @@ func (fes *APIServer) GetBlockchainDotComExchangeRate() (_exchangeRate float64, } blockchainDotComExchangeRate, err := stats.Max(exchangeRatesFetched) if err != nil { - glog.Errorf("GetBlockchainDotComExchangeRate: Problem getting max from list of float64s: %v", err) + glog.V(2).Infof("GetBlockchainDotComExchangeRate: Problem getting max from list of float64s: %v", err) return 0, err } glog.V(2).Infof("Blockchain exchange rate: %v %v", blockchainDotComExchangeRate, exchangeRatesFetched) if fes.backendServer != nil && fes.backendServer.GetStatsdClient() != nil { if err = fes.backendServer.GetStatsdClient().Gauge("BLOCKCHAIN_LAST_TRADE_PRICE", blockchainDotComExchangeRate, []string{}, 1); err != nil { - glog.Errorf("GetBlockchainDotComExchangeRate: Error logging Last Trade Price of %f to datadog: %v", blockchainDotComExchangeRate, err) + glog.V(2).Infof("GetBlockchainDotComExchangeRate: Error logging Last Trade Price of %f to datadog: %v", blockchainDotComExchangeRate, err) } } return blockchainDotComExchangeRate, nil diff --git a/routes/bitcoin_price.go b/routes/bitcoin_price.go index 5f7842ee..31f8e2d6 100644 --- a/routes/bitcoin_price.go +++ b/routes/bitcoin_price.go @@ -4,11 +4,12 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/golang/glog" - "github.com/montanaflynn/stats" "io/ioutil" "net/http" "strconv" + + "github.com/golang/glog" + "github.com/montanaflynn/stats" ) type CoinbaseResponse struct { @@ -206,7 +207,7 @@ func GetUSDToBTCPrice() (float64, error) { amount, err := getCoinbasePrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Coinbase price: %v", err) + glog.V(2).Infof("Error fetching Coinbase price: %v", err) } if amount != 0 { @@ -217,7 +218,7 @@ func GetUSDToBTCPrice() (float64, error) { amount, err := getCoingeckoPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Coingecko price: %v", err) + glog.V(2).Infof("Error fetching Coingecko price: %v", err) } if amount != 0 { @@ -228,7 +229,7 @@ func GetUSDToBTCPrice() (float64, error) { amount, err := getBlockchainDotcomPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching blockchain.com price: %v", err) + glog.V(2).Infof("Error fetching blockchain.com price: %v", err) } if amount != 0 { @@ -239,7 +240,7 @@ func GetUSDToBTCPrice() (float64, error) { amount, err := getGeminiPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Gemini price: %v", err) + glog.V(2).Infof("Error fetching Gemini price: %v", err) } if amount != 0 { @@ -250,7 +251,7 @@ func GetUSDToBTCPrice() (float64, error) { amount, err := getKrakenPrice() if err != nil { // The amount will be zero in this case, which is fine - glog.Errorf("Error fetching Kraken price: %v", err) + glog.V(2).Infof("Error fetching Kraken price: %v", err) } if amount != 0 { diff --git a/routes/hot_feed.go b/routes/hot_feed.go index 9a884efa..9c1b127a 100644 --- a/routes/hot_feed.go +++ b/routes/hot_feed.go @@ -109,9 +109,9 @@ func (fes *APIServer) StartHotFeedRoutine() { // The business. func (fes *APIServer) UpdateHotFeed(resetCache bool) { - glog.Info("Refreshing hot feed...") + glog.V(2).Info("Refreshing hot feed...") if resetCache { - glog.Info("Resetting hot feed cache.") + glog.V(2).Info("Resetting hot feed cache.") fes.PostTagToPostHashesMap = make(map[string]map[lib.BlockHash]bool) fes.PostHashToPostTagsMap = make(map[lib.BlockHash][]string) fes.HotFeedBlockCache = make(map[lib.BlockHash]*lib.MsgDeSoBlock) @@ -137,7 +137,7 @@ func (fes *APIServer) UpdateHotFeed(resetCache bool) { // Replace the HotFeedApprovedPostsMap and HotFeedPKIDMultiplier map with the fresh ones. fes.HotFeedApprovedPostsToMultipliers = hotFeedApprovedPosts fes.HotFeedPKIDMultipliers = hotFeedPKIDMultipliers - glog.Infof("Updated hot feed maps") + glog.V(2).Infof("Updated hot feed maps") } func (fes *APIServer) UpdateHotFeedApprovedPostsMap(hotFeedApprovedPosts map[lib.BlockHash]float64) { @@ -412,7 +412,7 @@ func (fes *APIServer) UpdateHotFeedOrderedList( } // Log how long this routine takes, since it could be heavy. - glog.Info("UpdateHotFeedOrderedList: Starting new update cycle.") + glog.V(2).Info("UpdateHotFeedOrderedList: Starting new update cycle.") start := time.Now() // Get a utxoView for lookups. diff --git a/routes/server.go b/routes/server.go index e5531599..2a90dd2f 100644 --- a/routes/server.go +++ b/routes/server.go @@ -68,6 +68,7 @@ const ( RoutePathAppendExtraData = "/api/v0/append-extra-data" RoutePathGetTransactionSpending = "/api/v0/get-transaction-spending" RoutePathGetSignatureIndex = "/api/v0/signature-index" + RoutePathGetTxnConstructionParams = "/api/v0/txn-construction-params" RoutePathGetUsersStateless = "/api/v0/get-users-stateless" RoutePathDeleteIdentities = "/api/v0/delete-identities" @@ -1024,6 +1025,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.GetSignatureIndex, PublicAccess, }, + { + "GetTxnConstructionParams", + []string{"POST", "OPTIONS"}, + RoutePathGetTxnConstructionParams, + fes.GetTxnConstructionParams, + PublicAccess, + }, { "GetNotifications", []string{"POST", "OPTIONS"}, diff --git a/routes/transaction.go b/routes/transaction.go index 7bf7c1e8..026ed68e 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4198,3 +4198,74 @@ func (fes *APIServer) GetSignatureIndex(ww http.ResponseWriter, req *http.Reques } return } + +type GetTxnConstructionParamsRequest struct { + MinFeeRateNanosPerKB uint64 + MempoolCongestionFactorBasisPoints uint64 + MempoolPriorityPercentileBasisPoints uint64 + PastBlocksCongestionFactorBasisPoints uint64 + PastBlocksPriorityPercentileBasisPoints uint64 + MaxBlockSize uint64 +} + +type GetTxnConstructionParamsResponse struct { + FeeRateNanosPerKB uint64 + BlockHeight uint64 +} + +func (fes *APIServer) GetTxnConstructionParams(ww http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(req.Body) + requestData := GetTxnConstructionParamsRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, "GetTxnConstructionParams: Problem parsing request body: "+err.Error()) + return + } + + // TODO: replace lib.MaxBasisPoints w/ a param defined by a flag from core. + mempoolCongestionFactorBasisPoints := requestData.MempoolCongestionFactorBasisPoints + if requestData.MempoolCongestionFactorBasisPoints == 0 { + mempoolCongestionFactorBasisPoints = lib.MaxBasisPoints + } + + mempoolPriorityPercentileBasisPoints := requestData.MempoolPriorityPercentileBasisPoints + if requestData.MempoolPriorityPercentileBasisPoints == 0 { + mempoolPriorityPercentileBasisPoints = lib.MaxBasisPoints + } + + pastBlocksCongestionFactorBasisPoints := requestData.PastBlocksCongestionFactorBasisPoints + if requestData.PastBlocksCongestionFactorBasisPoints == 0 { + pastBlocksCongestionFactorBasisPoints = lib.MaxBasisPoints + } + + pastBlocksPriorityPercentileBasisPoints := requestData.PastBlocksPriorityPercentileBasisPoints + if requestData.PastBlocksPriorityPercentileBasisPoints == 0 { + pastBlocksPriorityPercentileBasisPoints = lib.MaxBasisPoints + } + + maxBlockSize := requestData.MaxBlockSize + if requestData.MaxBlockSize == 0 { + maxBlockSize = fes.Params.MaxBlockSizeBytes + } + + // Get the fees from the mempool + feeRate, err := fes.backendServer.GetMempool().EstimateFeeRate( + requestData.MinFeeRateNanosPerKB, + mempoolCongestionFactorBasisPoints, + mempoolPriorityPercentileBasisPoints, + pastBlocksCongestionFactorBasisPoints, + pastBlocksPriorityPercentileBasisPoints, + maxBlockSize, + ) + if err != nil { + _AddBadRequestError(ww, "GetTxnConstructionParams: Problem getting fees: "+err.Error()) + return + } + // Return the fees + if err = json.NewEncoder(ww).Encode(GetTxnConstructionParamsResponse{ + FeeRateNanosPerKB: feeRate, + BlockHeight: uint64(fes.backendServer.GetBlockchain().BlockTip().Height), + }); err != nil { + _AddBadRequestError(ww, "GetTxnConstructionParams: Problem encoding response as JSON: "+err.Error()) + return + } +} diff --git a/routes/verify.go b/routes/verify.go index e668b593..9c9910eb 100644 --- a/routes/verify.go +++ b/routes/verify.go @@ -1469,6 +1469,9 @@ func (fes *APIServer) SetJumioUSDCents() { glog.Errorf("SetJumioUSDCents: Error getting Jumio USD Cents from global state: %v", err) return } + if len(val) == 0 { + return + } jumioUSDCents, bytesRead := lib.Uvarint(val) if bytesRead <= 0 { glog.Errorf("SetJumioUSDCents: invalid bytes read: %v", bytesRead) @@ -1487,6 +1490,9 @@ func (fes *APIServer) SetJumioKickbackUSDCents() { glog.Errorf("SetJumioKickbackUSDCents: Error getting Jumio Kickback USD Cents from global state: %v", err) return } + if len(val) == 0 { + return + } jumioKickbackUSDCents, bytesRead := lib.Uvarint(val) if bytesRead <= 0 { glog.Errorf("SetJumioKickbackUSDCents: invalid bytes read: %v", bytesRead) diff --git a/scripts/pos/validator_registration.go b/scripts/pos/validator_registration.go new file mode 100644 index 00000000..cbe79499 --- /dev/null +++ b/scripts/pos/validator_registration.go @@ -0,0 +1,198 @@ +package main + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "time" + + "github.com/btcsuite/btcd/btcec" + "github.com/deso-protocol/backend/routes" + "github.com/deso-protocol/core/bls" + "github.com/deso-protocol/core/lib" + "github.com/holiman/uint256" + "github.com/pkg/errors" + "github.com/tyler-smith/go-bip39" +) + +var desoSourceSeedPhrase = "" +var validatorSeedPhrase = "SEED PHRASE HERE" +var nodeApiUrl = "http://localhost:18001" +var validatorDomain string = "localhost:19000" + +var params = &lib.DeSoTestnetParams + +func getBLSVotingAuthorizationAndPublicKey(blsKeyStore *lib.BLSKeystore, transactorPublicKey *lib.PublicKey) ( + *bls.PublicKey, *bls.Signature, +) { + votingAuthPayload := lib.CreateValidatorVotingAuthorizationPayload(transactorPublicKey.ToBytes()) + votingAuthorization, err := blsKeyStore.GetSigner().Sign(votingAuthPayload) + if err != nil { + panic(err) + } + return blsKeyStore.GetSigner().GetPublicKey(), votingAuthorization +} + +func makePostRequest[TPayload any, TResponse any](url string, payload TPayload) TResponse { + postBody, err := json.Marshal(payload) + if err != nil { + panic(errors.Wrap(err, "main(): Could not complete request")) + } + postBuffer := bytes.NewBuffer(postBody) + + // Execute request. + resp, err := http.Post(url, "application/json", postBuffer) + if err != nil { + panic(errors.Wrap(err, "main(): failed request")) + } + if resp.StatusCode != 200 { + bodyBytes, _ := ioutil.ReadAll(resp.Body) + panic(errors.Errorf("main(): Received non 200 response code: "+ + "Status Code: %v Body: %v", resp.StatusCode, string(bodyBytes))) + } + + var decodedResponse TResponse + + // Process Response. + err = json.NewDecoder(resp.Body).Decode(&decodedResponse) + if err != nil { + panic(errors.Wrap(err, "main(): Failed to decode response\n")) + } + err = resp.Body.Close() + if err != nil { + panic(errors.Wrap(err, "main(): Failed to decode body\n")) + } + + return decodedResponse +} + +func signAndSubmitTxn(txn *lib.MsgDeSoTxn, privKey *btcec.PrivateKey, nodeURL string) { + signature, err := txn.Sign(privKey) + if err != nil { + panic(err) + } + + txn.Signature.SetSignature(signature) + + txnBytes, err := txn.ToBytes(false) + if err != nil { + panic(err) + } + + txnHex := hex.EncodeToString(txnBytes) + + submitTransactionRequest := routes.SubmitTransactionRequest{ + TransactionHex: txnHex, + } + + makePostRequest[routes.SubmitTransactionRequest, routes.SubmitTransactionResponse]( + nodeURL+routes.RoutePathSubmitTransaction, submitTransactionRequest, + ) +} + +func constructSendDESOTxn(senderPubKey *lib.PublicKey, recipientPubKey *lib.PublicKey) routes.SendDeSoResponse { + senderPublicKeyString := lib.PkToString(senderPubKey.ToBytes(), params) + recipientPublicKeyString := lib.PkToString(recipientPubKey.ToBytes(), params) + + sendDESOTxnRequest := routes.SendDeSoRequest{ + SenderPublicKeyBase58Check: senderPublicKeyString, + RecipientPublicKeyOrUsername: recipientPublicKeyString, + AmountNanos: 11 * 1e9, + MinFeeRateNanosPerKB: 1000, + } + + return makePostRequest[routes.SendDeSoRequest, routes.SendDeSoResponse]( + nodeApiUrl+routes.RoutePathSendDeSo, sendDESOTxnRequest, + ) +} + +func constructRegisterAsValidatorTxn(keystore *lib.BLSKeystore, pubKey *lib.PublicKey) routes.ValidatorTxnResponse { + _, votingAuthorization := getBLSVotingAuthorizationAndPublicKey(keystore, pubKey) + + publicKeyString := lib.PkToString(pubKey.ToBytes(), params) + + request := routes.RegisterAsValidatorRequest{ + TransactorPublicKeyBase58Check: publicKeyString, + Domains: []string{validatorDomain}, + DisableDelegatedStake: false, + VotingPublicKey: keystore.GetSigner().GetPublicKey().ToString(), + VotingAuthorization: votingAuthorization.ToString(), + ExtraData: map[string]string{}, + MinFeeRateNanosPerKB: 1000, + TransactionFees: []routes.TransactionFee{}, + } + + return makePostRequest[routes.RegisterAsValidatorRequest, routes.ValidatorTxnResponse]( + nodeApiUrl+routes.RoutePathValidators+"/register", request, + ) +} + +func constructStakeTxn(pubKey *lib.PublicKey) routes.StakeTxnResponse { + publicKeyString := lib.PkToString(pubKey.ToBytes(), params) + + request := routes.StakeRequest{ + TransactorPublicKeyBase58Check: publicKeyString, + ValidatorPublicKeyBase58Check: publicKeyString, + RewardMethod: routes.PayToBalance, + StakeAmountNanos: uint256.NewInt().SetUint64(9 * 1e9), + ExtraData: map[string]string{}, + MinFeeRateNanosPerKB: 1000, + TransactionFees: []routes.TransactionFee{}, + } + + return makePostRequest[routes.StakeRequest, routes.StakeTxnResponse](nodeApiUrl+routes.RoutePathStake, request) +} + +func generatePubAndPrivKeys(seedPhrase string) (*lib.PublicKey, *btcec.PrivateKey) { + seedBytes, err := bip39.NewSeedWithErrorChecking(seedPhrase, "") + if err != nil { + panic(errors.Wrap(err, "main(): Could not generate key pair from mnemonic")) + } + + pubKey, privKey, _, err := lib.ComputeKeysFromSeed(seedBytes, 0, &lib.DeSoTestnetParams) + if err != nil { + panic(errors.Wrap(err, "main(): Could not generate key pair from mnemonic")) + } + + publicKey := lib.NewPublicKey(pubKey.SerializeCompressed()) + return publicKey, privKey +} + +func generateKeystore(seedPhrase string) *lib.BLSKeystore { + keystore, err := lib.NewBLSKeystore(seedPhrase) + if err != nil { + panic(errors.Wrap(err, "main(): Could not generate keystore")) + } + return keystore +} + +func main() { + fmt.Printf("Network Type: %s\n", params.NetworkType.String()) + + desoSourcePubKey, desoSourcePrivKey := generatePubAndPrivKeys(desoSourceSeedPhrase) + + validatorKeystore := generateKeystore(validatorSeedPhrase) + validatorPubKey, validatorPrivKey := generatePubAndPrivKeys(validatorSeedPhrase) + + // First send some DESO to the validator + sendDESOTxn := constructSendDESOTxn(desoSourcePubKey, validatorPubKey) + signAndSubmitTxn(sendDESOTxn.Transaction, desoSourcePrivKey, nodeApiUrl) + fmt.Println("DESO Sent ") + + time.Sleep(5 * time.Second) + + // Register the validator + validatorRegistrationTxn := constructRegisterAsValidatorTxn(validatorKeystore, validatorPubKey) + signAndSubmitTxn(validatorRegistrationTxn.Transaction, validatorPrivKey, nodeApiUrl) + fmt.Println("Validator Registered") + + time.Sleep(5 * time.Second) + + // Have the validator stake to itself + stakeTxn := constructStakeTxn(validatorPubKey) + signAndSubmitTxn(stakeTxn.Transaction, validatorPrivKey, nodeApiUrl) + fmt.Println("Stake Transaction Submitted") +} diff --git a/test.Dockerfile b/test.Dockerfile index e0cca585..89bc12bb 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -23,7 +23,6 @@ RUN git pull && \ git pull origin feature/proof-of-stake # TODO: Revert to `git pull` once core PR is merged. RUN go mod download -RUN ./scripts/install-relic.sh # Try to checkout to the specified branch. If it fails, checkout main. RUN git checkout ${BRANCH_NAME} || (echo "Branch ${BRANCH_NAME} not found. Falling back to main." && git checkout main) @@ -50,4 +49,4 @@ COPY main.go . # build backend RUN GOOS=linux go build -mod=mod -a -installsuffix cgo -o bin/backend main.go -ENTRYPOINT ["go", "test", "-tags", "relic", "-v", "github.com/deso-protocol/backend/routes"] +ENTRYPOINT ["go", "test", "-v", "github.com/deso-protocol/backend/routes"] From 53d53af70312153be72f76fa77ebccb0fed6d69a Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 21 Mar 2024 18:24:33 -0400 Subject: [PATCH 36/99] Update usages of EnumerateKeysForPrefix (#559) --- routes/exchange_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/routes/exchange_test.go b/routes/exchange_test.go index ad159f5f..be9add02 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -1344,12 +1344,13 @@ func TestAPI(t *testing.T) { // block reward rather than three. { prefix := lib.DbTxindexTxIDKey(&lib.BlockHash{})[0] - txnsInTransactionIndex, _ := lib.EnumerateKeysForPrefix(apiServer.TXIndex.TXIndexChain.DB(), []byte{prefix}) + txnsInTransactionIndex, _ := lib.EnumerateKeysForPrefix( + apiServer.TXIndex.TXIndexChain.DB(), []byte{prefix}, true) require.Equal(1+len(apiServer.Params.SeedTxns)+len(apiServer.Params.SeedBalances), len(txnsInTransactionIndex)) } { keysInPublicKeyTable, _ := lib.EnumerateKeysForPrefix( - apiServer.TXIndex.TXIndexChain.DB(), lib.DbTxindexPublicKeyPrefix([]byte{})) + apiServer.TXIndex.TXIndexChain.DB(), lib.DbTxindexPublicKeyPrefix([]byte{}), true) // There should be two keys since one is the miner public key and // the other is a dummy public key corresponding to the input of // a block reward txn. Plus one for the seed balance, which creates @@ -1429,12 +1430,13 @@ func TestAPI(t *testing.T) { // Now everything should be reset properly. { prefix := lib.DbTxindexTxIDKey(&lib.BlockHash{})[0] - txnsInTransactionIndex, _ := lib.EnumerateKeysForPrefix(apiServer.TXIndex.TXIndexChain.DB(), []byte{prefix}) + txnsInTransactionIndex, _ := lib.EnumerateKeysForPrefix( + apiServer.TXIndex.TXIndexChain.DB(), []byte{prefix}, true) require.Equal(5+len(apiServer.Params.SeedTxns)+len(apiServer.Params.SeedBalances), len(txnsInTransactionIndex)) } { keysInPublicKeyTable, _ := lib.EnumerateKeysForPrefix( - apiServer.TXIndex.TXIndexChain.DB(), lib.DbTxindexPublicKeyPrefix([]byte{})) + apiServer.TXIndex.TXIndexChain.DB(), lib.DbTxindexPublicKeyPrefix([]byte{}), true) // Three pairs for the block rewards and two pairs for the transactions // we created. require.Equal(10+ From 6e0c3b80e14a47eefdd18cef407c90261bfa39e2 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 21 Mar 2024 18:26:10 -0400 Subject: [PATCH 37/99] Remove relic tag from validator test (#561) --- routes/validators_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/routes/validators_test.go b/routes/validators_test.go index e2f61459..a98260ea 100644 --- a/routes/validators_test.go +++ b/routes/validators_test.go @@ -1,5 +1,3 @@ -//go:build relic - package routes import ( From 42462cdaa6c603badd14100df7b0c395a9a17db4 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 28 Mar 2024 12:43:39 -0400 Subject: [PATCH 38/99] Allow orphans in block index (#567) --- scripts/tools/toolslib/chain.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/tools/toolslib/chain.go b/scripts/tools/toolslib/chain.go index 2b712f09..b2df849a 100644 --- a/scripts/tools/toolslib/chain.go +++ b/scripts/tools/toolslib/chain.go @@ -19,14 +19,14 @@ func OpenDataDir(dataDir string) (*badger.DB, error) { } // Returns the best chain associated with a badgerDB handle. -func GetBestChainFromBadger(syncedDBHandle *badger.DB) ([]*lib.BlockNode, error) { +func GetBestChainFromBadger(syncedDBHandle *badger.DB, params *lib.DeSoParams) ([]*lib.BlockNode, error) { bestBlockHash := lib.DbGetBestHash(syncedDBHandle, nil, lib.ChainTypeDeSoBlock) if bestBlockHash == nil { return nil, errors.Errorf("GetBestChainFromBadger() could not find a blockchain in the provided db") } // Fetch the block index. - blockIndex, err := lib.GetBlockIndex(syncedDBHandle, false /*bitcoinNodes*/) + blockIndex, err := lib.GetBlockIndex(syncedDBHandle, false /*bitcoinNodes*/, params) if err != nil { return nil, errors.Errorf("GetBestChainFromBadger() could not get blockIndex") } From 782ff5e5fcfe7416db52be760f649650205977a1 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 29 Mar 2024 16:15:18 -0400 Subject: [PATCH 39/99] Fix max block size logic (#568) --- routes/transaction.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/routes/transaction.go b/routes/transaction.go index b18c42bb..14daf9fb 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4265,7 +4265,15 @@ func (fes *APIServer) GetTxnConstructionParams(ww http.ResponseWriter, req *http maxBlockSize := requestData.MaxBlockSize if requestData.MaxBlockSize == 0 { - maxBlockSize = fes.Params.MaxBlockSizeBytes + maxBlockSize = fes.Params.MaxBlockSizeBytesPoW + if fes.Params.IsPoSBlockHeight(uint64(fes.blockchain.BlockTip().Height)) { + uncommittedTipView, err := fes.blockchain.GetUncommittedTipView() + if err != nil { + _AddBadRequestError(ww, "GetTxnConstructionParams: Problem getting uncommitted tip view: "+err.Error()) + return + } + maxBlockSize = uncommittedTipView.GetSoftMaxBlockSizeBytesPoS() + } } // Get the fees from the mempool From 5efbb3fc09f1f933f562c203d8b952979da63619 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 29 Mar 2024 18:08:38 -0400 Subject: [PATCH 40/99] Empty commit to trigger CI From 1c65e5f6c02b3423e27718363d2c596811a59705 Mon Sep 17 00:00:00 2001 From: diamondhands0 <81935176+diamondhands0@users.noreply.github.com> Date: Mon, 1 Apr 2024 16:23:16 -0700 Subject: [PATCH 41/99] Upgrade Badger version (#566) --- cmd/node.go | 2 +- go.mod | 40 +-- go.sum | 342 ++++------------------- routes/exchange_test.go | 2 +- routes/global_state.go | 2 +- routes/server.go | 2 +- routes/user.go | 2 +- scripts/tools/clear_ancestral_records.go | 3 +- scripts/tools/toolslib/chain.go | 2 +- 9 files changed, 75 insertions(+), 322 deletions(-) diff --git a/cmd/node.go b/cmd/node.go index 38d55113..08093982 100644 --- a/cmd/node.go +++ b/cmd/node.go @@ -7,7 +7,7 @@ import ( "github.com/deso-protocol/backend/routes" coreCmd "github.com/deso-protocol/core/cmd" "github.com/deso-protocol/core/lib" - "github.com/dgraph-io/badger/v3" + "github.com/dgraph-io/badger/v4" "github.com/golang/glog" "github.com/kevinburke/twilio-go" ) diff --git a/go.mod b/go.mod index 1046a98b..a5a3ac73 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ go 1.20 replace github.com/deso-protocol/core => ../core/ require ( - cloud.google.com/go/storage v1.15.0 + cloud.google.com/go/storage v1.27.0 github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcutil v1.0.2 github.com/davecgh/go-spew v1.1.1 github.com/deso-protocol/core v0.0.0-00010101000000-000000000000 github.com/deso-protocol/go-deadlock v1.0.0 - github.com/dgraph-io/badger/v3 v3.2103.5 + github.com/dgraph-io/badger/v4 v4.2.0 github.com/fatih/structs v1.1.0 github.com/golang-jwt/jwt/v4 v4.1.0 github.com/golang/glog v1.0.0 @@ -28,24 +28,26 @@ require ( github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/tyler-smith/go-bip39 v1.1.0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d golang.org/x/image v0.15.0 golang.org/x/sync v0.1.0 - google.golang.org/api v0.46.0 + google.golang.org/api v0.103.0 gopkg.in/DataDog/dd-trace-go.v1 v1.29.0 ) require ( - cloud.google.com/go v0.81.0 // indirect + cloud.google.com/go v0.107.0 // indirect + cloud.google.com/go/compute v1.15.1 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v0.8.0 // indirect github.com/DataDog/datadog-go v4.5.0+incompatible // indirect github.com/Microsoft/go-winio v0.4.16 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/bwesterb/go-ristretto v1.2.0 // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cloudflare/circl v1.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect @@ -67,15 +69,15 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.3 // indirect github.com/google/flatbuffers v2.0.0+incompatible // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 // indirect - github.com/google/uuid v1.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.8 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jstemmer/go-junit-report v0.9.1 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 // indirect github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect @@ -111,21 +113,19 @@ require ( github.com/vmihailenco/msgpack/v5 v5.3.1 // indirect github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - go.opencensus.io v0.23.0 // indirect - golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.6.0 // indirect - golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/oauth2 v0.4.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect golang.org/x/tools v0.6.0 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gonum.org/v1/gonum v0.6.1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab // indirect - google.golang.org/grpc v1.37.0 // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/grpc v1.53.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/AlecAivazis/survey.v1 v1.8.7 // indirect gopkg.in/ini.v1 v1.51.0 // indirect gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect diff --git a/go.sum b/go.sum index 1c3ac420..056a9eb6 100644 --- a/go.sum +++ b/go.sum @@ -5,40 +5,22 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.15.0 h1:Ljj+ZXVEhCr/1+4ZhvtteN1ND7UUsNTlduGclLh8GO0= -cloud.google.com/go/storage v1.15.0/go.mod h1:mjjQMoxxyGH7Jr8K5qrx6N2O0AHsczI61sMNn03GIZI= +cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= @@ -63,7 +45,6 @@ github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= @@ -74,7 +55,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -108,10 +88,10 @@ github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7N github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -120,17 +100,11 @@ github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GK github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -150,8 +124,8 @@ github.com/deso-protocol/go-deadlock v1.0.0 h1:mw0pHy/19zgC+JFBStuQt1+1Ehv5OKA5N github.com/deso-protocol/go-deadlock v1.0.0/go.mod h1:K0Wd2OV2x7ck7SMYDraWerpKjFKUeBqaFcwz21tmkb8= github.com/deso-protocol/go-merkle-tree v1.0.0 h1:9zkI5dQsITYy77s4kbTGPQmZnhQ+LsH/kRdL5l/Yzvg= github.com/deso-protocol/go-merkle-tree v1.0.0/go.mod h1:V/vbg/maaNv6G7zf9VVs645nLFx/jsO2L/awFB/S/ZU= -github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= -github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= +github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= +github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -170,9 +144,6 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.9.25 h1:mMiw/zOOtCLdGLWfcekua0qPrJTe7FVIiHJ4IKNTfR0= github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= @@ -195,8 +166,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/git-chglog/git-chglog v0.0.0-20200414013904-db796966b373 h1:MHrlpWOOFhCfY1L9iCIUy5cv5HgDtempICenzJt+7ws= github.com/git-chglog/git-chglog v0.0.0-20200414013904-db796966b373/go.mod h1:Dcsy1kii/xFyNad5JqY/d0GO5mu91sungp5xotbm3Yk= 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/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -221,25 +190,16 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 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= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -249,7 +209,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -258,47 +217,37 @@ github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI= github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210125172800-10e9aeb4a998/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= @@ -327,9 +276,6 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -343,7 +289,6 @@ github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -361,8 +306,6 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22 github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -394,7 +337,6 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -496,7 +438,6 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -519,13 +460,10 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= @@ -533,7 +471,6 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= @@ -542,8 +479,9 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8 github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= 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 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -552,8 +490,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= @@ -571,7 +510,6 @@ github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkU github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/unrolled/secure v1.0.8 h1:JaMvKbe4CRt8oyxVXn+xY+6jlqd7pyJNSVkmsBxxQsM= github.com/unrolled/secure v1.0.8/go.mod h1:fO+mEan+FLB0CdEnHf6Q4ZZVNqG+5fuLFnP8p0BXDPI= github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= @@ -593,20 +531,13 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -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.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -615,7 +546,6 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -639,16 +569,10 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 h1:A1gGSx58LAGVHUUsOf7IiR0u8Xb6W51gRwfDBhkdcaw= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= @@ -659,26 +583,16 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -696,65 +610,31 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c h1:SgVl/sCtkicsS7psKkje4H9YtjdEl3xsYh7N+5TDHqY= -golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -765,7 +645,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -774,69 +653,37 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w 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= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -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-20210503080704-8803ae5d1324/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= -golang.org/x/text v0.3.6/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/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -859,49 +706,19 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn 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-20191112195655-aa38f8e97acc/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= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.1 h1:/LSrTrgZtpbXyAR6+0e152SROCkJJSh7goYWVmdPFGc= gonum.org/v1/gonum v0.6.1/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -913,31 +730,13 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= -google.golang.org/api v0.46.0 h1:jkDWHOBIoNSD0OQpq4rtBVu+Rh325MPjXG1rakAp8JU= -google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= +google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -949,60 +748,18 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -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-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= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210420162539-3c870d7478d2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab h1:dkb90hr43A2Q5as5ZBphcOF2II0+EqfCBqGp7qFSpN4= -google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1011,11 +768,11 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/AlecAivazis/survey.v1 v1.8.7 h1:oBJqtgsyBLg9K5FK9twNUbcPnbCPoh+R9a+7nag3qJM= gopkg.in/AlecAivazis/survey.v1 v1.8.7/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= gopkg.in/DataDog/dd-trace-go.v1 v1.29.0 h1:3C1EEjgFTPqrnS2SXuSqkBbZGacIOPJ7ScGJk4nrP9s= @@ -1023,7 +780,6 @@ gopkg.in/DataDog/dd-trace-go.v1 v1.29.0/go.mod h1:FLwUDeuH0z5hkvgvd04/M3MHQN4AF5 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1055,12 +811,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w= mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ= pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/routes/exchange_test.go b/routes/exchange_test.go index be9add02..9f0d1674 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -17,7 +17,7 @@ import ( coreCmd "github.com/deso-protocol/core/cmd" "github.com/deso-protocol/core/lib" - "github.com/dgraph-io/badger/v3" + "github.com/dgraph-io/badger/v4" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/routes/global_state.go b/routes/global_state.go index 3f761b3b..85d5f1fd 100644 --- a/routes/global_state.go +++ b/routes/global_state.go @@ -10,7 +10,7 @@ import ( "github.com/deso-protocol/core/lib" - "github.com/dgraph-io/badger/v3" + "github.com/dgraph-io/badger/v4" "github.com/nyaruka/phonenumbers" "github.com/pkg/errors" ) diff --git a/routes/server.go b/routes/server.go index 2a90dd2f..628e08c4 100644 --- a/routes/server.go +++ b/routes/server.go @@ -19,7 +19,7 @@ import ( "github.com/tyler-smith/go-bip39" "github.com/deso-protocol/core/lib" - "github.com/dgraph-io/badger/v3" + "github.com/dgraph-io/badger/v4" "github.com/golang/glog" "github.com/kevinburke/twilio-go" muxtrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/gorilla/mux" diff --git a/routes/user.go b/routes/user.go index 410a94d2..2484e844 100644 --- a/routes/user.go +++ b/routes/user.go @@ -18,7 +18,7 @@ import ( "github.com/holiman/uint256" "github.com/btcsuite/btcd/btcec" - "github.com/dgraph-io/badger/v3" + "github.com/dgraph-io/badger/v4" "github.com/gorilla/mux" "github.com/deso-protocol/core/lib" diff --git a/scripts/tools/clear_ancestral_records.go b/scripts/tools/clear_ancestral_records.go index 7f862488..1b5aa1c8 100644 --- a/scripts/tools/clear_ancestral_records.go +++ b/scripts/tools/clear_ancestral_records.go @@ -2,9 +2,10 @@ package main import ( "fmt" + "github.com/deso-protocol/backend/scripts/tools/toolslib" "github.com/deso-protocol/core/lib" - "github.com/dgraph-io/badger/v3" + "github.com/dgraph-io/badger/v4" "github.com/pkg/errors" ) diff --git a/scripts/tools/toolslib/chain.go b/scripts/tools/toolslib/chain.go index b2df849a..032b5662 100644 --- a/scripts/tools/toolslib/chain.go +++ b/scripts/tools/toolslib/chain.go @@ -2,7 +2,7 @@ package toolslib import ( "github.com/deso-protocol/core/lib" - "github.com/dgraph-io/badger/v3" + "github.com/dgraph-io/badger/v4" "github.com/pkg/errors" ) From 993b149c898ff04c34ae4ae8ec4e65a7954b2742 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Mon, 1 Apr 2024 19:36:22 -0400 Subject: [PATCH 42/99] Fix Update global params tests (#571) --- routes/admin_transaction_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/routes/admin_transaction_test.go b/routes/admin_transaction_test.go index 20ecfd4d..fd8229e0 100644 --- a/routes/admin_transaction_test.go +++ b/routes/admin_transaction_test.go @@ -97,20 +97,20 @@ func TestUpdateGlobalParams(t *testing.T) { // Update all GlobalParam fields. updateGlobalParams(&UpdateGlobalParamsRequest{ UpdaterPublicKeyBase58Check: senderPkString, - MinimumNetworkFeeNanosPerKB: 99, + MinimumNetworkFeeNanosPerKB: 1000, StakeLockupEpochDuration: 4, ValidatorJailEpochDuration: 4, LeaderScheduleMaxNumValidators: 101, ValidatorSetMaxNumValidators: 102, EpochDurationNumBlocks: 3601, JailInactiveValidatorGracePeriodEpochs: 49, - MinFeeRateNanosPerKB: 99, + MinFeeRateNanosPerKB: 1000, }) } { // Verify all updated GlobalParam fields. globalParams := getGlobalParams() - require.Equal(t, globalParams.MinimumNetworkFeeNanosPerKB, uint64(99)) + require.Equal(t, globalParams.MinimumNetworkFeeNanosPerKB, uint64(1000)) require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(4)) require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(4)) require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(101)) @@ -122,15 +122,15 @@ func TestUpdateGlobalParams(t *testing.T) { // Update only one GlobalParam field. updateGlobalParams(&UpdateGlobalParamsRequest{ UpdaterPublicKeyBase58Check: senderPkString, - MinimumNetworkFeeNanosPerKB: 99, + MinimumNetworkFeeNanosPerKB: 1000, JailInactiveValidatorGracePeriodEpochs: 50, - MinFeeRateNanosPerKB: 99, + MinFeeRateNanosPerKB: 1000, }) } { // Verify updated GlobalParam field. And other fields retain old values. globalParams := getGlobalParams() - require.Equal(t, globalParams.MinimumNetworkFeeNanosPerKB, uint64(99)) + require.Equal(t, globalParams.MinimumNetworkFeeNanosPerKB, uint64(1000)) require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(4)) require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(4)) require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(101)) From 38c3cf7ad49d7e327411e043bff94bc71bcefae5 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 2 Apr 2024 14:20:25 -0400 Subject: [PATCH 43/99] trigger build (#572) From c32371570aa84672043216f707958a154a1598d1 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 2 Apr 2024 14:53:37 -0400 Subject: [PATCH 44/99] trigger build (#573) From 323b8bd2fedab20e2ac00ee7db762c53c924367d Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 2 Apr 2024 15:23:41 -0400 Subject: [PATCH 45/99] trigger build (#574) From 5e71dafae22f7725d6b4722813400b93a4b27d6e Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 3 Apr 2024 18:40:42 -0400 Subject: [PATCH 46/99] Empty commit to trigger CI From 99e2e4ab8e31bd674e9924ec22b53ab18b349cb8 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 4 Apr 2024 10:40:15 -0400 Subject: [PATCH 47/99] bls pub key enhancements build (#576) From eb8bc223b6b66eb7e8ab5b7f91f57160221d9d60 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 4 Apr 2024 10:58:49 -0400 Subject: [PATCH 48/99] allow txn relay in needs blocks build (#577) From c7c9a7818f518bdc8e9c84c9aceb7c1f04d508da Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:39:45 -0400 Subject: [PATCH 49/99] fix txn relay pos check build (#578) From 01cff1f8922a5963ab7c9dbf2e7eb9a5ddedcf23 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Thu, 4 Apr 2024 17:37:48 -0400 Subject: [PATCH 50/99] Empty commit to trigger CI From 998a1b6a74966f21e92e55b12c14a3b3ec20bf57 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Thu, 4 Apr 2024 17:56:57 -0400 Subject: [PATCH 51/99] Fix backend CI --- routes/admin_transaction_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/admin_transaction_test.go b/routes/admin_transaction_test.go index fd8229e0..44eaf3cc 100644 --- a/routes/admin_transaction_test.go +++ b/routes/admin_transaction_test.go @@ -90,7 +90,7 @@ func TestUpdateGlobalParams(t *testing.T) { require.Equal(t, globalParams.StakeLockupEpochDuration, uint64(3)) require.Equal(t, globalParams.ValidatorJailEpochDuration, uint64(3)) require.Equal(t, globalParams.LeaderScheduleMaxNumValidators, uint64(100)) - require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(10)) + require.Equal(t, globalParams.EpochDurationNumBlocks, uint64(144)) require.Equal(t, globalParams.JailInactiveValidatorGracePeriodEpochs, uint64(3)) } { From 08039b75da88be7be332b06c47c449ef8e1cb4c8 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:41:44 -0400 Subject: [PATCH 52/99] Use GetCurrentGlobalParamsEntry instead of GlobalParamsEntry (#580) --- .gitignore | 2 ++ routes/base.go | 2 +- routes/nft.go | 32 ++++++++++++++++---------------- routes/shared.go | 5 +++-- routes/transaction.go | 4 ++-- routes/user.go | 2 +- routes/verify.go | 4 +++- 7 files changed, 28 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 0ff977e4..92068074 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ backend .idea .vscode mem.log + +__debug_* \ No newline at end of file diff --git a/routes/base.go b/routes/base.go index ce0359a0..bfdc91ce 100644 --- a/routes/base.go +++ b/routes/base.go @@ -389,7 +389,7 @@ func (fes *APIServer) GetAppState(ww http.ResponseWriter, req *http.Request) { } // Compute a default fee rate. - globalParams := utxoView.GlobalParamsEntry + globalParams := utxoView.GetCurrentGlobalParamsEntry() defaultFeeRateNanosPerKB := fes.MinFeeRateNanosPerKB if globalParams != nil && globalParams.MinimumNetworkFeeNanosPerKB > 0 { defaultFeeRateNanosPerKB = globalParams.MinimumNetworkFeeNanosPerKB diff --git a/routes/nft.go b/routes/nft.go index c6affae5..65fbe757 100644 --- a/routes/nft.go +++ b/routes/nft.go @@ -124,15 +124,15 @@ func (fes *APIServer) CreateNFT(ww http.ResponseWriter, req *http.Request) { } else if requestData.UpdaterPublicKeyBase58Check == "" { _AddBadRequestError(ww, fmt.Sprintf("CreateNFT: Must include UpdaterPublicKeyBase58Check")) return - } else if utxoView.GlobalParamsEntry.MaxCopiesPerNFT == 0 { + } else if utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT == 0 { _AddBadRequestError(ww, "NFT minting has not been enabled yet. Check back soon :)") return - } else if requestData.NumCopies <= 0 || requestData.NumCopies > int(utxoView.GlobalParamsEntry.MaxCopiesPerNFT) { + } else if requestData.NumCopies <= 0 || requestData.NumCopies > int(utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT) { _AddBadRequestError(ww, fmt.Sprintf( "CreateNFT: NumCopies must be between %d and %d, received: %d", - 1, utxoView.GlobalParamsEntry.MaxCopiesPerNFT, requestData.NumCopies)) + 1, utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT, requestData.NumCopies)) return } else if requestData.NFTRoyaltyToCreatorBasisPoints < 0 || requestData.NFTRoyaltyToCreatorBasisPoints > int(fes.Params.MaxNFTRoyaltyBasisPoints) { @@ -238,7 +238,7 @@ func (fes *APIServer) CreateNFT(ww http.ResponseWriter, req *http.Request) { return } - nftFee := utxoView.GlobalParamsEntry.CreateNFTFeeNanos * uint64(requestData.NumCopies) + nftFee := utxoView.GetCurrentGlobalParamsEntry().CreateNFTFeeNanos * uint64(requestData.NumCopies) extraData, err := EncodeExtraDataMap(requestData.ExtraData) if err != nil { @@ -342,10 +342,10 @@ func (fes *APIServer) UpdateNFT(ww http.ResponseWriter, req *http.Request) { _AddBadRequestError(ww, fmt.Sprintf("UpdateNFT: Must include UpdaterPublicKeyBase58Check")) return - } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GlobalParamsEntry.MaxCopiesPerNFT) { + } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT) { _AddBadRequestError(ww, fmt.Sprintf( "UpdateNFT: SerialNumbers must be between %d and %d, received: %d", - 1, utxoView.GlobalParamsEntry.MaxCopiesPerNFT, requestData.SerialNumber)) + 1, utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT, requestData.SerialNumber)) return } else if requestData.MinBidAmountNanos < 0 { @@ -492,10 +492,10 @@ func (fes *APIServer) CreateNFTBid(ww http.ResponseWriter, req *http.Request) { _AddBadRequestError(ww, fmt.Sprintf("CreateNFTBid: Must include UpdaterPublicKeyBase58Check")) return - } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GlobalParamsEntry.MaxCopiesPerNFT) { + } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT) { _AddBadRequestError(ww, fmt.Sprintf( "CreateNFTBid: SerialNumbers must be between %d and %d, received: %d", - 1, utxoView.GlobalParamsEntry.MaxCopiesPerNFT, requestData.SerialNumber)) + 1, utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT, requestData.SerialNumber)) return } else if requestData.BidAmountNanos < 0 { @@ -654,10 +654,10 @@ func (fes *APIServer) AcceptNFTBid(ww http.ResponseWriter, req *http.Request) { "AcceptNFTBid: Must include UpdaterPublicKeyBase58Check and BidderPublicKeyBase58Check")) return - } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GlobalParamsEntry.MaxCopiesPerNFT) { + } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT) { _AddBadRequestError(ww, fmt.Sprintf( "AcceptNFTBid: SerialNumbers must be between %d and %d, received: %d", - 1, utxoView.GlobalParamsEntry.MaxCopiesPerNFT, requestData.SerialNumber)) + 1, utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT, requestData.SerialNumber)) return } else if requestData.BidAmountNanos < 0 { @@ -1573,10 +1573,10 @@ func (fes *APIServer) TransferNFT(ww http.ResponseWriter, req *http.Request) { _AddBadRequestError(ww, fmt.Sprintf("TransferNFT: Must include UpdaterPublicKeyBase58Check")) return - } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GlobalParamsEntry.MaxCopiesPerNFT) { + } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT) { _AddBadRequestError(ww, fmt.Sprintf( "TransferNFT: SerialNumbers must be between %d and %d, received: %d", - 1, utxoView.GlobalParamsEntry.MaxCopiesPerNFT, requestData.SerialNumber)) + 1, utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT, requestData.SerialNumber)) return } @@ -1730,10 +1730,10 @@ func (fes *APIServer) AcceptNFTTransfer(ww http.ResponseWriter, req *http.Reques _AddBadRequestError(ww, fmt.Sprintf("AcceptNFTTransfer: Must include UpdaterPublicKeyBase58Check")) return - } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GlobalParamsEntry.MaxCopiesPerNFT) { + } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT) { _AddBadRequestError(ww, fmt.Sprintf( "AcceptNFTTransfer: SerialNumbers must be between %d and %d, received: %d", - 1, utxoView.GlobalParamsEntry.MaxCopiesPerNFT, requestData.SerialNumber)) + 1, utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT, requestData.SerialNumber)) return } @@ -1869,10 +1869,10 @@ func (fes *APIServer) BurnNFT(ww http.ResponseWriter, req *http.Request) { _AddBadRequestError(ww, fmt.Sprintf("BurnNFT: Must include UpdaterPublicKeyBase58Check")) return - } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GlobalParamsEntry.MaxCopiesPerNFT) { + } else if requestData.SerialNumber <= 0 || requestData.SerialNumber > int(utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT) { _AddBadRequestError(ww, fmt.Sprintf( "BurnNFT: SerialNumbers must be between %d and %d, received: %d", - 1, utxoView.GlobalParamsEntry.MaxCopiesPerNFT, requestData.SerialNumber)) + 1, utxoView.GetCurrentGlobalParamsEntry().MaxCopiesPerNFT, requestData.SerialNumber)) return } diff --git a/routes/shared.go b/routes/shared.go index d5a67200..0a38d046 100644 --- a/routes/shared.go +++ b/routes/shared.go @@ -394,8 +394,9 @@ func (fes *APIServer) SendSeedDeSo(recipientPkBytes []byte, amountNanos uint64, } minFee := fes.MinFeeRateNanosPerKB - if utxoView.GlobalParamsEntry != nil && utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB > 0 { - minFee = utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB + if utxoView.GetCurrentGlobalParamsEntry() != nil && + utxoView.GetCurrentGlobalParamsEntry().MinimumNetworkFeeNanosPerKB > 0 { + minFee = utxoView.GetCurrentGlobalParamsEntry().MinimumNetworkFeeNanosPerKB } _, _, _, _, err = fes.blockchain.AddInputsAndChangeToTransaction(txn, minFee, fes.backendServer.GetMempool()) if err != nil { diff --git a/routes/transaction.go b/routes/transaction.go index 14daf9fb..301c4339 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -478,7 +478,7 @@ func (fes *APIServer) CompProfileCreation(profilePublicKey []byte, userMetadata return 0, nil, nil } // Additional fee is set to the create profile fee when we are creating a profile - additionalFees := utxoView.GlobalParamsEntry.CreateProfileFeeNanos + additionalFees := utxoView.GetCurrentGlobalParamsEntry().CreateProfileFeeNanos if additionalFees == 0 { return 0, nil, nil } @@ -496,7 +496,7 @@ func (fes *APIServer) CompProfileCreation(profilePublicKey []byte, userMetadata if err != nil { return 0, nil, errors.Wrap(fmt.Errorf("UpdateProfile: error getting current balance: %v", err), "") } - createProfileFeeNanos := utxoView.GlobalParamsEntry.CreateProfileFeeNanos + createProfileFeeNanos := utxoView.GetCurrentGlobalParamsEntry().CreateProfileFeeNanos // If a user is jumio verified, we just comp the profile even if their balance is greater than the create profile fee. // If a user has a phone number verified but is not jumio verified, we need to check that they haven't spent all their diff --git a/routes/user.go b/routes/user.go index 2484e844..b837375e 100644 --- a/routes/user.go +++ b/routes/user.go @@ -99,7 +99,7 @@ func (fes *APIServer) updateUsersStateless(userList []*User, skipForLeaderboard if err != nil { return nil, fmt.Errorf("updateUserFields: Error calling GetAugmentedUtxoViewForPublicKey: %v", err) } - globalParams := utxoView.GlobalParamsEntry + globalParams := utxoView.GetCurrentGlobalParamsEntry() for _, user := range userList { // If we get an error updating the user, log it but don't stop the show. if err = fes.updateUserFieldsStateless( diff --git a/routes/verify.go b/routes/verify.go index 9c9910eb..8ac0fe7e 100644 --- a/routes/verify.go +++ b/routes/verify.go @@ -143,7 +143,9 @@ func (fes *APIServer) canUserCreateProfile(userMetadata *UserMetadata, utxoView // User can create a profile if they have a phone number or if they have enough DeSo to cover the create profile fee. // User can also create a profile if they've successfully filled out a captcha. // The PhoneNumber is only set if the user has passed phone number verification. - if userMetadata.PhoneNumber != "" || totalBalanceNanos >= utxoView.GlobalParamsEntry.CreateProfileFeeNanos || userMetadata.LastHcaptchaBlockHeight > 0 { + if userMetadata.PhoneNumber != "" || + totalBalanceNanos >= utxoView.GetCurrentGlobalParamsEntry().CreateProfileFeeNanos || + userMetadata.LastHcaptchaBlockHeight > 0 { return true, nil } From b93bb61606e7c92539a24df88d6030c193122675 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 5 Apr 2024 14:57:50 -0400 Subject: [PATCH 53/99] Empty commit for CI From e1184017b4822548dcefad4f0d21c764a276a894 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 5 Apr 2024 16:10:48 -0400 Subject: [PATCH 54/99] Empty commit for CI From 75737909801404d70b7c1e52169442f3c0f2dde1 Mon Sep 17 00:00:00 2001 From: Jon Pollock <135658176+poolcoke@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:46:50 -0700 Subject: [PATCH 55/99] Atomic Transaction Support for Backend (#560) --- routes/atomic_txns.go | 106 ++++++++++++++++++++++++++++++++++++++++++ routes/server.go | 10 ++++ 2 files changed, 116 insertions(+) create mode 100644 routes/atomic_txns.go diff --git a/routes/atomic_txns.go b/routes/atomic_txns.go new file mode 100644 index 00000000..72b94991 --- /dev/null +++ b/routes/atomic_txns.go @@ -0,0 +1,106 @@ +package routes + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "github.com/deso-protocol/core/lib" + "io" + "net/http" +) + +type CreateAtomicTxnsWrapperRequest struct { + Transactions []*lib.MsgDeSoTxn + ExtraData map[string]string +} + +type CreateAtomicTxnsWrapperResponse struct { + // TransactionsWrapped as a helpful sanity check for the caller of the + // CreateAtomicTxnsWrapper endpoint. That being said, the caller should + // also sanity check that the returned wrapper transaction has the atomic + // transactions ordered correctly. + TransactionsWrapped uint64 `safeForLogging:"true"` + + // TotalFeeNanos represents the total fees paid cumulatively by all + // wrapper atomic transactions and is consistent with the + // returned Transaction.TxnFeeNanos field. + TotalFeeNanos uint64 + Transaction *lib.MsgDeSoTxn + TransactionHex string +} + +func (fes *APIServer) CreateAtomicTxnsWrapper(ww http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := CreateAtomicTxnsWrapperRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateAtomicTxnsWrapper: Error parsing request body: %v", err)) + return + } + + // Grab a view (needed for getting global params, etc). + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateAtomicTxnsWrapper: Error getting utxoView: %v", err)) + return + } + + // Validate the request data. + if len(requestData.Transactions) == 0 { + _AddBadRequestError(ww, fmt.Sprint("CreateAtomicTxnsWrapper: must have at least one transaction "+ + "in Transactions")) + return + } + + // Encode the ExtraData map. + extraData, err := EncodeExtraDataMap(requestData.ExtraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateAtomicTxnsWrapper: Problem encoding ExtraData: %v", err)) + return + } + + // Construct the atomic transactions wrapper transaction type. + txn, totalFees, err := fes.blockchain.CreateAtomicTxnsWrapper(requestData.Transactions, extraData) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateAtomicTxnsWrapper: Problem constructing transaction: %v", err)) + return + } + + // Serialize the transaction. + txnBytes, err := txn.ToBytes(true) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CreateAtomicTxnsWrapper: Problem serializing transaction: %v", err)) + return + } + txnSizeBytes := uint64(len(txnBytes)) + + // Validate that: + // (1) The resulting transaction is not over the size limit of an atomic transaction. + // (2) The resulting wrapper transactions have sufficient fees to cover the wrapper. + if txnSizeBytes > utxoView.GetCurrentGlobalParamsEntry().MaxTxnSizeBytesPoS { + _AddBadRequestError(ww, fmt.Sprint("CreateAtomicTxnsWrapper: Resulting wrapper transaction too large")) + return + } + if txnSizeBytes != 0 && utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB != 0 { + // Check for overflow or minimum network fee not met. + if totalFees != ((totalFees*1000)/1000) || + (totalFees*1000)/uint64(txnSizeBytes) < utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB { + _AddBadRequestError(ww, fmt.Sprint("CreateAtomicTxnsWrapper: Transactions used to construct"+ + " atomic transaction do not cumulatively pay sufficient network fees to cover wrapper")) + return + } + } + + // Construct a response. + res := CreateAtomicTxnsWrapperResponse{ + TransactionsWrapped: uint64(len(txn.TxnMeta.(*lib.AtomicTxnsWrapperMetadata).Txns)), + TotalFeeNanos: totalFees, + Transaction: txn, + TransactionHex: hex.EncodeToString(txnBytes), + } + + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, + fmt.Sprintf("CreateAtomicTxnsWrapper: Problem serializing object to JSON: %v", err)) + return + } +} diff --git a/routes/server.go b/routes/server.go index 628e08c4..8c84afde 100644 --- a/routes/server.go +++ b/routes/server.go @@ -331,6 +331,9 @@ const ( RoutePathCoinUnlock = "/api/v0/coin-unlock" RoutePathLockupYieldCurvePoints = "/api/v0/lockup-yield-curve-points" RoutePathLockedBalanceEntries = "/api/v0/locked-balance-entries" + + // atomic_txns.go + RoutePathCreateAtomicTxnsWrapper = "/api/v0/create-atomic-txns-wrapper" ) // APIServer provides the interface between the blockchain and things like the @@ -1419,6 +1422,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.LockedBalanceEntries, PublicAccess, }, + { + "CreateAtomicTxnsWrapper", + []string{"POST", "OPTIONS"}, + RoutePathCreateAtomicTxnsWrapper, + fes.CreateAtomicTxnsWrapper, + PublicAccess, + }, // Jumio Routes { "JumioBegin", From 61ea63809d1795d95b32973ff4eb0db4feb418c9 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:48:41 -0400 Subject: [PATCH 56/99] Update usage of CreateAtomicTxnsWrapper (#581) --- routes/atomic_txns.go | 7 ++++--- scripts/tools/toolslib/offline_basic_transfer.go | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/routes/atomic_txns.go b/routes/atomic_txns.go index 72b94991..10990def 100644 --- a/routes/atomic_txns.go +++ b/routes/atomic_txns.go @@ -59,7 +59,8 @@ func (fes *APIServer) CreateAtomicTxnsWrapper(ww http.ResponseWriter, req *http. } // Construct the atomic transactions wrapper transaction type. - txn, totalFees, err := fes.blockchain.CreateAtomicTxnsWrapper(requestData.Transactions, extraData) + txn, totalFees, err := fes.blockchain.CreateAtomicTxnsWrapper( + requestData.Transactions, extraData, fes.backendServer.GetMempool()) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateAtomicTxnsWrapper: Problem constructing transaction: %v", err)) return @@ -80,10 +81,10 @@ func (fes *APIServer) CreateAtomicTxnsWrapper(ww http.ResponseWriter, req *http. _AddBadRequestError(ww, fmt.Sprint("CreateAtomicTxnsWrapper: Resulting wrapper transaction too large")) return } - if txnSizeBytes != 0 && utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB != 0 { + if txnSizeBytes != 0 && utxoView.GetCurrentGlobalParamsEntry().MinimumNetworkFeeNanosPerKB != 0 { // Check for overflow or minimum network fee not met. if totalFees != ((totalFees*1000)/1000) || - (totalFees*1000)/uint64(txnSizeBytes) < utxoView.GlobalParamsEntry.MinimumNetworkFeeNanosPerKB { + (totalFees*1000)/uint64(txnSizeBytes) < utxoView.GetCurrentGlobalParamsEntry().MinimumNetworkFeeNanosPerKB { _AddBadRequestError(ww, fmt.Sprint("CreateAtomicTxnsWrapper: Transactions used to construct"+ " atomic transaction do not cumulatively pay sufficient network fees to cover wrapper")) return diff --git a/scripts/tools/toolslib/offline_basic_transfer.go b/scripts/tools/toolslib/offline_basic_transfer.go index f24f6895..2bbe6c36 100644 --- a/scripts/tools/toolslib/offline_basic_transfer.go +++ b/scripts/tools/toolslib/offline_basic_transfer.go @@ -78,7 +78,7 @@ func _computeFee(txn *lib.MsgDeSoTxn, feeRateNanosPerKB uint64) (*lib.MsgDeSoTxn if (uint64(txnWithSigLen)*feeRateNanosPerKB)%1000 != 0 { feeAmountNanos++ } - txn.TxnFeeNanos = uint64(feeAmountNanos) + lib.UpdateTxnFee(txn, uint64(feeAmountNanos)) } return txn, nil } From 001661ca26c33d2c62a36672a4b46c0d85c4ca3c Mon Sep 17 00:00:00 2001 From: Jon Pollock <135658176+poolcoke@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:35:35 -0700 Subject: [PATCH 57/99] Add a Preceding Transaction Field to Transaction Endpoints. (#570) * Simple CreateAtomicTxnsWrapper scaffolding. * Update method on CreateAtomicTxnsWrapper. * Use lib.GetAugmentedUniversalViewWithAdditionalTransactions for UpdateProfile. * Use MaxTxnSizeBytesPoS for atomic transaction construction. * Use updated lib.GetAugmentedUniversalViewWithAdditionalTransactions parameters. * Gate preceding transactions middleware on POST requests. * Use anonymous struct to simplify preceding transaction middleware. * Update stateful transaction endpoints to use GetAugmentedUniversalViewWithAdditionalTransactions. * Simple CreateAtomicTxnsWrapper scaffolding. * Update method on CreateAtomicTxnsWrapper. * Use MaxTxnSizeBytesPoS for atomic transaction construction. * Fix MaxTxnSizeBytes bug --------- Co-authored-by: diamondhands Co-authored-by: Lazy Nina <81658138+lazynina@users.noreply.github.com> --- cmd/run.go | 7 ++++ config/config.go | 6 ++++ routes/access_group.go | 14 ++++++-- routes/admin_transaction.go | 26 +++++++++++--- routes/admin_user.go | 4 +-- routes/atomic_txns.go | 1 + routes/hot_feed.go | 4 +-- routes/nft.go | 49 +++++++++++++++++++++---- routes/server.go | 46 ++++++++++++++++++++++++ routes/stake.go | 14 ++++++-- routes/transaction.go | 72 ++++++++++++++++++++++++++++++------- 11 files changed, 211 insertions(+), 32 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index 02486a57..9c62b2bd 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -112,6 +112,13 @@ func init() { runCmd.PersistentFlags().String("amplitude-key", "", "Client-side amplitude key for instrumenting user behavior.") runCmd.PersistentFlags().String("amplitude-domain", "api.amplitude.com", "Client-side amplitude API Endpoint.") + // Transactions + runCmd.PersistentFlags().Int("max-optional-preceding-transactions", 0, + "If set, enables certain transaction construction "+ + "endpoints to accept transactions that should be connected "+ + "before constructing the specified transaction. "+ + "Setting this flag can aid in workflows that deal with atomic transaction construction.") + // User Interface runCmd.PersistentFlags().String("support-email", "", "Show a support email to users of this node") runCmd.PersistentFlags().Bool("show-processing-spinners", false, diff --git a/config/config.go b/config/config.go index 81b9b47a..a5e566ec 100644 --- a/config/config.go +++ b/config/config.go @@ -46,6 +46,9 @@ type Config struct { // Analytics AmplitudeKey string + // Transactions + MaxOptionalPrecedingTransactions int + // Images GCPCredentialsPath string GCPBucketName string @@ -148,6 +151,9 @@ func LoadConfig(coreConfig *coreCmd.Config) *Config { // Analytics config.AmplitudeKey = viper.GetString("amplitude-key") + // Transactions + config.MaxOptionalPrecedingTransactions = viper.GetInt("max-optional-preceding-transactions") + // Images config.GCPCredentialsPath = viper.GetString("gcp-credentials-path") config.GCPBucketName = viper.GetString("gcp-bucket-name") diff --git a/routes/access_group.go b/routes/access_group.go index 6a5b7278..3da7973b 100644 --- a/routes/access_group.go +++ b/routes/access_group.go @@ -27,6 +27,8 @@ type CreateAccessGroupRequest struct { TransactionFees []TransactionFee `safeForLogging:"true"` // ExtraData is an arbitrary key value map ExtraData map[string]string + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // struct to construct the response to create an access group. @@ -85,7 +87,10 @@ func (fes *APIServer) accessGroupHandler( "public key %s: %v", accessGroupPkBytes, err) } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { return fmt.Errorf("error getting view: %v", err) } @@ -227,6 +232,8 @@ type AddAccessGroupMembersRequest struct { TransactionFees []TransactionFee `safeForLogging:"true"` // ExtraData is an arbitrary key value map ExtraData map[string]string + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // struct to construct the response to create an access group. @@ -274,7 +281,10 @@ func (fes *APIServer) accessGroupMemberHandler( "public key and access group key name %s: %v", requestData.AccessGroupKeyName, err) } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { return fmt.Errorf("error getting utxo view: %v", err) } diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index 4f6bbceb..9cd7e11d 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -157,6 +157,8 @@ type UpdateGlobalParamsRequest struct { // Whether or not we should broadcast the transaction after constructing // it. This will also validate the transaction if it's set. Broadcast bool `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // UpdateGlobalParamsResponse ... @@ -192,7 +194,10 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque } // Get a utxoView. - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateGlobalParams: Error constucting utxoView: %v", err)) return @@ -316,6 +321,8 @@ type SwapIdentityRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // SwapIdentityResponse ... @@ -327,7 +334,13 @@ type SwapIdentityResponse struct { TransactionHex string } -func (fes *APIServer) getPublicKeyFromUsernameOrPublicKeyString(usernameOrPublicKey string) ([]byte, error) { +func (fes *APIServer) getPublicKeyFromUsernameOrPublicKeyString( + usernameOrPublicKey string, + optionalPrecedingTransactions []*lib.MsgDeSoTxn, +) ( + []byte, + error, +) { if (strings.HasPrefix(usernameOrPublicKey, fes.PublicKeyBase58Prefix)) && len(usernameOrPublicKey) >= btcec.PubKeyBytesLenCompressed { @@ -341,7 +354,10 @@ func (fes *APIServer) getPublicKeyFromUsernameOrPublicKeyString(usernameOrPublic } // Otherwise, parse the string as a username - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + optionalPrecedingTransactions, + ) if err != nil { return nil, errors.Wrap(fmt.Errorf("getPublicKeyFromUsernameOrPublicKeyString: Error generating "+ "view to verify username: %v", err), "") @@ -382,13 +398,13 @@ func (fes *APIServer) SwapIdentity(ww http.ResponseWriter, req *http.Request) { } fromPublicKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString( - requestData.FromUsernameOrPublicKeyBase58Check) + requestData.FromUsernameOrPublicKeyBase58Check, requestData.OptionalPrecedingTransactions) if err != nil { _AddBadRequestError(ww, err.Error()) return } toPublicKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString( - requestData.ToUsernameOrPublicKeyBase58Check) + requestData.ToUsernameOrPublicKeyBase58Check, requestData.OptionalPrecedingTransactions) if err != nil { _AddBadRequestError(ww, err.Error()) return diff --git a/routes/admin_user.go b/routes/admin_user.go index f6948806..bc9eb092 100644 --- a/routes/admin_user.go +++ b/routes/admin_user.go @@ -675,7 +675,7 @@ func (fes *APIServer) AdminGrantVerificationBadge(ww http.ResponseWriter, req *h } // Verify the username has an underlying profile - pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(usernameToVerify) + pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(usernameToVerify, nil) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AdminGrantVerificationBadge: Username %s has no associated underlying publickey.", usernameToVerify)) @@ -781,7 +781,7 @@ func (fes *APIServer) AdminRemoveVerificationBadge(ww http.ResponseWriter, req * } // Verify the username has an underlying profile - pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(usernameToRemove) + pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(usernameToRemove, nil) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Username has no associated underlying publickey")) return diff --git a/routes/atomic_txns.go b/routes/atomic_txns.go index 10990def..86539f8c 100644 --- a/routes/atomic_txns.go +++ b/routes/atomic_txns.go @@ -81,6 +81,7 @@ func (fes *APIServer) CreateAtomicTxnsWrapper(ww http.ResponseWriter, req *http. _AddBadRequestError(ww, fmt.Sprint("CreateAtomicTxnsWrapper: Resulting wrapper transaction too large")) return } + if txnSizeBytes != 0 && utxoView.GetCurrentGlobalParamsEntry().MinimumNetworkFeeNanosPerKB != 0 { // Check for overflow or minimum network fee not met. if totalFees != ((totalFees*1000)/1000) || diff --git a/routes/hot_feed.go b/routes/hot_feed.go index 9c1b127a..cf9ce469 100644 --- a/routes/hot_feed.go +++ b/routes/hot_feed.go @@ -1325,7 +1325,7 @@ func (fes *APIServer) AdminUpdateHotFeedUserMultiplier(ww http.ResponseWriter, r } // Verify the username has an underlying profile. - pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(requestData.Username) + pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(requestData.Username, nil) if err != nil { _AddBadRequestError(ww, fmt.Sprintf( @@ -1394,7 +1394,7 @@ func (fes *APIServer) AdminGetHotFeedUserMultiplier(ww http.ResponseWriter, req } // Verify the username has an underlying profile. - pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(requestData.Username) + pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(requestData.Username, nil) if err != nil { _AddBadRequestError(ww, fmt.Sprintf( diff --git a/routes/nft.go b/routes/nft.go index 65fbe757..07cedbd2 100644 --- a/routes/nft.go +++ b/routes/nft.go @@ -89,6 +89,8 @@ type CreateNFTRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type CreateNFTResponse struct { @@ -110,7 +112,10 @@ func (fes *APIServer) CreateNFT(ww http.ResponseWriter, req *http.Request) { } // Grab a view (needed for getting global params, etc). - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateNFT: Error getting utxoView: %v", err)) return @@ -306,6 +311,8 @@ type UpdateNFTRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type UpdateNFTResponse struct { @@ -327,7 +334,10 @@ func (fes *APIServer) UpdateNFT(ww http.ResponseWriter, req *http.Request) { return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateNFT: Error getting utxoView: %v", err)) return @@ -454,6 +464,8 @@ type CreateNFTBidRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type CreateNFTBidResponse struct { @@ -477,7 +489,10 @@ func (fes *APIServer) CreateNFTBid(ww http.ResponseWriter, req *http.Request) { return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateNFTBid: Error getting utxoView: %v", err)) return @@ -615,6 +630,8 @@ type AcceptNFTBidRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type AcceptNFTBidResponse struct { @@ -638,7 +655,10 @@ func (fes *APIServer) AcceptNFTBid(ww http.ResponseWriter, req *http.Request) { return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AcceptNFTBid: Error getting utxoView: %v", err)) return @@ -1531,6 +1551,8 @@ type TransferNFTRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type TransferNFTResponse struct { @@ -1554,7 +1576,10 @@ func (fes *APIServer) TransferNFT(ww http.ResponseWriter, req *http.Request) { return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferNFT: Error getting utxoView: %v", err)) return @@ -1693,6 +1718,8 @@ type AcceptNFTTransferRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type AcceptNFTTransferResponse struct { @@ -1715,7 +1742,10 @@ func (fes *APIServer) AcceptNFTTransfer(ww http.ResponseWriter, req *http.Reques return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("AcceptNFTTransfer: Error getting utxoView: %v", err)) return @@ -1832,6 +1862,8 @@ type BurnNFTRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type BurnNFTResponse struct { @@ -1854,7 +1886,10 @@ func (fes *APIServer) BurnNFT(ww http.ResponseWriter, req *http.Request) { return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("BurnNFT: Error getting utxoView: %v", err)) return diff --git a/routes/server.go b/routes/server.go index 8c84afde..e27ab69d 100644 --- a/routes/server.go +++ b/routes/server.go @@ -2344,6 +2344,7 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { // If the route is not "PublicAccess" we wrap it in a function to check that the caller // has the correct permissions before calling its handler. + handler = CheckPrecedingTransactions(handler, fes.Config.MaxOptionalPrecedingTransactions) if route.AccessLevel != PublicAccess { handler = fes.CheckAdminPublicKey(handler, route.AccessLevel) } @@ -2369,6 +2370,51 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { return router } +// CheckPrecedingTransactions is middleware that ensures any request body with the "OptionalPrecedingTransactions" +// field set is limited in how many transactions are being sent to the server. +// +// By default, the maximum number that can be sent to the server is zero. The OptionalPrecedingTransactions field +// is used in constructing UtxoViews for atomic transaction workflows. +func CheckPrecedingTransactions(inner http.Handler, precedingTransactionsLimit int) http.Handler { + return http.HandlerFunc(func(ww http.ResponseWriter, rr *http.Request) { + // If the request is NOT a POST request, skip this middleware as the request has no relevant payload. + if rr.Method != "POST" { + inner.ServeHTTP(ww, rr) + return + } + + // Read and replace the request body. + data, err := io.ReadAll(rr.Body) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CheckPrecedingTransactions: %v", err)) + return + } + rr.Body.Close() + rr.Body = io.NopCloser(bytes.NewReader(data)) + + // Unmarshal the request such that we snag the OptionalPrecedingTransactions field from relevant endpoints. + var optionalPrecedingTransactionsStruct struct { + OptionalPrecedingTransactions []*lib.MsgDeSoTxn + } + if err := json.Unmarshal(data, &optionalPrecedingTransactionsStruct); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("CheckPrecedingTransactions failed to unmarshal json: %v", err)) + return + } + + // Validate the number of transactions being sent to the endpoint. + if optionalPrecedingTransactionsStruct.OptionalPrecedingTransactions != nil && + len(optionalPrecedingTransactionsStruct.OptionalPrecedingTransactions) > precedingTransactionsLimit { + _AddBadRequestError(ww, + fmt.Sprintf("CheckPrecedingTransactions: too many optional preceding transactions: %d > %d", + len(optionalPrecedingTransactionsStruct.OptionalPrecedingTransactions), precedingTransactionsLimit)) + return + } + + // Pass the request down to the next handler. + inner.ServeHTTP(ww, rr) + }) +} + // Logger ... func Logger(inner http.Handler, name string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/routes/stake.go b/routes/stake.go index 891d9c74..734e4af7 100644 --- a/routes/stake.go +++ b/routes/stake.go @@ -55,6 +55,8 @@ type StakeRequest struct { ExtraData map[string]string `safeForLogging:"true"` MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type UnstakeRequest struct { @@ -64,6 +66,8 @@ type UnstakeRequest struct { ExtraData map[string]string `safeForLogging:"true"` MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } type UnlockStakeRequest struct { @@ -159,7 +163,10 @@ func (fes *APIServer) CreateStakeTxn(ww http.ResponseWriter, req *http.Request) return } stakeAmountNanosUint64 := requestData.StakeAmountNanos.Uint64() - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateStakeTxn: Problem fetching utxoView: %v", err)) return @@ -273,7 +280,10 @@ func (fes *APIServer) CreateUnstakeTxn(ww http.ResponseWriter, req *http.Request _AddBadRequestError(ww, fmt.Sprint("CreateUnstakeTxn: UnstakeAmountNanos must be a uint64")) return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateUnstakeTxn: Problem fetching utxoView: %v", err)) return diff --git a/routes/transaction.go b/routes/transaction.go index 301c4339..798fe953 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -238,6 +238,8 @@ type UpdateProfileRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // UpdateProfileResponse ... @@ -282,8 +284,10 @@ func (fes *APIServer) UpdateProfile(ww http.ResponseWriter, req *http.Request) { _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Problem with getUserMetadataFromGlobalState: %v", err)) return } - - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Error fetching mempool view: %v", err)) return @@ -1022,6 +1026,8 @@ type SendDeSoRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // SendDeSoResponse ... @@ -1062,7 +1068,10 @@ func (fes *APIServer) SendDeSo(ww http.ResponseWriter, req *http.Request) { } else { // TODO(performance): This is inefficient because it loads all mempool // transactions. - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SendDeSo: Error generating "+ "view to verify username: %v", err)) @@ -1321,6 +1330,8 @@ type SubmitPostRequest struct { // If true, the post will be "frozen", i.e. no longer editable. IsFrozen bool `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // SubmitPostResponse ... @@ -1410,8 +1421,10 @@ func (fes *APIServer) SubmitPost(ww http.ResponseWriter, req *http.Request) { postHashToModify = postHashToModifyBytes } - var utxoView *lib.UtxoView - utxoView, err = fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("SubmitPost: Error getting utxoView")) return @@ -1732,6 +1745,8 @@ type BuyOrSellCreatorCoinRequest struct { BitCloutToSellNanos uint64 `safeForLogging:"true"` // Deprecated BitCloutToAddNanos uint64 `safeForLogging:"true"` // Deprecated MinBitCloutExpectedNanos uint64 `safeForLogging:"true"` // Deprecated + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // BuyOrSellCreatorCoinResponse ... @@ -1846,7 +1861,10 @@ func (fes *APIServer) BuyOrSellCreatorCoin(ww http.ResponseWriter, req *http.Req // Add node source to txn metadata fes.AddNodeSourceToTxnMetadata(txn) - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUtxoViewForPublicKey(updaterPublicKeyBytes, txn) + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("BuyOrSellCreatorCoin: Problem computing view for transaction: %v", err)) return @@ -2002,6 +2020,8 @@ type TransferCreatorCoinRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // TransferCreatorCoinResponse ... @@ -2058,7 +2078,10 @@ func (fes *APIServer) TransferCreatorCoin(ww http.ResponseWriter, req *http.Requ var receiverPublicKeyBytes []byte if uint64(len(requestData.ReceiverUsernameOrPublicKeyBase58Check)) <= fes.Params.MaxUsernameLengthBytes { // The receiver string is too short to be a public key. Lookup the username. - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferCreatorCoin: Problem fetching utxoView: %v", err)) return @@ -2362,6 +2385,8 @@ type DAOCoinRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // DAOCoinResponse ... @@ -2400,7 +2425,10 @@ func (fes *APIServer) DAOCoin(ww http.ResponseWriter, req *http.Request) { return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("DAOCoin: Problem computing view: %v", err)) return @@ -2538,6 +2566,8 @@ type TransferDAOCoinRequest struct { // No need to specify ProfileEntryResponse in each TransactionFee TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // TransferDAOCoinResponse ... @@ -2567,7 +2597,10 @@ func (fes *APIServer) TransferDAOCoin(ww http.ResponseWriter, req *http.Request) return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("TransferDAOCoin: Problem fetching utxoView: %v", err)) return @@ -2707,6 +2740,8 @@ type DAOCoinLimitOrderCreationRequest struct { MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // CreateDAOCoinLimitOrder Constructs a transaction that creates a DAO coin limit order for the specified @@ -2795,7 +2830,10 @@ func (fes *APIServer) CreateDAOCoinLimitOrder(ww http.ResponseWriter, req *http. return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("CreateDAOCoinLimitOrder: problem fetching utxoView: %v", err)) return @@ -2897,6 +2935,8 @@ type DAOCoinMarketOrderCreationRequest struct { MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } func (fes *APIServer) CreateDAOCoinMarketOrder(ww http.ResponseWriter, req *http.Request) { @@ -2973,7 +3013,10 @@ func (fes *APIServer) CreateDAOCoinMarketOrder(ww http.ResponseWriter, req *http return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("CreateDAOCoinMarketOrder: problem fetching utxoView: %v", err)) return @@ -3073,6 +3116,8 @@ type DAOCoinLimitOrderWithCancelOrderIDRequest struct { MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` TransactionFees []TransactionFee `safeForLogging:"true"` + + OptionalPrecedingTransactions []*lib.MsgDeSoTxn `safeForLogging:"true"` } // CancelDAOCoinLimitOrder Constructs a transaction that cancels an existing DAO coin limit order with the specified @@ -3097,7 +3142,10 @@ func (fes *APIServer) CancelDAOCoinLimitOrder(ww http.ResponseWriter, req *http. return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := lib.GetAugmentedUniversalViewWithAdditionalTransactions( + fes.backendServer.GetMempool(), + requestData.OptionalPrecedingTransactions, + ) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("CancelDAOCoinLimitOrder: problem fetching utxoView: %v", err)) return From d2134ea4d91e5ace02dcac55efe78fbe41c35555 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:14:41 -0400 Subject: [PATCH 58/99] Add all new global params attributes to update global params txn construction endpoint (#583) --- routes/admin_transaction.go | 112 ++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index 9cd7e11d..dc7c634f 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -130,6 +130,14 @@ type UpdateGlobalParamsRequest struct { // are included when generating a new Proof-of-Stake validator set. ValidatorSetMaxNumValidators uint64 `safeForLogging:"true"` + // StakingRewardsMaxNumStakes is the maximum number of stakes that + // are eligible to receive rewards in the end of epoch hook. + StakingRewardsMaxNumStakes uint64 `safeForLogging:"true"` + + // StakingRewardsAPYBasisPoints is the annual percentage yield that + // is used to compute end-of-epoch staking rewards. + StakingRewardsAPYBasisPoints uint64 `safeForLogging:"true"` + // EpochDurationNumBlocks is the number of blocks included in one epoch. EpochDurationNumBlocks uint64 `safeForLogging:"true"` @@ -138,6 +146,45 @@ type UpdateGlobalParamsRequest struct { // blocks) before they are jailed. JailInactiveValidatorGracePeriodEpochs uint64 `safeForLogging:"true"` + // MaximumVestedIntersectionsPerLockupTransaction is the maximum number + // of intersections that can be vested per lockup transaction. + MaximumVestedIntersectionsPerLockupTransaction int `safeForLogging:"true"` + + // FeeBucketGrowthRateBasisPoints is the growth rate in basis points of + // fee buckets for the mempool's transaction register. + FeeBucketGrowthRateBasisPoints uint64 `safeForLogging:"true"` + + // BlockTimestampDriftNanoSecs is the maximum number of nanoseconds from the current timestamp that + // we will allow a PoS block to be submitted. + BlockTimestampDriftNanoSecs int64 `safeForLogging:"true"` + + // MempoolMaxSizeBytes is the maximum size of the mempool in bytes. + MempoolMaxSizeBytes uint64 `safeForLogging:"true"` + + // MempoolFeeEstimatorNumMempoolBlocks is the number of possible future blocks to a txn may be placed + // into when consider when estimating the fee for a new txn. + MempoolFeeEstimatorNumMempoolBlocks uint64 + + // MempoolFeeEstimatorNumPastBlocks is the number of past blocks to reference txn fees from when estimating + // the fee for a new txn. + MempoolFeeEstimatorNumPastBlocks uint64 + + // MaxBlockSizeBytesPoS is the maximum size of a block in bytes. + MaxBlockSizeBytesPoS uint64 + + // SoftMaxBlockSizeBytesPoS is the ideal steady state size of a block in bytes. + // This value will be used to control size of block production and congestion in fee estimation. + SoftMaxBlockSizeBytesPoS uint64 + + // MaxTxnSizeBytesPoS is the maximum size of a transaction in bytes allowed. + MaxTxnSizeBytesPoS uint64 + + // BlockProductionIntervalMillisecondsPoS is the time in milliseconds to produce blocks. + BlockProductionIntervalMillisecondsPoS uint64 + + // TimeoutIntervalMillisecondsPoS is the time in milliseconds to wait before timing out a view. + TimeoutIntervalMillisecondsPoS uint64 + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` // No need to specify ProfileEntryResponse in each TransactionFee @@ -256,6 +303,16 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque extraData[lib.ValidatorSetMaxNumValidatorsKey] = lib.UintToBuf(requestData.ValidatorSetMaxNumValidators) } + if requestData.StakingRewardsMaxNumStakes > 0 && + requestData.StakingRewardsMaxNumStakes != globalParamsEntry.StakingRewardsMaxNumStakes { + extraData[lib.StakingRewardsMaxNumStakesKey] = lib.UintToBuf(requestData.StakingRewardsMaxNumStakes) + } + + if requestData.StakingRewardsAPYBasisPoints > 0 && + requestData.StakingRewardsAPYBasisPoints != globalParamsEntry.StakingRewardsAPYBasisPoints { + extraData[lib.StakingRewardsAPYBasisPointsKey] = lib.UintToBuf(requestData.StakingRewardsAPYBasisPoints) + } + if requestData.EpochDurationNumBlocks > 0 && requestData.EpochDurationNumBlocks != globalParamsEntry.EpochDurationNumBlocks { extraData[lib.EpochDurationNumBlocksKey] = lib.UintToBuf(requestData.EpochDurationNumBlocks) @@ -266,6 +323,61 @@ func (fes *APIServer) UpdateGlobalParams(ww http.ResponseWriter, req *http.Reque extraData[lib.JailInactiveValidatorGracePeriodEpochsKey] = lib.UintToBuf(requestData.JailInactiveValidatorGracePeriodEpochs) } + if requestData.MaximumVestedIntersectionsPerLockupTransaction > 0 && + requestData.MaximumVestedIntersectionsPerLockupTransaction != globalParamsEntry.MaximumVestedIntersectionsPerLockupTransaction { + extraData[lib.MaximumVestedIntersectionsPerLockupTransactionKey] = lib.IntToBuf(int64(requestData.MaximumVestedIntersectionsPerLockupTransaction)) + } + + if requestData.FeeBucketGrowthRateBasisPoints > 0 && + requestData.FeeBucketGrowthRateBasisPoints != globalParamsEntry.FeeBucketGrowthRateBasisPoints { + extraData[lib.FeeBucketGrowthRateBasisPointsKey] = lib.UintToBuf(requestData.FeeBucketGrowthRateBasisPoints) + } + + if requestData.BlockTimestampDriftNanoSecs > 0 && + requestData.BlockTimestampDriftNanoSecs != globalParamsEntry.BlockTimestampDriftNanoSecs { + extraData[lib.BlockTimestampDriftNanoSecsKey] = lib.IntToBuf(requestData.BlockTimestampDriftNanoSecs) + } + + if requestData.MempoolMaxSizeBytes > 0 && + requestData.MempoolMaxSizeBytes != globalParamsEntry.MempoolMaxSizeBytes { + extraData[lib.MempoolMaxSizeBytesKey] = lib.UintToBuf(requestData.MempoolMaxSizeBytes) + } + + if requestData.MempoolFeeEstimatorNumMempoolBlocks > 0 && + requestData.MempoolFeeEstimatorNumMempoolBlocks != globalParamsEntry.MempoolFeeEstimatorNumMempoolBlocks { + extraData[lib.MempoolFeeEstimatorNumMempoolBlocksKey] = lib.UintToBuf(requestData.MempoolFeeEstimatorNumMempoolBlocks) + } + + if requestData.MempoolFeeEstimatorNumPastBlocks > 0 && + requestData.MempoolFeeEstimatorNumPastBlocks != globalParamsEntry.MempoolFeeEstimatorNumPastBlocks { + extraData[lib.MempoolFeeEstimatorNumPastBlocksKey] = lib.UintToBuf(requestData.MempoolFeeEstimatorNumPastBlocks) + } + + if requestData.MaxBlockSizeBytesPoS > 0 && + requestData.MaxBlockSizeBytesPoS != globalParamsEntry.MaxBlockSizeBytesPoS { + extraData[lib.MaxBlockSizeBytesPoSKey] = lib.UintToBuf(requestData.MaxBlockSizeBytesPoS) + } + + if requestData.SoftMaxBlockSizeBytesPoS > 0 && + requestData.SoftMaxBlockSizeBytesPoS != globalParamsEntry.SoftMaxBlockSizeBytesPoS { + extraData[lib.SoftMaxBlockSizeBytesPoSKey] = lib.UintToBuf(requestData.SoftMaxBlockSizeBytesPoS) + } + + if requestData.MaxTxnSizeBytesPoS > 0 && + requestData.MaxTxnSizeBytesPoS != globalParamsEntry.MaxTxnSizeBytesPoS { + extraData[lib.MaxTxnSizeBytesPoSKey] = lib.UintToBuf(requestData.MaxTxnSizeBytesPoS) + } + + if requestData.BlockProductionIntervalMillisecondsPoS > 0 && + requestData.BlockProductionIntervalMillisecondsPoS != globalParamsEntry.BlockProductionIntervalMillisecondsPoS { + extraData[lib.BlockProductionIntervalPoSKey] = lib.UintToBuf(requestData.BlockProductionIntervalMillisecondsPoS) + } + + if requestData.TimeoutIntervalMillisecondsPoS > 0 && + requestData.TimeoutIntervalMillisecondsPoS != globalParamsEntry.TimeoutIntervalMillisecondsPoS { + extraData[lib.TimeoutIntervalPoSKey] = lib.UintToBuf(requestData.TimeoutIntervalMillisecondsPoS) + } + // Try and create the update txn for the user. txn, totalInput, changeAmount, fees, err := fes.blockchain.CreateUpdateGlobalParamsTxn( updaterPkBytes, From 911df1c9bb5e3d23172b113410a0209befa13911 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 9 Apr 2024 16:32:29 -0400 Subject: [PATCH 59/99] Trigger CI From 9aa87a8ae689004d69f1514b4f6d506eecb798cc Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:01:58 -0400 Subject: [PATCH 60/99] Add get committed tip info endpoint (#582) --- routes/exchange_test.go | 2 +- routes/server.go | 7 +++++++ routes/transaction.go | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/routes/exchange_test.go b/routes/exchange_test.go index 9f0d1674..57872a68 100644 --- a/routes/exchange_test.go +++ b/routes/exchange_test.go @@ -138,7 +138,7 @@ func NewLowDifficultyBlockchainWithParams(t *testing.T, params *lib.DeSoParams) // Temporarily modify the seed balances to make a specific public // key have some DeSo chain, err := lib.NewBlockchain([]string{blockSignerPk}, 0, 0, - ¶msCopy, timesource, db, nil, nil, nil, false) + ¶msCopy, timesource, db, nil, nil, nil, false, nil) if err != nil { log.Fatal(err) } diff --git a/routes/server.go b/routes/server.go index e27ab69d..bcdcdc69 100644 --- a/routes/server.go +++ b/routes/server.go @@ -1035,6 +1035,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.GetTxnConstructionParams, PublicAccess, }, + { + "GetCommittedTipBlockInfo", + []string{"GET"}, + lib.RoutePathGetCommittedTipBlockInfo, + fes.GetCommittedTipBlockInfo, + PublicAccess, + }, { "GetNotifications", []string{"POST", "OPTIONS"}, diff --git a/routes/transaction.go b/routes/transaction.go index 798fe953..403a4a15 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4346,3 +4346,23 @@ func (fes *APIServer) GetTxnConstructionParams(ww http.ResponseWriter, req *http return } } + +func (fes *APIServer) GetCommittedTipBlockInfo(ww http.ResponseWriter, req *http.Request) { + // Get the block tip from the blockchain. + fes.backendServer.GetBlockchain().ChainLock.RLock() + blockTip, idx := fes.backendServer.GetBlockchain().GetCommittedTip() + fes.backendServer.GetBlockchain().ChainLock.RUnlock() + if idx == -1 { + _AddBadRequestError(ww, "GetCommittedTipBlockInfo: Problem getting block tip") + return + } + // Return the block tip. + if err := json.NewEncoder(ww).Encode(&lib.CheckpointBlockInfo{ + Height: blockTip.Header.Height, + Hash: blockTip.Hash, + HashHex: blockTip.Hash.String(), + }); err != nil { + _AddBadRequestError(ww, "GetCommittedTipBlockInfo: Problem encoding response as JSON: "+err.Error()) + return + } +} From de2e7011b55d31d9dbef197de15f9ed959a25e4f Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 9 Apr 2024 18:08:54 -0400 Subject: [PATCH 61/99] Trigger CI From df0500bb12059486fd31b037e271c11ea90f6960 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 9 Apr 2024 18:34:19 -0400 Subject: [PATCH 62/99] Empty commit for CI From 4bcee2d40b71a2abf103d9bc559c66304e214090 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:52:57 -0400 Subject: [PATCH 63/99] Update node info endpoint to return info about connections to validators (#586) --- routes/admin_node.go | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/routes/admin_node.go b/routes/admin_node.go index 21692b7c..fec25442 100644 --- a/routes/admin_node.go +++ b/routes/admin_node.go @@ -63,6 +63,26 @@ type PeerResponse struct { IsSyncPeer bool } +type RemoteNodeResponse struct { + // The latest block height the validator is at. + LatestBlockHeight uint64 + + // RemoteNodeStatus is the string representation of the RemoteNode's status. + RemoteNodeStatus string + + // PeerResponse is the IP and port of the peer the validator is connected to. + PeerResponse *PeerResponse + + // PeerConnected is a boolean indicating whether the peer is connected. + PeerConnected bool + + // ValidatorResponse is the ValidatorEntry converted to a human-readable response. + ValidatorResponse *ValidatorResponse + + // IsValidator is a boolean indicating whether the remote node is a validator. + IsValidator bool +} + // NodeControlResponse ... type NodeControlResponse struct { // The current status the DeSo node is at in terms of syncing the DeSo @@ -73,6 +93,8 @@ type NodeControlResponse struct { DeSoInboundPeers []*PeerResponse DeSoUnconnectedPeers []*PeerResponse + RemoteNodeConnections []*RemoteNodeResponse + MinerPublicKeys []string } @@ -197,6 +219,23 @@ func (fes *APIServer) _handleNodeControlGetInfo( publicKey.SerializeCompressed(), fes.Params)) } + // Get the network manager connections + networkManagerConnections := fes.backendServer.GetNetworkManagerConnections() + uncommittedTipView, err := fes.backendServer.GetBlockchain().GetUncommittedTipView() + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("NodeControl: Problem getting uncommitted tip view: %v", err)) + return + } + remoteNodeConnections := make([]*RemoteNodeResponse, 0) + for _, connection := range networkManagerConnections { + remoteNodeConnection, err := _remoteNodeToResponse(connection, uncommittedTipView, fes.Params) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("NodeControl: Problem getting remote node response: %v", err)) + return + } + remoteNodeConnections = append(remoteNodeConnections, remoteNodeConnection) + } + res := NodeControlResponse{ DeSoStatus: desoNodeStatus, @@ -205,6 +244,8 @@ func (fes *APIServer) _handleNodeControlGetInfo( DeSoUnconnectedPeers: desoUnconnectedPeers, MinerPublicKeys: minerPublicKeyStrs, + + RemoteNodeConnections: remoteNodeConnections, } if err := json.NewEncoder(ww).Encode(res); err != nil { _AddBadRequestError(ww, fmt.Sprintf("NodeControl: Problem encoding response as JSON: %v", err)) @@ -212,6 +253,30 @@ func (fes *APIServer) _handleNodeControlGetInfo( } } +func _remoteNodeToResponse(remoteNode *lib.RemoteNode, utxoView *lib.UtxoView, params *lib.DeSoParams) (*RemoteNodeResponse, error) { + remoteNodeResponse := &RemoteNodeResponse{} + remoteNodeResponse.PeerResponse = &PeerResponse{ + IP: remoteNode.GetPeer().IP(), + ProtocolPort: remoteNode.GetPeer().Port(), + } + remoteNodeResponse.RemoteNodeStatus = remoteNode.GetStatus().String() + remoteNodeResponse.PeerConnected = remoteNode.GetPeer().Connected() + remoteNodeResponse.IsValidator = remoteNode.IsValidator() + remoteNodeResponse.LatestBlockHeight = remoteNode.GetLatestBlockHeight() + if remoteNodeResponse.IsValidator { + blsPublicKeyPKIDPairEntry, err := utxoView.GetBLSPublicKeyPKIDPairEntry(remoteNode.GetValidatorPublicKey()) + if err != nil { + return nil, fmt.Errorf("_remoteNodeToResponse: Problem getting BLS public key PKID pair entry: %v", err) + } + validatorEntry, err := utxoView.GetValidatorByPKID(blsPublicKeyPKIDPairEntry.PKID) + if err != nil { + return nil, fmt.Errorf("_remoteNodeToResponse: Problem getting validator entry: %v", err) + } + remoteNodeResponse.ValidatorResponse = _convertValidatorEntryToResponse(utxoView, validatorEntry, params) + } + return nil, nil +} + func (fes *APIServer) _handleConnectDeSoNode( ww http.ResponseWriter, ip string, protocolPort uint16) { From 53adfeed13af6121f11d8758914c0d7899654a90 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:29:22 -0400 Subject: [PATCH 64/99] Upgrade go to 1.22 (#585) --- .github/workflows/ci.yaml | 4 ++-- Dockerfile | 2 +- go.mod | 2 +- test.Dockerfile | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 811c1372..08435898 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,7 +15,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: "1.20" + go-version: "1.22" - name: Checkout branch uses: actions/checkout@v3 @@ -32,7 +32,7 @@ jobs: # - name: Install go # uses: actions/setup-go@v3 # with: -# go-version: "1.20" +# go-version: "1.22" # # - name: Install os dependencies # run: sudo apt-get install -y libvips-tools libvips-dev && vips -v diff --git a/Dockerfile b/Dockerfile index 26b104bd..e9d21f64 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ RUN apk update RUN apk upgrade RUN apk add --update bash cmake g++ gcc git make vips-dev -COPY --from=golang:1.20-alpine /usr/local/go/ /usr/local/go/ +COPY --from=golang:1.22-alpine /usr/local/go/ /usr/local/go/ ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /deso/src diff --git a/go.mod b/go.mod index a5a3ac73..318adc58 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/deso-protocol/backend -go 1.20 +go 1.22 replace github.com/deso-protocol/core => ../core/ diff --git a/test.Dockerfile b/test.Dockerfile index 89bc12bb..53954666 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -4,7 +4,7 @@ RUN apk update RUN apk upgrade RUN apk add --update bash cmake g++ gcc git make vips-dev -COPY --from=golang:1.20-alpine /usr/local/go/ /usr/local/go/ +COPY --from=golang:1.22-alpine /usr/local/go/ /usr/local/go/ ENV PATH="/usr/local/go/bin:${PATH}" # Declare an ARG for the branch name with a default value of "main" From 9f108080ed8b13d8b0f7907539fc942e96fb32f3 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:31:30 -0400 Subject: [PATCH 65/99] Upgrade deps (#569) --- config/config.go | 2 +- go.mod | 225 +++-- go.sum | 901 ++++++++---------- routes/access_group_test.go | 6 +- routes/admin_fees.go | 2 +- routes/admin_node.go | 12 +- routes/admin_referrals.go | 4 +- routes/admin_transaction.go | 4 +- routes/admin_user.go | 2 +- routes/associations_test.go | 4 +- routes/dao_coin_exchange.go | 40 +- routes/dao_coin_exchange_test.go | 34 +- routes/eth.go | 2 +- routes/exchange.go | 6 +- routes/lockups.go | 12 +- routes/media.go | 4 +- routes/message.go | 7 +- routes/post.go | 2 +- routes/referrals.go | 2 +- routes/server.go | 6 +- routes/transaction.go | 17 +- routes/tutorial.go | 2 +- routes/user.go | 2 +- routes/wyre.go | 2 +- scripts/pos/validator_registration.go | 2 +- scripts/tools/bitclout_pub_key_to_btc_addr.go | 4 +- scripts/tools/bitclout_pub_key_to_eth_addr.go | 2 +- scripts/tools/daodao-message-notify.go | 4 +- scripts/tools/toolslib/basic_transfer.go | 2 +- scripts/tools/toolslib/creator_coins.go | 2 +- scripts/tools/toolslib/dao.go | 2 +- scripts/tools/toolslib/diamonds.go | 2 +- scripts/tools/toolslib/jwt.go | 2 +- scripts/tools/toolslib/keys.go | 2 +- scripts/tools/toolslib/messages.go | 2 +- scripts/tools/toolslib/nft.go | 2 +- .../tools/toolslib/offline_basic_transfer.go | 4 +- scripts/tools/toolslib/update_bitcoin.go | 2 +- scripts/tools/toolslib/update_profile.go | 2 +- 39 files changed, 633 insertions(+), 703 deletions(-) diff --git a/config/config.go b/config/config.go index a5e566ec..a180ba70 100644 --- a/config/config.go +++ b/config/config.go @@ -234,7 +234,7 @@ func LoadConfig(coreConfig *coreCmd.Config) *Config { panic(fmt.Sprintf("metamask-airdrop-eth-minimum value %v overflows uint256", metamaskAirdropMinStr)) } } else { - config.MetamaskAirdropEthMinimum = uint256.NewInt() + config.MetamaskAirdropEthMinimum = uint256.NewInt(0) } config.MetamaskAirdropDESONanosAmount = viper.GetUint64("metamask-airdrop-deso-nanos-amount") diff --git a/go.mod b/go.mod index 318adc58..c3ffc721 100644 --- a/go.mod +++ b/go.mod @@ -5,131 +5,176 @@ go 1.22 replace github.com/deso-protocol/core => ../core/ require ( - cloud.google.com/go/storage v1.27.0 - github.com/btcsuite/btcd v0.21.0-beta - github.com/btcsuite/btcutil v1.0.2 - github.com/davecgh/go-spew v1.1.1 - github.com/deso-protocol/core v0.0.0-00010101000000-000000000000 + cloud.google.com/go/storage v1.40.0 + github.com/btcsuite/btcd v0.24.0 + github.com/btcsuite/btcd/btcec/v2 v2.3.3 + github.com/btcsuite/btcd/btcutil v1.1.5 + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 + github.com/deso-protocol/core v1.2.9 github.com/deso-protocol/go-deadlock v1.0.0 github.com/dgraph-io/badger/v4 v4.2.0 github.com/fatih/structs v1.1.0 - github.com/golang-jwt/jwt/v4 v4.1.0 - github.com/golang/glog v1.0.0 - github.com/gorilla/mux v1.8.0 - github.com/h2non/bimg v1.1.5 - github.com/holiman/uint256 v1.1.1 - github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 + github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/golang/glog v1.2.1 + github.com/gorilla/mux v1.8.1 + github.com/h2non/bimg v1.1.9 + github.com/holiman/uint256 v1.2.4 + github.com/kevinburke/twilio-go v0.0.0-20231009225535-38b36b35294d github.com/mitchellh/go-homedir v1.1.0 - github.com/mitchellh/mapstructure v1.1.2 - github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe - github.com/nyaruka/phonenumbers v1.0.69 + github.com/mitchellh/mapstructure v1.5.0 + github.com/montanaflynn/stats v0.7.1 + github.com/nyaruka/phonenumbers v1.3.4 github.com/pkg/errors v0.9.1 - github.com/sendgrid/sendgrid-go v3.10.0+incompatible - github.com/spf13/cobra v1.1.3 + github.com/sendgrid/sendgrid-go v3.14.0+incompatible + github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.7.1 - github.com/stretchr/testify v1.8.1 + github.com/spf13/viper v1.18.2 + github.com/stretchr/testify v1.9.0 github.com/tyler-smith/go-bip39 v1.1.0 - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d + golang.org/x/crypto v0.22.0 golang.org/x/image v0.15.0 - golang.org/x/sync v0.1.0 - google.golang.org/api v0.103.0 - gopkg.in/DataDog/dd-trace-go.v1 v1.29.0 + golang.org/x/sync v0.7.0 + google.golang.org/api v0.172.0 + gopkg.in/DataDog/dd-trace-go.v1 v1.62.0 ) require ( - cloud.google.com/go v0.107.0 // indirect - cloud.google.com/go/compute v1.15.1 // indirect + cloud.google.com/go v0.112.2 // indirect + cloud.google.com/go/compute v1.25.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.8.0 // indirect - github.com/DataDog/datadog-go v4.5.0+incompatible // indirect - github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect + cloud.google.com/go/iam v1.1.7 // indirect + github.com/AlecAivazis/survey/v2 v2.3.7 // indirect + github.com/DataDog/appsec-internal-go v1.5.0 // indirect + github.com/DataDog/datadog-agent/pkg/obfuscate v0.52.1 // indirect + github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.52.1 // indirect + github.com/DataDog/datadog-go v4.8.3+incompatible // indirect + github.com/DataDog/datadog-go/v5 v5.5.0 // indirect + github.com/DataDog/go-libddwaf/v2 v2.4.2 // indirect + github.com/DataDog/go-sqllexer v0.0.11 // indirect + github.com/DataDog/go-tuf v1.1.0-0.5.2 // indirect + github.com/DataDog/gostackparse v0.7.0 // indirect + github.com/DataDog/sketches-go v1.4.4 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/andygrunwald/go-jira v1.16.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect - github.com/bwesterb/go-ristretto v1.2.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cloudflare/circl v1.1.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/decred/dcrd/lru v1.1.1 // indirect + github.com/bwesterb/go-ristretto v1.2.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cloudflare/circl v1.3.7 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/lru v1.1.2 // indirect github.com/deso-protocol/go-merkle-tree v1.0.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/ebitengine/purego v0.7.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/ethereum/go-ethereum v1.9.25 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/ethereum/go-ethereum v1.13.14 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gernest/mention v2.0.0+incompatible // indirect - github.com/git-chglog/git-chglog v0.0.0-20200414013904-db796966b373 // indirect - github.com/go-pg/pg/v10 v10.10.0 // indirect + github.com/git-chglog/git-chglog v0.15.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-pg/pg/v10 v10.12.0 // indirect github.com/go-pg/zerochecker v0.2.0 // indirect - github.com/gofrs/uuid v4.0.0+incompatible // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/google/flatbuffers v2.0.0+incompatible // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.8 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.3 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/hcl v1.0.1-vault-5 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 // indirect - github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect - github.com/klauspost/compress v1.12.3 // indirect - github.com/magiconair/properties v1.8.1 // indirect - github.com/mattn/go-colorable v0.1.9 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mattn/goveralls v0.0.6 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/kevinburke/rest v0.0.0-20231107185522-a9c371f90234 // indirect + github.com/klauspost/compress v1.17.8 // indirect + github.com/kyokomi/emoji/v2 v2.2.12 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/goveralls v0.0.12 // indirect + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oleiade/lane v1.0.1 // indirect - github.com/onflow/crypto v0.25.0 // indirect - github.com/pelletier/go-toml v1.7.0 // indirect - github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect - github.com/philhofer/fwd v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/onflow/crypto v0.25.1 // indirect + github.com/outcaste-io/ristretto v0.2.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/petermattis/goid v0.0.0-20240327183114-c42a807a84ba // indirect + github.com/philhofer/fwd v1.1.2 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 // indirect github.com/robinjoseph08/go-pg-migrations/v3 v3.0.0 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect - github.com/sendgrid/rest v2.6.4+incompatible // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect + github.com/sendgrid/rest v2.6.9+incompatible // indirect github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - github.com/spf13/afero v1.1.2 // indirect - github.com/spf13/cast v1.3.0 // indirect - github.com/spf13/jwalterweatherman v1.0.0 // indirect - github.com/subosito/gotenv v1.2.0 // indirect - github.com/tinylib/msgp v1.1.2 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tinylib/msgp v1.1.9 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/trivago/tgo v1.0.7 // indirect github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df // indirect github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect github.com/ttacon/libphonenumber v1.2.1 // indirect - github.com/unrolled/secure v1.0.8 // indirect - github.com/urfave/cli v1.22.1 // indirect + github.com/unrolled/secure v1.14.0 // indirect + github.com/urfave/cli/v2 v2.27.1 // indirect github.com/vmihailenco/bufpool v0.1.11 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.1 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.4.0 // indirect - golang.org/x/sys v0.5.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.50.0 // indirect + go.opentelemetry.io/otel v1.25.0 // indirect + go.opentelemetry.io/otel/metric v1.25.0 // indirect + go.opentelemetry.io/otel/trace v1.25.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/oauth2 v0.19.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect - golang.org/x/tools v0.6.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - gonum.org/v1/gonum v0.6.1 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect - google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/AlecAivazis/survey.v1 v1.8.7 // indirect - gopkg.in/ini.v1 v1.51.0 // indirect - gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.20.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + gonum.org/v1/gonum v0.15.0 // indirect + google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - mellium.im/sasl v0.2.1 // indirect + mellium.im/sasl v0.3.1 // indirect ) diff --git a/go.sum b/go.sum index 056a9eb6..41a3cbac 100644 --- a/go.sum +++ b/go.sum @@ -1,125 +1,116 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go v0.112.2 h1:ZaGT6LiG7dBzi6zNOvVZwacaXlmf3lRqnC4DQzqyRQw= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= -github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= -github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +cloud.google.com/go/iam v1.1.7 h1:z4VHOhwKLF/+UYXAJDFwGtNF0b6gjsW1Pk9Ml0U/IoM= +cloud.google.com/go/iam v1.1.7/go.mod h1:J4PMPg8TtyurAUvSmPj8FF3EDgY1SPRZxcUGrn7WXGA= +cloud.google.com/go/storage v1.40.0 h1:VEpDQV5CJxFmJ6ueWNsKxcr1QAYOXEgxDa+sBbJahPw= +cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g= +github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= +github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v4.5.0+incompatible h1:MyyuIz5LVAI3Im+0F/tfo64ETyH4sNVynZ29yOiHm50= -github.com/DataDog/datadog-go v4.5.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= +github.com/DataDog/appsec-internal-go v1.5.0 h1:8kS5zSx5T49uZ8dZTdT19QVAvC/B8ByyZdhQKYQWHno= +github.com/DataDog/appsec-internal-go v1.5.0/go.mod h1:pEp8gjfNLtEOmz+iZqC8bXhu0h4k7NUsW/qiQb34k1U= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.52.1 h1:/oxF4p/4XUGNpNw2TE7vDu/pJV3elEAZ+jES0/MWtiI= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.52.1/go.mod h1:AVPQWekk3h9AOC7+plBlNB68Sy6UIGFoMMVUDeSoNoI= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.52.1 h1:mmkGuCHBFuDBpuwNMcqtY1x1I2fCaPH2Br4xPAAjbkM= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.52.1/go.mod h1:JhAilx32dkIgoDkFXquCTfaWDsAOfe+vfBaxbiZoPI0= +github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= +github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go/v5 v5.5.0 h1:G5KHeB8pWBNXT4Jtw0zAkhdxEAWSpWH00geHI6LDrKU= +github.com/DataDog/datadog-go/v5 v5.5.0/go.mod h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw= +github.com/DataDog/go-libddwaf/v2 v2.4.2 h1:ilquGKUmN9/Ty0sIxiEyznVRxP3hKfmH15Y1SMq5gjA= +github.com/DataDog/go-libddwaf/v2 v2.4.2/go.mod h1:gsCdoijYQfj8ce/T2bEDNPZFIYnmHluAgVDpuQOWMZE= +github.com/DataDog/go-sqllexer v0.0.11 h1:OfPBjmayreblOXreszbrOTICNZ3qWrA6Bg4sypvxpbw= +github.com/DataDog/go-sqllexer v0.0.11/go.mod h1:KwkYhpFEVIq+BfobkTC1vfqm4gTi65skV/DpDBXtexc= +github.com/DataDog/go-tuf v1.1.0-0.5.2 h1:4CagiIekonLSfL8GMHRHcHudo1fQnxELS9g4tiAupQ4= +github.com/DataDog/go-tuf v1.1.0-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= +github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= +github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= +github.com/DataDog/sketches-go v1.4.4 h1:dF52vzXRFSPOj2IjXSWLvXq3jubL4CI69kwYjJ1w5Z8= +github.com/DataDog/sketches-go v1.4.4/go.mod h1:XR0ns2RtEEF09mDKXiKZiQg+nfZStrq1ZuL1eezeZe0= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ= +github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU= github.com/brianvoe/gofakeit v3.18.0+incompatible h1:wDOmHc9DLG4nRjUVVaxA+CEglKOW72Y5+4WNxUIkjM8= -github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/brianvoe/gofakeit v3.18.0+incompatible/go.mod h1:kfwdRA90vvNhPutZWfH7WPaDzUjz+CZFqG+rPkOjGOc= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= -github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= -github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= -github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= +github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= +github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/bwesterb/go-ristretto v1.2.0 h1:xxWOVbN5m8NNKiSDZXE1jtZvZnC6JSJ9cYFADiZcWtw= -github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= +github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY= -github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= +github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/decred/dcrd/lru v1.1.1 h1:kWFDaW0OWx6AD6Ki342c+JPmHbiVdE6rK81pT3fuo/Y= -github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY= +github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8= github.com/deso-protocol/go-deadlock v1.0.0 h1:mw0pHy/19zgC+JFBStuQt1+1Ehv5OKA5NxXqecnL5ic= github.com/deso-protocol/go-deadlock v1.0.0/go.mod h1:K0Wd2OV2x7ck7SMYDraWerpKjFKUeBqaFcwz21tmkb8= github.com/deso-protocol/go-merkle-tree v1.0.0 h1:9zkI5dQsITYy77s4kbTGPQmZnhQ+LsH/kRdL5l/Yzvg= @@ -128,74 +119,67 @@ github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8Bzu github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA= +github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.9.25 h1:mMiw/zOOtCLdGLWfcekua0qPrJTe7FVIiHJ4IKNTfR0= -github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= -github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/ethereum/go-ethereum v1.13.14 h1:EwiY3FZP94derMCIam1iW4HFVrSgIcpsu0HwTQtm6CQ= +github.com/ethereum/go-ethereum v1.13.14/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fergusstrange/embedded-postgres v1.19.0 h1:NqDufJHeA03U7biULlPHZ0pZ10/mDOMKPILEpT50Fyk= -github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fergusstrange/embedded-postgres v1.26.0 h1:mTgUBNST+6zro0TkIb9Fuo9Qg8mSU0ILus9jZKmFmJg= +github.com/fergusstrange/embedded-postgres v1.26.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gernest/mention v2.0.0+incompatible h1:pTXnujBC6tqlw5awDkLojq92TXbt0F+4+8FBlQC+di8= github.com/gernest/mention v2.0.0+incompatible/go.mod h1:/z3Hb+4gaPF+vL8og/lj6Au5j8hh5EfU7/EknmDUuO4= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/git-chglog/git-chglog v0.0.0-20200414013904-db796966b373 h1:MHrlpWOOFhCfY1L9iCIUy5cv5HgDtempICenzJt+7ws= github.com/git-chglog/git-chglog v0.0.0-20200414013904-db796966b373/go.mod h1:Dcsy1kii/xFyNad5JqY/d0GO5mu91sungp5xotbm3Yk= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/git-chglog/git-chglog v0.15.4 h1:BwPDj7AghQTfpXO+UxG4mZM5MUTe9wfDuenF3jpyNf0= +github.com/git-chglog/git-chglog v0.15.4/go.mod h1:BmWdTpqBVzPjKNrBTZGcQCrQV9zq6gFKurhWNnJbYDA= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-pg/pg/v10 v10.5.0/go.mod h1:BfgPoQnD2wXNd986RYEHzikqv9iE875PrFaZ9vXvtNM= -github.com/go-pg/pg/v10 v10.10.0 h1:xc5zWYQ/55XI8pk5NkK+ixXqbJh1vnOun3VODPmbYfY= -github.com/go-pg/pg/v10 v10.10.0/go.mod h1:EmoJGYErc+stNN/1Jf+o4csXuprjxcRztBnn6cHe38E= +github.com/go-pg/pg/v10 v10.12.0 h1:rBmfDDHTN7FQW0OemYmcn5UuBy6wkYWgh/Oqt1OBEB8= +github.com/go-pg/pg/v10 v10.12.0/go.mod h1:USA08CdIasAn0F6wC1nBf5nQhMHewVQodWoH89RPXaI= github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU= github.com/go-pg/zerochecker v0.2.0/go.mod h1:NJZ4wKL0NmTtz0GKCoJ8kym6Xn/EQzXRl2OnAe7MmDo= -github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= -github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -209,16 +193,13 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI= -github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= +github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -227,261 +208,204 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20210125172800-10e9aeb4a998/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -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/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/h2non/bimg v1.1.5 h1:o3xsUBxM8s7+e7PmpiWIkEYdeYayJ94eh4cJLx67m1k= -github.com/h2non/bimg v1.1.5/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/h2non/bimg v1.1.9 h1:WH20Nxko9l/HFm4kZCA3Phbgu2cbHvYzxwxn9YROEGg= +github.com/h2non/bimg v1.1.9/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= +github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw= -github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= -github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/log15 v3.0.0-testing.5+incompatible/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 h1:K8qael4LemsmJCGt+ccI8b0fCNFDttmEu3qtpFt3G0M= github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7/go.mod h1:/Pk5i/SqYdYv1cie5wGwoZ4P6TpgMi+Yf58mtJSHdOw= -github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c h1:hnbwWED5rIu+UaMkLR3JtnscMVGqp35lfzQwLuZAAUY= -github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I= -github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 h1:PSsFm2SRpq9LnaRHLz4u9ZZ3liWjgXM6OMxXE4/qlgY= -github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73/go.mod h1:Fm9alkN1/LPVY1eqD/psyMwPWE4VWl4P01/nTYZKzBk= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kevinburke/rest v0.0.0-20231107185522-a9c371f90234 h1:wMgTpL99gp1GUW9n7rtSB7Oad7xAKX+KgHftVctE7RQ= +github.com/kevinburke/rest v0.0.0-20231107185522-a9c371f90234/go.mod h1:dcLMT8KO9krIMJQ4578Lex1Su6ewuJUqEDeQ1nTORug= +github.com/kevinburke/twilio-go v0.0.0-20231009225535-38b36b35294d h1:EtrDnkat2jYA91OGm+dizL8RaF+GGy3EY/zLW59JhV8= +github.com/kevinburke/twilio-go v0.0.0-20231009225535-38b36b35294d/go.mod h1:4ljZgMTVLbuhqWMcxXPQRsGJ/XJ0xdGzbdLOJACnYco= 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/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= -github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= -github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kyokomi/emoji/v2 v2.2.12 h1:sSVA5nH9ebR3Zji1o31wu3yOwD1zKXQA2z0zUyeit60= +github.com/kyokomi/emoji/v2 v2.2.12/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/goveralls v0.0.6 h1:cr8Y0VMo/MnEZBjxNN/vh6G90SZ7IMb6lms1dzMoO+Y= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/goveralls v0.0.6/go.mod h1:h8b4ow6FxSPMQHF6o2ve3qsclnffZjYTNEKmLesRwqw= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mattn/goveralls v0.0.12 h1:PEEeF0k1SsTjOBQ8FOmrOAoCu4ytuMaWCnWe94zxbCg= +github.com/mattn/goveralls v0.0.12/go.mod h1:44ImGEUfmqH8bBtaMrYKsM65LXfNLWmwaxFGjZwgMSQ= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nyaruka/phonenumbers v1.0.69 h1:j9h62+vaRMdcdjQfCdI2iHAtd1jjKYVQuJRQEu6mFIY= -github.com/nyaruka/phonenumbers v1.0.69/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/nyaruka/phonenumbers v1.3.4 h1:bF1Wdh++fxw09s3surhVeBhXEcUKG07pHeP8HQXqjn8= +github.com/nyaruka/phonenumbers v1.3.4/go.mod h1:Ut+eFwikULbmCenH6InMKL9csUNLyxHuBLyfkpum11s= github.com/oleiade/lane v1.0.1 h1:hXofkn7GEOubzTwNpeL9MaNy8WxolCYb9cInAIeqShU= github.com/oleiade/lane v1.0.1/go.mod h1:IyTkraa4maLfjq/GmHR+Dxb4kCMtEGeb+qmhlrQ5Mk4= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onflow/crypto v0.25.0 h1:BeWbLsh3ZD13Ej+Uky6kg1PL1ZIVBDVX+2MVBNwqddg= -github.com/onflow/crypto v0.25.0/go.mod h1:C8FbaX0x8y+FxWjbkHy0Q4EASCDR9bSPWZqlpCLYyVI= +github.com/onflow/crypto v0.25.1 h1:0txy2PKPMM873JbpxQNbJmuOJtD56bfs48RQfm0ts5A= +github.com/onflow/crypto v0.25.1/go.mod h1:C8FbaX0x8y+FxWjbkHy0Q4EASCDR9bSPWZqlpCLYyVI= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 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/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= +github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/petermattis/goid v0.0.0-20240327183114-c42a807a84ba h1:3jPgmsFGBID1wFfU2AbYocNcN4wqU68UaHSdMjiw/7U= +github.com/petermattis/goid v0.0.0-20240327183114-c42a807a84ba/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA= +github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/robinjoseph08/go-pg-migrations/v3 v3.0.0 h1:0/H63lDsoNYVn5YmP6VLDEnnKkoVYiHx7udTWCK4BUI= github.com/robinjoseph08/go-pg-migrations/v3 v3.0.0/go.mod h1:nOkSFfwwDUBFnDDQqMRC2p4PDE7GZb/KSVqILVB3bmw= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sendgrid/rest v2.6.4+incompatible h1:lq6gAQxLwVBf3mVyCCSHI6mgF+NfaJFJHjT0kl6SSo8= -github.com/sendgrid/rest v2.6.4+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= -github.com/sendgrid/sendgrid-go v3.10.0+incompatible h1:aSYyurHxEZSDy7kxhvZ4fH0inNkEEmRssZNbAmETR2c= -github.com/sendgrid/sendgrid-go v3.10.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +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/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= +github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= +github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= +github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= +github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fcif2i7P7wzISv1sU6DUA= +github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1fOy4Ee11vHhUFHQNpHhrBneOCNHVXS5w= github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y= -github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +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= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= -github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= -github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= 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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -491,275 +415,243 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= -github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= -github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= +github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= +github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM= +github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc= github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df h1:Y2l28Jr3vOEeYtxfVbMtVfOdAwuUqWaP9fvNKiBVeXY= github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df/go.mod h1:pnyouUty/nBr/zm3GYwTIt+qFTLWbdjeLjZmJdzJOu8= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w= github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWLBMElR4= github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/unrolled/secure v1.0.8 h1:JaMvKbe4CRt8oyxVXn+xY+6jlqd7pyJNSVkmsBxxQsM= -github.com/unrolled/secure v1.0.8/go.mod h1:fO+mEan+FLB0CdEnHf6Q4ZZVNqG+5fuLFnP8p0BXDPI= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= +github.com/unrolled/secure v1.14.0 h1:u9vJTU/pR4Bny0ntLUMxdfLtmIRGvQf2sEFuA0TG9AE= +github.com/unrolled/secure v1.14.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= +github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/vmihailenco/bufpool v0.1.11 h1:gOq2WmBrq0i2yW5QJ16ykccQ4wH9UyEsgLm6czKAd94= github.com/vmihailenco/bufpool v0.1.11/go.mod h1:AFf/MOy3l2CFTKbxwt0mp2MwnqjNEs5H/UxrkA5jxTQ= github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1/go.mod h1:xlngVLeyQ/Qi05oQxhQ+oTuqa03RjMwMfk/7/TCs+QI= github.com/vmihailenco/msgpack/v5 v5.0.0-beta.8/go.mod h1:HVxBVPUK/+fZMonk4bi1islLa8V3cfnBug0+4dykPzo= -github.com/vmihailenco/msgpack/v5 v5.3.1 h1:0i85a4dsZh8mC//wmyyTEzidDLPQfQAxZIOLtafGbFY= -github.com/vmihailenco/msgpack/v5 v5.3.1/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0 h1:zvpPXY7RfYAGSdYQLjp6zxdJNSYD/+FFoCTQN9IPxBs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0/go.mod h1:BMn8NB1vsxTljvuorms2hyOs8IBuuBEq0pl7ltOfy30= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.50.0 h1:cEPbyTSEHlQR89XVlyo78gqluF8Y3oMeBkXGWzQsfXY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.50.0/go.mod h1:DKdbWcT4GH1D0Y3Sqt/PFXt2naRKDWtU+eE6oLdFNA8= go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= +go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= +go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= +go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 h1:A1gGSx58LAGVHUUsOf7IiR0u8Xb6W51gRwfDBhkdcaw= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= +golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 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-20200301022130-244492dfa37a/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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190222072716-a9d3bda3a223/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-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= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/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-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -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-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 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/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= 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= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.6.1 h1:/LSrTrgZtpbXyAR6+0e152SROCkJJSh7goYWVmdPFGc= -gonum.org/v1/gonum v0.6.1/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= +google.golang.org/api v0.172.0 h1:/1OcMZGPmW1rX2LCu2CmGUD1KXK1+pfzxotxyRUCCdk= +google.golang.org/api v0.172.0/go.mod h1:+fJZq6QXWfa9pXhnIzsjx4yI22d4aI9ZpLb58gvXjis= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw= +google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= +google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda h1:b6F6WIV4xHHD0FA4oIyzU6mHWg2WI2X1RBehwa5QN38= +google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda/go.mod h1:AHcE/gZH76Bk/ROZhQphlRoWo5xKDEtz3eVEO1LfA8c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -770,35 +662,27 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/AlecAivazis/survey.v1 v1.8.7 h1:oBJqtgsyBLg9K5FK9twNUbcPnbCPoh+R9a+7nag3qJM= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/AlecAivazis/survey.v1 v1.8.7/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= -gopkg.in/DataDog/dd-trace-go.v1 v1.29.0 h1:3C1EEjgFTPqrnS2SXuSqkBbZGacIOPJ7ScGJk4nrP9s= -gopkg.in/DataDog/dd-trace-go.v1 v1.29.0/go.mod h1:FLwUDeuH0z5hkvgvd04/M3MHQN4AF5pQDnedeWRWvok= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/DataDog/dd-trace-go.v1 v1.62.0 h1:jeZxE4ZlfAc+R0zO5TEmJBwOLet3NThsOfYJeSQg1x0= +gopkg.in/DataDog/dd-trace-go.v1 v1.62.0/go.mod h1:YTvYkk3PTsfw0OWrRFxV/IQ5Gy4nZ5TRvxTAP3JcIzs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/kyokomi/emoji.v1 v1.5.1 h1:beetH5mWDMzFznJ+Qzd5KVHp79YKhVUMcdO8LpRLeGw= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/kyokomi/emoji.v1 v1.5.1/go.mod h1:N9AZ6hi1jHOPn34PsbpufQZUcKftSD7WgS2pgpmH4Lg= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -806,13 +690,12 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/gotraceui v0.2.0 h1:dmNsfQ9Vl3GwbiVD7Z8d/osC6WtGGrasyrC2suc4ZIQ= +honnef.co/go/gotraceui v0.2.0/go.mod h1:qHo4/W75cA3bX0QQoSvDjbJa4R8mAyyFjbWAj63XElc= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w= mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ= +mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= +mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= diff --git a/routes/access_group_test.go b/routes/access_group_test.go index ef058388..4354513c 100644 --- a/routes/access_group_test.go +++ b/routes/access_group_test.go @@ -5,7 +5,7 @@ import ( "encoding/hex" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/stretchr/testify/assert" @@ -19,7 +19,7 @@ import ( func signTransaction(t *testing.T, txn *lib.MsgDeSoTxn) { privKeyBytes, _, err := lib.Base58CheckDecode(senderPrivString) require.NoError(t, err) - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) + privKey, _ := btcec.PrivKeyFromBytes(privKeyBytes) txnSignature, err := txn.Sign(privKey) require.NoError(t, err) txn.Signature.SetSignature(txnSignature) @@ -141,7 +141,7 @@ func TestAPIAccessGroupBaseGroupMembership(t *testing.T) { func generateRandomPublicKey(t *testing.T) (publicKeyBytes []byte) { t.Helper() require := require.New(t) - randomPrivateKey, err := btcec.NewPrivateKey(btcec.S256()) + randomPrivateKey, err := btcec.NewPrivateKey() require.NoError(err) randomPublicKeyBytes := randomPrivateKey.PubKey().SerializeCompressed() return randomPublicKeyBytes diff --git a/routes/admin_fees.go b/routes/admin_fees.go index d8c64829..22186d1b 100644 --- a/routes/admin_fees.go +++ b/routes/admin_fees.go @@ -5,7 +5,7 @@ import ( "encoding/gob" "encoding/json" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/golang/glog" "io" diff --git a/routes/admin_node.go b/routes/admin_node.go index fec25442..c133567b 100644 --- a/routes/admin_node.go +++ b/routes/admin_node.go @@ -13,7 +13,7 @@ import ( "strings" "time" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" ) @@ -192,8 +192,8 @@ func (fes *APIServer) _handleNodeControlGetInfo( desoAddrs := fes.backendServer.AddrMgr.AddressCache() sort.Slice(desoAddrs, func(ii, jj int) bool { // Use a hash to get a random but deterministic ordering. - hashI := string(lib.Sha256DoubleHash([]byte(desoAddrs[ii].IP.String() + fmt.Sprintf(":%d", desoAddrs[ii].Port)))[:]) - hashJ := string(lib.Sha256DoubleHash([]byte(desoAddrs[jj].IP.String() + fmt.Sprintf(":%d", desoAddrs[jj].Port)))[:]) + hashI := string(lib.Sha256DoubleHash([]byte(desoAddrs[ii].Addr.String() + fmt.Sprintf(":%d", desoAddrs[ii].Port)))[:]) + hashJ := string(lib.Sha256DoubleHash([]byte(desoAddrs[jj].Addr.String() + fmt.Sprintf(":%d", desoAddrs[jj].Port)))[:]) return hashI < hashJ }) @@ -201,12 +201,12 @@ func (fes *APIServer) _handleNodeControlGetInfo( if len(desoUnconnectedPeers) >= 250 { break } - addr := netAddr.IP.String() + fmt.Sprintf(":%d", netAddr.Port) + addr := netAddr.Addr.String() + fmt.Sprintf(":%d", netAddr.Port) if _, exists := existingDeSoPeers[addr]; exists { continue } desoUnconnectedPeers = append(desoUnconnectedPeers, &PeerResponse{ - IP: netAddr.IP.String(), + IP: netAddr.Addr.String(), ProtocolPort: netAddr.Port, // Unconnected peers are not sync peers so leave it set to false. }) @@ -450,7 +450,7 @@ func (fes *APIServer) NodeControl(ww http.ResponseWriter, req *http.Request) { _AddBadRequestError(ww, fmt.Sprintf("NodeControlRequest: Problem decoding miner public key from base58 %s: %v", pkStr, err)) return } - pk, err := btcec.ParsePubKey(publicKeyBytes, btcec.S256()) + pk, err := btcec.ParsePubKey(publicKeyBytes) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("NodeControlRequest: Problem parsing miner public key %s: %v", pkStr, err)) return diff --git a/routes/admin_referrals.go b/routes/admin_referrals.go index aa62fb8d..543a283c 100644 --- a/routes/admin_referrals.go +++ b/routes/admin_referrals.go @@ -16,8 +16,8 @@ import ( "github.com/davecgh/go-spew/spew" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcutil/base58" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil/base58" "github.com/deso-protocol/core/lib" "github.com/golang/glog" "github.com/pkg/errors" diff --git a/routes/admin_transaction.go b/routes/admin_transaction.go index dc7c634f..b7a547b0 100644 --- a/routes/admin_transaction.go +++ b/routes/admin_transaction.go @@ -8,7 +8,7 @@ import ( "net/http" "strings" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" ) @@ -596,7 +596,7 @@ func (fes *APIServer) TestSignTransactionWithDerivedKey(ww http.ResponseWriter, _AddBadRequestError(ww, fmt.Sprintf("TestSignTransactionWithDerivedKey: Problem decoding seed hex %v", err)) return } - privKeyBytes, _ := btcec.PrivKeyFromBytes(btcec.S256(), privBytes) + privKeyBytes, _ := btcec.PrivKeyFromBytes(privBytes) // Sign the transaction with a derived key. Since the txn extraData must be modified, // we also get new transaction bytes, along with the signature. diff --git a/routes/admin_user.go b/routes/admin_user.go index bc9eb092..1566b2a2 100644 --- a/routes/admin_user.go +++ b/routes/admin_user.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" ) diff --git a/routes/associations_test.go b/routes/associations_test.go index f47d568b..1f84d2b6 100644 --- a/routes/associations_test.go +++ b/routes/associations_test.go @@ -5,7 +5,7 @@ import ( "encoding/hex" "encoding/json" "errors" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/config" coreCmd "github.com/deso-protocol/core/cmd" "github.com/deso-protocol/core/lib" @@ -644,7 +644,7 @@ func newTestApiServer(t *testing.T) *APIServer { func signTxn(t *testing.T, txn *lib.MsgDeSoTxn, privKeyBase58Check string) { privKeyBytes, _, err := lib.Base58CheckDecode(privKeyBase58Check) require.NoError(t, err) - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) + privKey, _ := btcec.PrivKeyFromBytes(privKeyBytes) txnSignature, err := txn.Sign(privKey) require.NoError(t, err) txn.Signature.SetSignature(txnSignature) diff --git a/routes/dao_coin_exchange.go b/routes/dao_coin_exchange.go index 090fee66..90ebce44 100644 --- a/routes/dao_coin_exchange.go +++ b/routes/dao_coin_exchange.go @@ -374,7 +374,7 @@ func (fes *APIServer) GetBestAvailableExchangeRateCoinsToBuyPerCoinToSell( return "0", nil } - bestExchangeRate := uint256.NewInt() + bestExchangeRate := uint256.NewInt(0) for _, order := range orders { // ScaledExchangeRateCoinsToSellPerCoinToBuy has the buying coin is the denominator, so we want to find // the highest available ScaledExchangeRateCoinsToSellPerCoinToBuy @@ -463,8 +463,8 @@ func CalculateScaledExchangeRateFromPriceString( // Scale up the price to account for DAO Coin -> DESO trades if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { - product := uint256.NewInt() - overflow := product.MulOverflow(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) + product := uint256.NewInt(0) + _, overflow := product.MulOverflow(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) if overflow { return nil, errors.Errorf("Overflow when converting %v to a scaled exchange rate", price) } @@ -475,7 +475,7 @@ func CalculateScaledExchangeRateFromPriceString( if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { // We intentionally want to round the exchange rate down for BID orders so precision loss does not prevent the // order from not getting matched with an ASK order with the same input price - quotient := uint256.NewInt().Div(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) + quotient := uint256.NewInt(0).Div(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) if quotient.IsZero() { return nil, errors.Errorf("The %v produces a scaled exchange rate that is too small", price) } @@ -514,15 +514,15 @@ func CalculateScaledExchangeRateFromFloat( } if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { // Buying coin is $DESO - product := uint256.NewInt() - overflow := product.MulOverflow(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) + product := uint256.NewInt(0) + _, overflow := product.MulOverflow(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) if overflow { return nil, errors.Errorf("Overflow when convering %f to a scaled exchange rate", exchangeRateCoinsToSellPerCoinToBuy) } return product, nil } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { // Selling coin is $DESO - quotient := uint256.NewInt().Div(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) + quotient := uint256.NewInt(0).Div(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) if quotient.IsZero() { return nil, errors.Errorf("The float value %f is too small to produce a scaled exchange rate", exchangeRateCoinsToSellPerCoinToBuy) } @@ -687,7 +687,7 @@ func calculateQuantityToFillAsDAOCoinBaseUnits(quantityToFill string) (*uint256. func calculateQuantityToFillAsDESONanos(quantityToFill string) (*uint256.Int, error) { scaledQuantity, err := lib.ScaleFloatFormatStringToUint256( quantityToFill, - uint256.NewInt().SetUint64(lib.NanosPerUnit), + uint256.NewInt(lib.NanosPerUnit), ) if err != nil { return nil, err @@ -766,9 +766,9 @@ func orderFillTypeToUint64( // returns (1e18 / 1e9), which represents the difference in scaling factor for DAO coin base units and $DESO nanos func getDESOToDAOCoinBaseUnitsScalingFactor() *uint256.Int { - return uint256.NewInt().Div( + return uint256.NewInt(0).Div( lib.BaseUnitsPerCoin, - uint256.NewInt().SetUint64(lib.NanosPerUnit), + uint256.NewInt(lib.NanosPerUnit), ) } @@ -869,14 +869,14 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( sellingCoinPKID := &lib.ZeroPKID // Calculate current balance for transactor. - transactorSellingBalanceBaseUnits := uint256.NewInt() + transactorSellingBalanceBaseUnits := uint256.NewInt(0) if sellingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { // Get $DESO balance nanos. desoBalanceNanos, err := utxoView.GetDeSoBalanceNanosForPublicKey(transactorPublicKey) if err != nil { return errors.Errorf("Error getting transactor DESO balance: %v", err) } - transactorSellingBalanceBaseUnits = uint256.NewInt().SetUint64(desoBalanceNanos) + transactorSellingBalanceBaseUnits = uint256.NewInt(desoBalanceNanos) } else { // Get selling coin PKID and public key from public key base58 check. sellingCoinPKID, err = fes.getPKIDFromPublicKeyBase58Check( @@ -904,7 +904,7 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( } // Calculate total selling quantity for current order. - totalSellingBaseUnits := uint256.NewInt() + totalSellingBaseUnits := uint256.NewInt(0) if operationType == DAOCoinLimitOrderOperationTypeStringASK { totalSellingBaseUnits = quantityToFillInBaseUnits } else if operationType == DAOCoinLimitOrderOperationTypeStringBID { @@ -1023,7 +1023,7 @@ func (fes *APIServer) getDAOCoinLimitOrderSimulatedExecutionResult( if buyingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { // If the buying coin is DESO, then the ending balance change will have the transaction fee subtracted. In order to // isolate the amount of the buying coin bought as a part of this order, we need to add back the transaction fee - buyingCoinEndingBalance.Add(buyingCoinEndingBalance, uint256.NewInt().SetUint64(txnFees)) + buyingCoinEndingBalance.Add(buyingCoinEndingBalance, uint256.NewInt(txnFees)) } sellingCoinEndingBalance, err := fes.getTransactorDesoOrDaoCoinBalance(utxoView, transactorPublicKeyBase58Check, sellingDAOCoinCreatorPublicKeyBase58Check) @@ -1034,7 +1034,7 @@ func (fes *APIServer) getDAOCoinLimitOrderSimulatedExecutionResult( // If the selling coin is DESO, then the ending balance will have the network fee subtracted. In order to isolate // the amount of the selling coin sold as a part of this order, we need to add back the transaction fee to the // ending balance - sellingCoinEndingBalance.Add(sellingCoinEndingBalance, uint256.NewInt().SetUint64(txnFees)) + sellingCoinEndingBalance.Add(sellingCoinEndingBalance, uint256.NewInt(txnFees)) } buyingCoinBalanceChange := "0.0" @@ -1050,13 +1050,13 @@ func (fes *APIServer) getDAOCoinLimitOrderSimulatedExecutionResult( // Convert buying coin balance change from uint256 to as a decimal string (ex: 1.23) buyingCoinBalanceChange = lib.FormatScaledUint256AsDecimalString( - uint256.NewInt().Sub(buyingCoinEndingBalance, buyingCoinStartingBalance).ToBig(), + uint256.NewInt(0).Sub(buyingCoinEndingBalance, buyingCoinStartingBalance).ToBig(), getScalingFactorForCoin(buyingDAOCoinCreatorPublicKeyBase58Check).ToBig(), ) // Convert selling coin balance change from uint256 to as a decimal string (ex: 1.23) sellingCoinBalanceChange = lib.FormatScaledUint256AsDecimalString( - uint256.NewInt().Sub(sellingCoinStartingBalance, sellingCoinEndingBalance).ToBig(), + uint256.NewInt(0).Sub(sellingCoinStartingBalance, sellingCoinEndingBalance).ToBig(), getScalingFactorForCoin(sellingDAOCoinCreatorPublicKeyBase58Check).ToBig(), ) @@ -1082,7 +1082,7 @@ func (fes *APIServer) getTransactorDesoOrDaoCoinBalance( if err != nil { return nil, errors.Errorf("Error getting transactor DESO balance: %v", err) } - return uint256.NewInt().SetUint64(desoBalanceNanos), nil + return uint256.NewInt(desoBalanceNanos), nil } daoCoinCreatorPublicKey, _, err := lib.Base58CheckDecode(desoOrDAOCoinCreatorPublicKeyBase58Check) @@ -1100,7 +1100,7 @@ func (fes *APIServer) getTransactorDesoOrDaoCoinBalance( func getScalingFactorForCoin(coinCreatorPublicKeyBase58Check string) *uint256.Int { if coinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { - return uint256.NewInt().SetUint64(lib.NanosPerUnit) + return uint256.NewInt(lib.NanosPerUnit) } - return uint256.NewInt().Set(lib.BaseUnitsPerCoin) + return uint256.NewInt(0).Set(lib.BaseUnitsPerCoin) } diff --git a/routes/dao_coin_exchange_test.go b/routes/dao_coin_exchange_test.go index 5b3d03c3..57e1ffdb 100644 --- a/routes/dao_coin_exchange_test.go +++ b/routes/dao_coin_exchange_test.go @@ -41,17 +41,17 @@ func TestCalculateScaledExchangeRate(t *testing.T) { // Test when buying coin is a DAO coin and selling coin is a DAO coin, for various exchange rates for _, testCase := range successTestCases { exchangeRate := testCase.floatValue - expectedScaledExchangeRate := uint256.NewInt() + expectedScaledExchangeRate := uint256.NewInt(0) if testCase.expectedWholeNumberDigits > 0 { - expectedScaledExchangeRate = uint256.NewInt().Mul( - lib.OneE38, uint256.NewInt().SetUint64(uint64(testCase.expectedWholeNumberDigits)), + expectedScaledExchangeRate = uint256.NewInt(0).Mul( + lib.OneE38, uint256.NewInt(uint64(testCase.expectedWholeNumberDigits)), ) } if testCase.decimalDigitExponent < 0 { expectedScaledExchangeRate.Add( expectedScaledExchangeRate, - uint256.NewInt().Div(lib.OneE38, uint256.NewInt().SetUint64(uint64(-testCase.decimalDigitExponent))), + uint256.NewInt(0).Div(lib.OneE38, uint256.NewInt(uint64(-testCase.decimalDigitExponent))), ) } scaledExchangeRate, err := CalculateScaledExchangeRateFromFloat( @@ -72,7 +72,7 @@ func TestCalculateScaledExchangeRate(t *testing.T) { ) require.NoError(t, err) // expectedScaledExchangeRate / 1e9 - expectedScaledExchangeRate := uint256.NewInt().Div(lib.OneE38, desoToDaoCoinBaseUnitsScalingFactor) + expectedScaledExchangeRate := uint256.NewInt(0).Div(lib.OneE38, desoToDaoCoinBaseUnitsScalingFactor) require.Equal(t, expectedScaledExchangeRate, scaledExchangeRate) } @@ -84,7 +84,7 @@ func TestCalculateScaledExchangeRate(t *testing.T) { 1.0, ) require.NoError(t, err) - expectedScaledExchangeRate := uint256.NewInt().Mul( + expectedScaledExchangeRate := uint256.NewInt(0).Mul( lib.OneE38, desoToDaoCoinBaseUnitsScalingFactor, ) @@ -211,9 +211,9 @@ func TestCalculateExchangeRateAsFloat(t *testing.T) { desoToDaoCoinBaseUnitsScalingFactor := getDESOToDAOCoinBaseUnitsScalingFactor() // equivalent to 100.00000001 - scaledExchangeRate := uint256.NewInt().Add( - uint256.NewInt().Mul(lib.OneE38, uint256.NewInt().SetUint64(100)), // 100 - uint256.NewInt().Div(lib.OneE38, uint256.NewInt().SetUint64(100000000)), // 0.00000001 + scaledExchangeRate := uint256.NewInt(0).Add( + uint256.NewInt(0).Mul(lib.OneE38, uint256.NewInt(100)), // 100 + uint256.NewInt(0).Div(lib.OneE38, uint256.NewInt(100000000)), // 0.00000001 ) expectedExchangeRate := 100.00000001 @@ -257,7 +257,7 @@ func TestCalculatePriceStringFromScaledExchangeRate(t *testing.T) { desoToDaoCoinBaseUnitsScalingFactor := getDESOToDAOCoinBaseUnitsScalingFactor() // equivalent to 100 scaled up by 1e38 - scaledExchangeRate := uint256.NewInt().Mul(lib.OneE38, uint256.NewInt().SetUint64(100)) + scaledExchangeRate := uint256.NewInt(0).Mul(lib.OneE38, uint256.NewInt(100)) expectedStringExchangeRate := "100.0" expectedInvertedStringExchangeRate := "0.01" @@ -292,7 +292,7 @@ func TestCalculatePriceStringFromScaledExchangeRate(t *testing.T) { daoCoinPubKeyBase58Check, desoPubKeyBase58Check, // need to account for exchange rate being scaled up by 1e9 for orders selling deso for dao coins - uint256.NewInt().Div(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), + uint256.NewInt(0).Div(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), DAOCoinLimitOrderOperationTypeStringBID, ) require.NoError(t, err) @@ -305,7 +305,7 @@ func TestCalculatePriceStringFromScaledExchangeRate(t *testing.T) { daoCoinPubKeyBase58Check, desoPubKeyBase58Check, // need to account for exchange rate being scaled up by 1e9 for orders selling deso for dao coins - uint256.NewInt().Div(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), + uint256.NewInt(0).Div(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), DAOCoinLimitOrderOperationTypeStringASK, ) require.NoError(t, err) @@ -318,7 +318,7 @@ func TestCalculatePriceStringFromScaledExchangeRate(t *testing.T) { desoPubKeyBase58Check, daoCoinPubKeyBase58Check, // need to account for exchange rate being scaled down by 1e9 for orders selling dao coins for deso - uint256.NewInt().Mul(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), + uint256.NewInt(0).Mul(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), DAOCoinLimitOrderOperationTypeStringBID, ) require.NoError(t, err) @@ -331,7 +331,7 @@ func TestCalculatePriceStringFromScaledExchangeRate(t *testing.T) { desoPubKeyBase58Check, daoCoinPubKeyBase58Check, // need to account for exchange rate being scaled down by 1e9 for orders selling dao coins for deso - uint256.NewInt().Mul(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), + uint256.NewInt(0).Mul(scaledExchangeRate, desoToDaoCoinBaseUnitsScalingFactor), DAOCoinLimitOrderOperationTypeStringASK, ) require.NoError(t, err) @@ -340,7 +340,7 @@ func TestCalculatePriceStringFromScaledExchangeRate(t *testing.T) { } func TestCalculateQuantityToFillAsBaseUnits(t *testing.T) { - expectedValueIfDESO := uint256.NewInt().SetUint64(lib.NanosPerUnit) + expectedValueIfDESO := uint256.NewInt(lib.NanosPerUnit) expectedValueIfDAOCoin := &(*lib.BaseUnitsPerCoin) quantity := float64(1) @@ -535,7 +535,7 @@ func TestCalculateStringQuantityFromBaseUnits(t *testing.T) { desoPubKeyBase58Check, daoCoinPubKeyBase58Check, DAOCoinLimitOrderOperationTypeStringBID, - uint256.NewInt().SetUint64(0), + uint256.NewInt(0), ) require.Error(t, err) } @@ -546,7 +546,7 @@ func TestCalculateStringQuantityFromBaseUnits(t *testing.T) { desoPubKeyBase58Check, daoCoinPubKeyBase58Check, DAOCoinLimitOrderOperationTypeStringASK, - uint256.NewInt().SetUint64(0), + uint256.NewInt(0), ) require.Error(t, err) } diff --git a/routes/eth.go b/routes/eth.go index 2a8f9d5f..f88187d3 100644 --- a/routes/eth.go +++ b/routes/eth.go @@ -14,8 +14,8 @@ import ( "strings" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" "golang.org/x/crypto/sha3" "encoding/hex" diff --git a/routes/exchange.go b/routes/exchange.go index 5f035dbb..7733c067 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -15,7 +15,7 @@ import ( "github.com/pkg/errors" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/golang/glog" bip39 "github.com/tyler-smith/go-bip39" ) @@ -724,7 +724,7 @@ func (fes *APIServer) APITransferDeSo(ww http.ResponseWriter, rr *http.Request) "base58 private key: %v", err)) return } - senderPriv, senderPub := btcec.PrivKeyFromBytes(btcec.S256(), senderPrivBytes) + senderPriv, senderPub := btcec.PrivKeyFromBytes(senderPrivBytes) if senderPriv == nil { APIAddError(ww, fmt.Sprintf("APITransferDeSo: Problem parsing sender "+ "base58 private key")) @@ -739,7 +739,7 @@ func (fes *APIServer) APITransferDeSo(ww http.ResponseWriter, rr *http.Request) "base58 public key %s: %v", transferDeSoRequest.RecipientPublicKeyBase58Check, err)) return } - recipientPub, err := btcec.ParsePubKey(recipientPubBytes, btcec.S256()) + recipientPub, err := btcec.ParsePubKey(recipientPubBytes) if err != nil { APIAddError(ww, fmt.Sprintf("APITransferDeSo: Problem encoding recipient "+ "base58 public key %s: %v", transferDeSoRequest.RecipientPublicKeyBase58Check, err)) diff --git a/routes/lockups.go b/routes/lockups.go index 45d7f08f..2810907c 100644 --- a/routes/lockups.go +++ b/routes/lockups.go @@ -660,19 +660,19 @@ func (fes *APIServer) LockedBalanceEntries(ww http.ResponseWriter, req *http.Req // NOTE: It's possible to create multiple locked balance entries that are impossible to unlock due to overflow. // As such, if the addition triggers an overflow we will just ignore adding more and use the max Uint256. var newTotalLockedBaseUnits *uint256.Int - if uint256.NewInt().Sub( + if uint256.NewInt(0).Sub( lib.MaxUint256, &cumulativeResponse.TotalLockedBaseUnits).Lt(&lockedBalanceEntry.BalanceBaseUnits) { newTotalLockedBaseUnits = lib.MaxUint256 } else { - newTotalLockedBaseUnits = uint256.NewInt().Add( + newTotalLockedBaseUnits = uint256.NewInt(0).Add( &cumulativeResponse.TotalLockedBaseUnits, &lockedBalanceEntry.BalanceBaseUnits) } // Compute how much (if any) is unlockable in the give entry. - unlockableBaseUnitsFromEntry := uint256.NewInt() - newTotalUnlockableBaseUnits := uint256.NewInt() + unlockableBaseUnitsFromEntry := uint256.NewInt(0) + newTotalUnlockableBaseUnits := uint256.NewInt(0) if lockedBalanceEntry.UnlockTimestampNanoSecs < currentTimestampNanoSecs { // Check if the locked balance entry is unvested or vested. if lockedBalanceEntry.UnlockTimestampNanoSecs == lockedBalanceEntry.VestingEndTimestampNanoSecs { @@ -687,12 +687,12 @@ func (fes *APIServer) LockedBalanceEntries(ww http.ResponseWriter, req *http.Req } } } - if uint256.NewInt().Sub( + if uint256.NewInt(0).Sub( lib.MaxUint256, &cumulativeResponse.UnlockableBaseUnits).Lt(unlockableBaseUnitsFromEntry) { newTotalUnlockableBaseUnits = lib.MaxUint256 } else { - newTotalUnlockableBaseUnits = uint256.NewInt().Add( + newTotalUnlockableBaseUnits = uint256.NewInt(0).Add( &cumulativeResponse.UnlockableBaseUnits, unlockableBaseUnitsFromEntry) } diff --git a/routes/media.go b/routes/media.go index 95e25746..85c0e51f 100644 --- a/routes/media.go +++ b/routes/media.go @@ -101,9 +101,9 @@ func validateImageSize(encodedImageContentBytes []byte, extension string) error if err != nil { return errors.Wrap(err, "validateImageSize: Problem decoding image config") } - if imageConfig.Width > bimg.MaxSize || imageConfig.Height > bimg.MaxSize { + if imageConfig.Width > bimg.MaxSize() || imageConfig.Height > bimg.MaxSize() { return fmt.Errorf("validateImageSize: image too large. Max dimensions are %v x %v. ImageConfig dimensions are %v x %v", - bimg.MaxSize, bimg.MaxSize, imageConfig.Width, imageConfig.Height) + bimg.MaxSize(), bimg.MaxSize(), imageConfig.Width, imageConfig.Height) } return nil } diff --git a/routes/message.go b/routes/message.go index e30f75a8..61eaf869 100644 --- a/routes/message.go +++ b/routes/message.go @@ -5,7 +5,8 @@ import ( "encoding/hex" "encoding/json" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" + ecdsa2 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" "io" @@ -1008,13 +1009,13 @@ func VerifyBytesSignature(signerPk, data, signatureBytes []byte) error { bytes := lib.Sha256DoubleHash(data) // Convert signatureBytes to *btcec.Signature. - sign, err := btcec.ParseDERSignature(signatureBytes, btcec.S256()) + sign, err := ecdsa2.ParseDERSignature(signatureBytes) if err != nil { return errors.Wrapf(err, "VerifyBytesSignature: Problem parsing access signatureBytes: ") } // Parse signer public key - ownerPk, err := btcec.ParsePubKey(signerPk, btcec.S256()) + ownerPk, err := btcec.ParsePubKey(signerPk) if err != nil { return errors.Wrapf(err, "VerifyBytesSignature: Problem parsing signer public key: ") } diff --git a/routes/post.go b/routes/post.go index 4011b435..fdcfecdd 100644 --- a/routes/post.go +++ b/routes/post.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" ) diff --git a/routes/referrals.go b/routes/referrals.go index bf89f2b1..c6335e8a 100644 --- a/routes/referrals.go +++ b/routes/referrals.go @@ -6,7 +6,7 @@ import ( "io" "net/http" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" ) diff --git a/routes/server.go b/routes/server.go index bcdcdc69..1a379b5a 100644 --- a/routes/server.go +++ b/routes/server.go @@ -13,7 +13,7 @@ import ( "github.com/pkg/errors" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/config" "github.com/golang-jwt/jwt/v4" "github.com/tyler-smith/go-bip39" @@ -2645,7 +2645,7 @@ func (fes *APIServer) ValidateJWT(publicKey string, jwtToken string) (bool, erro return false, errors.Wrapf(err, "Problem decoding public key") } - pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) + pubKey, err := btcec.ParsePubKey(pubKeyBytes) if err != nil { return false, errors.Wrapf(err, "Problem parsing public key") } @@ -2663,7 +2663,7 @@ func (fes *APIServer) ValidateJWT(publicKey string, jwtToken string) (bool, erro if err != nil { return nil, errors.Wrapf(err, "Problem decoding derived public key") } - derivedPublicKey, err := btcec.ParsePubKey(derivedPublicKeyBytes, btcec.S256()) + derivedPublicKey, err := btcec.ParsePubKey(derivedPublicKeyBytes) if err != nil { return nil, errors.Wrapf(err, "Problem parsing derived public key bytes") } diff --git a/routes/transaction.go b/routes/transaction.go index 403a4a15..e530e5a3 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + ecdsa2 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" "io" "math/big" "net/http" @@ -15,10 +16,10 @@ import ( "github.com/holiman/uint256" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" "github.com/deso-protocol/core/lib" "github.com/golang/glog" "github.com/pkg/errors" @@ -806,7 +807,7 @@ func (fes *APIServer) ExchangeBitcoinStateless(ww http.ResponseWriter, req *http _AddBadRequestError(ww, fmt.Sprintf("ExchangeBitcoinStateless: Failed to decode hash: %v", err)) return } - parsedSig, err := btcec.ParseDERSignature(sig, btcec.S256()) + parsedSig, err := ecdsa2.ParseDERSignature(sig) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("ExchangeBitcoinStateless: Parsing "+ "signature failed: %v: %v", signedHash, err)) @@ -2471,7 +2472,7 @@ func (fes *APIServer) DAOCoin(ww http.ResponseWriter, req *http.Request) { "DAOCoin: Must be profile owner in order to perform %v operation", requestData.OperationType)) return } - zero := uint256.NewInt() + zero := uint256.NewInt(0) if operationType == lib.DAOCoinOperationTypeMint && requestData.CoinsToMintNanos.Eq(zero) { _AddBadRequestError(ww, fmt.Sprint("DAOCoin: Cannot mint 0 coins")) return @@ -2779,7 +2780,7 @@ func (fes *APIServer) CreateDAOCoinLimitOrder(ww http.ResponseWriter, req *http. } // Validated and parse price to a scaled exchange rate - scaledExchangeRateCoinsToSellPerCoinToBuy := uint256.NewInt() + scaledExchangeRateCoinsToSellPerCoinToBuy := uint256.NewInt(0) if requestData.Price == "" && requestData.ExchangeRateCoinsToSellPerCoinToBuy == 0 { err = errors.Errorf("Price must be provided as a valid decimal string (ex: 1.23)") } else if requestData.Price != "" { @@ -2805,7 +2806,7 @@ func (fes *APIServer) CreateDAOCoinLimitOrder(ww http.ResponseWriter, req *http. } // Parse and validated quantity - quantityToFillInBaseUnits := uint256.NewInt() + quantityToFillInBaseUnits := uint256.NewInt(0) if requestData.Quantity == "" && requestData.QuantityToFill == 0 { err = errors.Errorf("Quantity must be provided as a valid decimal string (ex: 1.23)") } else if requestData.Quantity != "" { @@ -2964,7 +2965,7 @@ func (fes *APIServer) CreateDAOCoinMarketOrder(ww http.ResponseWriter, req *http // Validate and convert quantity to base units // Parse and validated quantity - quantityToFillInBaseUnits := uint256.NewInt() + quantityToFillInBaseUnits := uint256.NewInt(0) if requestData.Quantity == "" && requestData.QuantityToFill == 0 { err = errors.Errorf("CreateDAOCoinMarketOrder: Quantity must be provided as a valid decimal string (ex: 1.23)") } else if requestData.Quantity != "" { @@ -3033,7 +3034,7 @@ func (fes *APIServer) CreateDAOCoinMarketOrder(ww http.ResponseWriter, req *http } // override the initial value and explicitly set to 0 for clarity - zeroUint256 := uint256.NewInt().SetUint64(0) + zeroUint256 := uint256.NewInt(0) res, err := fes.createDAOCoinLimitOrderResponse( utxoView, diff --git a/routes/tutorial.go b/routes/tutorial.go index e335334b..a78b6625 100644 --- a/routes/tutorial.go +++ b/routes/tutorial.go @@ -8,7 +8,7 @@ import ( "net/http" "time" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" ) diff --git a/routes/user.go b/routes/user.go index b837375e..5fa54bc5 100644 --- a/routes/user.go +++ b/routes/user.go @@ -17,7 +17,7 @@ import ( "github.com/holiman/uint256" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/dgraph-io/badger/v4" "github.com/gorilla/mux" diff --git a/routes/wyre.go b/routes/wyre.go index 48482205..3329ee5c 100644 --- a/routes/wyre.go +++ b/routes/wyre.go @@ -8,7 +8,7 @@ import ( "encoding/hex" "encoding/json" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/fatih/structs" "github.com/golang/glog" diff --git a/scripts/pos/validator_registration.go b/scripts/pos/validator_registration.go index cbe79499..b1100f82 100644 --- a/scripts/pos/validator_registration.go +++ b/scripts/pos/validator_registration.go @@ -9,7 +9,7 @@ import ( "net/http" "time" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/bls" "github.com/deso-protocol/core/lib" diff --git a/scripts/tools/bitclout_pub_key_to_btc_addr.go b/scripts/tools/bitclout_pub_key_to_btc_addr.go index 0870eb89..3530c360 100644 --- a/scripts/tools/bitclout_pub_key_to_btc_addr.go +++ b/scripts/tools/bitclout_pub_key_to_btc_addr.go @@ -3,8 +3,8 @@ package main import ( "flag" "fmt" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" "github.com/deso-protocol/core/lib" "os" ) @@ -16,7 +16,7 @@ func main() { if err != nil { panic(err) } - //pubKey, err := btcec.ParsePubKey(pkBytes, btcec.S256()) + //pubKey, err := btcec.ParsePubKey(pkBytes) //if err != nil { // panic(err) //} diff --git a/scripts/tools/bitclout_pub_key_to_eth_addr.go b/scripts/tools/bitclout_pub_key_to_eth_addr.go index 25faf544..53968f01 100644 --- a/scripts/tools/bitclout_pub_key_to_eth_addr.go +++ b/scripts/tools/bitclout_pub_key_to_eth_addr.go @@ -4,8 +4,8 @@ import ( "encoding/hex" "flag" "fmt" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" "github.com/deso-protocol/core/lib" "golang.org/x/crypto/sha3" "os" diff --git a/scripts/tools/daodao-message-notify.go b/scripts/tools/daodao-message-notify.go index 5c3cd38a..abe497e3 100644 --- a/scripts/tools/daodao-message-notify.go +++ b/scripts/tools/daodao-message-notify.go @@ -6,7 +6,7 @@ import ( "encoding/json" "flag" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/backend/scripts/tools/toolslib" "github.com/deso-protocol/core/lib" @@ -303,7 +303,7 @@ func main() { continue } } - toBTCECPubKey, err := btcec.ParsePubKey(toKeyBytes, btcec.S256()) + toBTCECPubKey, err := btcec.ParsePubKey(toKeyBytes) if err != nil { if err != nil { fmt.Printf("main(): Ran into an error when trying to btcec parse pk (%s): %s\n", toPubKey, err.Error()) diff --git a/scripts/tools/toolslib/basic_transfer.go b/scripts/tools/toolslib/basic_transfer.go index 74d2e515..b0d3376f 100644 --- a/scripts/tools/toolslib/basic_transfer.go +++ b/scripts/tools/toolslib/basic_transfer.go @@ -3,7 +3,7 @@ package toolslib import ( "bytes" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" diff --git a/scripts/tools/toolslib/creator_coins.go b/scripts/tools/toolslib/creator_coins.go index b6e5a9f6..21aff923 100644 --- a/scripts/tools/toolslib/creator_coins.go +++ b/scripts/tools/toolslib/creator_coins.go @@ -3,7 +3,7 @@ package toolslib import ( "bytes" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" diff --git a/scripts/tools/toolslib/dao.go b/scripts/tools/toolslib/dao.go index 878122c7..0f5b3bda 100644 --- a/scripts/tools/toolslib/dao.go +++ b/scripts/tools/toolslib/dao.go @@ -3,7 +3,7 @@ package toolslib import ( "bytes" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/holiman/uint256" diff --git a/scripts/tools/toolslib/diamonds.go b/scripts/tools/toolslib/diamonds.go index 58f3da8a..09f6bdd6 100644 --- a/scripts/tools/toolslib/diamonds.go +++ b/scripts/tools/toolslib/diamonds.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/hex" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" diff --git a/scripts/tools/toolslib/jwt.go b/scripts/tools/toolslib/jwt.go index c8ca3ffe..3c5b6365 100644 --- a/scripts/tools/toolslib/jwt.go +++ b/scripts/tools/toolslib/jwt.go @@ -1,7 +1,7 @@ package toolslib import ( - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/fatih/structs" "github.com/golang-jwt/jwt/v4" "github.com/pkg/errors" diff --git a/scripts/tools/toolslib/keys.go b/scripts/tools/toolslib/keys.go index c9e87c57..760aa8fa 100644 --- a/scripts/tools/toolslib/keys.go +++ b/scripts/tools/toolslib/keys.go @@ -1,7 +1,7 @@ package toolslib import ( - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/tyler-smith/go-bip39" ) diff --git a/scripts/tools/toolslib/messages.go b/scripts/tools/toolslib/messages.go index 827ed174..95713c36 100644 --- a/scripts/tools/toolslib/messages.go +++ b/scripts/tools/toolslib/messages.go @@ -3,7 +3,7 @@ package toolslib import ( "bytes" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" diff --git a/scripts/tools/toolslib/nft.go b/scripts/tools/toolslib/nft.go index 1588c026..fdb151df 100644 --- a/scripts/tools/toolslib/nft.go +++ b/scripts/tools/toolslib/nft.go @@ -3,7 +3,7 @@ package toolslib import ( "bytes" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" diff --git a/scripts/tools/toolslib/offline_basic_transfer.go b/scripts/tools/toolslib/offline_basic_transfer.go index 2bbe6c36..b87ec315 100644 --- a/scripts/tools/toolslib/offline_basic_transfer.go +++ b/scripts/tools/toolslib/offline_basic_transfer.go @@ -1,14 +1,14 @@ package toolslib import ( - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" ) // ACCOUNT GENERATION func accountGeneration() (*btcec.PrivateKey, *btcec.PublicKey, error) { - privKey, err := btcec.NewPrivateKey(btcec.S256()) + privKey, err := btcec.NewPrivateKey() if err != nil { return nil, nil, errors.Wrap(err, "accountGeneration() failed to generate private key") } diff --git a/scripts/tools/toolslib/update_bitcoin.go b/scripts/tools/toolslib/update_bitcoin.go index bbebf72e..fa04408f 100644 --- a/scripts/tools/toolslib/update_bitcoin.go +++ b/scripts/tools/toolslib/update_bitcoin.go @@ -3,7 +3,7 @@ package toolslib import ( "bytes" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" diff --git a/scripts/tools/toolslib/update_profile.go b/scripts/tools/toolslib/update_profile.go index f581677e..d4687b16 100644 --- a/scripts/tools/toolslib/update_profile.go +++ b/scripts/tools/toolslib/update_profile.go @@ -3,7 +3,7 @@ package toolslib import ( "bytes" "encoding/json" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/deso-protocol/backend/routes" "github.com/deso-protocol/core/lib" "github.com/pkg/errors" From 254a9ca6e9bbf42cc169119d146ecee25a88df7f Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Thu, 11 Apr 2024 17:30:43 -0400 Subject: [PATCH 66/99] Empty commit for CI From cec7df9a16f05ca4e9ddfda199e34c4fe3bdb7a9 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 11 Apr 2024 19:51:44 -0400 Subject: [PATCH 67/99] Fix remote node to response (#587) --- routes/admin_node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/admin_node.go b/routes/admin_node.go index c133567b..5d15db06 100644 --- a/routes/admin_node.go +++ b/routes/admin_node.go @@ -274,7 +274,7 @@ func _remoteNodeToResponse(remoteNode *lib.RemoteNode, utxoView *lib.UtxoView, p } remoteNodeResponse.ValidatorResponse = _convertValidatorEntryToResponse(utxoView, validatorEntry, params) } - return nil, nil + return remoteNodeResponse, nil } func (fes *APIServer) _handleConnectDeSoNode( From 0f202c41f9e3798370611347a621d08d918ca019 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 11 Apr 2024 20:15:53 -0400 Subject: [PATCH 68/99] trigger build 04-11-24 (#588) From d50b28a93ce546979589fb6186b1a1a53b61d5ad Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 12 Apr 2024 13:39:36 -0400 Subject: [PATCH 69/99] Empty commit to trigger CI From 758d4f81dc3d541646cadb6708a0c5e9c7f4649f Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 12 Apr 2024 13:54:49 -0400 Subject: [PATCH 70/99] Block until read only view regenerates in afterProcessSubmitPostTransaction (#590) --- routes/transaction.go | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/transaction.go b/routes/transaction.go index e530e5a3..09700621 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -134,6 +134,7 @@ func (fes *APIServer) SubmitTransaction(ww http.ResponseWriter, req *http.Reques // 1. Attach the PostEntry to the response so the client can render it // 2. Attempt to auto-whitelist the post for the global feed func (fes *APIServer) _afterProcessSubmitPostTransaction(txn *lib.MsgDeSoTxn, response *SubmitTransactionResponse) error { + fes.backendServer.GetMempool().BlockUntilReadOnlyViewRegenerated() utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { return errors.Errorf("Problem with GetAugmentedUniversalView: %v", err) From 15dcd32b022ad3bd2b5dccbcf559e7983c69f2a5 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 12 Apr 2024 14:29:51 -0400 Subject: [PATCH 71/99] Add LatestView to CheckpointBlockInfo endpoint (#589) --- routes/transaction.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/routes/transaction.go b/routes/transaction.go index 09700621..ee7c128e 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4360,9 +4360,10 @@ func (fes *APIServer) GetCommittedTipBlockInfo(ww http.ResponseWriter, req *http } // Return the block tip. if err := json.NewEncoder(ww).Encode(&lib.CheckpointBlockInfo{ - Height: blockTip.Header.Height, - Hash: blockTip.Hash, - HashHex: blockTip.Hash.String(), + Height: blockTip.Header.Height, + Hash: blockTip.Hash, + HashHex: blockTip.Hash.String(), + LatestView: fes.backendServer.GetLatestView(), }); err != nil { _AddBadRequestError(ww, "GetCommittedTipBlockInfo: Problem encoding response as JSON: "+err.Error()) return From 5db55b6024b8390b585bfbbe69e2bef4283ae1f5 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 12 Apr 2024 16:02:29 -0400 Subject: [PATCH 72/99] Empty trigger for CI From 2918414f77587db7f8a54ce1f902e180f0991082 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 12 Apr 2024 16:46:47 -0400 Subject: [PATCH 73/99] Empty commit to trigger CI From f8323c29d338cddda26b8408cdf292d5d825a9dd Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Sat, 13 Apr 2024 19:26:06 -0400 Subject: [PATCH 74/99] Empty commit to trigger CI From 4ae79d708121bcef338fb502bd1835a3a3f19916 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:52:11 -0400 Subject: [PATCH 75/99] Update usage of EstimateFeeRate (#592) --- routes/transaction.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/routes/transaction.go b/routes/transaction.go index ee7c128e..90254cad 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4327,7 +4327,7 @@ func (fes *APIServer) GetTxnConstructionParams(ww http.ResponseWriter, req *http } // Get the fees from the mempool - feeRate, err := fes.backendServer.GetMempool().EstimateFeeRate( + feeRate := fes.backendServer.GetMempool().EstimateFeeRate( requestData.MinFeeRateNanosPerKB, mempoolCongestionFactorBasisPoints, mempoolPriorityPercentileBasisPoints, @@ -4335,12 +4335,8 @@ func (fes *APIServer) GetTxnConstructionParams(ww http.ResponseWriter, req *http pastBlocksPriorityPercentileBasisPoints, maxBlockSize, ) - if err != nil { - _AddBadRequestError(ww, "GetTxnConstructionParams: Problem getting fees: "+err.Error()) - return - } // Return the fees - if err = json.NewEncoder(ww).Encode(GetTxnConstructionParamsResponse{ + if err := json.NewEncoder(ww).Encode(GetTxnConstructionParamsResponse{ FeeRateNanosPerKB: feeRate, BlockHeight: uint64(fes.backendServer.GetBlockchain().BlockTip().Height), }); err != nil { From cb4acd946d34c6a1cf6980d16576ffea2fea8e5f Mon Sep 17 00:00:00 2001 From: Jon Pollock <135658176+poolcoke@users.noreply.github.com> Date: Tue, 16 Apr 2024 11:16:58 -0700 Subject: [PATCH 76/99] Submit atomic transactions endpoint. (#594) * Simple CreateAtomicTxnsWrapper scaffolding. * Update method on CreateAtomicTxnsWrapper. * Use MaxTxnSizeBytesPoS for atomic transaction construction. * Subsidized Update Profile Scaffolding * Simple CreateAtomicTxnsWrapper scaffolding. * Update method on CreateAtomicTxnsWrapper. * Use MaxTxnSizeBytesPoS for atomic transaction construction. * Fix MaxTxnSizeBytes bug * Implemented Subsidized Update Profile. * Add an endpoint for easily submitting incomplete atomic transactions. * Fix submit-atomic-transaction by using incomplete atomic hex. * Use mempool is update profile subsidization. * Remove subsidized update profile. --------- Co-authored-by: diamondhands --- routes/atomic_txns.go | 1 - routes/server.go | 10 ++ routes/transaction.go | 310 +++++++++++++++++++++++++++++++----------- 3 files changed, 240 insertions(+), 81 deletions(-) diff --git a/routes/atomic_txns.go b/routes/atomic_txns.go index 86539f8c..10990def 100644 --- a/routes/atomic_txns.go +++ b/routes/atomic_txns.go @@ -81,7 +81,6 @@ func (fes *APIServer) CreateAtomicTxnsWrapper(ww http.ResponseWriter, req *http. _AddBadRequestError(ww, fmt.Sprint("CreateAtomicTxnsWrapper: Resulting wrapper transaction too large")) return } - if txnSizeBytes != 0 && utxoView.GetCurrentGlobalParamsEntry().MinimumNetworkFeeNanosPerKB != 0 { // Check for overflow or minimum network fee not met. if totalFees != ((totalFees*1000)/1000) || diff --git a/routes/server.go b/routes/server.go index 1a379b5a..2da2c5f4 100644 --- a/routes/server.go +++ b/routes/server.go @@ -50,6 +50,7 @@ const ( // transaction.go RoutePathGetTxn = "/api/v0/get-txn" RoutePathSubmitTransaction = "/api/v0/submit-transaction" + RoutePathSubmitAtomicTransaction = "/api/v0/submit-atomic-transaction" RoutePathUpdateProfile = "/api/v0/update-profile" RoutePathExchangeBitcoin = "/api/v0/exchange-bitcoin" RoutePathSendDeSo = "/api/v0/send-deso" @@ -679,6 +680,15 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { PublicAccess, }, + // Route for submitting incomplete atomic transactions and their signatures for network broadcast + { + "SubmitAtomicTransaction", + []string{"POST", "OPTIONS"}, + RoutePathSubmitAtomicTransaction, + fes.SubmitAtomicTransaction, + PublicAccess, + }, + // Temporary route to wipe seedinfo cookies { "DeleteIdentities", diff --git a/routes/transaction.go b/routes/transaction.go index 90254cad..81116d6d 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -72,6 +72,146 @@ func (fes *APIServer) GetTxn(ww http.ResponseWriter, req *http.Request) { } } +// SubmitAtomicTransactionRequest is meant to aid in the submission of atomic transactions +// with identity service signed transactions. Specifically, it takes an incomplete atomic transaction +// and "completes" the transaction by adding in identity service signed transactions. +type SubmitAtomicTransactionRequest struct { + // IncompleteAtomicTransactionHex is a hex encoded transaction of type TxnTypeAtomicTxnsWrapper who + // is "incomplete" only by missing the signature fields of various inner transactions. + IncompleteAtomicTransactionHex string `safeForLogging:"true"` + + // SignedInnerTransactionsHex are the hex-encoded signed inner transactions that + // will be used to complete the atomic transaction. + SignedInnerTransactionsHex []string `safeForLogging:"true"` +} + +type SubmitAtomicTransactionResponse struct { + Transaction *lib.MsgDeSoTxn + TxnHashHex string + TransactionIDBase58Check string +} + +func (fes *APIServer) SubmitAtomicTransaction(ww http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := SubmitAtomicTransactionRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("SubmitAtomicTransaction: Problem parsing request body: %v", err)) + return + } + + // Fetch the incomplete atomic transaction. + atomicTxnBytes, err := hex.DecodeString(requestData.IncompleteAtomicTransactionHex) + if err != nil { + _AddBadRequestError(ww, + fmt.Sprintf("SubmitAtomicTransaction: "+ + "Problem deserializing atomic transaction hex: %v", err)) + return + } + atomicTxn := &lib.MsgDeSoTxn{} + err = atomicTxn.FromBytes(atomicTxnBytes) + if err != nil { + _AddBadRequestError(ww, + fmt.Sprintf("SubmitAtomicTransaction: "+ + "Problem deserializing atomic transaction from bytes: %v", err)) + return + } + if atomicTxn.TxnMeta.GetTxnType() != lib.TxnTypeAtomicTxnsWrapper { + _AddBadRequestError(ww, fmt.Sprintf("SubmitAtomicTransaction: "+ + "IncompleteAtomicTransaction must be an atomic transaction")) + return + } + + // Create a map from the pre-signature inner transaction hash to DeSo signature. + innerTxnPreSignatureHashToSignature := make(map[lib.BlockHash]lib.DeSoSignature) + for ii, signedInnerTxnHex := range requestData.SignedInnerTransactionsHex { + // Decode the signed inner transaction. + signedTxnBytes, err := hex.DecodeString(signedInnerTxnHex) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "SubmitAtomicTransaction: Problem decoding signed transaction hex: %v", err)) + return + } + + // Deserialize the signed transaction. + signedInnerTxn := &lib.MsgDeSoTxn{} + if err := signedInnerTxn.FromBytes(signedTxnBytes); err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "SubmitAtomicTransaction: Problem deserializing signed transaction %d from bytes: %v", + ii, err)) + return + } + + // Verify the signature is present. + if signedInnerTxn.Signature.Sign == nil { + _AddBadRequestError(ww, fmt.Sprintf( + "SubmitAtomicTransaction: Signed transaction %d hex missing signature", ii)) + return + } + + // Find the pre-signature DeSo transaction hash. + // NOTE: We do not use the lib.MsgDeSoTxn.Hash() function here as + // the transactions included in the atomic transaction do not yet + // have their signature fields set. + preSignatureInnerTxnBytes, err := signedInnerTxn.ToBytes(true) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "SubmitAtomicTransaction: Problem serializing "+ + "signed transaction %d without signature: %v", ii, err)) + return + } + preSignatureInnerTxnHash := lib.Sha256DoubleHash(preSignatureInnerTxnBytes) + innerTxnPreSignatureHashToSignature[*preSignatureInnerTxnHash] = signedInnerTxn.Signature + } + + // Based on the provided signatures, complete the atomic transaction. + for jj, innerTxn := range atomicTxn.TxnMeta.(*lib.AtomicTxnsWrapperMetadata).Txns { + // Skip signed inner transactions. + if innerTxn.Signature.Sign != nil { + continue + } + + // Find the pre-signature DeSo transaction hash for this transaction. + preSignatureInnerTxnBytes, err := innerTxn.ToBytes(true) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "SubmitAtomicTransaction: Problem serializing "+ + "transaction %d of atomic transaction wrapper without signature: %v", jj, err)) + return + } + preSignatureInnerTxnHash := lib.Sha256DoubleHash(preSignatureInnerTxnBytes) + + // Check that we have the signature. + if _, exists := innerTxnPreSignatureHashToSignature[*preSignatureInnerTxnHash]; !exists { + _AddBadRequestError(ww, fmt.Sprintf( + "SubmitAtomicTransaction: Transaction %d in atomic transaction still missing signature", jj)) + return + } + + // Set the signature in the atomic transaction. + atomicTxn.TxnMeta.(*lib.AtomicTxnsWrapperMetadata).Txns[jj].Signature = + innerTxnPreSignatureHashToSignature[*preSignatureInnerTxnHash] + } + + // Verify and broadcast the completed atomic transaction. + if err := fes.backendServer.VerifyAndBroadcastTransaction(atomicTxn); err != nil { + _AddBadRequestError(ww, + fmt.Sprintf("SubmitAtomicTransaction: Problem broadcasting transaction: %v", err)) + return + } + + res := &SubmitAtomicTransactionResponse{ + Transaction: atomicTxn, + TxnHashHex: atomicTxn.Hash().String(), + TransactionIDBase58Check: lib.PkToString(atomicTxn.Hash()[:], fes.Params), + } + + if err := json.NewEncoder(ww).Encode(res); err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "SubmitAtomicTransaction: Problem encoding response as JSON: %v", err)) + return + } +} + type SubmitTransactionRequest struct { TransactionHex string `safeForLogging:"true"` } @@ -324,89 +464,12 @@ func (fes *APIServer) UpdateProfile(ww http.ResponseWriter, req *http.Request) { profilePublicKey = profilePublicKeyBytess } - if len(requestData.NewUsername) > 0 && strings.Index(requestData.NewUsername, fes.PublicKeyBase58Prefix) == 0 { - _AddBadRequestError(ww, fmt.Sprintf( - "UpdateProfile: Username cannot start with %s", fes.PublicKeyBase58Prefix)) - return - } - - if uint64(len([]byte(requestData.NewUsername))) > utxoView.Params.MaxUsernameLengthBytes { - _AddBadRequestError(ww, lib.RuleErrorProfileUsernameTooLong.Error()) - return - } - - if uint64(len([]byte(requestData.NewDescription))) > utxoView.Params.MaxUserDescriptionLengthBytes { - _AddBadRequestError(ww, lib.RuleErrorProfileDescriptionTooLong.Error()) - return - } - - // If an image is set on the request then resize it. - // Convert image to base64 by stripping the data: prefix. - if requestData.NewProfilePic != "" { - // split on base64 to get the extension - extensionSplit := strings.Split(requestData.NewProfilePic, ";base64") - if len(extensionSplit) != 2 { - _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Problem parsing profile pic extension: %v", err)) - return - } - extension := extensionSplit[0] - switch { - case strings.Contains(extension, "image/png"): - extension = ".png" - case strings.Contains(extension, "image/jpeg"): - extension = ".jpeg" - case strings.Contains(extension, "image/webp"): - extension = ".webp" - case strings.Contains(extension, "image/gif"): - extension = ".gif" - default: - _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Unsupported image type: %v", extension)) - return - } - var resizedImageBytes []byte - resizedImageBytes, err = resizeAndConvertToWebp( - requestData.NewProfilePic, uint(fes.Params.MaxProfilePicDimensions), extension) - if err != nil { - _AddBadRequestError(ww, fmt.Sprintf("Problem resizing profile picture: %v", err)) - return - } - // Convert the image back into base64 - webpBase64 := base64.StdEncoding.EncodeToString(resizedImageBytes) - requestData.NewProfilePic = "data:image/webp;base64," + webpBase64 - if uint64(len([]byte(requestData.NewProfilePic))) > utxoView.Params.MaxProfilePicLengthBytes { - _AddBadRequestError(ww, lib.RuleErrorMaxProfilePicSize.Error()) - return - } - } - - // CreatorBasisPoints > 0 < max, uint64 can't be less than zero - if requestData.NewCreatorBasisPoints > fes.Params.MaxCreatorBasisPoints { - _AddBadRequestError(ww, fmt.Sprintf( - "UpdateProfile: Creator percentage must be less than %v percent", - fes.Params.MaxCreatorBasisPoints/100)) + // Validate the request. + if err := fes.ValidateAndConvertUpdateProfileRequest(&requestData, profilePublicKey, utxoView); err != nil { + _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Problem validating request: %v", err)) return } - // Verify that this username doesn't exist in the mempool. - if len(requestData.NewUsername) > 0 { - - utxoView.GetProfileEntryForUsername([]byte(requestData.NewUsername)) - existingProfile, usernameExists := utxoView.ProfileUsernameToProfileEntry[lib.MakeUsernameMapKey([]byte(requestData.NewUsername))] - if usernameExists && existingProfile != nil && !existingProfile.IsDeleted() { - // Check that the existing profile does not belong to the profile public key - if utxoView.GetPKIDForPublicKey(profilePublicKey) != utxoView.GetPKIDForPublicKey(existingProfile.PublicKey) { - _AddBadRequestError(ww, fmt.Sprintf( - "UpdateProfile: Username %v already exists", string(existingProfile.Username))) - return - } - - } - if !lib.UsernameRegex.Match([]byte(requestData.NewUsername)) { - _AddBadRequestError(ww, lib.RuleErrorInvalidUsername.Error()) - return - } - } - extraData, err := EncodeExtraDataMap(requestData.ExtraData) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Problem encoding ExtraData: %v", err)) @@ -476,6 +539,93 @@ func (fes *APIServer) UpdateProfile(ww http.ResponseWriter, req *http.Request) { } } +func (fes *APIServer) ValidateAndConvertUpdateProfileRequest( + requestData *UpdateProfileRequest, + profilePublicKey []byte, + utxoView *lib.UtxoView, +) error { + if len(requestData.NewUsername) > 0 && strings.Index(requestData.NewUsername, fes.PublicKeyBase58Prefix) == 0 { + return fmt.Errorf( + "ValidateAndConvertUpdateProfileRequest: Username cannot start with %s", fes.PublicKeyBase58Prefix) + } + + if uint64(len([]byte(requestData.NewUsername))) > utxoView.Params.MaxUsernameLengthBytes { + return errors.Wrap(lib.RuleErrorProfileUsernameTooLong, "ValidateAndConvertUpdateProfileRequest") + } + + if uint64(len([]byte(requestData.NewDescription))) > utxoView.Params.MaxUserDescriptionLengthBytes { + return errors.Wrap(lib.RuleErrorProfileDescriptionTooLong, "ValidateAndConvertUpdateProfileRequest") + } + + // If an image is set on the request then resize it. + // Convert image to base64 by stripping the data: prefix. + if requestData.NewProfilePic != "" { + // split on base64 to get the extension + extensionSplit := strings.Split(requestData.NewProfilePic, ";base64") + if len(extensionSplit) != 2 { + return fmt.Errorf("ValidateAndConvertUpdateProfileRequest: " + + "Problem parsing profile pic extension; invalid extension split") + } + extension := extensionSplit[0] + switch { + case strings.Contains(extension, "image/png"): + extension = ".png" + case strings.Contains(extension, "image/jpeg"): + extension = ".jpeg" + case strings.Contains(extension, "image/webp"): + extension = ".webp" + case strings.Contains(extension, "image/gif"): + extension = ".gif" + default: + return fmt.Errorf( + "ValidateAndConvertUpdateProfileRequest: Unsupported image type: %v", extension) + } + var resizedImageBytes []byte + resizedImageBytes, err := resizeAndConvertToWebp( + requestData.NewProfilePic, uint(fes.Params.MaxProfilePicDimensions), extension) + if err != nil { + return fmt.Errorf( + "ValidateAndConvertUpdateProfileRequest: Problem resizing profile picture: %v", err) + } + // Convert the image back into base64 + webpBase64 := base64.StdEncoding.EncodeToString(resizedImageBytes) + requestData.NewProfilePic = "data:image/webp;base64," + webpBase64 + if uint64(len([]byte(requestData.NewProfilePic))) > utxoView.Params.MaxProfilePicLengthBytes { + return errors.Wrap(lib.RuleErrorMaxProfilePicSize, "ValidateAndConvertUpdateProfileRequest") + } + } + + // CreatorBasisPoints > 0 < max, uint64 can't be less than zero + if requestData.NewCreatorBasisPoints > fes.Params.MaxCreatorBasisPoints { + return fmt.Errorf( + "ValidateAndConvertUpdateProfileRequest: Creator percentage must be less than %v percent", + fes.Params.MaxCreatorBasisPoints/100) + } + + // Verify that this username doesn't exist in the mempool. + if len(requestData.NewUsername) > 0 { + + utxoView.GetProfileEntryForUsername([]byte(requestData.NewUsername)) + existingProfile, usernameExists := + utxoView.ProfileUsernameToProfileEntry[lib.MakeUsernameMapKey([]byte(requestData.NewUsername))] + if usernameExists && existingProfile != nil && !existingProfile.IsDeleted() { + // Check that the existing profile does not belong to the profile public key + if utxoView.GetPKIDForPublicKey(profilePublicKey) != + utxoView.GetPKIDForPublicKey(existingProfile.PublicKey) { + return fmt.Errorf( + "ValidateAndConvertUpdateProfileRequest: Username %v already exists", + string(existingProfile.Username)) + } + + } + if !lib.UsernameRegex.Match([]byte(requestData.NewUsername)) { + return errors.Wrap(lib.RuleErrorInvalidUsername, "ValidateAndConvertUpdateProfileRequest") + } + } + + return nil +} + func (fes *APIServer) CompProfileCreation(profilePublicKey []byte, userMetadata *UserMetadata, utxoView *lib.UtxoView) (_additionalFee uint64, _txnHash *lib.BlockHash, _err error) { // Determine if this is a profile creation request and if we need to comp the user for creating the profile. existingProfileEntry := utxoView.GetProfileEntryForPublicKey(profilePublicKey) From cc9870b1e3211c3cca9a0503021b46ade2d865c3 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 16 Apr 2024 14:28:33 -0400 Subject: [PATCH 77/99] Empty commit to trigger CI From a62423c20ea7bf8931e9c267c2486cbd99c2572d Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Wed, 17 Apr 2024 10:02:42 -0400 Subject: [PATCH 78/99] Make utxo ops nil on APITransactionToResponse for inner txns (#595) --- routes/exchange.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/routes/exchange.go b/routes/exchange.go index 7733c067..056cccb7 100644 --- a/routes/exchange.go +++ b/routes/exchange.go @@ -640,6 +640,11 @@ func APITransactionToResponse( basicMetadata := *txnMeta.BasicTransferTxindexMetadata basicMetadata.UtxoOps = nil txnMetaResponse.BasicTransferTxindexMetadata = &basicMetadata + if txnMeta.AtomicTxnsWrapperTxindexMetadata != nil { + for _, innerMetadata := range txnMeta.AtomicTxnsWrapperTxindexMetadata.InnerTxnsTransactionMetadata { + innerMetadata.BasicTransferTxindexMetadata.UtxoOps = nil + } + } } txnBytes, _ := txnn.ToBytes(false /*preSignature*/) From e19e7ef9dba6335c1260e2016c88830b12a76f1b Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Thu, 18 Apr 2024 10:39:19 -0400 Subject: [PATCH 79/99] Empty commit to trigger CI From fca75d3ea4deeb0fa2e9707a88ad5df9da3f7a74 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Thu, 18 Apr 2024 17:19:42 -0400 Subject: [PATCH 80/99] Empty commit to CI From e83b02116153daf255ced950e348fff87f91547e Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Fri, 19 Apr 2024 09:37:41 -0400 Subject: [PATCH 81/99] Add Script To Make Global Params Changes on Regtest Node (#597) * Add Script To Make Global Params Changes on Regtest Node * Remove public key --- scripts/global_params/update_global_params.go | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 scripts/global_params/update_global_params.go diff --git a/scripts/global_params/update_global_params.go b/scripts/global_params/update_global_params.go new file mode 100644 index 00000000..ad1cd4ab --- /dev/null +++ b/scripts/global_params/update_global_params.go @@ -0,0 +1,113 @@ +package globalparams + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/deso-protocol/backend/routes" + "github.com/deso-protocol/core/lib" + "github.com/pkg/errors" + "github.com/tyler-smith/go-bip39" +) + +var superAdminSeedPhrase = "" + +var nodeURL = "" +var params = &lib.DeSoTestnetParams + +func makePostRequest[TPayload any, TResponse any](url string, payload TPayload) TResponse { + postBody, err := json.Marshal(payload) + if err != nil { + panic(errors.Wrap(err, "main(): Could not complete request")) + } + postBuffer := bytes.NewBuffer(postBody) + + // Execute request. + resp, err := http.Post(url, "application/json", postBuffer) + if err != nil { + panic(errors.Wrap(err, "main(): failed request")) + } + if resp.StatusCode != 200 { + bodyBytes, _ := ioutil.ReadAll(resp.Body) + panic(errors.Errorf("main(): Received non 200 response code: "+ + "Status Code: %v Body: %v", resp.StatusCode, string(bodyBytes))) + } + + var decodedResponse TResponse + + // Process Response. + err = json.NewDecoder(resp.Body).Decode(&decodedResponse) + if err != nil { + panic(errors.Wrap(err, "main(): Failed to decode response\n")) + } + err = resp.Body.Close() + if err != nil { + panic(errors.Wrap(err, "main(): Failed to decode body\n")) + } + + return decodedResponse +} + +func signAndSubmitTxn(txn *lib.MsgDeSoTxn, privKey *btcec.PrivateKey, nodeURL string) { + signature, err := txn.Sign(privKey) + if err != nil { + panic(err) + } + + txn.Signature.SetSignature(signature) + + txnBytes, err := txn.ToBytes(false) + if err != nil { + panic(err) + } + + txnHex := hex.EncodeToString(txnBytes) + + submitTransactionRequest := routes.SubmitTransactionRequest{ + TransactionHex: txnHex, + } + + makePostRequest[routes.SubmitTransactionRequest, routes.SubmitTransactionResponse]( + nodeURL+routes.RoutePathSubmitTransaction, submitTransactionRequest, + ) +} + +func constructUpdateGlobalParams(adminPublicKey *lib.PublicKey) routes.UpdateGlobalParamsResponse { + adminPublicKeyString := lib.PkToString(adminPublicKey.ToBytes(), params) + + request := routes.UpdateGlobalParamsRequest{ + UpdaterPublicKeyBase58Check: adminPublicKeyString, + } + + res := makePostRequest[routes.UpdateGlobalParamsRequest, routes.UpdateGlobalParamsResponse]( + nodeURL+routes.RoutePathUpdateGlobalParams, request, + ) + return res +} + +func generatePubAndPrivKeys(seedPhrase string) (*lib.PublicKey, *btcec.PrivateKey) { + seedBytes, err := bip39.NewSeedWithErrorChecking(seedPhrase, "") + if err != nil { + panic(errors.Wrap(err, "main(): Could not generate key pair from mnemonic")) + } + + pubKey, privKey, _, err := lib.ComputeKeysFromSeed(seedBytes, 0, &lib.DeSoTestnetParams) + if err != nil { + panic(errors.Wrap(err, "main(): Could not generate key pair from mnemonic")) + } + + publicKey := lib.NewPublicKey(pubKey.SerializeCompressed()) + fmt.Println(lib.PkToString(pubKey.SerializeCompressed(), params)) + return publicKey, privKey +} + +func main() { + adminPublicKey, adminPrivKey := generatePubAndPrivKeys(superAdminSeedPhrase) + updateGlobalParamsTxn := constructUpdateGlobalParams(adminPublicKey) + signAndSubmitTxn(updateGlobalParamsTxn.Transaction, adminPrivKey, nodeURL) +} From e06af2d079afe064548cb61bd47233e3837f9034 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:51:28 -0400 Subject: [PATCH 82/99] trigger build 041924 (#599) From 20c5e08dbceff38241a438b9e6f448dece16bec8 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 19 Apr 2024 14:52:40 -0400 Subject: [PATCH 83/99] Fix update_glboal_params package --- scripts/global_params/update_global_params.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/global_params/update_global_params.go b/scripts/global_params/update_global_params.go index ad1cd4ab..615da6d6 100644 --- a/scripts/global_params/update_global_params.go +++ b/scripts/global_params/update_global_params.go @@ -1,4 +1,4 @@ -package globalparams +package main import ( "bytes" From 5f3bae388bf792a615e5b0248e25694cd2ee76f2 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:57:02 -0400 Subject: [PATCH 84/99] Support MinFeeRateNanosPerKB in atomic txn construction (#602) --- routes/atomic_txns.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/routes/atomic_txns.go b/routes/atomic_txns.go index 10990def..0db40ea0 100644 --- a/routes/atomic_txns.go +++ b/routes/atomic_txns.go @@ -10,8 +10,9 @@ import ( ) type CreateAtomicTxnsWrapperRequest struct { - Transactions []*lib.MsgDeSoTxn - ExtraData map[string]string + Transactions []*lib.MsgDeSoTxn + ExtraData map[string]string + MinFeeRateNanosPerKB uint64 `safeForLogging:"true"` } type CreateAtomicTxnsWrapperResponse struct { @@ -60,7 +61,7 @@ func (fes *APIServer) CreateAtomicTxnsWrapper(ww http.ResponseWriter, req *http. // Construct the atomic transactions wrapper transaction type. txn, totalFees, err := fes.blockchain.CreateAtomicTxnsWrapper( - requestData.Transactions, extraData, fes.backendServer.GetMempool()) + requestData.Transactions, extraData, fes.backendServer.GetMempool(), requestData.MinFeeRateNanosPerKB) if err != nil { _AddBadRequestError(ww, fmt.Sprintf("CreateAtomicTxnsWrapper: Problem constructing transaction: %v", err)) return From ed304f6147b176ffd6f78f93c630831b2eebcd68 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Mon, 22 Apr 2024 23:02:01 -0400 Subject: [PATCH 85/99] update call site for EstimateFeeRate (#603) --- routes/transaction.go | 50 ++----------------------------------------- 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/routes/transaction.go b/routes/transaction.go index 81116d6d..7c6e1657 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -4421,12 +4421,7 @@ func (fes *APIServer) GetSignatureIndex(ww http.ResponseWriter, req *http.Reques } type GetTxnConstructionParamsRequest struct { - MinFeeRateNanosPerKB uint64 - MempoolCongestionFactorBasisPoints uint64 - MempoolPriorityPercentileBasisPoints uint64 - PastBlocksCongestionFactorBasisPoints uint64 - PastBlocksPriorityPercentileBasisPoints uint64 - MaxBlockSize uint64 + MinFeeRateNanosPerKB uint64 } type GetTxnConstructionParamsResponse struct { @@ -4442,49 +4437,8 @@ func (fes *APIServer) GetTxnConstructionParams(ww http.ResponseWriter, req *http return } - // TODO: replace lib.MaxBasisPoints w/ a param defined by a flag from core. - mempoolCongestionFactorBasisPoints := requestData.MempoolCongestionFactorBasisPoints - if requestData.MempoolCongestionFactorBasisPoints == 0 { - mempoolCongestionFactorBasisPoints = lib.MaxBasisPoints - } - - mempoolPriorityPercentileBasisPoints := requestData.MempoolPriorityPercentileBasisPoints - if requestData.MempoolPriorityPercentileBasisPoints == 0 { - mempoolPriorityPercentileBasisPoints = lib.MaxBasisPoints - } - - pastBlocksCongestionFactorBasisPoints := requestData.PastBlocksCongestionFactorBasisPoints - if requestData.PastBlocksCongestionFactorBasisPoints == 0 { - pastBlocksCongestionFactorBasisPoints = lib.MaxBasisPoints - } - - pastBlocksPriorityPercentileBasisPoints := requestData.PastBlocksPriorityPercentileBasisPoints - if requestData.PastBlocksPriorityPercentileBasisPoints == 0 { - pastBlocksPriorityPercentileBasisPoints = lib.MaxBasisPoints - } - - maxBlockSize := requestData.MaxBlockSize - if requestData.MaxBlockSize == 0 { - maxBlockSize = fes.Params.MaxBlockSizeBytesPoW - if fes.Params.IsPoSBlockHeight(uint64(fes.blockchain.BlockTip().Height)) { - uncommittedTipView, err := fes.blockchain.GetUncommittedTipView() - if err != nil { - _AddBadRequestError(ww, "GetTxnConstructionParams: Problem getting uncommitted tip view: "+err.Error()) - return - } - maxBlockSize = uncommittedTipView.GetSoftMaxBlockSizeBytesPoS() - } - } - // Get the fees from the mempool - feeRate := fes.backendServer.GetMempool().EstimateFeeRate( - requestData.MinFeeRateNanosPerKB, - mempoolCongestionFactorBasisPoints, - mempoolPriorityPercentileBasisPoints, - pastBlocksCongestionFactorBasisPoints, - pastBlocksPriorityPercentileBasisPoints, - maxBlockSize, - ) + feeRate := fes.backendServer.GetMempool().EstimateFeeRate(requestData.MinFeeRateNanosPerKB) // Return the fees if err := json.NewEncoder(ww).Encode(GetTxnConstructionParamsResponse{ FeeRateNanosPerKB: feeRate, From 1a2970608189365a186dfb93231365583d488243 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Tue, 23 Apr 2024 00:00:06 -0400 Subject: [PATCH 86/99] trigger build 042324 From 3ce33b5fd68b51748f48fc754f98dd1110a2d790 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Tue, 23 Apr 2024 09:46:23 -0400 Subject: [PATCH 87/99] trigger build 042324 From 7da26994a1aed7f8efb6895d1ec0fd062270adb0 Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:24:39 -0400 Subject: [PATCH 88/99] Gracefully Handle RemoteNode Response When Peer Is Not a Registered Validator (#604) --- routes/admin_node.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/routes/admin_node.go b/routes/admin_node.go index 5d15db06..c7ec25b2 100644 --- a/routes/admin_node.go +++ b/routes/admin_node.go @@ -268,6 +268,11 @@ func _remoteNodeToResponse(remoteNode *lib.RemoteNode, utxoView *lib.UtxoView, p if err != nil { return nil, fmt.Errorf("_remoteNodeToResponse: Problem getting BLS public key PKID pair entry: %v", err) } + // If the node identified itself as a validator but it does not have a validator entry in the UtxoView, + // then it is not a registered validator. We should not return a ValidatorResponse in this case. + if blsPublicKeyPKIDPairEntry == nil { + return remoteNodeResponse, nil + } validatorEntry, err := utxoView.GetValidatorByPKID(blsPublicKeyPKIDPairEntry.PKID) if err != nil { return nil, fmt.Errorf("_remoteNodeToResponse: Problem getting validator entry: %v", err) From 5b073a41a76e93ab6798e2ce5ce130af469faedd Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 23 Apr 2024 15:14:09 -0400 Subject: [PATCH 89/99] Empty commit to trigger CI From 89f1e50b0a6636a4c42dd61cbb53bacea6cb27da Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 23 Apr 2024 15:54:08 -0400 Subject: [PATCH 90/99] Empty commit to trigger CI From 30095a2b2ba1ccd4ad1f74128eed143415818534 Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:57:19 -0400 Subject: [PATCH 91/99] Gracefully Handle Nil Peer in RemoteNodeToResponse (#605) --- .DS_Store | Bin 0 -> 8196 bytes routes/admin_node.go | 15 +++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fa8ef999abb81457ce7baacbdef885cbf8ccdb5b GIT binary patch literal 8196 zcmeHM%Wl&^6upzAvC|6CML`u3!V=pmw1^ZCn~)}pN<5^xP$57eZrl>p^+d7LEUHS` z1HZs8Ah!Gm{0l2MbH^#pq?J$?s1h@k=Qy5oX6`*Ru`@0aiN>(IMzl;sE)Io@3#iU0 zs$Cs3rI1~@4iwN6N$OI#8Ohxsnqk`u)&c8)b-+4c9k32u1_$uWR>eK%xvyJoZ5^-< z{Fe@>`-6u=VLijKM!t2R;w=EMgv(rTj(q@YybS9Zjy19red^tV$fP3MVhAlqyQk>D zdWK_-T24aCNn|67Y=8{CRpX)oS5K3=>3@a~GYzFs?7 z@s8K-)oLr=gVox}NyWW(`_7}S_Ca(Q%a0s6iR|VCtWoMC-1So5?& zf*)I0PHxJACv^G`!l=9!Oa5Bcp+a|e* zI~c!%9AiX+c&6Dr^ZD<^9N3B*(!gM7j6$uBd_QIMBjJ*0FDO6Z>R(Nx8uOme;DH2166728ICpL3W|LZz&6;*I`B^&_zhR` BRLKAU literal 0 HcmV?d00001 diff --git a/routes/admin_node.go b/routes/admin_node.go index c7ec25b2..2fb55289 100644 --- a/routes/admin_node.go +++ b/routes/admin_node.go @@ -255,12 +255,19 @@ func (fes *APIServer) _handleNodeControlGetInfo( func _remoteNodeToResponse(remoteNode *lib.RemoteNode, utxoView *lib.UtxoView, params *lib.DeSoParams) (*RemoteNodeResponse, error) { remoteNodeResponse := &RemoteNodeResponse{} - remoteNodeResponse.PeerResponse = &PeerResponse{ - IP: remoteNode.GetPeer().IP(), - ProtocolPort: remoteNode.GetPeer().Port(), + + // If the remote node connection has been attempted but a peer hasn't been attached yet, there is no peer + // information to return. + peer := remoteNode.GetPeer() + if peer != nil { + remoteNodeResponse.PeerResponse = &PeerResponse{ + IP: remoteNode.GetPeer().IP(), + ProtocolPort: remoteNode.GetPeer().Port(), + } } + remoteNodeResponse.RemoteNodeStatus = remoteNode.GetStatus().String() - remoteNodeResponse.PeerConnected = remoteNode.GetPeer().Connected() + remoteNodeResponse.PeerConnected = peer != nil && remoteNode.GetPeer().Connected() remoteNodeResponse.IsValidator = remoteNode.IsValidator() remoteNodeResponse.LatestBlockHeight = remoteNode.GetLatestBlockHeight() if remoteNodeResponse.IsValidator { From a64e6f1eeeb54da28431c0e6e6977537b3587434 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 24 Apr 2024 18:00:15 -0400 Subject: [PATCH 92/99] Empty commit to trigger CI From f743062e705701f1c796c402e949ae3f900624bf Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:58:36 -0400 Subject: [PATCH 93/99] Fix panic in get block template (#606) --- routes/miner.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/routes/miner.go b/routes/miner.go index 69891e77..6bcd3af2 100644 --- a/routes/miner.go +++ b/routes/miner.go @@ -96,15 +96,20 @@ func (fes *APIServer) GetBlockTemplate(ww http.ResponseWriter, req *http.Request return } + difficultyTargetHex := "" + if diffTarget != nil { + difficultyTargetHex = hex.EncodeToString(diffTarget[:]) + } + res := &GetBlockTemplateResponse{ BlockID: blockID, Headers: headers, ExtraDatas: extraDatas, - DifficultyTargetHex: hex.EncodeToString(diffTarget[:]), + DifficultyTargetHex: difficultyTargetHex, LatestBlockTemplateStats: fes.blockProducer.GetLatestBlockTemplateStats(), } - if err := json.NewEncoder(ww).Encode(res); err != nil { + if err = json.NewEncoder(ww).Encode(res); err != nil { _AddBadRequestError(ww, fmt.Sprintf("GetBlockTemplate: Problem encoding response as JSON: %v", err)) return } From 139b949ffb47f7c938052b79e4d11068425e13ba Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Thu, 25 Apr 2024 17:30:01 -0400 Subject: [PATCH 94/99] Empty commit to trigger CI From d33ed314764bb463b33821b25181f87b1220f572 Mon Sep 17 00:00:00 2001 From: tholonious <99746187+tholonious@users.noreply.github.com> Date: Thu, 25 Apr 2024 18:19:33 -0400 Subject: [PATCH 95/99] Fix Failing Unit Tests (#607) --- routes/validators_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/routes/validators_test.go b/routes/validators_test.go index a98260ea..743317bc 100644 --- a/routes/validators_test.go +++ b/routes/validators_test.go @@ -29,7 +29,7 @@ func TestValidatorRegistration(t *testing.T) { // Send POST request. body := &RegisterAsValidatorRequest{ TransactorPublicKeyBase58Check: senderPkString, - Domains: []string{"https://sender-001.deso.com", "https://sender-002.deso.com"}, + Domains: []string{"sender-001.deso.com:18000", "sender-002.deso.com:18000"}, DisableDelegatedStake: false, VotingPublicKey: votingPublicKey.ToString(), VotingAuthorization: votingAuthorization.ToString(), @@ -56,8 +56,8 @@ func TestValidatorRegistration(t *testing.T) { require.Equal(t, txn.PublicKey, senderPkBytes) txnMeta := txn.TxnMeta.(*lib.RegisterAsValidatorMetadata) require.Len(t, txnMeta.Domains, 2) - require.Equal(t, txnMeta.Domains[0], []byte("https://sender-001.deso.com")) - require.Equal(t, txnMeta.Domains[1], []byte("https://sender-002.deso.com")) + require.Equal(t, txnMeta.Domains[0], []byte("sender-001.deso.com:18000")) + require.Equal(t, txnMeta.Domains[1], []byte("sender-002.deso.com:18000")) require.False(t, txnMeta.DisableDelegatedStake) require.True(t, txnMeta.VotingPublicKey.Eq(votingPublicKey)) require.True(t, txnMeta.VotingAuthorization.Eq(votingAuthorization)) @@ -91,8 +91,8 @@ func TestValidatorRegistration(t *testing.T) { // Verify response fields. require.Equal(t, validatorResponse.ValidatorPublicKeyBase58Check, senderPkString) require.Len(t, validatorResponse.Domains, 2) - require.Equal(t, validatorResponse.Domains[0], "https://sender-001.deso.com") - require.Equal(t, validatorResponse.Domains[1], "https://sender-002.deso.com") + require.Equal(t, validatorResponse.Domains[0], "sender-001.deso.com:18000") + require.Equal(t, validatorResponse.Domains[1], "sender-002.deso.com:18000") require.False(t, validatorResponse.DisableDelegatedStake) require.Equal(t, validatorResponse.VotingPublicKey, votingPublicKey.ToString()) require.Equal(t, validatorResponse.VotingAuthorization, votingAuthorization.ToString()) From 00709df7b27fcdb55e0c22960fb926da8312fdc9 Mon Sep 17 00:00:00 2001 From: diamondhands0 <81935176+diamondhands0@users.noreply.github.com> Date: Fri, 26 Apr 2024 07:44:10 -0700 Subject: [PATCH 96/99] Add simple status check for node to backend (#608) * wip * wip --- routes/server.go | 10 +++++++++- routes/validators.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/routes/server.go b/routes/server.go index 2da2c5f4..0ae9fd24 100644 --- a/routes/server.go +++ b/routes/server.go @@ -317,7 +317,8 @@ const ( RoutePathStateChecksum = "/api/v0/state-checksum" // validators.go - RoutePathValidators = "/api/v0/validators" + RoutePathValidators = "/api/v0/validators" + RoutePathCheckNodeStatus = "/api/v0/check-node-status" // stake.go RoutePathStake = "/api/v0/stake" @@ -1353,6 +1354,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.GetValidatorByPublicKeyBase58Check, PublicAccess, }, + { + "CheckNodeStatus", + []string{"POST", "OPTIONS"}, + RoutePathCheckNodeStatus, + fes.CheckNodeStatus, + PublicAccess, + }, { "CreateStakeTxn", []string{"POST", "OPTIONS"}, diff --git a/routes/validators.go b/routes/validators.go index 8b447ebf..9c6278cd 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -9,7 +9,9 @@ import ( "github.com/gorilla/mux" "github.com/holiman/uint256" "io" + "net" "net/http" + "time" ) type RegisterAsValidatorRequest struct { @@ -352,6 +354,44 @@ func (fes *APIServer) GetValidatorByPublicKeyBase58Check(ww http.ResponseWriter, } } +type CheckNodeStatusRequest struct { + NodeHostPort string `safeForLogging:"true"` +} + +type CheckNodeStatusResponse struct { + Success bool `safeForLogging:"true"` +} + +func (fes *APIServer) CheckNodeStatus(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := CheckNodeStatusRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, "UnjailValidator: problem parsing request body") + return + } + + // We do an *extremely* simple check for now, which is that we just check to see if the node + // is reachable at all. + // TODO: We should beef this up to test an actual version handshake or something more robust. + conn, err := net.DialTimeout("tcp", requestData.NodeHostPort, 5*time.Second) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "Problem connecting to %v: %v", requestData.NodeHostPort, err)) + return + } + // If we get here it means we succeeded. Close the connection to clean up. + conn.Close() + + res := CheckNodeStatusResponse{ + Success: true, + } + if err := json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "UnjailValidator: problem encoding response as JSON") + return + } +} + func _convertValidatorEntryToResponse( utxoView *lib.UtxoView, validatorEntry *lib.ValidatorEntry, params *lib.DeSoParams, ) *ValidatorResponse { From 90fc2e096588cea90fcaa869d20bc4bdd9905ec2 Mon Sep 17 00:00:00 2001 From: diamondhands0 <81935176+diamondhands0@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:11:16 -0700 Subject: [PATCH 97/99] Upgrades to support DeSo AMMs and CCV2 (#609) This PR contains several SAFE upgrades to backend to support the various things we need for DeSo AMMs: - Add a `TxnStatus` field that can be provided as an argument to `GetDAOCoinLimitOrders`, `GetTxn`, and `GetTransactorDAOCoinLimitOrders`. This param allows the caller to either consider *unconfirmed txns*, which was the existing behavior before the introduction of this field, or to only consider *confirmed* txns. The latter is what we need for the AMM since we only want to be reacting to things that are finalized. Note that this change is SAFE because the default value is TxnStatusUnconfirmed, which was the pre-existing behavior. If you don't pass the argument, as none of the existing callers do, you will get the exact same result. It's only if you pass TxnStatusConfirmed, as the AMM code does, that you will get a different result than before. - Make it so that you can provide a list of OrderIds to `GetDAOCoinLimitOrdersRequest` and get back the ones that are currently on the book. Needed for the main loop of the AMM. - Introduce a new function called `IsDesoPkid` that flexibly allows the caller of backend endpoints to specify any of {"DESO", MiannetZeroPkidBase58Check, TestnetZeroPkidBase58Check} and get the same behavior. This change is needed because some things rely on using a ZeroPkid while other things rely on the "DESO" string being passed. This change is SAFE because it makes these functions LESS restrictive, and all pre-existing code that calls the endpoints with "DESO" are unaffected. - Allow for filtering by buying/selling pkid in `GetTransactorDAOCoinLimitOrders` . This is needed for the main loop of the AMM. This change is SAFE because the params are optional, and leaving them out gives you the exact same behavior as before. --- routes/dao_coin_exchange.go | 243 ++++++++++++++++++++++++++++++++---- routes/transaction.go | 41 +++++- 2 files changed, 252 insertions(+), 32 deletions(-) diff --git a/routes/dao_coin_exchange.go b/routes/dao_coin_exchange.go index 90ebce44..9b7fe2d6 100644 --- a/routes/dao_coin_exchange.go +++ b/routes/dao_coin_exchange.go @@ -2,6 +2,7 @@ package routes import ( "bytes" + "encoding/hex" "encoding/json" "fmt" "github.com/deso-protocol/core/lib" @@ -18,6 +19,13 @@ import ( type GetDAOCoinLimitOrdersRequest struct { DAOCoin1CreatorPublicKeyBase58Check string `safeForLogging:"true"` DAOCoin2CreatorPublicKeyBase58Check string `safeForLogging:"true"` + + // A list of hex OrderIds that we will fetch + OrderIds []string `safeForLogging:"true"` + // If unset, defaults to TxnStatusUnconfirmed. If set to "unconfirmed" we will + // consider all txns including those in the mempool. If set to "confirmed" then + // we will only consider txns that have been confirmed according to consensus. + TxnStatus TxnStatus `safeForLogging:"true"` } type GetDAOCoinLimitOrdersResponse struct { @@ -63,8 +71,8 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re return } - if requestData.DAOCoin1CreatorPublicKeyBase58Check == DESOCoinIdentifierString && - requestData.DAOCoin2CreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(requestData.DAOCoin1CreatorPublicKeyBase58Check) && + IsDesoPkid(requestData.DAOCoin2CreatorPublicKeyBase58Check) { _AddBadRequestError( ww, fmt.Sprint("GetDAOCoinLimitOrders: Must provide either a "+ @@ -74,16 +82,115 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re return } + txnStatus := requestData.TxnStatus + if txnStatus == "" { + txnStatus = TxnStatusUnconfirmed + } else if txnStatus != TxnStatusUnconfirmed && + txnStatus != TxnStatusConfirmed { + + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Invalid TxnStatus: %v. Options "+ + "are {unconfirmed, confirmed}.", txnStatus), + ) + return + } + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetDAOCoinLimitOrders: Problem fetching utxoView: %v", err)) return } + if txnStatus == TxnStatusConfirmed { + utxoView = lib.NewUtxoView( + fes.backendServer.GetBlockchain().DB(), + fes.Params, + nil, + fes.backendServer.GetBlockchain().Snapshot(), + nil) + } + + // If they requested a specific set of OrderIds then fetch them directly + if len(requestData.OrderIds) > 0 { + // Don't allow fetching more than this many orders + maxOrdersToFetch := 10000 + if len(requestData.OrderIds) > maxOrdersToFetch { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Cannot fetch more than %v orders at once", maxOrdersToFetch), + ) + return + } + ordersToReturn := make([]DAOCoinLimitOrderEntryResponse, 0, len(requestData.OrderIds)) + for _, orderIdHex := range requestData.OrderIds { + orderIdBytes, err := hex.DecodeString(orderIdHex) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Invalid OrderId: %v", err), + ) + return + } + if len(orderIdBytes) != 32 { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Block hash has length (%d) but should "+ + "be (%d)", len(orderIdBytes), 32), + ) + return + } + orderId := lib.BlockHash{} + copy(orderId[:], orderIdBytes) + orderEntry, err := utxoView.GetDAOCoinLimitOrderEntry(&orderId) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Error fetching order: %v", err), + ) + return + } + if orderEntry == nil { + continue + } + if orderEntry.IsDeleted() { + continue + } + orderRes, err := buildDAOCoinLimitOrderResponse( + lib.Base58CheckEncode(orderEntry.TransactorPKID[:], false, fes.Params), + lib.Base58CheckEncode(orderEntry.BuyingDAOCoinCreatorPKID[:], false, fes.Params), + lib.Base58CheckEncode(orderEntry.SellingDAOCoinCreatorPKID[:], false, fes.Params), + orderEntry, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Error building order response: %v", err), + ) + return + } + if orderRes == nil { + _AddInternalServerError(ww, "GetDAOCoinLimitOrders: Error building order "+ + "response: nil order response") + return + } + ordersToReturn = append(ordersToReturn, *orderRes) + } + if err = json.NewEncoder(ww).Encode(GetDAOCoinLimitOrdersResponse{ + Orders: ordersToReturn, + }); err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Problem encoding response as JSON: %v", err), + ) + return + } + return + } coin1PKID := &lib.ZeroPKID coin2PKID := &lib.ZeroPKID - if requestData.DAOCoin1CreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(requestData.DAOCoin1CreatorPublicKeyBase58Check) { coin1PKID, err = fes.getPKIDFromPublicKeyBase58Check( utxoView, requestData.DAOCoin1CreatorPublicKeyBase58Check, @@ -97,7 +204,7 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re } } - if requestData.DAOCoin2CreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(requestData.DAOCoin2CreatorPublicKeyBase58Check) { coin2PKID, err = fes.getPKIDFromPublicKeyBase58Check( utxoView, requestData.DAOCoin2CreatorPublicKeyBase58Check, @@ -145,7 +252,12 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re } type GetTransactorDAOCoinLimitOrdersRequest struct { - TransactorPublicKeyBase58Check string `safeForLogging:"true"` + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + BuyingCoinPublicKeyBase58Check string `safeForLogging:"true"` + SellingCoinPublicKeyBase58Check string `safeForLogging:"true"` + // Defaults to TxnStatusUnconfirmed. If set to "unconfirmed" we will consider all + // txns including those in the mempool. + TxnStatus TxnStatus `safeForLogging:"true"` } func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Request) { @@ -159,11 +271,34 @@ func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, re return } + txnStatus := requestData.TxnStatus + if txnStatus == "" { + txnStatus = TxnStatusUnconfirmed + } + if txnStatus != TxnStatusUnconfirmed && + txnStatus != TxnStatusConfirmed { + + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid TxnStatus: %v. Options "+ + "are {unconfirmed, confirmed}.", txnStatus), + ) + return + } + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Problem fetching utxoView: %v", err)) return } + if txnStatus == TxnStatusConfirmed { + utxoView = lib.NewUtxoView( + fes.backendServer.GetBlockchain().DB(), + fes.Params, + nil, + fes.backendServer.GetBlockchain().Snapshot(), + nil) + } transactorPKID, err := fes.getPKIDFromPublicKeyBase58Check( utxoView, @@ -176,8 +311,45 @@ func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, re ) return } + var buyingCoinPkid *lib.PKID + if requestData.BuyingCoinPublicKeyBase58Check != "" { + if IsDesoPkid(requestData.BuyingCoinPublicKeyBase58Check) { + buyingCoinPkid = &lib.ZeroPKID + } else { + buyingCoinPkid, err = fes.getPKIDFromPublicKeyBase58Check( + utxoView, + requestData.BuyingCoinPublicKeyBase58Check, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid BuyingCoinPublicKeyBase58Check: %v", err), + ) + return + } + } + } + var sellingCoinPkid *lib.PKID + if requestData.SellingCoinPublicKeyBase58Check != "" { + if IsDesoPkid(requestData.SellingCoinPublicKeyBase58Check) { + sellingCoinPkid = &lib.ZeroPKID + } else { + sellingCoinPkid, err = fes.getPKIDFromPublicKeyBase58Check( + utxoView, + requestData.SellingCoinPublicKeyBase58Check, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid SellingCoinPublicKeyBase58Check: %v", err), + ) + return + } + } + } - orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor(transactorPKID) + orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor( + transactorPKID, buyingCoinPkid, sellingCoinPkid) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Error getting limit orders: %v", err)) return @@ -324,6 +496,14 @@ func buildDAOCoinLimitOrderResponse( return nil, err } + // We always want to return the identifier string for DESO coins in the API response + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { + buyingCoinPublicKeyBase58Check = DESOCoinIdentifierString + } + if IsDesoPkid(sellingCoinPublicKeyBase58Check) { + sellingCoinPublicKeyBase58Check = DESOCoinIdentifierString + } + return &DAOCoinLimitOrderEntryResponse{ TransactorPublicKeyBase58Check: transactorPublicKeyBase58Check, @@ -436,10 +616,10 @@ func CalculateScaledExchangeRateFromPriceString( // For DESO <-> DAO coin trades, we scale the calculated exchange rate up or down by 1e9 to account for the // scaling factor difference between DESO nanos and DAO coin base units - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { // Scale the exchange rate up by 1e9 if the buying coin is DESO rawScaledExchangeRateAsBigInt.Mul(rawScaledExchangeRateAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { // Scale the exchange rate down by 1e9 if the selling coin is DESO if and round the quotient up. // For the same reason as above, we round up the quotient, so it matches with bid orders created using the // same input price @@ -462,7 +642,7 @@ func CalculateScaledExchangeRateFromPriceString( // Beyond this point, we know that the operation type is lib.DAOCoinLimitOrderOperationTypeBID // Scale up the price to account for DAO Coin -> DESO trades - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { product := uint256.NewInt(0) _, overflow := product.MulOverflow(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) if overflow { @@ -472,7 +652,7 @@ func CalculateScaledExchangeRateFromPriceString( } // Scale down the price to account for DAO Coin -> DESO trades - if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingCoinPublicKeyBase58Check) { // We intentionally want to round the exchange rate down for BID orders so precision loss does not prevent the // order from not getting matched with an ASK order with the same input price quotient := uint256.NewInt(0).Div(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) @@ -512,7 +692,7 @@ func CalculateScaledExchangeRateFromFloat( if rawScaledExchangeRate.IsZero() { return nil, errors.Errorf("The float value %f is too small to produce a scaled exchange rate", exchangeRateCoinsToSellPerCoinToBuy) } - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { // Buying coin is $DESO product := uint256.NewInt(0) _, overflow := product.MulOverflow(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) @@ -520,7 +700,7 @@ func CalculateScaledExchangeRateFromFloat( return nil, errors.Errorf("Overflow when convering %f to a scaled exchange rate", exchangeRateCoinsToSellPerCoinToBuy) } return product, nil - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { // Selling coin is $DESO quotient := uint256.NewInt(0).Div(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) if quotient.IsZero() { @@ -543,9 +723,9 @@ func CalculatePriceStringFromScaledExchangeRate( ) (string, error) { scaledExchangeRateAsBigInt := scaledValueExchangeRate.ToBig() - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { scaledExchangeRateAsBigInt.Div(scaledExchangeRateAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { scaledExchangeRateAsBigInt.Mul(scaledExchangeRateAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) } @@ -578,9 +758,9 @@ func CalculateFloatFromScaledExchangeRate( scaledValue *uint256.Int, ) (float64, error) { scaledValueAsBigInt := scaledValue.ToBig() - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { scaledValueAsBigInt.Div(scaledValueAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { scaledValueAsBigInt.Mul(scaledValueAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) } @@ -698,6 +878,17 @@ func calculateQuantityToFillAsDESONanos(quantityToFill string) (*uint256.Int, er return scaledQuantity, nil } +var ( + DeSoZeroPkidMainnetBase58 = lib.PkToStringMainnet(lib.ZeroPKID[:]) + DeSoZeroPkidTestnetBase58 = lib.PkToStringTestnet(lib.ZeroPKID[:]) +) + +func IsDesoPkid(pk string) bool { + return (pk == DESOCoinIdentifierString || + pk == DeSoZeroPkidMainnetBase58 || + pk == DeSoZeroPkidTestnetBase58) +} + // given a buying coin, selling coin, and operation type, this determines if the QuantityToFill field // for the coin the quantity field refers to is $DESO. If it's not $DESO, then it's assumed to be a DAO coin func isCoinToFillDESO( @@ -705,8 +896,8 @@ func isCoinToFillDESO( sellingCoinPublicKeyBase58Check string, operationTypeString DAOCoinLimitOrderOperationTypeString, ) bool { - return buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString && operationTypeString == DAOCoinLimitOrderOperationTypeStringBID || - sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString && operationTypeString == DAOCoinLimitOrderOperationTypeStringASK + return IsDesoPkid(buyingCoinPublicKeyBase58Check) && operationTypeString == DAOCoinLimitOrderOperationTypeStringBID || + IsDesoPkid(sellingCoinPublicKeyBase58Check) && operationTypeString == DAOCoinLimitOrderOperationTypeStringASK } // DAOCoinLimitOrderOperationTypeString A convenience type that uses a string to represent BID / ASK side in the API, @@ -856,7 +1047,7 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( // If buying $DESO, the buying PKID is the ZeroPKID. Else it's the DAO coin's PKID. buyingCoinPKID := &lib.ZeroPKID - if buyingDAOCoinCreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { buyingCoinPKID, err = fes.getPKIDFromPublicKeyBase58Check( utxoView, buyingDAOCoinCreatorPublicKeyBase58Check) if err != nil { @@ -870,7 +1061,7 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( // Calculate current balance for transactor. transactorSellingBalanceBaseUnits := uint256.NewInt(0) - if sellingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) { // Get $DESO balance nanos. desoBalanceNanos, err := utxoView.GetDeSoBalanceNanosForPublicKey(transactorPublicKey) if err != nil { @@ -898,7 +1089,7 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( } // Get open orders for this transactor - orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor(transactorPKID) + orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor(transactorPKID, nil, nil) if err != nil { return errors.Errorf("Error getting limit orders: %v", err) } @@ -949,7 +1140,7 @@ func (fes *APIServer) validateDAOCoinOrderTransferRestriction( // If buying $DESO, this never has a transfer restriction. We validate // that you own sufficient of your selling coin elsewhere. - if buyingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { return nil } @@ -1020,7 +1211,7 @@ func (fes *APIServer) getDAOCoinLimitOrderSimulatedExecutionResult( if err != nil { return nil, err } - if buyingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { // If the buying coin is DESO, then the ending balance change will have the transaction fee subtracted. In order to // isolate the amount of the buying coin bought as a part of this order, we need to add back the transaction fee buyingCoinEndingBalance.Add(buyingCoinEndingBalance, uint256.NewInt(txnFees)) @@ -1030,7 +1221,7 @@ func (fes *APIServer) getDAOCoinLimitOrderSimulatedExecutionResult( if err != nil { return nil, err } - if sellingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) { // If the selling coin is DESO, then the ending balance will have the network fee subtracted. In order to isolate // the amount of the selling coin sold as a part of this order, we need to add back the transaction fee to the // ending balance @@ -1076,7 +1267,7 @@ func (fes *APIServer) getTransactorDesoOrDaoCoinBalance( return nil, errors.Errorf("Error decoding transactor public key: %v", err) } - if desoOrDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(desoOrDAOCoinCreatorPublicKeyBase58Check) { // Get $DESO balance nanos. desoBalanceNanos, err := utxoView.GetDeSoBalanceNanosForPublicKey(transactorPublicKey) if err != nil { @@ -1099,7 +1290,7 @@ func (fes *APIServer) getTransactorDesoOrDaoCoinBalance( } func getScalingFactorForCoin(coinCreatorPublicKeyBase58Check string) *uint256.Int { - if coinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(coinCreatorPublicKeyBase58Check) { return uint256.NewInt(lib.NanosPerUnit) } return uint256.NewInt(0).Set(lib.BaseUnitsPerCoin) diff --git a/routes/transaction.go b/routes/transaction.go index 7c6e1657..f0626e0b 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -25,9 +25,21 @@ import ( "github.com/pkg/errors" ) +type TxnStatus string + +const ( + TxnStatusUnconfirmed TxnStatus = "unconfirmed" + TxnStatusConfirmed TxnStatus = "confirmed" + // TODO: It would be useful to have one that is "InBlock" or something like that, which + // means we'll consider txns that are in unconfirmed blocks but will *not* consider txns + // that are in the mempool. It's a kindof middle-ground. +) + type GetTxnRequest struct { // TxnHashHex to fetch. TxnHashHex string `safeForLogging:"true"` + // If unset, defaults to TxnStatusUnconfirmed + TxnStatus TxnStatus `safeForLogging:"true"` } type GetTxnResponse struct { @@ -58,10 +70,27 @@ func (fes *APIServer) GetTxn(ww http.ResponseWriter, req *http.Request) { copy(txnHash[:], txnHashBytes) } - txnFound := fes.backendServer.GetMempool().IsTransactionInPool(txnHash) - if !txnFound { + txnFound := false + txnStatus := requestData.TxnStatus + if txnStatus == "" { + txnStatus = TxnStatusUnconfirmed + } + switch txnStatus { + case TxnStatusUnconfirmed: + txnFound = fes.backendServer.GetMempool().IsTransactionInPool(txnHash) + if !txnFound { + txnFound = lib.DbCheckTxnExistence(fes.TXIndex.TXIndexChain.DB(), nil, txnHash) + } + case TxnStatusConfirmed: + // In this case we will not consider a txn until it shows up in txindex, which means that + // it is confirmed. txnFound = lib.DbCheckTxnExistence(fes.TXIndex.TXIndexChain.DB(), nil, txnHash) + default: + _AddBadRequestError(ww, fmt.Sprintf("GetTxn: Invalid TxnStatus: %v. Options are "+ + "{unconfirmed, confirmed}", txnStatus)) + return } + res := &GetTxnResponse{ TxnFound: txnFound, } @@ -3231,8 +3260,8 @@ func (fes *APIServer) getBuyingAndSellingDAOCoinPublicKeys( buyingDAOCoinCreatorPublicKeyBase58Check string, sellingDAOCoinCreatorPublicKeyBase58Check string, ) ([]byte, []byte, error) { - if sellingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString && - buyingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) && + IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { return nil, nil, errors.Errorf("'DESO' specified for both the " + "coin to buy and the coin to sell. At least one must specify a valid DAO public key whose coin " + "will be bought or sold") @@ -3243,14 +3272,14 @@ func (fes *APIServer) getBuyingAndSellingDAOCoinPublicKeys( var err error - if buyingDAOCoinCreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { buyingCoinPublicKey, err = GetPubKeyBytesFromBase58Check(buyingDAOCoinCreatorPublicKeyBase58Check) if err != nil { return nil, nil, err } } - if sellingDAOCoinCreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) { sellingCoinPublicKey, err = GetPubKeyBytesFromBase58Check(sellingDAOCoinCreatorPublicKeyBase58Check) if err != nil { return nil, nil, err From 927e7ee000a8d6137de41b2c01457c35bef40687 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:13:40 -0400 Subject: [PATCH 98/99] Add GetDaoCaoinLimitOrdersById (#610) --- routes/dao_coin_exchange.go | 316 +++++++++++++++++++++--------------- routes/server.go | 8 + routes/transaction.go | 18 +- 3 files changed, 198 insertions(+), 144 deletions(-) diff --git a/routes/dao_coin_exchange.go b/routes/dao_coin_exchange.go index 9b7fe2d6..7aae6890 100644 --- a/routes/dao_coin_exchange.go +++ b/routes/dao_coin_exchange.go @@ -20,11 +20,9 @@ type GetDAOCoinLimitOrdersRequest struct { DAOCoin1CreatorPublicKeyBase58Check string `safeForLogging:"true"` DAOCoin2CreatorPublicKeyBase58Check string `safeForLogging:"true"` - // A list of hex OrderIds that we will fetch - OrderIds []string `safeForLogging:"true"` - // If unset, defaults to TxnStatusUnconfirmed. If set to "unconfirmed" we will - // consider all txns including those in the mempool. If set to "confirmed" then - // we will only consider txns that have been confirmed according to consensus. + // If unset, defaults to TxnStatusInMempool. If set to "InMempool" we will + // consider all txns including those in the mempool. If set to "Committed" then + // we will only consider txns that have been committed according to consensus. TxnStatus TxnStatus `safeForLogging:"true"` } @@ -60,6 +58,26 @@ type DAOCoinLimitOrderEntryResponse struct { const DESOCoinIdentifierString = "DESO" +func (fes *APIServer) GetUtxoViewGivenTxnStatus( + txnStatus TxnStatus, +) ( + *lib.UtxoView, + error, +) { + if txnStatus == TxnStatusInMempool { + return fes.backendServer.GetMempool().GetAugmentedUniversalView() + } + if txnStatus == TxnStatusCommitted { + return lib.NewUtxoView( + fes.backendServer.GetBlockchain().DB(), + fes.Params, + nil, + fes.backendServer.GetBlockchain().Snapshot(), + nil), nil + } + return nil, errors.New("GetUtxoViewGivenTxnStatus: Invalid TxnStatus") +} + func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Request) { decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) requestData := GetDAOCoinLimitOrdersRequest{} @@ -84,108 +102,24 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re txnStatus := requestData.TxnStatus if txnStatus == "" { - txnStatus = TxnStatusUnconfirmed - } else if txnStatus != TxnStatusUnconfirmed && - txnStatus != TxnStatusConfirmed { + txnStatus = TxnStatusInMempool + } + if txnStatus != TxnStatusInMempool && + txnStatus != TxnStatusCommitted { _AddBadRequestError( ww, fmt.Sprintf("GetDAOCoinLimitOrders: Invalid TxnStatus: %v. Options "+ - "are {unconfirmed, confirmed}.", txnStatus), + "are {InMempool, Committed}.", txnStatus), ) return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := fes.GetUtxoViewGivenTxnStatus(txnStatus) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetDAOCoinLimitOrders: Problem fetching utxoView: %v", err)) return } - if txnStatus == TxnStatusConfirmed { - utxoView = lib.NewUtxoView( - fes.backendServer.GetBlockchain().DB(), - fes.Params, - nil, - fes.backendServer.GetBlockchain().Snapshot(), - nil) - } - - // If they requested a specific set of OrderIds then fetch them directly - if len(requestData.OrderIds) > 0 { - // Don't allow fetching more than this many orders - maxOrdersToFetch := 10000 - if len(requestData.OrderIds) > maxOrdersToFetch { - _AddBadRequestError( - ww, - fmt.Sprintf("GetDAOCoinLimitOrders: Cannot fetch more than %v orders at once", maxOrdersToFetch), - ) - return - } - ordersToReturn := make([]DAOCoinLimitOrderEntryResponse, 0, len(requestData.OrderIds)) - for _, orderIdHex := range requestData.OrderIds { - orderIdBytes, err := hex.DecodeString(orderIdHex) - if err != nil { - _AddBadRequestError( - ww, - fmt.Sprintf("GetDAOCoinLimitOrders: Invalid OrderId: %v", err), - ) - return - } - if len(orderIdBytes) != 32 { - _AddBadRequestError( - ww, - fmt.Sprintf("GetDAOCoinLimitOrders: Block hash has length (%d) but should "+ - "be (%d)", len(orderIdBytes), 32), - ) - return - } - orderId := lib.BlockHash{} - copy(orderId[:], orderIdBytes) - orderEntry, err := utxoView.GetDAOCoinLimitOrderEntry(&orderId) - if err != nil { - _AddBadRequestError( - ww, - fmt.Sprintf("GetDAOCoinLimitOrders: Error fetching order: %v", err), - ) - return - } - if orderEntry == nil { - continue - } - if orderEntry.IsDeleted() { - continue - } - orderRes, err := buildDAOCoinLimitOrderResponse( - lib.Base58CheckEncode(orderEntry.TransactorPKID[:], false, fes.Params), - lib.Base58CheckEncode(orderEntry.BuyingDAOCoinCreatorPKID[:], false, fes.Params), - lib.Base58CheckEncode(orderEntry.SellingDAOCoinCreatorPKID[:], false, fes.Params), - orderEntry, - ) - if err != nil { - _AddBadRequestError( - ww, - fmt.Sprintf("GetDAOCoinLimitOrders: Error building order response: %v", err), - ) - return - } - if orderRes == nil { - _AddInternalServerError(ww, "GetDAOCoinLimitOrders: Error building order "+ - "response: nil order response") - return - } - ordersToReturn = append(ordersToReturn, *orderRes) - } - if err = json.NewEncoder(ww).Encode(GetDAOCoinLimitOrdersResponse{ - Orders: ordersToReturn, - }); err != nil { - _AddBadRequestError( - ww, - fmt.Sprintf("GetDAOCoinLimitOrders: Problem encoding response as JSON: %v", err), - ) - return - } - return - } coin1PKID := &lib.ZeroPKID coin2PKID := &lib.ZeroPKID @@ -251,11 +185,129 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re } } +type GetDAOCoinLimitOrdersByIdRequest struct { + // A list of hex OrderIds that we will fetch + OrderIds []string `safeForLogging:"true"` + // If unset, defaults to TxnStatusInMempool. If set to "InMempool" we will + // consider all txns including those in the mempool. If set to "Committed" then + // we will only consider txns that have been committed according to consensus. + TxnStatus TxnStatus `safeForLogging:"true"` +} + +func (fes *APIServer) GetDAOCoinLimitOrdersById(ww http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := GetDAOCoinLimitOrdersByIdRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrdersById: Problem parsing request body: %v", err), + ) + return + } + + txnStatus := requestData.TxnStatus + if txnStatus == "" { + txnStatus = TxnStatusInMempool + } + if txnStatus != TxnStatusInMempool && + txnStatus != TxnStatusCommitted { + + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrdersById: Invalid TxnStatus: %v. Options "+ + "are {InMempool, Committed}.", txnStatus), + ) + return + } + + utxoView, err := fes.GetUtxoViewGivenTxnStatus(txnStatus) + if err != nil { + _AddInternalServerError(ww, fmt.Sprintf("GetDAOCoinLimitOrdersById: Problem fetching utxoView: %v", err)) + return + } + + // Don't allow fetching more than this many orders + maxOrdersToFetch := 10000 + if len(requestData.OrderIds) > maxOrdersToFetch { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrdersById: Cannot fetch more than %v orders at once", maxOrdersToFetch), + ) + return + } + ordersToReturn := make([]DAOCoinLimitOrderEntryResponse, 0, len(requestData.OrderIds)) + for _, orderIdHex := range requestData.OrderIds { + orderIdBytes, err := hex.DecodeString(orderIdHex) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrdersById: Invalid OrderId: %v", err), + ) + return + } + if len(orderIdBytes) != 32 { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrdersById: Block hash has length (%d) but should "+ + "be (%d)", len(orderIdBytes), 32), + ) + return + } + orderId := lib.BlockHash{} + copy(orderId[:], orderIdBytes) + orderEntry, err := utxoView.GetDAOCoinLimitOrderEntry(&orderId) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrdersById: Error fetching order: %v", err), + ) + return + } + if orderEntry == nil { + continue + } + if orderEntry.IsDeleted() { + continue + } + transactorPublicKey := utxoView.GetPublicKeyForPKID(orderEntry.TransactorPKID) + buyingCoinPublicKey := utxoView.GetPublicKeyForPKID(orderEntry.BuyingDAOCoinCreatorPKID) + sellingCoinPublicKey := utxoView.GetPublicKeyForPKID(orderEntry.SellingDAOCoinCreatorPKID) + orderRes, err := buildDAOCoinLimitOrderResponse( + lib.Base58CheckEncode(transactorPublicKey, false, fes.Params), + lib.Base58CheckEncode(buyingCoinPublicKey, false, fes.Params), + lib.Base58CheckEncode(sellingCoinPublicKey, false, fes.Params), + orderEntry, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrdersById: Error building order response: %v", err), + ) + return + } + if orderRes == nil { + _AddInternalServerError(ww, "GetDAOCoinLimitOrdersById: Error building order "+ + "response: nil order response") + return + } + ordersToReturn = append(ordersToReturn, *orderRes) + } + if err = json.NewEncoder(ww).Encode(GetDAOCoinLimitOrdersResponse{ + Orders: ordersToReturn, + }); err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Problem encoding response as JSON: %v", err), + ) + return + } +} + type GetTransactorDAOCoinLimitOrdersRequest struct { TransactorPublicKeyBase58Check string `safeForLogging:"true"` BuyingCoinPublicKeyBase58Check string `safeForLogging:"true"` SellingCoinPublicKeyBase58Check string `safeForLogging:"true"` - // Defaults to TxnStatusUnconfirmed. If set to "unconfirmed" we will consider all + // Defaults to TxnStatusInMempool. If set to "InMempool" we will consider all // txns including those in the mempool. TxnStatus TxnStatus `safeForLogging:"true"` } @@ -273,32 +325,24 @@ func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, re txnStatus := requestData.TxnStatus if txnStatus == "" { - txnStatus = TxnStatusUnconfirmed + txnStatus = TxnStatusInMempool } - if txnStatus != TxnStatusUnconfirmed && - txnStatus != TxnStatusConfirmed { + if txnStatus != TxnStatusInMempool && + txnStatus != TxnStatusCommitted { _AddBadRequestError( ww, fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid TxnStatus: %v. Options "+ - "are {unconfirmed, confirmed}.", txnStatus), + "are {InMempool, Committed}.", txnStatus), ) return } - utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + utxoView, err := fes.GetUtxoViewGivenTxnStatus(txnStatus) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Problem fetching utxoView: %v", err)) return } - if txnStatus == TxnStatusConfirmed { - utxoView = lib.NewUtxoView( - fes.backendServer.GetBlockchain().DB(), - fes.Params, - nil, - fes.backendServer.GetBlockchain().Snapshot(), - nil) - } transactorPKID, err := fes.getPKIDFromPublicKeyBase58Check( utxoView, @@ -313,38 +357,30 @@ func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, re } var buyingCoinPkid *lib.PKID if requestData.BuyingCoinPublicKeyBase58Check != "" { - if IsDesoPkid(requestData.BuyingCoinPublicKeyBase58Check) { - buyingCoinPkid = &lib.ZeroPKID - } else { - buyingCoinPkid, err = fes.getPKIDFromPublicKeyBase58Check( - utxoView, - requestData.BuyingCoinPublicKeyBase58Check, + buyingCoinPkid, err = fes.getPKIDFromPublicKeyBase58CheckOrDESOString( + utxoView, + requestData.BuyingCoinPublicKeyBase58Check, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid BuyingCoinPublicKeyBase58Check: %v", err), ) - if err != nil { - _AddBadRequestError( - ww, - fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid BuyingCoinPublicKeyBase58Check: %v", err), - ) - return - } + return } } var sellingCoinPkid *lib.PKID if requestData.SellingCoinPublicKeyBase58Check != "" { - if IsDesoPkid(requestData.SellingCoinPublicKeyBase58Check) { - sellingCoinPkid = &lib.ZeroPKID - } else { - sellingCoinPkid, err = fes.getPKIDFromPublicKeyBase58Check( - utxoView, - requestData.SellingCoinPublicKeyBase58Check, + sellingCoinPkid, err = fes.getPKIDFromPublicKeyBase58CheckOrDESOString( + utxoView, + requestData.SellingCoinPublicKeyBase58Check, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid SellingCoinPublicKeyBase58Check: %v", err), ) - if err != nil { - _AddBadRequestError( - ww, - fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid SellingCoinPublicKeyBase58Check: %v", err), - ) - return - } + return } } @@ -363,6 +399,16 @@ func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, re } } +func (fes *APIServer) getPKIDFromPublicKeyBase58CheckOrDESOString( + utxoView *lib.UtxoView, + publicKeyBase58Check string, +) (*lib.PKID, error) { + if IsDesoPkid(publicKeyBase58Check) { + return &lib.ZeroPKID, nil + } + return fes.getPKIDFromPublicKeyBase58Check(utxoView, publicKeyBase58Check) +} + func (fes *APIServer) getPKIDFromPublicKeyBase58Check( utxoView *lib.UtxoView, publicKeyBase58Check string, diff --git a/routes/server.go b/routes/server.go index 0ae9fd24..e46edf5e 100644 --- a/routes/server.go +++ b/routes/server.go @@ -100,6 +100,7 @@ const ( // dao_coin_exchange.go RoutePathGetDaoCoinLimitOrders = "/api/v0/get-dao-coin-limit-orders" + RoutePathGetDaoCoinLimitOrdersById = "/api/v0/get-dao-coin-limit-orders-by-id" RoutePathGetTransactorDaoCoinLimitOrders = "/api/v0/get-transactor-dao-coin-limit-orders" // post.go @@ -1235,6 +1236,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.GetDAOCoinLimitOrders, PublicAccess, }, + { + "GetDAOCoinLimitOrdersById", + []string{"POST", "OPTIONS"}, + RoutePathGetDaoCoinLimitOrdersById, + fes.GetDAOCoinLimitOrdersById, + PublicAccess, + }, { "GetTransactorDAOCoinLimitOrders", []string{"POST", "OPTIONS"}, diff --git a/routes/transaction.go b/routes/transaction.go index f0626e0b..557c8f4d 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -28,9 +28,9 @@ import ( type TxnStatus string const ( - TxnStatusUnconfirmed TxnStatus = "unconfirmed" - TxnStatusConfirmed TxnStatus = "confirmed" - // TODO: It would be useful to have one that is "InBlock" or something like that, which + TxnStatusInMempool TxnStatus = "InMempool" + TxnStatusCommitted TxnStatus = "Committed" + // TODO: It would be useful to have one that is "UnconfirmedBlocks" or something like that, which // means we'll consider txns that are in unconfirmed blocks but will *not* consider txns // that are in the mempool. It's a kindof middle-ground. ) @@ -38,7 +38,7 @@ const ( type GetTxnRequest struct { // TxnHashHex to fetch. TxnHashHex string `safeForLogging:"true"` - // If unset, defaults to TxnStatusUnconfirmed + // If unset, defaults to TxnStatusInMempool TxnStatus TxnStatus `safeForLogging:"true"` } @@ -73,21 +73,21 @@ func (fes *APIServer) GetTxn(ww http.ResponseWriter, req *http.Request) { txnFound := false txnStatus := requestData.TxnStatus if txnStatus == "" { - txnStatus = TxnStatusUnconfirmed + txnStatus = TxnStatusInMempool } switch txnStatus { - case TxnStatusUnconfirmed: + case TxnStatusInMempool: txnFound = fes.backendServer.GetMempool().IsTransactionInPool(txnHash) if !txnFound { txnFound = lib.DbCheckTxnExistence(fes.TXIndex.TXIndexChain.DB(), nil, txnHash) } - case TxnStatusConfirmed: + case TxnStatusCommitted: // In this case we will not consider a txn until it shows up in txindex, which means that - // it is confirmed. + // it is committed. txnFound = lib.DbCheckTxnExistence(fes.TXIndex.TXIndexChain.DB(), nil, txnHash) default: _AddBadRequestError(ww, fmt.Sprintf("GetTxn: Invalid TxnStatus: %v. Options are "+ - "{unconfirmed, confirmed}", txnStatus)) + "{InMempool, Committed}", txnStatus)) return } From e55f4146e6f8fc1ffefdddb569841b0d4469791c Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Fri, 26 Apr 2024 16:14:44 -0400 Subject: [PATCH 99/99] trigger build