From 11ba62105c604694f1f43ee07c12ec35b9ee2b46 Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 9 Aug 2021 22:24:21 +0800 Subject: [PATCH 01/21] fix(transcation):#195 fixed min_confirmation bug on veriry transaction --- core/transaction/entity.go | 82 +++++++++++++------- core/transaction/err.go | 13 ++++ core/util/httpnet.go | 25 ++++-- go.mod | 3 + go.sum | 34 ++++++++- zboxcore/conf/conf.go | 152 +++++++++++++++++++++++++++++++++++++ zboxcore/conf/conf_test.go | 54 +++++++++++++ zboxcore/conf/config.go | 34 +++++++++ zboxcore/conf/network.go | 9 +++ 9 files changed, 366 insertions(+), 40 deletions(-) create mode 100644 core/transaction/err.go create mode 100644 zboxcore/conf/conf.go create mode 100644 zboxcore/conf/conf_test.go create mode 100644 zboxcore/conf/config.go create mode 100644 zboxcore/conf/network.go diff --git a/core/transaction/entity.go b/core/transaction/entity.go index 2ece2887a..e0e7ace19 100644 --- a/core/transaction/entity.go +++ b/core/transaction/entity.go @@ -3,19 +3,20 @@ package transaction import ( "encoding/json" "fmt" + "strconv" + "strings" "sync" + "github.com/0chain/errors" "github.com/0chain/gosdk/core/common" - "github.com/0chain/gosdk/core/common/errors" "github.com/0chain/gosdk/core/encryption" "github.com/0chain/gosdk/core/util" + "github.com/0chain/gosdk/zboxcore/conf" ) const TXN_SUBMIT_URL = "v1/transaction/put" const TXN_VERIFY_URL = "v1/transaction/get/confirmation?hash=" -var ErrNoTxnDetail = errors.New("missing_transaction_detail", "No transaction detail was found on any of the sharders") - //Transaction entity that encapsulates the transaction related data and meta data type Transaction struct { Hash string `json:"hash,omitempty"` @@ -204,61 +205,86 @@ func sendTransactionToURL(url string, txn *Transaction, wg *sync.WaitGroup) ([]b return nil, errors.Wrap(err, errors.New("transaction_send_error", postResponse.Body)) } +// VerifyTransaction query transaction status from sharders, and verify it by mininal confirmation func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) { numSharders := len(sharders) + + if numSharders == 0 { + return nil, ErrNoAvailableSharder + } + numSuccess := 0 var retTxn *Transaction - var customError error + + //leave first item for ErrTooLessConfirmation + var msgList = make([]string, 1, numSharders) + for _, sharder := range sharders { url := fmt.Sprintf("%v/%v%v", sharder, TXN_VERIFY_URL, txnHash) req, err := util.NewHTTPGetRequest(url) if err != nil { - customError = errors.Wrap(customError, err) - numSharders-- + msgList = append(msgList, err.Error()+": ", url) continue } response, err := req.Get() if err != nil { - customError = errors.Wrap(customError, err) - numSharders-- + msgList = append(msgList, err.Error()+": ", url) continue } else { if response.StatusCode != 200 { - customError = errors.Wrap(customError, err) + msgList = append(msgList, strconv.Itoa(response.StatusCode)+": "+response.Body+" "+url) continue } + contents := response.Body var objmap map[string]json.RawMessage err = json.Unmarshal([]byte(contents), &objmap) if err != nil { - customError = errors.Wrap(customError, err) + msgList = append(msgList, "json: "+contents) continue } - if _, ok := objmap["txn"]; !ok { + txnRawJSON, ok := objmap["txn"] + + // txn data is found, success + if ok { + txn := &Transaction{} + err = json.Unmarshal(txnRawJSON, txn) + if err != nil { + msgList = append(msgList, "json: "+string(txnRawJSON)) + continue + } + if len(txn.Signature) > 0 { + retTxn = txn + } + numSuccess++ + + } else { + // txn data is not found, but get block_hash, success if _, ok := objmap["block_hash"]; ok { numSuccess++ } else { - customError = errors.Wrap(customError, fmt.Sprintf("Sharder does not have the block summary with url: %s, contents: %s", url, contents)) + // txn and block_hash + msgList = append(msgList, fmt.Sprintf("Sharder does not have the block summary with url: %s, contents: %s", url, contents)) } - continue - } - txn := &Transaction{} - err = json.Unmarshal(objmap["txn"], txn) - if err != nil { - customError = errors.Wrap(customError, err) - continue - } - if len(txn.Signature) > 0 { - retTxn = txn + } - numSuccess++ + } } - if numSharders == 0 || float64(numSuccess*1.0/numSharders) > 0.5 { - if retTxn != nil { - return retTxn, nil + + consensus := int(float64(numSuccess) / float64(numSharders) * 100) + + if consensus >= conf.Config.MinConfirmation { + + if retTxn == nil { + return nil, errors.Throw(ErrNoTxnDetail, strings.Join(msgList, "\r\n")) } - return nil, errors.Wrap(customError, ErrNoTxnDetail) + + return retTxn, nil } - return nil, errors.Wrap(customError, errors.New("transaction_not_found", "Transaction was not found on any of the sharders")) + + msgList[0] = fmt.Sprintf("want %v, but got %v ", conf.Config.MinConfirmation, consensus) + + return nil, errors.Throw(ErrTooLessConfirmation, strings.Join(msgList, "\r\n")) + } diff --git a/core/transaction/err.go b/core/transaction/err.go new file mode 100644 index 000000000..f1305125e --- /dev/null +++ b/core/transaction/err.go @@ -0,0 +1,13 @@ +package transaction + +import "errors" + +var ( + // ErrNoAvailableSharder no any available sharder + ErrNoAvailableSharder = errors.New("[sharder] there is no any available sharder") + // ErrNoTxnDetail No transaction detail was found on any of the sharders + ErrNoTxnDetail = errors.New("[sc] no transaction detail was found on any of the sharders") + + // ErrTooLessConfirmation too less sharder to confirm transaction + ErrTooLessConfirmation = errors.New("[sc] too less sharders to confirm it") +) diff --git a/core/util/httpnet.go b/core/util/httpnet.go index 67093fec1..268428627 100644 --- a/core/util/httpnet.go +++ b/core/util/httpnet.go @@ -112,28 +112,37 @@ func httpDo(req *http.Request, ctx context.Context, cncl context.CancelFunc, f f } } +// NewHTTPGetRequest create a GetRequest instance with 60s timeout func NewHTTPGetRequest(url string) (*GetRequest, error) { - var ctx, _ = context.WithTimeout(context.Background(), 60*time.Second) + var ctx, cancel = context.WithTimeout(context.Background(), 60*time.Second) + go func() { + //call cancel to avoid memory leak here + <-ctx.Done() + + cancel() + + }() + return NewHTTPGetRequestContext(ctx, url) } -func NewHTTPGetRequestContext(ctx context.Context, url string) ( - gr *GetRequest, err error) { +// NewHTTPGetRequestContext create a GetRequest with context and url +func NewHTTPGetRequestContext(ctx context.Context, url string) (*GetRequest, error) { - var req *http.Request - if req, err = http.NewRequest(http.MethodGet, url, nil); err != nil { - return + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, err } req.Header.Set("Content-Type", "application/json; charset=utf-8") req.Header.Set("Access-Control-Allow-Origin", "*") - gr = new(GetRequest) + gr := new(GetRequest) gr.PostRequest = &PostRequest{} gr.url = url gr.req = req gr.ctx, gr.cncl = context.WithCancel(ctx) - return + return gr, nil } func NewHTTPPostRequest(url string, data interface{}) (*PostRequest, error) { diff --git a/go.mod b/go.mod index 194d019fa..53ada5477 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,16 @@ module github.com/0chain/gosdk require ( + github.com/0chain/errors v1.0.1 github.com/ethereum/go-ethereum v1.10.3 github.com/h2non/filetype v1.0.9 github.com/herumi/bls-go-binary v0.0.0-20191119080710-898950e1a520 github.com/klauspost/reedsolomon v1.9.11 github.com/lithammer/shortuuid/v3 v3.0.7 github.com/miguelmota/go-ethereum-hdwallet v0.0.1 + github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.1.2 + github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.7.0 github.com/tyler-smith/go-bip39 v1.1.0 go.dedis.ch/kyber/v3 v3.0.5 diff --git a/go.sum b/go.sum index da5f69bc7..4980bb0e0 100644 --- a/go.sum +++ b/go.sum @@ -280,7 +280,9 @@ 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/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/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/gordonklaus/ineffassign v0.0.0-20210729092907-69aca2aeecd0/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -321,6 +323,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/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= @@ -376,6 +379,7 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ 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/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= +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= @@ -421,6 +425,7 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +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= github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o= @@ -439,11 +444,13 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mdempsky/unconvert v0.0.0-20200228143138-95ecdbfc0b5f/go.mod h1:AmCV4WB3cDMZqgPk+OUQKumliiQS4ZYsBt3AXekyuAU= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miguelmota/go-ethereum-hdwallet v0.0.1 h1:DWqgZtKWTGcHR5QsprMJItZiJ2xVEQTv640r597ul8M= github.com/miguelmota/go-ethereum-hdwallet v0.0.1/go.mod h1:iowKavXnc0NVNiv/UKYYBo3SjADph5PUvYQTjOIV9as= 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/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= @@ -508,6 +515,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= @@ -566,6 +574,7 @@ github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeC github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= 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/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= @@ -585,19 +594,26 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +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/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= 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 v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +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.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= @@ -617,6 +633,7 @@ 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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= @@ -646,6 +663,7 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -762,8 +780,9 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 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= @@ -825,8 +844,10 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210313202042-bd2e13477e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 h1:EjgCl+fVlIaPJSori0ikSz3uV0DOHKWOJFpv1sAAhBM= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -876,8 +897,10 @@ golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/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.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5-0.20210701083923-20dafe5d6055 h1:NERXP1LBH5J8EdMKMlgDICTiE9eH6TbSsgKffA5Zkr8= +golang.org/x/tools v0.1.5-0.20210701083923-20dafe5d6055/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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= @@ -959,6 +982,7 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= @@ -995,8 +1019,10 @@ 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.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +honnef.co/go/tools v0.2.0 h1:ws8AfbgTX3oIczLPNPCu5166oBg9ST2vNs0rcht+mDE= +honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= +mvdan.cc/unparam v0.0.0-20210701114405-894c3c7ee6a6/go.mod h1:NijgoTDkB71ywH6oehYVF5YQKtiZ4BOos+O87CC6sdk= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/zboxcore/conf/conf.go b/zboxcore/conf/conf.go new file mode 100644 index 000000000..dfd932055 --- /dev/null +++ b/zboxcore/conf/conf.go @@ -0,0 +1,152 @@ +// pakcage conf provide config helpers for ~/.zcn/config.yaml, ~/.zcn/network.yaml and ~/.zcn/wallet.json + +package conf + +import ( + "errors" + "fmt" + "net/url" + "os" + "path" + "strings" + + thrown "github.com/0chain/errors" + "github.com/mitchellh/go-homedir" + "github.com/spf13/viper" +) + +var ( + // DefaultConfigFileName default config file in ~/.zcn + DefaultConfigFileName = "config.yaml" + + // Config current config instance for zbox + Config ZConfig +) + +var ( + // ErrMssingConfig config file is missing + ErrMssingConfig = errors.New("[conf]missing config file") + // ErrInvalidValue invalid value in config + ErrInvalidValue = errors.New("[conf]invalid value") + // ErrBadFormat fail to parse config via spf13/viper + ErrBadFormat = errors.New("[conf]bad format") +) + +func init() { + LoadDefault() +} + +// LoadDefault load and parse config from ~/.zcn/config.yaml +func LoadDefault() error { + return Load(DefaultConfigFileName) +} + +// Load load and parse config file in ~/.zcn folder. it is ~/.zcn/config.yaml if file is invalid. +// Example: +// conf.Load("stream.yaml"), it will load settings from ~/.zcn/stream.yaml +func Load(fileName string) error { + file := path.Join(getConfigDir(), fileName) + _, err := os.Stat(file) + + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return thrown.Throw(ErrMssingConfig, err.Error()) + } + return err + } + + cfg, err := loadConfigFile(file) + + if err != nil { + return err + } + + Config = cfg + return nil +} + +func loadConfigFile(file string) (ZConfig, error) { + + var cfg ZConfig + + v := viper.New() + + v.SetConfigFile(file) + + if err := v.ReadInConfig(); err != nil { + return cfg, thrown.Throw(ErrBadFormat, err.Error()) + } + + blockWorker := strings.TrimSpace(v.GetString("block_worker")) + + if isURL(blockWorker) == false { + return cfg, thrown.Throw(ErrInvalidValue, "block_worker="+blockWorker) + } + + minSubmit := v.GetInt("min_submit") + + if minSubmit < 1 { + minSubmit = 50 + } else if minSubmit > 100 { + minSubmit = 100 + } + + minCfm := v.GetInt("min_confirmation") + + if minCfm < 1 { + minCfm = 50 + } else if minCfm > 100 { + minCfm = 100 + } + + CfmChainLength := v.GetInt("confirmation_chain_length") + + if CfmChainLength < 1 { + CfmChainLength = 3 + } + + // additional settings depending network latency + + maxTxnQuery := v.GetInt("max_txn_query") + if maxTxnQuery < 1 { + maxTxnQuery = 5 + } + + querySleepTime := v.GetInt("query_sleep_time") + if querySleepTime < 1 { + querySleepTime = 5 + } + + cfg.BlockWorker = blockWorker + cfg.PreferredBlobbers = v.GetStringSlice("preferred_blobbers") + cfg.MinSubmit = minSubmit + cfg.MinConfirmation = minCfm + cfg.ConfirmationChainLength = CfmChainLength + cfg.MaxTxnQuery = maxTxnQuery + cfg.QuerySleepTime = querySleepTime + + return cfg, nil + +} + +// getConfigDir get config directory , default is ~/.zcn/ +func getConfigDir() string { + + var configDir string + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + configDir = home + string(os.PathSeparator) + ".zcn" + + os.MkdirAll(configDir, 0744) + + return configDir +} + +func isURL(s string) bool { + u, err := url.Parse(s) + return err == nil && u.Scheme != "" && u.Host != "" +} diff --git a/zboxcore/conf/conf_test.go b/zboxcore/conf/conf_test.go new file mode 100644 index 000000000..b344b8f68 --- /dev/null +++ b/zboxcore/conf/conf_test.go @@ -0,0 +1,54 @@ +package conf + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func setUpConfig(name, content string) { + + ioutil.WriteFile(filepath.Join(getConfigDir(), name), []byte(content), 0744) +} + +func tearDownConfig(name string) { + os.Remove(filepath.Join(getConfigDir(), name)) +} + +func TestMissingConfig(t *testing.T) { + + configFile := "missing_config.yaml" + + err := Load(configFile) + + require.ErrorIs(t, err, ErrMssingConfig) +} + +func TestBadFormat(t *testing.T) { + + setUpConfig("bad_format.yaml", ` +{ + block_worker:"", + +`) + defer tearDownConfig("bad_format.yaml") + + err := Load("bad_format.yaml") + + require.ErrorIs(t, err, ErrBadFormat) +} + +func TestInvalidBlockWorker(t *testing.T) { + + setUpConfig("invalid_blockworker.yaml", ` +block_worker: 127.0.0.1:9091 +`) + defer tearDownConfig("invalid_blockworker.yaml") + + err := Load("invalid_blockworker.yaml") + + require.ErrorIs(t, err, ErrInvalidValue) +} diff --git a/zboxcore/conf/config.go b/zboxcore/conf/config.go new file mode 100644 index 000000000..6a33a9d04 --- /dev/null +++ b/zboxcore/conf/config.go @@ -0,0 +1,34 @@ +package conf + +// ZConfig settings from ~/.zcn/config.yaml +// block_worker: http://198.18.0.98:9091 +// signature_scheme: bls0chain +// min_submit: 50 +// min_confirmation: 50 +// confirmation_chain_length: 3 +// max_txn_query: 5 +// query_sleep_time: 5 +// # # OPTIONAL - Uncomment to use/ Add more if you want +// # preferred_blobbers: +// # - http://one.devnet-0chain.net:31051 +// # - http://one.devnet-0chain.net:31052 +// # - http://one.devnet-0chain.net:31053 +type ZConfig struct { + // BlockWorker the url of 0dns's network api + BlockWorker string + // PreferredBlobbers preferred blobbers on new allocation + PreferredBlobbers []string + + // MinSubmit mininal submit from blobber + MinSubmit int + // MinConfirmation mininal confirmation from sharders + MinConfirmation int + // CconfirmationChainLength minial confirmation chain length + ConfirmationChainLength int + + // additional settings depending network latency + // MaxTxnQuery maximum transcation query from sharders + MaxTxnQuery int + // QuerySleepTime sleep time before transcation query + QuerySleepTime int +} diff --git a/zboxcore/conf/network.go b/zboxcore/conf/network.go new file mode 100644 index 000000000..9a629e119 --- /dev/null +++ b/zboxcore/conf/network.go @@ -0,0 +1,9 @@ +package conf + +// ZNetwork settings from ~/.zcn/network.yaml +type ZNetwork struct { + // Sharders sharder list of blockchain + Sharders []string + // Miners miner list of blockchain + Miners []string +} From e220b04556528af29f0fd23d039369d5c305b35f Mon Sep 17 00:00:00 2001 From: Lz Date: Tue, 10 Aug 2021 00:22:44 +0800 Subject: [PATCH 02/21] fix(transcation):#195 removed fmt.Println --- zboxcore/conf/conf.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zboxcore/conf/conf.go b/zboxcore/conf/conf.go index dfd932055..6d649add8 100644 --- a/zboxcore/conf/conf.go +++ b/zboxcore/conf/conf.go @@ -4,7 +4,6 @@ package conf import ( "errors" - "fmt" "net/url" "os" "path" @@ -136,8 +135,7 @@ func getConfigDir() string { // Find home directory. home, err := homedir.Dir() if err != nil { - fmt.Println(err) - os.Exit(1) + panic(err) } configDir = home + string(os.PathSeparator) + ".zcn" From 266210852c88c10fe6a1f6b15ec3fd094fc7ac82 Mon Sep 17 00:00:00 2001 From: Lz Date: Tue, 10 Aug 2021 16:59:53 +0800 Subject: [PATCH 03/21] fix(transcation):#195 test result based on ErrNoTxnDetail instead of error message in Test_Sharder_Verify_Txn_Failed --- go.sum | 21 ++++++--------------- zboxcore/sdk/allocation_test.go | 25 +++++++++++++++++-------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/go.sum b/go.sum index 4980bb0e0..5a6c434b3 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/0chain/errors v1.0.1 h1:e1jyKmYtF5jQdFOeEAjdfyLe5D46HrNO46Z97tWvEh8= +github.com/0chain/errors v1.0.1/go.mod h1:5t76jLb56TKfg/K2VD+eUMmNZJ42QsIRI8KzWuztwU4= 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= @@ -282,7 +284,6 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 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/gordonklaus/ineffassign v0.0.0-20210729092907-69aca2aeecd0/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -444,7 +445,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mdempsky/unconvert v0.0.0-20200228143138-95ecdbfc0b5f/go.mod h1:AmCV4WB3cDMZqgPk+OUQKumliiQS4ZYsBt3AXekyuAU= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miguelmota/go-ethereum-hdwallet v0.0.1 h1:DWqgZtKWTGcHR5QsprMJItZiJ2xVEQTv640r597ul8M= github.com/miguelmota/go-ethereum-hdwallet v0.0.1/go.mod h1:iowKavXnc0NVNiv/UKYYBo3SjADph5PUvYQTjOIV9as= @@ -574,7 +574,6 @@ github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeC github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= 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/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= @@ -663,7 +662,6 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -780,9 +778,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 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= @@ -844,10 +841,8 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210313202042-bd2e13477e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 h1:EjgCl+fVlIaPJSori0ikSz3uV0DOHKWOJFpv1sAAhBM= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -897,10 +892,8 @@ golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/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-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5-0.20210701083923-20dafe5d6055 h1:NERXP1LBH5J8EdMKMlgDICTiE9eH6TbSsgKffA5Zkr8= -golang.org/x/tools v0.1.5-0.20210701083923-20dafe5d6055/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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= @@ -1019,10 +1012,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.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -honnef.co/go/tools v0.2.0 h1:ws8AfbgTX3oIczLPNPCu5166oBg9ST2vNs0rcht+mDE= -honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -mvdan.cc/unparam v0.0.0-20210701114405-894c3c7ee6a6/go.mod h1:NijgoTDkB71ywH6oehYVF5YQKtiZ4BOos+O87CC6sdk= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/zboxcore/sdk/allocation_test.go b/zboxcore/sdk/allocation_test.go index 9a58e70dd..a8fc864e8 100644 --- a/zboxcore/sdk/allocation_test.go +++ b/zboxcore/sdk/allocation_test.go @@ -2694,11 +2694,12 @@ func TestAllocation_CommitFolderChange(t *testing.T) { blockchain.SetQuerySleepTime(1) tests := []struct { - name string - parameters parameters - setup func(*testing.T, string, *Allocation) (teardown func(*testing.T)) - wantErr bool - errMsg string + name string + parameters parameters + setup func(*testing.T, string, *Allocation) (teardown func(*testing.T)) + wantErr bool + errMsg string + exceptedError error }{ { name: "Test_Uninitialized_Failed", @@ -2723,8 +2724,9 @@ func TestAllocation_CommitFolderChange(t *testing.T) { setupHttpResponse(t, testCaseName+"mockSharders", http.MethodGet, http.StatusBadRequest, []byte("")) return nil }, - wantErr: true, - errMsg: "transaction_not_found: Transaction was not found on any of the sharders", + wantErr: true, + exceptedError: transaction.ErrNoTxnDetail, + errMsg: "transaction_not_found: Transaction was not found on any of the sharders", }, { name: "Test_Max_Retried_Failed", @@ -2783,7 +2785,14 @@ func TestAllocation_CommitFolderChange(t *testing.T) { _, err := a.CommitFolderChange(tt.parameters.operation, tt.parameters.preValue, tt.parameters.currValue) require.EqualValues(tt.wantErr, err != nil) if err != nil { - require.EqualValues(tt.errMsg, errors.Top(err)) + + // test it by predefined error variable instead of error message + if tt.exceptedError != nil { + require.ErrorsIs(t, tt.exceptedError, err) + } else { + require.EqualValues(tt.errMsg, errors.Top(err)) + } + return } require.NoErrorf(err, "unexpected error: %v", err) From 2a460b34938333cfb97634a218dad71d4e6ea418 Mon Sep 17 00:00:00 2001 From: Lz Date: Tue, 10 Aug 2021 17:10:32 +0800 Subject: [PATCH 04/21] fix(transcation):#195 test result based on ErrNoTxnDetail instead of error message in Test_Sharder_Verify_Txn_Failed --- zboxcore/sdk/allocation_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zboxcore/sdk/allocation_test.go b/zboxcore/sdk/allocation_test.go index a8fc864e8..79eb18f9d 100644 --- a/zboxcore/sdk/allocation_test.go +++ b/zboxcore/sdk/allocation_test.go @@ -2788,7 +2788,7 @@ func TestAllocation_CommitFolderChange(t *testing.T) { // test it by predefined error variable instead of error message if tt.exceptedError != nil { - require.ErrorsIs(t, tt.exceptedError, err) + require.ErrorIs(t, tt.exceptedError, err) } else { require.EqualValues(tt.errMsg, errors.Top(err)) } From 926a8fa39c95258b1601fc05b2a0c32c90203d56 Mon Sep 17 00:00:00 2001 From: Lz Date: Tue, 10 Aug 2021 18:19:03 +0800 Subject: [PATCH 05/21] fix(transcation):#195 fixed Test_Sharder_Verify_Txn_Failed --- zboxcore/sdk/allocation_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zboxcore/sdk/allocation_test.go b/zboxcore/sdk/allocation_test.go index 79eb18f9d..fd63740ec 100644 --- a/zboxcore/sdk/allocation_test.go +++ b/zboxcore/sdk/allocation_test.go @@ -2725,7 +2725,7 @@ func TestAllocation_CommitFolderChange(t *testing.T) { return nil }, wantErr: true, - exceptedError: transaction.ErrNoTxnDetail, + exceptedError: transaction.ErrTooLessConfirmation, errMsg: "transaction_not_found: Transaction was not found on any of the sharders", }, { @@ -2788,7 +2788,7 @@ func TestAllocation_CommitFolderChange(t *testing.T) { // test it by predefined error variable instead of error message if tt.exceptedError != nil { - require.ErrorIs(t, tt.exceptedError, err) + require.ErrorIs(err, tt.exceptedError) } else { require.EqualValues(tt.errMsg, errors.Top(err)) } From e40ebebb3dac8fe9c46253761ab59943e32e4764 Mon Sep 17 00:00:00 2001 From: Lz Date: Tue, 10 Aug 2021 18:28:35 +0800 Subject: [PATCH 06/21] fix(transcation):#195 fixed Test_Sharder_Verify_Txn_Failed --- core/transaction/entity.go | 2 +- go.mod | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/transaction/entity.go b/core/transaction/entity.go index e0e7ace19..2976b3c9c 100644 --- a/core/transaction/entity.go +++ b/core/transaction/entity.go @@ -274,7 +274,7 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) consensus := int(float64(numSuccess) / float64(numSharders) * 100) - if consensus >= conf.Config.MinConfirmation { + if consensus > 0 && consensus >= conf.Config.MinConfirmation { if retTxn == nil { return nil, errors.Throw(ErrNoTxnDetail, strings.Join(msgList, "\r\n")) diff --git a/go.mod b/go.mod index 53ada5477..e486df1f2 100644 --- a/go.mod +++ b/go.mod @@ -19,3 +19,5 @@ require ( ) go 1.13 + +replace github.com/0chain/errros => ../errors From d4d05f4c8cf7aefbc081f1c89c24f0bcb8843137 Mon Sep 17 00:00:00 2001 From: Lz Date: Tue, 10 Aug 2021 23:21:29 +0800 Subject: [PATCH 07/21] fix(transcation):#195 removed go mod replace on go.mod --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index e486df1f2..9e23b5353 100644 --- a/go.mod +++ b/go.mod @@ -20,4 +20,3 @@ require ( go 1.13 -replace github.com/0chain/errros => ../errors From 739b48207eb012460603db09ec7ac85f79a32ff3 Mon Sep 17 00:00:00 2001 From: Lz Date: Wed, 11 Aug 2021 00:12:35 +0800 Subject: [PATCH 08/21] fix(transcation):#195 remove global variables --- {zboxcore => core}/conf/conf.go | 43 ++++++---------------------- {zboxcore => core}/conf/conf_test.go | 6 ++-- {zboxcore => core}/conf/config.go | 4 +-- {zboxcore => core}/conf/network.go | 4 +-- core/transaction/entity.go | 8 +++--- 5 files changed, 20 insertions(+), 45 deletions(-) rename {zboxcore => core}/conf/conf.go (80%) rename {zboxcore => core}/conf/conf_test.go (88%) rename {zboxcore => core}/conf/config.go (93%) rename {zboxcore => core}/conf/network.go (64%) diff --git a/zboxcore/conf/conf.go b/core/conf/conf.go similarity index 80% rename from zboxcore/conf/conf.go rename to core/conf/conf.go index 6d649add8..738c7cc19 100644 --- a/zboxcore/conf/conf.go +++ b/core/conf/conf.go @@ -14,14 +14,6 @@ import ( "github.com/spf13/viper" ) -var ( - // DefaultConfigFileName default config file in ~/.zcn - DefaultConfigFileName = "config.yaml" - - // Config current config instance for zbox - Config ZConfig -) - var ( // ErrMssingConfig config file is missing ErrMssingConfig = errors.New("[conf]missing config file") @@ -31,43 +23,28 @@ var ( ErrBadFormat = errors.New("[conf]bad format") ) -func init() { - LoadDefault() -} - // LoadDefault load and parse config from ~/.zcn/config.yaml -func LoadDefault() error { - return Load(DefaultConfigFileName) +func LoadDefault() (Config, error) { + return Load("config.yaml") } // Load load and parse config file in ~/.zcn folder. it is ~/.zcn/config.yaml if file is invalid. // Example: // conf.Load("stream.yaml"), it will load settings from ~/.zcn/stream.yaml -func Load(fileName string) error { +func Load(fileName string) (Config, error) { + + var cfg Config + file := path.Join(getConfigDir(), fileName) _, err := os.Stat(file) if err != nil { if errors.Is(err, os.ErrNotExist) { - return thrown.Throw(ErrMssingConfig, err.Error()) + return cfg, thrown.Throw(ErrMssingConfig, err.Error()) } - return err + return cfg, err } - cfg, err := loadConfigFile(file) - - if err != nil { - return err - } - - Config = cfg - return nil -} - -func loadConfigFile(file string) (ZConfig, error) { - - var cfg ZConfig - v := viper.New() v.SetConfigFile(file) @@ -85,9 +62,7 @@ func loadConfigFile(file string) (ZConfig, error) { minSubmit := v.GetInt("min_submit") if minSubmit < 1 { - minSubmit = 50 - } else if minSubmit > 100 { - minSubmit = 100 + minSubmit = 3 } minCfm := v.GetInt("min_confirmation") diff --git a/zboxcore/conf/conf_test.go b/core/conf/conf_test.go similarity index 88% rename from zboxcore/conf/conf_test.go rename to core/conf/conf_test.go index b344b8f68..6cac1dceb 100644 --- a/zboxcore/conf/conf_test.go +++ b/core/conf/conf_test.go @@ -22,7 +22,7 @@ func TestMissingConfig(t *testing.T) { configFile := "missing_config.yaml" - err := Load(configFile) + _, err := Load(configFile) require.ErrorIs(t, err, ErrMssingConfig) } @@ -36,7 +36,7 @@ func TestBadFormat(t *testing.T) { `) defer tearDownConfig("bad_format.yaml") - err := Load("bad_format.yaml") + _, err := Load("bad_format.yaml") require.ErrorIs(t, err, ErrBadFormat) } @@ -48,7 +48,7 @@ block_worker: 127.0.0.1:9091 `) defer tearDownConfig("invalid_blockworker.yaml") - err := Load("invalid_blockworker.yaml") + _, err := Load("invalid_blockworker.yaml") require.ErrorIs(t, err, ErrInvalidValue) } diff --git a/zboxcore/conf/config.go b/core/conf/config.go similarity index 93% rename from zboxcore/conf/config.go rename to core/conf/config.go index 6a33a9d04..1a7e7fb53 100644 --- a/zboxcore/conf/config.go +++ b/core/conf/config.go @@ -1,6 +1,6 @@ package conf -// ZConfig settings from ~/.zcn/config.yaml +// Config settings from ~/.zcn/config.yaml // block_worker: http://198.18.0.98:9091 // signature_scheme: bls0chain // min_submit: 50 @@ -13,7 +13,7 @@ package conf // # - http://one.devnet-0chain.net:31051 // # - http://one.devnet-0chain.net:31052 // # - http://one.devnet-0chain.net:31053 -type ZConfig struct { +type Config struct { // BlockWorker the url of 0dns's network api BlockWorker string // PreferredBlobbers preferred blobbers on new allocation diff --git a/zboxcore/conf/network.go b/core/conf/network.go similarity index 64% rename from zboxcore/conf/network.go rename to core/conf/network.go index 9a629e119..ff02d38f2 100644 --- a/zboxcore/conf/network.go +++ b/core/conf/network.go @@ -1,7 +1,7 @@ package conf -// ZNetwork settings from ~/.zcn/network.yaml -type ZNetwork struct { +// Network settings from ~/.zcn/network.yaml +type Network struct { // Sharders sharder list of blockchain Sharders []string // Miners miner list of blockchain diff --git a/core/transaction/entity.go b/core/transaction/entity.go index 2976b3c9c..5f029e2c7 100644 --- a/core/transaction/entity.go +++ b/core/transaction/entity.go @@ -9,9 +9,9 @@ import ( "github.com/0chain/errors" "github.com/0chain/gosdk/core/common" + "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/encryption" "github.com/0chain/gosdk/core/util" - "github.com/0chain/gosdk/zboxcore/conf" ) const TXN_SUBMIT_URL = "v1/transaction/put" @@ -206,7 +206,7 @@ func sendTransactionToURL(url string, txn *Transaction, wg *sync.WaitGroup) ([]b } // VerifyTransaction query transaction status from sharders, and verify it by mininal confirmation -func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) { +func VerifyTransaction(txnHash string, sharders []string, cfg conf.Config) (*Transaction, error) { numSharders := len(sharders) if numSharders == 0 { @@ -274,7 +274,7 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) consensus := int(float64(numSuccess) / float64(numSharders) * 100) - if consensus > 0 && consensus >= conf.Config.MinConfirmation { + if consensus > 0 && consensus >= cfg.MinConfirmation { if retTxn == nil { return nil, errors.Throw(ErrNoTxnDetail, strings.Join(msgList, "\r\n")) @@ -283,7 +283,7 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) return retTxn, nil } - msgList[0] = fmt.Sprintf("want %v, but got %v ", conf.Config.MinConfirmation, consensus) + msgList[0] = fmt.Sprintf("want %v, but got %v ", cfg.MinConfirmation, consensus) return nil, errors.Throw(ErrTooLessConfirmation, strings.Join(msgList, "\r\n")) From 91b57231fad58e558e2bdfdd1150022c6bbdb3c0 Mon Sep 17 00:00:00 2001 From: Lz Date: Wed, 11 Aug 2021 00:36:08 +0800 Subject: [PATCH 09/21] fix(transcation):#195 updated comment --- core/conf/conf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/conf/conf.go b/core/conf/conf.go index 738c7cc19..1d16f8d58 100644 --- a/core/conf/conf.go +++ b/core/conf/conf.go @@ -28,7 +28,7 @@ func LoadDefault() (Config, error) { return Load("config.yaml") } -// Load load and parse config file in ~/.zcn folder. it is ~/.zcn/config.yaml if file is invalid. +// Load load and parse config file in ~/.zcn folder. // Example: // conf.Load("stream.yaml"), it will load settings from ~/.zcn/stream.yaml func Load(fileName string) (Config, error) { From f4b61a613691ab4649f13791f066c613b9aa387a Mon Sep 17 00:00:00 2001 From: Lz Date: Wed, 11 Aug 2021 01:00:16 +0800 Subject: [PATCH 10/21] fix(transcation):#195 refactor old methods with conf.Config --- zboxcore/sdk/allocation.go | 11 ++-- zboxcore/sdk/allocation_test.go | 5 +- zboxcore/sdk/commitmetaworker.go | 13 +++-- zboxcore/sdk/sdk.go | 96 ++++++++++++++++---------------- zcncore/transaction.go | 5 +- 5 files changed, 68 insertions(+), 62 deletions(-) diff --git a/zboxcore/sdk/allocation.go b/zboxcore/sdk/allocation.go index 30771f551..52a824ae8 100644 --- a/zboxcore/sdk/allocation.go +++ b/zboxcore/sdk/allocation.go @@ -17,13 +17,13 @@ import ( "sync" "time" - "github.com/0chain/gosdk/zboxcore/client" - "github.com/0chain/gosdk/zboxcore/fileref" - "github.com/0chain/gosdk/core/common" "github.com/0chain/gosdk/core/common/errors" + "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/zboxcore/blockchain" + "github.com/0chain/gosdk/zboxcore/client" + "github.com/0chain/gosdk/zboxcore/fileref" . "github.com/0chain/gosdk/zboxcore/logger" "github.com/0chain/gosdk/zboxcore/marker" "github.com/0chain/gosdk/zboxcore/zboxutil" @@ -1234,7 +1234,7 @@ type CommitFolderResponse struct { Data *CommitFolderData } -func (a *Allocation) CommitFolderChange(operation, preValue, currValue string) (string, error) { +func (a *Allocation) CommitFolderChange(operation, preValue, currValue string, cfg conf.Config) (string, error) { if !a.isInitialized() { return "", notInitialized } @@ -1264,8 +1264,9 @@ func (a *Allocation) CommitFolderChange(operation, preValue, currValue string) ( time.Sleep(querySleepTime) retries := 0 var t *transaction.Transaction + for retries < blockchain.GetMaxTxnQuery() { - t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders()) + t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders(), cfg) if err == nil { break } diff --git a/zboxcore/sdk/allocation_test.go b/zboxcore/sdk/allocation_test.go index fd63740ec..dcf803352 100644 --- a/zboxcore/sdk/allocation_test.go +++ b/zboxcore/sdk/allocation_test.go @@ -17,6 +17,7 @@ import ( "github.com/0chain/gosdk/core/common" "github.com/0chain/gosdk/core/common/errors" + "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/core/util" "github.com/0chain/gosdk/core/zcncrypto" @@ -2782,7 +2783,9 @@ func TestAllocation_CommitFolderChange(t *testing.T) { defer teardown(t) } } - _, err := a.CommitFolderChange(tt.parameters.operation, tt.parameters.preValue, tt.parameters.currValue) + cfg, _ := conf.LoadDefault() + + _, err := a.CommitFolderChange(tt.parameters.operation, tt.parameters.preValue, tt.parameters.currValue, cfg) require.EqualValues(tt.wantErr, err != nil) if err != nil { diff --git a/zboxcore/sdk/commitmetaworker.go b/zboxcore/sdk/commitmetaworker.go index b07864ce7..75f1dd181 100644 --- a/zboxcore/sdk/commitmetaworker.go +++ b/zboxcore/sdk/commitmetaworker.go @@ -5,17 +5,17 @@ import ( "context" "encoding/base64" "encoding/json" - "mime/multipart" - "net/http" - "sync" - "time" - "github.com/0chain/gosdk/core/common/errors" + "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/zboxcore/blockchain" "github.com/0chain/gosdk/zboxcore/client" . "github.com/0chain/gosdk/zboxcore/logger" "github.com/0chain/gosdk/zboxcore/zboxutil" + "mime/multipart" + "net/http" + "sync" + "time" ) type CommitMetaData struct { @@ -29,6 +29,7 @@ type CommitMetaRequest struct { a *Allocation authToken string wg *sync.WaitGroup + cfg conf.Config } type CommitMetaResponse struct { @@ -59,7 +60,7 @@ func (req *CommitMetaRequest) processCommitMetaRequest() { retries := 0 var t *transaction.Transaction for retries < blockchain.GetMaxTxnQuery() { - t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders()) + t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders(), req.cfg) if err == nil { break } diff --git a/zboxcore/sdk/sdk.go b/zboxcore/sdk/sdk.go index a713acf5b..e979551ff 100644 --- a/zboxcore/sdk/sdk.go +++ b/zboxcore/sdk/sdk.go @@ -13,15 +13,15 @@ import ( "github.com/0chain/gosdk/core/common/errors" "github.com/0chain/gosdk/core/logger" - "github.com/0chain/gosdk/zboxcore/marker" - "github.com/0chain/gosdk/core/common" + "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/core/version" "github.com/0chain/gosdk/zboxcore/blockchain" "github.com/0chain/gosdk/zboxcore/client" "github.com/0chain/gosdk/zboxcore/encryption" . "github.com/0chain/gosdk/zboxcore/logger" + "github.com/0chain/gosdk/zboxcore/marker" "github.com/0chain/gosdk/zboxcore/zboxutil" ) @@ -125,13 +125,13 @@ func SetNetwork(miners []string, sharders []string) { // read pool // -func CreateReadPool() (err error) { +func CreateReadPool(cfg conf.Config) (err error) { if !sdkInitialized { return sdkNotInitialized } _, _, err = smartContractTxn(transaction.SmartContractTxnData{ Name: transaction.STORAGESC_CREATE_READ_POOL, - }) + }, cfg) return } @@ -205,7 +205,7 @@ func GetReadPoolInfo(clientID string) (info *AllocationPoolStats, err error) { // ReadPoolLock locks given number of tokes for given duration in read pool. func ReadPoolLock(dur time.Duration, allocID, blobberID string, - tokens, fee int64) (err error) { + tokens, fee int64, cfg conf.Config) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -225,12 +225,12 @@ func ReadPoolLock(dur time.Duration, allocID, blobberID string, Name: transaction.STORAGESC_READ_POOL_LOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, tokens, fee) + _, _, err = smartContractTxnValueFee(sn, tokens, fee, cfg) return } // ReadPoolUnlock unlocks tokens in expired read pool -func ReadPoolUnlock(poolID string, fee int64) (err error) { +func ReadPoolUnlock(poolID string, fee int64, cfg conf.Config) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -246,7 +246,7 @@ func ReadPoolUnlock(poolID string, fee int64) (err error) { Name: transaction.STORAGESC_READ_POOL_UNLOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, 0, fee) + _, _, err = smartContractTxnValueFee(sn, 0, fee, cfg) return } @@ -386,7 +386,7 @@ type stakePoolRequest struct { } // StakePoolLock locks tokens lack in stake pool -func StakePoolLock(blobberID string, value, fee int64) (poolID string, err error) { +func StakePoolLock(blobberID string, value, fee int64, cfg conf.Config) (poolID string, err error) { if !sdkInitialized { return poolID, sdkNotInitialized } @@ -400,7 +400,7 @@ func StakePoolLock(blobberID string, value, fee int64) (poolID string, err error Name: transaction.STORAGESC_STAKE_POOL_LOCK, InputArgs: &spr, } - poolID, _, err = smartContractTxnValueFee(sn, value, fee) + poolID, _, err = smartContractTxnValueFee(sn, value, fee, cfg) return } @@ -418,7 +418,7 @@ type StakePoolUnlockUnstake struct { // future. The time is maximal time that can be lesser in some cases. To // unlock tokens can't be unlocked now, wait the time and unlock them (call // this function again). -func StakePoolUnlock(blobberID, poolID string, fee int64) ( +func StakePoolUnlock(blobberID, poolID string, fee int64, cfg conf.Config) ( unstake common.Timestamp, err error) { if !sdkInitialized { @@ -438,7 +438,7 @@ func StakePoolUnlock(blobberID, poolID string, fee int64) ( } var out string - if _, out, err = smartContractTxnValueFee(sn, 0, fee); err != nil { + if _, out, err = smartContractTxnValueFee(sn, 0, fee, cfg); err != nil { return // an error } @@ -451,7 +451,7 @@ func StakePoolUnlock(blobberID, poolID string, fee int64) ( } // StakePoolPayInterests unlocks a stake pool rewards. -func StakePoolPayInterests(bloberID string) (err error) { +func StakePoolPayInterests(bloberID string, cfg conf.Config) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -466,7 +466,7 @@ func StakePoolPayInterests(bloberID string) (err error) { Name: transaction.STORAGESC_STAKE_POOL_PAY_INTERESTS, InputArgs: &spr, } - _, _, err = smartContractTxnValueFee(sn, 0, 0) + _, _, err = smartContractTxnValueFee(sn, 0, 0, cfg) return } @@ -504,7 +504,7 @@ func GetWritePoolInfo(clientID string) (info *AllocationPoolStats, err error) { // WritePoolLock locks given number of tokes for given duration in read pool. func WritePoolLock(dur time.Duration, allocID, blobberID string, - tokens, fee int64) (err error) { + tokens, fee int64, cfg conf.Config) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -524,12 +524,12 @@ func WritePoolLock(dur time.Duration, allocID, blobberID string, Name: transaction.STORAGESC_WRITE_POOL_LOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, tokens, fee) + _, _, err = smartContractTxnValueFee(sn, tokens, fee, cfg) return } // WritePoolUnlock unlocks tokens in expired read pool -func WritePoolUnlock(poolID string, fee int64) (err error) { +func WritePoolUnlock(poolID string, fee int64, cfg conf.Config) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -545,7 +545,7 @@ func WritePoolUnlock(poolID string, fee int64) (err error) { Name: transaction.STORAGESC_WRITE_POOL_UNLOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, 0, fee) + _, _, err = smartContractTxnValueFee(sn, 0, fee, cfg) return } @@ -827,29 +827,29 @@ func GetAllocationsForClient(clientID string) ([]*Allocation, error) { } func CreateAllocationWithBlobbers(datashards, parityshards int, size, expiry int64, - readPrice, writePrice PriceRange, mcct time.Duration, lock int64, blobbers []string) ( + readPrice, writePrice PriceRange, mcct time.Duration, lock int64, blobbers []string, cfg conf.Config) ( string, error) { return CreateAllocationForOwner(client.GetClientID(), client.GetClientPublicKey(), datashards, parityshards, size, expiry, readPrice, writePrice, mcct, lock, - blobbers) + blobbers, cfg) } func CreateAllocation(datashards, parityshards int, size, expiry int64, - readPrice, writePrice PriceRange, mcct time.Duration, lock int64) ( + readPrice, writePrice PriceRange, mcct time.Duration, lock int64, cfg conf.Config) ( string, error) { return CreateAllocationForOwner(client.GetClientID(), client.GetClientPublicKey(), datashards, parityshards, size, expiry, readPrice, writePrice, mcct, lock, - blockchain.GetPreferredBlobbers()) + blockchain.GetPreferredBlobbers(), cfg) } func CreateAllocationForOwner(owner, ownerpublickey string, datashards, parityshards int, size, expiry int64, readPrice, writePrice PriceRange, mcct time.Duration, - lock int64, preferredBlobbers []string) (hash string, err error) { + lock int64, preferredBlobbers []string, cfg conf.Config) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized @@ -873,11 +873,11 @@ func CreateAllocationForOwner(owner, ownerpublickey string, Name: transaction.NEW_ALLOCATION_REQUEST, InputArgs: allocationRequest, } - hash, _, err = smartContractTxnValue(sn, lock) + hash, _, err = smartContractTxnValue(sn, lock, cfg) return } -func AddFreeStorageAssigner(name, publicKey string, individualLimit, totalLimit float64) error { +func AddFreeStorageAssigner(name, publicKey string, individualLimit, totalLimit float64, cfg conf.Config) error { if !sdkInitialized { return sdkNotInitialized } @@ -893,12 +893,12 @@ func AddFreeStorageAssigner(name, publicKey string, individualLimit, totalLimit Name: transaction.ADD_FREE_ALLOCATION_ASSIGNER, InputArgs: input, } - _, _, err := smartContractTxn(sn) + _, _, err := smartContractTxn(sn, cfg) return err } -func CreateFreeAllocation(marker string, value int64) (string, error) { +func CreateFreeAllocation(marker string, value int64, cfg conf.Config) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -912,12 +912,12 @@ func CreateFreeAllocation(marker string, value int64) (string, error) { Name: transaction.NEW_FREE_ALLOCATION, InputArgs: input, } - hash, _, err := smartContractTxnValue(sn, value) + hash, _, err := smartContractTxnValue(sn, value, cfg) return hash, err } func UpdateAllocation(size int64, expiry int64, allocationID string, - lock int64, setImmutable bool) (hash string, err error) { + lock int64, setImmutable bool, cfg conf.Config) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized @@ -934,11 +934,11 @@ func UpdateAllocation(size int64, expiry int64, allocationID string, Name: transaction.STORAGESC_UPDATE_ALLOCATION, InputArgs: updateAllocationRequest, } - hash, _, err = smartContractTxnValue(sn, lock) + hash, _, err = smartContractTxnValue(sn, lock, cfg) return } -func CreateFreeUpdateAllocation(marker, allocationId string, value int64) (string, error) { +func CreateFreeUpdateAllocation(marker, allocationId string, value int64, cfg conf.Config) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -952,11 +952,11 @@ func CreateFreeUpdateAllocation(marker, allocationId string, value int64) (strin Name: transaction.FREE_UPDATE_ALLOCATION, InputArgs: input, } - hash, _, err := smartContractTxnValue(sn, value) + hash, _, err := smartContractTxnValue(sn, value, cfg) return hash, err } -func FinalizeAllocation(allocID string) (hash string, err error) { +func FinalizeAllocation(allocID string, cfg conf.Config) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -964,11 +964,11 @@ func FinalizeAllocation(allocID string) (hash string, err error) { Name: transaction.STORAGESC_FINALIZE_ALLOCATION, InputArgs: map[string]interface{}{"allocation_id": allocID}, } - hash, _, err = smartContractTxn(sn) + hash, _, err = smartContractTxn(sn, cfg) return } -func CancelAllocation(allocID string) (hash string, err error) { +func CancelAllocation(allocID string, cfg conf.Config) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -976,11 +976,11 @@ func CancelAllocation(allocID string) (hash string, err error) { Name: transaction.STORAGESC_CANCEL_ALLOCATION, InputArgs: map[string]interface{}{"allocation_id": allocID}, } - hash, _, err = smartContractTxn(sn) + hash, _, err = smartContractTxn(sn, cfg) return } -func AddCurator(curatorId, allocationId string) (string, error) { +func AddCurator(curatorId, allocationId string, cfg conf.Config) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -993,11 +993,11 @@ func AddCurator(curatorId, allocationId string) (string, error) { Name: transaction.STORAGESC_ADD_CURATOR, InputArgs: allocationRequest, } - hash, _, err := smartContractTxn(sn) + hash, _, err := smartContractTxn(sn, cfg) return hash, err } -func CuratorTransferAllocation(allocationId, newOwner, newOwnerPublicKey string) (string, error) { +func CuratorTransferAllocation(allocationId, newOwner, newOwnerPublicKey string, cfg conf.Config) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -1011,11 +1011,11 @@ func CuratorTransferAllocation(allocationId, newOwner, newOwnerPublicKey string) Name: transaction.STORAGESC_CURATOR_TRANSFER, InputArgs: allocationRequest, } - hash, _, err := smartContractTxn(sn) + hash, _, err := smartContractTxn(sn, cfg) return hash, err } -func UpdateBlobberSettings(blob *Blobber) (resp string, err error) { +func UpdateBlobberSettings(blob *Blobber, cfg conf.Config) (resp string, err error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -1023,24 +1023,24 @@ func UpdateBlobberSettings(blob *Blobber) (resp string, err error) { Name: transaction.STORAGESC_UPDATE_BLOBBER_SETTINGS, InputArgs: blob, } - resp, _, err = smartContractTxn(sn) + resp, _, err = smartContractTxn(sn, cfg) return } -func smartContractTxn(sn transaction.SmartContractTxnData) ( +func smartContractTxn(sn transaction.SmartContractTxnData, cfg conf.Config) ( hash, out string, err error) { - return smartContractTxnValue(sn, 0) + return smartContractTxnValue(sn, 0, cfg) } -func smartContractTxnValue(sn transaction.SmartContractTxnData, value int64) ( +func smartContractTxnValue(sn transaction.SmartContractTxnData, value int64, cfg conf.Config) ( hash, out string, err error) { - return smartContractTxnValueFee(sn, value, 0) + return smartContractTxnValueFee(sn, value, 0, cfg) } func smartContractTxnValueFee(sn transaction.SmartContractTxnData, - value, fee int64) (hash, out string, err error) { + value, fee int64, cfg conf.Config) (hash, out string, err error) { var requestBytes []byte if requestBytes, err = json.Marshal(sn); err != nil { @@ -1070,7 +1070,7 @@ func smartContractTxnValueFee(sn transaction.SmartContractTxnData, time.Sleep(querySleepTime) for retries < blockchain.GetMaxTxnQuery() { - t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders()) + t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders(), cfg) if err == nil { break } diff --git a/zcncore/transaction.go b/zcncore/transaction.go index 18b6b8536..103af6c6c 100644 --- a/zcncore/transaction.go +++ b/zcncore/transaction.go @@ -10,6 +10,7 @@ import ( "github.com/0chain/gosdk/core/block" "github.com/0chain/gosdk/core/common" "github.com/0chain/gosdk/core/common/errors" + "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/encryption" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/core/util" @@ -1277,14 +1278,14 @@ func (t *Transaction) RegisterVote(signerwalletstr string, msvstr string) error return nil } -func VerifyContentHash(metaTxnDataJSON string) (bool, error) { +func VerifyContentHash(metaTxnDataJSON string, cfg conf.Config) (bool, error) { var metaTxnData sdk.CommitMetaResponse err := json.Unmarshal([]byte(metaTxnDataJSON), &metaTxnData) if err != nil { return false, errors.New("metaTxnData_decode_error", "Unable to decode metaTxnData json") } - t, err := transaction.VerifyTransaction(metaTxnData.TxnID, blockchain.GetSharders()) + t, err := transaction.VerifyTransaction(metaTxnData.TxnID, blockchain.GetSharders(), cfg) if err != nil { return false, errors.New("fetch_txm_details", "Unable to fetch txn details") } From 4a0c9ae43f77573af70c3ec421f00953e468a47e Mon Sep 17 00:00:00 2001 From: Lz Date: Thu, 12 Aug 2021 15:15:27 +0800 Subject: [PATCH 11/21] fix(transcation):#195 revert it with global variables, and removed LoadDefault in init --- core/conf/conf.go | 50 +++---- core/conf/conf_test.go | 236 +++++++++++++++++++++++++------ core/conf/config.go | 7 + core/conf/mocks/ConfigReader.go | 54 +++++++ core/transaction/entity.go | 6 +- core/transaction/err.go | 13 -- core/transaction/vars.go | 30 ++++ zboxcore/sdk/allocation.go | 22 +-- zboxcore/sdk/allocation_test.go | 8 +- zboxcore/sdk/commitmetaworker.go | 4 +- zboxcore/sdk/sdk.go | 90 ++++++------ zcncore/transaction.go | 5 +- 12 files changed, 367 insertions(+), 158 deletions(-) create mode 100644 core/conf/mocks/ConfigReader.go delete mode 100644 core/transaction/err.go create mode 100644 core/transaction/vars.go diff --git a/core/conf/conf.go b/core/conf/conf.go index 1d16f8d58..1b860bd7d 100644 --- a/core/conf/conf.go +++ b/core/conf/conf.go @@ -6,11 +6,9 @@ import ( "errors" "net/url" "os" - "path" "strings" thrown "github.com/0chain/errors" - "github.com/mitchellh/go-homedir" "github.com/spf13/viper" ) @@ -19,28 +17,23 @@ var ( ErrMssingConfig = errors.New("[conf]missing config file") // ErrInvalidValue invalid value in config ErrInvalidValue = errors.New("[conf]invalid value") - // ErrBadFormat fail to parse config via spf13/viper - ErrBadFormat = errors.New("[conf]bad format") + // ErrBadParsing fail to parse config via spf13/viper + ErrBadParsing = errors.New("[conf]bad parsing") ) -// LoadDefault load and parse config from ~/.zcn/config.yaml -func LoadDefault() (Config, error) { - return Load("config.yaml") -} - -// Load load and parse config file in ~/.zcn folder. +// LoadFile load config from file // Example: -// conf.Load("stream.yaml"), it will load settings from ~/.zcn/stream.yaml -func Load(fileName string) (Config, error) { +// conf.Load("~/.zcn/config.yaml"), it will load settings from ~/.zcn/config.yaml +func LoadFile(file string) (Config, error) { var cfg Config + var err error - file := path.Join(getConfigDir(), fileName) - _, err := os.Stat(file) + _, err = os.Stat(file) if err != nil { if errors.Is(err, os.ErrNotExist) { - return cfg, thrown.Throw(ErrMssingConfig, err.Error()) + return cfg, thrown.Throw(ErrMssingConfig, file) } return cfg, err } @@ -50,9 +43,17 @@ func Load(fileName string) (Config, error) { v.SetConfigFile(file) if err := v.ReadInConfig(); err != nil { - return cfg, thrown.Throw(ErrBadFormat, err.Error()) + return cfg, thrown.Throw(ErrBadParsing, err.Error()) } + return Load(v) +} + +// Load load and parse config +func Load(v ConfigReader) (Config, error) { + + var cfg Config + blockWorker := strings.TrimSpace(v.GetString("block_worker")) if isURL(blockWorker) == false { @@ -80,7 +81,6 @@ func Load(fileName string) (Config, error) { } // additional settings depending network latency - maxTxnQuery := v.GetInt("max_txn_query") if maxTxnQuery < 1 { maxTxnQuery = 5 @@ -103,22 +103,6 @@ func Load(fileName string) (Config, error) { } -// getConfigDir get config directory , default is ~/.zcn/ -func getConfigDir() string { - - var configDir string - // Find home directory. - home, err := homedir.Dir() - if err != nil { - panic(err) - } - configDir = home + string(os.PathSeparator) + ".zcn" - - os.MkdirAll(configDir, 0744) - - return configDir -} - func isURL(s string) bool { u, err := url.Parse(s) return err == nil && u.Scheme != "" && u.Host != "" diff --git a/core/conf/conf_test.go b/core/conf/conf_test.go index 6cac1dceb..48911ae93 100644 --- a/core/conf/conf_test.go +++ b/core/conf/conf_test.go @@ -1,54 +1,200 @@ package conf import ( - "io/ioutil" - "os" - "path/filepath" "testing" + "github.com/0chain/gosdk/core/conf/mocks" "github.com/stretchr/testify/require" ) -func setUpConfig(name, content string) { - - ioutil.WriteFile(filepath.Join(getConfigDir(), name), []byte(content), 0744) -} - -func tearDownConfig(name string) { - os.Remove(filepath.Join(getConfigDir(), name)) -} - -func TestMissingConfig(t *testing.T) { - - configFile := "missing_config.yaml" - - _, err := Load(configFile) - - require.ErrorIs(t, err, ErrMssingConfig) -} - -func TestBadFormat(t *testing.T) { - - setUpConfig("bad_format.yaml", ` -{ - block_worker:"", - -`) - defer tearDownConfig("bad_format.yaml") - - _, err := Load("bad_format.yaml") - - require.ErrorIs(t, err, ErrBadFormat) -} - -func TestInvalidBlockWorker(t *testing.T) { - - setUpConfig("invalid_blockworker.yaml", ` -block_worker: 127.0.0.1:9091 -`) - defer tearDownConfig("invalid_blockworker.yaml") - - _, err := Load("invalid_blockworker.yaml") - - require.ErrorIs(t, err, ErrInvalidValue) +func TestConfigLoad(t *testing.T) { + + tests := []struct { + name string + exceptedErr error + + setup func(*testing.T) ConfigReader + run func(*require.Assertions, Config) + }{ + { + name: "Test_Config_Invalid_BlockWorker", + exceptedErr: ErrInvalidValue, + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + + }, + }, + { + name: "Test_Config_BlockWorker", + + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("http://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal("http://127.0.0.1:9091/dns", cfg.BlockWorker) + }, + }, + { + name: "Test_Config_Min_Submit_Less_Than_1", + + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal(3, cfg.MinSubmit) + }, + }, + { + name: "Test_Config_Min_Confirmation_Less_Than_1", + + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal(50, cfg.MinConfirmation) + }, + }, + { + name: "Test_Config_Min_Confirmation_Greater_100", + + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(101) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal(100, cfg.MinConfirmation) + }, + }, { + name: "Test_Config_Nax_Txn_Query_Less_Than_1", + + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal(5, cfg.QuerySleepTime) + }, + }, { + name: "Test_Config_Max_Txn_Query_Less_Than_1", + + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal(5, cfg.MaxTxnQuery) + }, + }, { + name: "Test_Config_Confirmation_Chain_Length_Less_Than_1", + + setup: func(t *testing.T) ConfigReader { + + reader := &mocks.ConfigReader{} + reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal(3, cfg.ConfirmationChainLength) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + require := require.New(t) + + reader := tt.setup(t) + + cfg, err := Load(reader) + + // test it by predefined error variable instead of error message + if tt.exceptedErr != nil { + require.ErrorIs(err, tt.exceptedErr) + } else { + require.Equal(nil, err) + } + + if tt.run != nil { + tt.run(require, cfg) + } + + }) + } } diff --git a/core/conf/config.go b/core/conf/config.go index 1a7e7fb53..a63f03520 100644 --- a/core/conf/config.go +++ b/core/conf/config.go @@ -32,3 +32,10 @@ type Config struct { // QuerySleepTime sleep time before transcation query QuerySleepTime int } + +// ConfigReader a config reader +type ConfigReader interface { + GetString(key string) string + GetInt(key string) int + GetStringSlice(key string) []string +} diff --git a/core/conf/mocks/ConfigReader.go b/core/conf/mocks/ConfigReader.go new file mode 100644 index 000000000..6c7f99367 --- /dev/null +++ b/core/conf/mocks/ConfigReader.go @@ -0,0 +1,54 @@ +// Code generated by mockery 2.9.0. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// ConfigReader is an autogenerated mock type for the ConfigReader type +type ConfigReader struct { + mock.Mock +} + +// GetInt provides a mock function with given fields: key +func (_m *ConfigReader) GetInt(key string) int { + ret := _m.Called(key) + + var r0 int + if rf, ok := ret.Get(0).(func(string) int); ok { + r0 = rf(key) + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} + +// GetString provides a mock function with given fields: key +func (_m *ConfigReader) GetString(key string) string { + ret := _m.Called(key) + + var r0 string + if rf, ok := ret.Get(0).(func(string) string); ok { + r0 = rf(key) + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GetStringSlice provides a mock function with given fields: key +func (_m *ConfigReader) GetStringSlice(key string) []string { + ret := _m.Called(key) + + var r0 []string + if rf, ok := ret.Get(0).(func(string) []string); ok { + r0 = rf(key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + return r0 +} diff --git a/core/transaction/entity.go b/core/transaction/entity.go index 5f029e2c7..51c996acb 100644 --- a/core/transaction/entity.go +++ b/core/transaction/entity.go @@ -9,7 +9,6 @@ import ( "github.com/0chain/errors" "github.com/0chain/gosdk/core/common" - "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/encryption" "github.com/0chain/gosdk/core/util" ) @@ -206,7 +205,7 @@ func sendTransactionToURL(url string, txn *Transaction, wg *sync.WaitGroup) ([]b } // VerifyTransaction query transaction status from sharders, and verify it by mininal confirmation -func VerifyTransaction(txnHash string, sharders []string, cfg conf.Config) (*Transaction, error) { +func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) { numSharders := len(sharders) if numSharders == 0 { @@ -274,6 +273,9 @@ func VerifyTransaction(txnHash string, sharders []string, cfg conf.Config) (*Tra consensus := int(float64(numSuccess) / float64(numSharders) * 100) + if cfg == nil { + return nil, ErrConfigIsNotInitialized + } if consensus > 0 && consensus >= cfg.MinConfirmation { if retTxn == nil { diff --git a/core/transaction/err.go b/core/transaction/err.go deleted file mode 100644 index f1305125e..000000000 --- a/core/transaction/err.go +++ /dev/null @@ -1,13 +0,0 @@ -package transaction - -import "errors" - -var ( - // ErrNoAvailableSharder no any available sharder - ErrNoAvailableSharder = errors.New("[sharder] there is no any available sharder") - // ErrNoTxnDetail No transaction detail was found on any of the sharders - ErrNoTxnDetail = errors.New("[sc] no transaction detail was found on any of the sharders") - - // ErrTooLessConfirmation too less sharder to confirm transaction - ErrTooLessConfirmation = errors.New("[sc] too less sharders to confirm it") -) diff --git a/core/transaction/vars.go b/core/transaction/vars.go new file mode 100644 index 000000000..55025dbd5 --- /dev/null +++ b/core/transaction/vars.go @@ -0,0 +1,30 @@ +package transaction + +import ( + "errors" + + "github.com/0chain/gosdk/core/conf" +) + +var ( + // Config + cfg *conf.Config +) + +// SetConfig set config variables for transaction +func SetConfig(c *conf.Config) { + cfg = c +} + +var ( + // ErrNoAvailableSharder no any available sharder + ErrNoAvailableSharder = errors.New("[txn] there is no any available sharder") + // ErrNoTxnDetail No transaction detail was found on any of the sharders + ErrNoTxnDetail = errors.New("[txn] no transaction detail was found on any of the sharders") + + // ErrTooLessConfirmation too less sharder to confirm transaction + ErrTooLessConfirmation = errors.New("[txn] too less sharders to confirm it") + + // ErrConfigIsNotInitialized config is not initialized + ErrConfigIsNotInitialized = errors.New("[txn] config is not initialized. please initialize it by transaction.SetConfig") +) diff --git a/zboxcore/sdk/allocation.go b/zboxcore/sdk/allocation.go index 18f8b5fa3..17a6bce84 100644 --- a/zboxcore/sdk/allocation.go +++ b/zboxcore/sdk/allocation.go @@ -8,9 +8,17 @@ import ( "encoding/hex" "encoding/json" "fmt" + "io/ioutil" + "mime/multipart" + "net/http" + "os" + "path/filepath" + "strings" + "sync" + "time" + "github.com/0chain/errors" "github.com/0chain/gosdk/core/common" - "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/zboxcore/blockchain" "github.com/0chain/gosdk/zboxcore/client" @@ -18,14 +26,6 @@ import ( . "github.com/0chain/gosdk/zboxcore/logger" "github.com/0chain/gosdk/zboxcore/marker" "github.com/0chain/gosdk/zboxcore/zboxutil" - "io/ioutil" - "mime/multipart" - "net/http" - "os" - "path/filepath" - "strings" - "sync" - "time" ) var ( @@ -1233,7 +1233,7 @@ type CommitFolderResponse struct { Data *CommitFolderData } -func (a *Allocation) CommitFolderChange(operation, preValue, currValue string, cfg conf.Config) (string, error) { +func (a *Allocation) CommitFolderChange(operation, preValue, currValue string) (string, error) { if !a.isInitialized() { return "", notInitialized } @@ -1265,7 +1265,7 @@ func (a *Allocation) CommitFolderChange(operation, preValue, currValue string, c var t *transaction.Transaction for retries < blockchain.GetMaxTxnQuery() { - t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders(), cfg) + t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders()) if err == nil { break } diff --git a/zboxcore/sdk/allocation_test.go b/zboxcore/sdk/allocation_test.go index 7501f84c1..c86b5e2a8 100644 --- a/zboxcore/sdk/allocation_test.go +++ b/zboxcore/sdk/allocation_test.go @@ -17,8 +17,8 @@ import ( "github.com/0chain/errors" "github.com/0chain/gosdk/core/common" - "github.com/0chain/gosdk/core/conf" + "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/core/util" "github.com/0chain/gosdk/core/zcncrypto" @@ -2718,6 +2718,9 @@ func TestAllocation_CommitFolderChange(t *testing.T) { { name: "Test_Sharder_Verify_Txn_Failed", setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) { + + transaction.SetConfig(&conf.Config{}) + body, err := json.Marshal(&transaction.Transaction{ Hash: mockHash, }) @@ -2784,9 +2787,8 @@ func TestAllocation_CommitFolderChange(t *testing.T) { defer teardown(t) } } - cfg, _ := conf.LoadDefault() - _, err := a.CommitFolderChange(tt.parameters.operation, tt.parameters.preValue, tt.parameters.currValue, cfg) + _, err := a.CommitFolderChange(tt.parameters.operation, tt.parameters.preValue, tt.parameters.currValue) require.EqualValues(tt.wantErr, err != nil) if err != nil { diff --git a/zboxcore/sdk/commitmetaworker.go b/zboxcore/sdk/commitmetaworker.go index 25f0ab05e..ffe39de93 100644 --- a/zboxcore/sdk/commitmetaworker.go +++ b/zboxcore/sdk/commitmetaworker.go @@ -11,7 +11,6 @@ import ( "time" "github.com/0chain/errors" - "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/zboxcore/blockchain" "github.com/0chain/gosdk/zboxcore/client" @@ -30,7 +29,6 @@ type CommitMetaRequest struct { a *Allocation authToken string wg *sync.WaitGroup - cfg conf.Config } type CommitMetaResponse struct { @@ -61,7 +59,7 @@ func (req *CommitMetaRequest) processCommitMetaRequest() { retries := 0 var t *transaction.Transaction for retries < blockchain.GetMaxTxnQuery() { - t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders(), req.cfg) + t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders()) if err == nil { break } diff --git a/zboxcore/sdk/sdk.go b/zboxcore/sdk/sdk.go index c66013518..d5970eef5 100644 --- a/zboxcore/sdk/sdk.go +++ b/zboxcore/sdk/sdk.go @@ -131,7 +131,7 @@ func CreateReadPool(cfg conf.Config) (err error) { } _, _, err = smartContractTxn(transaction.SmartContractTxnData{ Name: transaction.STORAGESC_CREATE_READ_POOL, - }, cfg) + }) return } @@ -205,7 +205,7 @@ func GetReadPoolInfo(clientID string) (info *AllocationPoolStats, err error) { // ReadPoolLock locks given number of tokes for given duration in read pool. func ReadPoolLock(dur time.Duration, allocID, blobberID string, - tokens, fee int64, cfg conf.Config) (err error) { + tokens, fee int64) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -225,12 +225,12 @@ func ReadPoolLock(dur time.Duration, allocID, blobberID string, Name: transaction.STORAGESC_READ_POOL_LOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, tokens, fee, cfg) + _, _, err = smartContractTxnValueFee(sn, tokens, fee) return } // ReadPoolUnlock unlocks tokens in expired read pool -func ReadPoolUnlock(poolID string, fee int64, cfg conf.Config) (err error) { +func ReadPoolUnlock(poolID string, fee int64) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -246,7 +246,7 @@ func ReadPoolUnlock(poolID string, fee int64, cfg conf.Config) (err error) { Name: transaction.STORAGESC_READ_POOL_UNLOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, 0, fee, cfg) + _, _, err = smartContractTxnValueFee(sn, 0, fee) return } @@ -386,7 +386,7 @@ type stakePoolRequest struct { } // StakePoolLock locks tokens lack in stake pool -func StakePoolLock(blobberID string, value, fee int64, cfg conf.Config) (poolID string, err error) { +func StakePoolLock(blobberID string, value, fee int64) (poolID string, err error) { if !sdkInitialized { return poolID, sdkNotInitialized } @@ -400,7 +400,7 @@ func StakePoolLock(blobberID string, value, fee int64, cfg conf.Config) (poolID Name: transaction.STORAGESC_STAKE_POOL_LOCK, InputArgs: &spr, } - poolID, _, err = smartContractTxnValueFee(sn, value, fee, cfg) + poolID, _, err = smartContractTxnValueFee(sn, value, fee) return } @@ -418,7 +418,7 @@ type StakePoolUnlockUnstake struct { // future. The time is maximal time that can be lesser in some cases. To // unlock tokens can't be unlocked now, wait the time and unlock them (call // this function again). -func StakePoolUnlock(blobberID, poolID string, fee int64, cfg conf.Config) ( +func StakePoolUnlock(blobberID, poolID string, fee int64) ( unstake common.Timestamp, err error) { if !sdkInitialized { @@ -438,7 +438,7 @@ func StakePoolUnlock(blobberID, poolID string, fee int64, cfg conf.Config) ( } var out string - if _, out, err = smartContractTxnValueFee(sn, 0, fee, cfg); err != nil { + if _, out, err = smartContractTxnValueFee(sn, 0, fee); err != nil { return // an error } @@ -451,7 +451,7 @@ func StakePoolUnlock(blobberID, poolID string, fee int64, cfg conf.Config) ( } // StakePoolPayInterests unlocks a stake pool rewards. -func StakePoolPayInterests(bloberID string, cfg conf.Config) (err error) { +func StakePoolPayInterests(bloberID string) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -466,7 +466,7 @@ func StakePoolPayInterests(bloberID string, cfg conf.Config) (err error) { Name: transaction.STORAGESC_STAKE_POOL_PAY_INTERESTS, InputArgs: &spr, } - _, _, err = smartContractTxnValueFee(sn, 0, 0, cfg) + _, _, err = smartContractTxnValueFee(sn, 0, 0) return } @@ -504,7 +504,7 @@ func GetWritePoolInfo(clientID string) (info *AllocationPoolStats, err error) { // WritePoolLock locks given number of tokes for given duration in read pool. func WritePoolLock(dur time.Duration, allocID, blobberID string, - tokens, fee int64, cfg conf.Config) (err error) { + tokens, fee int64) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -524,12 +524,12 @@ func WritePoolLock(dur time.Duration, allocID, blobberID string, Name: transaction.STORAGESC_WRITE_POOL_LOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, tokens, fee, cfg) + _, _, err = smartContractTxnValueFee(sn, tokens, fee) return } // WritePoolUnlock unlocks tokens in expired read pool -func WritePoolUnlock(poolID string, fee int64, cfg conf.Config) (err error) { +func WritePoolUnlock(poolID string, fee int64) (err error) { if !sdkInitialized { return sdkNotInitialized } @@ -545,7 +545,7 @@ func WritePoolUnlock(poolID string, fee int64, cfg conf.Config) (err error) { Name: transaction.STORAGESC_WRITE_POOL_UNLOCK, InputArgs: &req, } - _, _, err = smartContractTxnValueFee(sn, 0, fee, cfg) + _, _, err = smartContractTxnValueFee(sn, 0, fee) return } @@ -827,29 +827,29 @@ func GetAllocationsForClient(clientID string) ([]*Allocation, error) { } func CreateAllocationWithBlobbers(datashards, parityshards int, size, expiry int64, - readPrice, writePrice PriceRange, mcct time.Duration, lock int64, blobbers []string, cfg conf.Config) ( + readPrice, writePrice PriceRange, mcct time.Duration, lock int64, blobbers []string) ( string, error) { return CreateAllocationForOwner(client.GetClientID(), client.GetClientPublicKey(), datashards, parityshards, size, expiry, readPrice, writePrice, mcct, lock, - blobbers, cfg) + blobbers) } func CreateAllocation(datashards, parityshards int, size, expiry int64, - readPrice, writePrice PriceRange, mcct time.Duration, lock int64, cfg conf.Config) ( + readPrice, writePrice PriceRange, mcct time.Duration, lock int64) ( string, error) { return CreateAllocationForOwner(client.GetClientID(), client.GetClientPublicKey(), datashards, parityshards, size, expiry, readPrice, writePrice, mcct, lock, - blockchain.GetPreferredBlobbers(), cfg) + blockchain.GetPreferredBlobbers()) } func CreateAllocationForOwner(owner, ownerpublickey string, datashards, parityshards int, size, expiry int64, readPrice, writePrice PriceRange, mcct time.Duration, - lock int64, preferredBlobbers []string, cfg conf.Config) (hash string, err error) { + lock int64, preferredBlobbers []string) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized @@ -873,11 +873,11 @@ func CreateAllocationForOwner(owner, ownerpublickey string, Name: transaction.NEW_ALLOCATION_REQUEST, InputArgs: allocationRequest, } - hash, _, err = smartContractTxnValue(sn, lock, cfg) + hash, _, err = smartContractTxnValue(sn, lock) return } -func AddFreeStorageAssigner(name, publicKey string, individualLimit, totalLimit float64, cfg conf.Config) error { +func AddFreeStorageAssigner(name, publicKey string, individualLimit, totalLimit float64) error { if !sdkInitialized { return sdkNotInitialized } @@ -893,12 +893,12 @@ func AddFreeStorageAssigner(name, publicKey string, individualLimit, totalLimit Name: transaction.ADD_FREE_ALLOCATION_ASSIGNER, InputArgs: input, } - _, _, err := smartContractTxn(sn, cfg) + _, _, err := smartContractTxn(sn) return err } -func CreateFreeAllocation(marker string, value int64, cfg conf.Config) (string, error) { +func CreateFreeAllocation(marker string, value int64) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -912,12 +912,12 @@ func CreateFreeAllocation(marker string, value int64, cfg conf.Config) (string, Name: transaction.NEW_FREE_ALLOCATION, InputArgs: input, } - hash, _, err := smartContractTxnValue(sn, value, cfg) + hash, _, err := smartContractTxnValue(sn, value) return hash, err } func UpdateAllocation(size int64, expiry int64, allocationID string, - lock int64, setImmutable bool, cfg conf.Config) (hash string, err error) { + lock int64, setImmutable bool) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized @@ -934,11 +934,11 @@ func UpdateAllocation(size int64, expiry int64, allocationID string, Name: transaction.STORAGESC_UPDATE_ALLOCATION, InputArgs: updateAllocationRequest, } - hash, _, err = smartContractTxnValue(sn, lock, cfg) + hash, _, err = smartContractTxnValue(sn, lock) return } -func CreateFreeUpdateAllocation(marker, allocationId string, value int64, cfg conf.Config) (string, error) { +func CreateFreeUpdateAllocation(marker, allocationId string, value int64) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -952,11 +952,11 @@ func CreateFreeUpdateAllocation(marker, allocationId string, value int64, cfg co Name: transaction.FREE_UPDATE_ALLOCATION, InputArgs: input, } - hash, _, err := smartContractTxnValue(sn, value, cfg) + hash, _, err := smartContractTxnValue(sn, value) return hash, err } -func FinalizeAllocation(allocID string, cfg conf.Config) (hash string, err error) { +func FinalizeAllocation(allocID string) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -964,11 +964,11 @@ func FinalizeAllocation(allocID string, cfg conf.Config) (hash string, err error Name: transaction.STORAGESC_FINALIZE_ALLOCATION, InputArgs: map[string]interface{}{"allocation_id": allocID}, } - hash, _, err = smartContractTxn(sn, cfg) + hash, _, err = smartContractTxn(sn) return } -func CancelAllocation(allocID string, cfg conf.Config) (hash string, err error) { +func CancelAllocation(allocID string) (hash string, err error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -976,11 +976,11 @@ func CancelAllocation(allocID string, cfg conf.Config) (hash string, err error) Name: transaction.STORAGESC_CANCEL_ALLOCATION, InputArgs: map[string]interface{}{"allocation_id": allocID}, } - hash, _, err = smartContractTxn(sn, cfg) + hash, _, err = smartContractTxn(sn) return } -func AddCurator(curatorId, allocationId string, cfg conf.Config) (string, error) { +func AddCurator(curatorId, allocationId string) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -993,11 +993,11 @@ func AddCurator(curatorId, allocationId string, cfg conf.Config) (string, error) Name: transaction.STORAGESC_ADD_CURATOR, InputArgs: allocationRequest, } - hash, _, err := smartContractTxn(sn, cfg) + hash, _, err := smartContractTxn(sn) return hash, err } -func CuratorTransferAllocation(allocationId, newOwner, newOwnerPublicKey string, cfg conf.Config) (string, error) { +func CuratorTransferAllocation(allocationId, newOwner, newOwnerPublicKey string) (string, error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -1011,11 +1011,11 @@ func CuratorTransferAllocation(allocationId, newOwner, newOwnerPublicKey string, Name: transaction.STORAGESC_CURATOR_TRANSFER, InputArgs: allocationRequest, } - hash, _, err := smartContractTxn(sn, cfg) + hash, _, err := smartContractTxn(sn) return hash, err } -func UpdateBlobberSettings(blob *Blobber, cfg conf.Config) (resp string, err error) { +func UpdateBlobberSettings(blob *Blobber) (resp string, err error) { if !sdkInitialized { return "", sdkNotInitialized } @@ -1023,24 +1023,24 @@ func UpdateBlobberSettings(blob *Blobber, cfg conf.Config) (resp string, err err Name: transaction.STORAGESC_UPDATE_BLOBBER_SETTINGS, InputArgs: blob, } - resp, _, err = smartContractTxn(sn, cfg) + resp, _, err = smartContractTxn(sn) return } -func smartContractTxn(sn transaction.SmartContractTxnData, cfg conf.Config) ( +func smartContractTxn(sn transaction.SmartContractTxnData) ( hash, out string, err error) { - return smartContractTxnValue(sn, 0, cfg) + return smartContractTxnValue(sn, 0) } -func smartContractTxnValue(sn transaction.SmartContractTxnData, value int64, cfg conf.Config) ( +func smartContractTxnValue(sn transaction.SmartContractTxnData, value int64) ( hash, out string, err error) { - return smartContractTxnValueFee(sn, value, 0, cfg) + return smartContractTxnValueFee(sn, value, 0) } func smartContractTxnValueFee(sn transaction.SmartContractTxnData, - value, fee int64, cfg conf.Config) (hash, out string, err error) { + value, fee int64) (hash, out string, err error) { var requestBytes []byte if requestBytes, err = json.Marshal(sn); err != nil { @@ -1070,7 +1070,7 @@ func smartContractTxnValueFee(sn transaction.SmartContractTxnData, time.Sleep(querySleepTime) for retries < blockchain.GetMaxTxnQuery() { - t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders(), cfg) + t, err = transaction.VerifyTransaction(txn.Hash, blockchain.GetSharders()) if err == nil { break } diff --git a/zcncore/transaction.go b/zcncore/transaction.go index bee319eb9..747319fcf 100644 --- a/zcncore/transaction.go +++ b/zcncore/transaction.go @@ -11,7 +11,6 @@ import ( "github.com/0chain/gosdk/core/block" "github.com/0chain/gosdk/core/common" - "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/encryption" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/core/util" @@ -1279,14 +1278,14 @@ func (t *Transaction) RegisterVote(signerwalletstr string, msvstr string) error return nil } -func VerifyContentHash(metaTxnDataJSON string, cfg conf.Config) (bool, error) { +func VerifyContentHash(metaTxnDataJSON string) (bool, error) { var metaTxnData sdk.CommitMetaResponse err := json.Unmarshal([]byte(metaTxnDataJSON), &metaTxnData) if err != nil { return false, errors.New("metaTxnData_decode_error", "Unable to decode metaTxnData json") } - t, err := transaction.VerifyTransaction(metaTxnData.TxnID, blockchain.GetSharders(), cfg) + t, err := transaction.VerifyTransaction(metaTxnData.TxnID, blockchain.GetSharders()) if err != nil { return false, errors.New("fetch_txm_details", "Unable to fetch txn details") } From 19565b6964006c1ed2ca79d0a4ef2390b7be6aa8 Mon Sep 17 00:00:00 2001 From: Lz Date: Thu, 12 Aug 2021 17:04:00 +0800 Subject: [PATCH 12/21] fix(transcation):#195 added Network --- core/conf/conf.go | 96 +--------------- core/conf/config.go | 107 +++++++++++++++++- core/conf/{conf_test.go => config_test.go} | 79 +++++++++---- .../conf/mocks/{ConfigReader.go => Reader.go} | 10 +- core/conf/network.go | 47 ++++++++ zboxcore/sdk/sdk.go | 3 +- 6 files changed, 218 insertions(+), 124 deletions(-) rename core/conf/{conf_test.go => config_test.go} (69%) rename core/conf/mocks/{ConfigReader.go => Reader.go} (75%) diff --git a/core/conf/conf.go b/core/conf/conf.go index 1b860bd7d..d1897e5b8 100644 --- a/core/conf/conf.go +++ b/core/conf/conf.go @@ -4,12 +4,6 @@ package conf import ( "errors" - "net/url" - "os" - "strings" - - thrown "github.com/0chain/errors" - "github.com/spf13/viper" ) var ( @@ -21,89 +15,9 @@ var ( ErrBadParsing = errors.New("[conf]bad parsing") ) -// LoadFile load config from file -// Example: -// conf.Load("~/.zcn/config.yaml"), it will load settings from ~/.zcn/config.yaml -func LoadFile(file string) (Config, error) { - - var cfg Config - var err error - - _, err = os.Stat(file) - - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return cfg, thrown.Throw(ErrMssingConfig, file) - } - return cfg, err - } - - v := viper.New() - - v.SetConfigFile(file) - - if err := v.ReadInConfig(); err != nil { - return cfg, thrown.Throw(ErrBadParsing, err.Error()) - } - - return Load(v) -} - -// Load load and parse config -func Load(v ConfigReader) (Config, error) { - - var cfg Config - - blockWorker := strings.TrimSpace(v.GetString("block_worker")) - - if isURL(blockWorker) == false { - return cfg, thrown.Throw(ErrInvalidValue, "block_worker="+blockWorker) - } - - minSubmit := v.GetInt("min_submit") - - if minSubmit < 1 { - minSubmit = 3 - } - - minCfm := v.GetInt("min_confirmation") - - if minCfm < 1 { - minCfm = 50 - } else if minCfm > 100 { - minCfm = 100 - } - - CfmChainLength := v.GetInt("confirmation_chain_length") - - if CfmChainLength < 1 { - CfmChainLength = 3 - } - - // additional settings depending network latency - maxTxnQuery := v.GetInt("max_txn_query") - if maxTxnQuery < 1 { - maxTxnQuery = 5 - } - - querySleepTime := v.GetInt("query_sleep_time") - if querySleepTime < 1 { - querySleepTime = 5 - } - - cfg.BlockWorker = blockWorker - cfg.PreferredBlobbers = v.GetStringSlice("preferred_blobbers") - cfg.MinSubmit = minSubmit - cfg.MinConfirmation = minCfm - cfg.ConfirmationChainLength = CfmChainLength - cfg.MaxTxnQuery = maxTxnQuery - cfg.QuerySleepTime = querySleepTime - - return cfg, nil - -} - -func isURL(s string) bool { - u, err := url.Parse(s) - return err == nil && u.Scheme != "" && u.Host != "" +// Reader a config reader +type Reader interface { + GetString(key string) string + GetInt(key string) int + GetStringSlice(key string) []string } diff --git a/core/conf/config.go b/core/conf/config.go index a63f03520..f960a699e 100644 --- a/core/conf/config.go +++ b/core/conf/config.go @@ -1,5 +1,15 @@ package conf +import ( + "errors" + "net/url" + "os" + "strings" + + thrown "github.com/0chain/errors" + "github.com/spf13/viper" +) + // Config settings from ~/.zcn/config.yaml // block_worker: http://198.18.0.98:9091 // signature_scheme: bls0chain @@ -31,11 +41,98 @@ type Config struct { MaxTxnQuery int // QuerySleepTime sleep time before transcation query QuerySleepTime int + + // SignatureScheme signature scheme + SignatureScheme string + // ChainID which blockchain it is working + ChainID string +} + +// LoadConfigFile load and parse Config from file +func LoadConfigFile(file string) (Config, error) { + + var cfg Config + var err error + + _, err = os.Stat(file) + + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return cfg, thrown.Throw(ErrMssingConfig, file) + } + return cfg, err + } + + v := viper.New() + + v.SetConfigFile(file) + + if err := v.ReadInConfig(); err != nil { + return cfg, thrown.Throw(ErrBadParsing, err.Error()) + } + + return LoadConfig(v) +} + +// LoadConfig load and parse config +func LoadConfig(v Reader) (Config, error) { + + var cfg Config + + blockWorker := strings.TrimSpace(v.GetString("block_worker")) + + if isURL(blockWorker) == false { + return cfg, thrown.Throw(ErrInvalidValue, "block_worker="+blockWorker) + } + + minSubmit := v.GetInt("min_submit") + if minSubmit < 1 { + minSubmit = 50 + } else if minSubmit > 100 { + minSubmit = 100 + } + + minCfm := v.GetInt("min_confirmation") + + if minCfm < 1 { + minCfm = 50 + } else if minCfm > 100 { + minCfm = 100 + } + + CfmChainLength := v.GetInt("confirmation_chain_length") + + if CfmChainLength < 1 { + CfmChainLength = 3 + } + + // additional settings depending network latency + maxTxnQuery := v.GetInt("max_txn_query") + if maxTxnQuery < 1 { + maxTxnQuery = 5 + } + + querySleepTime := v.GetInt("query_sleep_time") + if querySleepTime < 1 { + querySleepTime = 5 + } + + cfg.BlockWorker = blockWorker + cfg.PreferredBlobbers = v.GetStringSlice("preferred_blobbers") + cfg.MinSubmit = minSubmit + cfg.MinConfirmation = minCfm + cfg.ConfirmationChainLength = CfmChainLength + cfg.MaxTxnQuery = maxTxnQuery + cfg.QuerySleepTime = querySleepTime + + cfg.SignatureScheme = v.GetString("signature_scheme") + cfg.ChainID = v.GetString("chain_id") + + return cfg, nil + } -// ConfigReader a config reader -type ConfigReader interface { - GetString(key string) string - GetInt(key string) int - GetStringSlice(key string) []string +func isURL(s string) bool { + u, err := url.Parse(s) + return err == nil && u.Scheme != "" && u.Host != "" } diff --git a/core/conf/conf_test.go b/core/conf/config_test.go similarity index 69% rename from core/conf/conf_test.go rename to core/conf/config_test.go index 48911ae93..c0d03dece 100644 --- a/core/conf/conf_test.go +++ b/core/conf/config_test.go @@ -7,29 +7,30 @@ import ( "github.com/stretchr/testify/require" ) -func TestConfigLoad(t *testing.T) { +func TestLoadConfig(t *testing.T) { tests := []struct { name string exceptedErr error - setup func(*testing.T) ConfigReader + setup func(*testing.T) Reader run func(*require.Assertions, Config) }{ { name: "Test_Config_Invalid_BlockWorker", exceptedErr: ErrInvalidValue, - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(0) reader.On("GetInt", "max_txn_query").Return(0) reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) - reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, @@ -40,9 +41,9 @@ func TestConfigLoad(t *testing.T) { { name: "Test_Config_BlockWorker", - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("http://127.0.0.1:9091/dns") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(0) @@ -50,6 +51,8 @@ func TestConfigLoad(t *testing.T) { reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, @@ -60,9 +63,9 @@ func TestConfigLoad(t *testing.T) { { name: "Test_Config_Min_Submit_Less_Than_1", - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(0) @@ -70,19 +73,43 @@ func TestConfigLoad(t *testing.T) { reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") + + return reader + }, + run: func(r *require.Assertions, cfg Config) { + r.Equal(50, cfg.MinSubmit) + }, + }, + { + name: "Test_Config_Min_Submit_Greater_Than_100", + + setup: func(t *testing.T) Reader { + + reader := &mocks.Reader{} + reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(101) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, run: func(r *require.Assertions, cfg Config) { - r.Equal(3, cfg.MinSubmit) + r.Equal(100, cfg.MinSubmit) }, }, { name: "Test_Config_Min_Confirmation_Less_Than_1", - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(0) @@ -90,6 +117,8 @@ func TestConfigLoad(t *testing.T) { reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, @@ -100,9 +129,9 @@ func TestConfigLoad(t *testing.T) { { name: "Test_Config_Min_Confirmation_Greater_100", - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(101) @@ -110,6 +139,8 @@ func TestConfigLoad(t *testing.T) { reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, @@ -119,9 +150,9 @@ func TestConfigLoad(t *testing.T) { }, { name: "Test_Config_Nax_Txn_Query_Less_Than_1", - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(0) @@ -129,6 +160,8 @@ func TestConfigLoad(t *testing.T) { reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, @@ -138,9 +171,9 @@ func TestConfigLoad(t *testing.T) { }, { name: "Test_Config_Max_Txn_Query_Less_Than_1", - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(0) @@ -148,6 +181,8 @@ func TestConfigLoad(t *testing.T) { reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, @@ -157,9 +192,9 @@ func TestConfigLoad(t *testing.T) { }, { name: "Test_Config_Confirmation_Chain_Length_Less_Than_1", - setup: func(t *testing.T) ConfigReader { + setup: func(t *testing.T) Reader { - reader := &mocks.ConfigReader{} + reader := &mocks.Reader{} reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") reader.On("GetInt", "min_submit").Return(0) reader.On("GetInt", "min_confirmation").Return(0) @@ -167,6 +202,8 @@ func TestConfigLoad(t *testing.T) { reader.On("GetInt", "query_sleep_time").Return(0) reader.On("GetInt", "confirmation_chain_length").Return(0) reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") return reader }, @@ -182,7 +219,7 @@ func TestConfigLoad(t *testing.T) { reader := tt.setup(t) - cfg, err := Load(reader) + cfg, err := LoadConfig(reader) // test it by predefined error variable instead of error message if tt.exceptedErr != nil { diff --git a/core/conf/mocks/ConfigReader.go b/core/conf/mocks/Reader.go similarity index 75% rename from core/conf/mocks/ConfigReader.go rename to core/conf/mocks/Reader.go index 6c7f99367..9bb859362 100644 --- a/core/conf/mocks/ConfigReader.go +++ b/core/conf/mocks/Reader.go @@ -4,13 +4,13 @@ package mocks import mock "github.com/stretchr/testify/mock" -// ConfigReader is an autogenerated mock type for the ConfigReader type -type ConfigReader struct { +// Reader is an autogenerated mock type for the Reader type +type Reader struct { mock.Mock } // GetInt provides a mock function with given fields: key -func (_m *ConfigReader) GetInt(key string) int { +func (_m *Reader) GetInt(key string) int { ret := _m.Called(key) var r0 int @@ -24,7 +24,7 @@ func (_m *ConfigReader) GetInt(key string) int { } // GetString provides a mock function with given fields: key -func (_m *ConfigReader) GetString(key string) string { +func (_m *Reader) GetString(key string) string { ret := _m.Called(key) var r0 string @@ -38,7 +38,7 @@ func (_m *ConfigReader) GetString(key string) string { } // GetStringSlice provides a mock function with given fields: key -func (_m *ConfigReader) GetStringSlice(key string) []string { +func (_m *Reader) GetStringSlice(key string) []string { ret := _m.Called(key) var r0 []string diff --git a/core/conf/network.go b/core/conf/network.go index ff02d38f2..8bd28e740 100644 --- a/core/conf/network.go +++ b/core/conf/network.go @@ -1,5 +1,13 @@ package conf +import ( + "errors" + "os" + + thrown "github.com/0chain/errors" + "github.com/spf13/viper" +) + // Network settings from ~/.zcn/network.yaml type Network struct { // Sharders sharder list of blockchain @@ -7,3 +15,42 @@ type Network struct { // Miners miner list of blockchain Miners []string } + +// IsValid check network if it has miners and sharders +func (n *Network) IsValid() bool { + return n != nil && len(n.Miners) > 0 && len(n.Sharders) > 0 +} + +// LoadNetworkFile load and parse Network from file +func LoadNetworkFile(file string) (Network, error) { + + var network Network + var err error + + _, err = os.Stat(file) + + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return network, thrown.Throw(ErrMssingConfig, file) + } + return network, err + } + + v := viper.New() + + v.SetConfigFile(file) + + if err := v.ReadInConfig(); err != nil { + return network, thrown.Throw(ErrBadParsing, err.Error()) + } + + return LoadNetwork(v), nil +} + +// LoadNetwork load and parse network +func LoadNetwork(v Reader) Network { + return Network{ + Sharders: v.GetStringSlice("sharders"), + Miners: v.GetStringSlice("miners"), + } +} diff --git a/zboxcore/sdk/sdk.go b/zboxcore/sdk/sdk.go index d5970eef5..3ca0c1e07 100644 --- a/zboxcore/sdk/sdk.go +++ b/zboxcore/sdk/sdk.go @@ -14,7 +14,6 @@ import ( "github.com/0chain/gosdk/core/logger" "github.com/0chain/gosdk/core/common" - "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/core/version" "github.com/0chain/gosdk/zboxcore/blockchain" @@ -125,7 +124,7 @@ func SetNetwork(miners []string, sharders []string) { // read pool // -func CreateReadPool(cfg conf.Config) (err error) { +func CreateReadPool() (err error) { if !sdkInitialized { return sdkNotInitialized } From ba46ea81a92fd41db3990bec358a3a118beca14a Mon Sep 17 00:00:00 2001 From: Lz Date: Sat, 14 Aug 2021 09:19:48 +0800 Subject: [PATCH 13/21] fix(conf):#195 moved magic number to predefined variables; added resty package --- core/conf/config.go | 25 ++++-- core/resty/mocks/Client.go | 37 ++++++++ core/resty/mocks/timeout.go | 21 +++++ core/resty/option.go | 32 +++++++ core/resty/resty.go | 162 ++++++++++++++++++++++++++++++++++++ core/resty/resty_test.go | 118 ++++++++++++++++++++++++++ core/resty/result.go | 9 ++ 7 files changed, 398 insertions(+), 6 deletions(-) create mode 100644 core/resty/mocks/Client.go create mode 100644 core/resty/mocks/timeout.go create mode 100644 core/resty/option.go create mode 100644 core/resty/resty.go create mode 100644 core/resty/resty_test.go create mode 100644 core/resty/result.go diff --git a/core/conf/config.go b/core/conf/config.go index f960a699e..c92100ad3 100644 --- a/core/conf/config.go +++ b/core/conf/config.go @@ -10,6 +10,19 @@ import ( "github.com/spf13/viper" ) +const ( + // DefaultMinSubmit default value for min_submit + DefaultMinSubmit = 50 + // DefaultMinConfirmation default value for min_confirmation + DefaultMinConfirmation = 50 + // DefaultMaxTxnQuery default value for max_txn_query + DefaultMaxTxnQuery = 5 + // DefaultConfirmationChainLength default value for confirmation_chain_length + DefaultConfirmationChainLength = 3 + // DefaultQuerySleepTime default value for query_sleep_time + DefaultQuerySleepTime = 5 +) + // Config settings from ~/.zcn/config.yaml // block_worker: http://198.18.0.98:9091 // signature_scheme: bls0chain @@ -81,13 +94,13 @@ func LoadConfig(v Reader) (Config, error) { blockWorker := strings.TrimSpace(v.GetString("block_worker")) - if isURL(blockWorker) == false { + if !isURL(blockWorker) { return cfg, thrown.Throw(ErrInvalidValue, "block_worker="+blockWorker) } minSubmit := v.GetInt("min_submit") if minSubmit < 1 { - minSubmit = 50 + minSubmit = DefaultMinSubmit } else if minSubmit > 100 { minSubmit = 100 } @@ -95,7 +108,7 @@ func LoadConfig(v Reader) (Config, error) { minCfm := v.GetInt("min_confirmation") if minCfm < 1 { - minCfm = 50 + minCfm = DefaultMinConfirmation } else if minCfm > 100 { minCfm = 100 } @@ -103,18 +116,18 @@ func LoadConfig(v Reader) (Config, error) { CfmChainLength := v.GetInt("confirmation_chain_length") if CfmChainLength < 1 { - CfmChainLength = 3 + CfmChainLength = DefaultConfirmationChainLength } // additional settings depending network latency maxTxnQuery := v.GetInt("max_txn_query") if maxTxnQuery < 1 { - maxTxnQuery = 5 + maxTxnQuery = DefaultMaxTxnQuery } querySleepTime := v.GetInt("query_sleep_time") if querySleepTime < 1 { - querySleepTime = 5 + querySleepTime = DefaultQuerySleepTime } cfg.BlockWorker = blockWorker diff --git a/core/resty/mocks/Client.go b/core/resty/mocks/Client.go new file mode 100644 index 000000000..db64565a0 --- /dev/null +++ b/core/resty/mocks/Client.go @@ -0,0 +1,37 @@ +// Code generated by mockery 2.9.0. DO NOT EDIT. + +package mocks + +import ( + http "net/http" + + mock "github.com/stretchr/testify/mock" +) + +// Client is an autogenerated mock type for the Client type +type Client struct { + mock.Mock +} + +// Do provides a mock function with given fields: req +func (_m *Client) Do(req *http.Request) (*http.Response, error) { + ret := _m.Called(req) + + var r0 *http.Response + if rf, ok := ret.Get(0).(func(*http.Request) *http.Response); ok { + r0 = rf(req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*http.Request) error); ok { + r1 = rf(req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/core/resty/mocks/timeout.go b/core/resty/mocks/timeout.go new file mode 100644 index 000000000..a14f100a3 --- /dev/null +++ b/core/resty/mocks/timeout.go @@ -0,0 +1,21 @@ +package mocks + +import ( + "context" + http "net/http" + "time" +) + +// Timeout mock any request with timeout +type Timeout struct { + Timeout time.Duration +} + +// Do provides a mock function with given fields: req +func (t *Timeout) Do(req *http.Request) (*http.Response, error) { + time.Sleep(t.Timeout) + + time.Sleep(1 * time.Second) + + return nil, context.DeadlineExceeded +} diff --git a/core/resty/option.go b/core/resty/option.go new file mode 100644 index 000000000..64f5a82c9 --- /dev/null +++ b/core/resty/option.go @@ -0,0 +1,32 @@ +package resty + +import ( + "time" +) + +// WithRetry set retry times if request is failure with 5xx status code. retry is ingore if it is less than 1. +func WithRetry(retry int) Option { + return func(r *Resty) { + if retry > 0 { + r.retry = retry + } + } +} + +// WithHeader set header for http request +func WithHeader(header map[string]string) Option { + return func(r *Resty) { + if len(header) > 0 { + r.header = header + } + } +} + +// WithTimeout set timeout of http request. +func WithTimeout(timeout time.Duration) Option { + return func(r *Resty) { + if timeout > 0 { + r.timeout = timeout + } + } +} diff --git a/core/resty/resty.go b/core/resty/resty.go new file mode 100644 index 000000000..aecd5ea8f --- /dev/null +++ b/core/resty/resty.go @@ -0,0 +1,162 @@ +// Package resty HTTP and REST client library with parallel feature +package resty + +import ( + "context" + "net/http" + "time" +) + +// New create a Resty instance. +func New(transport *http.Transport, handle Handle, opts ...Option) *Resty { + r := &Resty{ + transport: transport, + handle: handle, + } + + for _, option := range opts { + option(r) + } + + if r.transport == nil { + r.transport = &http.Transport{} + } + + client := &http.Client{ + Transport: r.transport, + } + if r.timeout > 0 { + client.Timeout = r.timeout + } + + r.client = client + + return r +} + +// Client http client +type Client interface { + Do(req *http.Request) (*http.Response, error) +} + +// Handle handler of http response +type Handle func(*http.Request, *http.Response, context.CancelFunc, error) error + +// Option set restry option +type Option func(*Resty) + +// Resty HTTP and REST client library with parallel feature +type Resty struct { + ctx context.Context + cancelFunc context.CancelFunc + qty int + done chan Result + + transport *http.Transport + client Client + handle Handle + + timeout time.Duration + retry int + header map[string]string +} + +// DoGet execute http requests with GET method in parallel +func (r *Resty) DoGet(ctx context.Context, urls ...string) { + r.ctx, r.cancelFunc = context.WithCancel(ctx) + + r.qty = len(urls) + r.done = make(chan Result, r.qty) + + for _, url := range urls { + req, err := http.NewRequest(http.MethodGet, url, nil) + for key, value := range r.header { + req.Header.Set(key, value) + } + + req.Close = true + req.Header.Set("Connection", "close") + + if err != nil { + + r.done <- Result{Request: req, Response: nil, Err: err} + + continue + } + + go r.httpDo(req) + } + +} + +func (r *Resty) httpDo(req *http.Request) { + + ctx, cancel := context.WithCancel(r.ctx) + defer cancel() + + c := make(chan error, 1) + defer close(c) + + go func(req *http.Request) { + var resp *http.Response + var err error + + if r.retry > 0 { + for i := 0; i < r.retry; i++ { + resp, err = r.client.Do(req) + if resp != nil && resp.StatusCode == 200 { + break + } + } + } else { + resp, err = r.client.Do(req.WithContext(r.ctx)) + } + + r.done <- Result{Request: req, Response: resp, Err: err} + + c <- err + + }(req.WithContext(ctx)) + + select { + case <-ctx.Done(): + r.transport.CancelRequest(req) + <-c + return + case <-c: + return + } + +} + +// Wait wait all of requests to done +func (r *Resty) Wait() []error { + + errs := make([]error, 0, r.qty) + done := 0 + + for { + + result := <-r.done + + if r.handle != nil { + err := r.handle(result.Request, result.Response, r.cancelFunc, result.Err) + + if err != nil { + errs = append(errs, err) + } + } else { + if result.Err != nil { + errs = append(errs, result.Err) + } + } + + done++ + + if done >= r.qty { + return errs + } + + } + +} diff --git a/core/resty/resty_test.go b/core/resty/resty_test.go new file mode 100644 index 000000000..61b852e34 --- /dev/null +++ b/core/resty/resty_test.go @@ -0,0 +1,118 @@ +package resty + +import ( + "context" + "io/ioutil" + "net/http" + "strings" + "testing" + "time" + + "github.com/0chain/gosdk/core/resty/mocks" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestResty(t *testing.T) { + + tests := []struct { + name string + urls []string + + statusCode int + exceptedErr error + + setup func(a *require.Assertions, name string, statusCode int, urls []string) (context.Context, *Resty) + }{ + { + name: "Test_Resty_Timeout", + exceptedErr: context.DeadlineExceeded, + urls: []string{"Test_Resty_Timeout_1", "Test_Resty_Timeout_2", "Test_Resty_Timeout_3"}, + setup: func(ra *require.Assertions, name string, statusCode int, urls []string) (context.Context, *Resty) { + + r := New(&http.Transport{}, nil) + r.client = &mocks.Timeout{ + Timeout: 1 * time.Second, + } + + ctx, cancel := context.WithTimeout(context.TODO(), 1*time.Second) + go func() { + <-ctx.Done() + cancel() + }() + + return ctx, r + }, + }, + { + name: "Test_Resty_All_Success", + statusCode: 200, + exceptedErr: context.DeadlineExceeded, + urls: []string{"http://Test_Resty_Timeout_1", "http://Test_Resty_Timeout_2"}, + setup: func(ra *require.Assertions, name string, statusCode int, urls []string) (context.Context, *Resty) { + + resty := New(&http.Transport{}, func(req *http.Request, resp *http.Response, cf context.CancelFunc, e error) error { + + ra.Equal(200, resp.StatusCode) + + buf, err := ioutil.ReadAll(resp.Body) + defer resp.Body.Close() + + ra.Equal(nil, err) + ra.Equal(name, string(buf)) + + return nil + }) + + client := &mocks.Client{} + + for _, url := range urls { + + func(u string) { + client.On("Do", mock.MatchedBy(func(r *http.Request) bool { + return r.URL.String() == u + })).Return(&http.Response{ + StatusCode: statusCode, + Body: ioutil.NopCloser(strings.NewReader(name)), + }, nil) + }(url) + + } + + resty.client = client + + ctx, cancel := context.WithTimeout(context.TODO(), 3*time.Second) + go func() { + <-ctx.Done() + cancel() + }() + + return context.TODO(), resty + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + r := require.New(t) + + ctx, resty := tt.setup(r, tt.name, tt.statusCode, tt.urls) + + resty.DoGet(ctx, tt.urls...) + + errs := resty.Wait() + + for _, err := range errs { + // test it by predefined error variable instead of error message + if tt.exceptedErr != nil { + + r.ErrorIs(err, tt.exceptedErr) + } else { + r.Equal(nil, err) + } + } + + }) + } +} diff --git a/core/resty/result.go b/core/resty/result.go new file mode 100644 index 000000000..49b095993 --- /dev/null +++ b/core/resty/result.go @@ -0,0 +1,9 @@ +package resty + +import "net/http" + +type Result struct { + Request *http.Request + Response *http.Response + Err error +} From 64a3bb79befed783e091d72bce48690463ff19a2 Mon Sep 17 00:00:00 2001 From: Lz Date: Sat, 14 Aug 2021 09:33:09 +0800 Subject: [PATCH 14/21] fix(conf):#195 refactored mock code --- core/conf/config_test.go | 98 +++++++++------------------------------- 1 file changed, 22 insertions(+), 76 deletions(-) diff --git a/core/conf/config_test.go b/core/conf/config_test.go index c0d03dece..29d6a7587 100644 --- a/core/conf/config_test.go +++ b/core/conf/config_test.go @@ -9,6 +9,22 @@ import ( func TestLoadConfig(t *testing.T) { + var mockDefaultReader = func() Reader { + reader := &mocks.Reader{} + reader.On("GetString", "block_worker").Return("http://127.0.0.1:9091/dns") + reader.On("GetInt", "min_submit").Return(0) + reader.On("GetInt", "min_confirmation").Return(0) + reader.On("GetInt", "max_txn_query").Return(0) + reader.On("GetInt", "query_sleep_time").Return(0) + reader.On("GetInt", "confirmation_chain_length").Return(0) + reader.On("GetStringSlice", "preferred_blobbers").Return(nil) + reader.On("GetString", "signature_scheme").Return("") + reader.On("GetString", "chain_id").Return("") + + return reader + + } + tests := []struct { name string exceptedErr error @@ -42,19 +58,7 @@ func TestLoadConfig(t *testing.T) { name: "Test_Config_BlockWorker", setup: func(t *testing.T) Reader { - - reader := &mocks.Reader{} - reader.On("GetString", "block_worker").Return("http://127.0.0.1:9091/dns") - reader.On("GetInt", "min_submit").Return(0) - reader.On("GetInt", "min_confirmation").Return(0) - reader.On("GetInt", "max_txn_query").Return(0) - reader.On("GetInt", "query_sleep_time").Return(0) - reader.On("GetInt", "confirmation_chain_length").Return(0) - reader.On("GetStringSlice", "preferred_blobbers").Return(nil) - reader.On("GetString", "signature_scheme").Return("") - reader.On("GetString", "chain_id").Return("") - - return reader + return mockDefaultReader() }, run: func(r *require.Assertions, cfg Config) { r.Equal("http://127.0.0.1:9091/dns", cfg.BlockWorker) @@ -64,19 +68,7 @@ func TestLoadConfig(t *testing.T) { name: "Test_Config_Min_Submit_Less_Than_1", setup: func(t *testing.T) Reader { - - reader := &mocks.Reader{} - reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") - reader.On("GetInt", "min_submit").Return(0) - reader.On("GetInt", "min_confirmation").Return(0) - reader.On("GetInt", "max_txn_query").Return(0) - reader.On("GetInt", "query_sleep_time").Return(0) - reader.On("GetInt", "confirmation_chain_length").Return(0) - reader.On("GetStringSlice", "preferred_blobbers").Return(nil) - reader.On("GetString", "signature_scheme").Return("") - reader.On("GetString", "chain_id").Return("") - - return reader + return mockDefaultReader() }, run: func(r *require.Assertions, cfg Config) { r.Equal(50, cfg.MinSubmit) @@ -108,19 +100,7 @@ func TestLoadConfig(t *testing.T) { name: "Test_Config_Min_Confirmation_Less_Than_1", setup: func(t *testing.T) Reader { - - reader := &mocks.Reader{} - reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") - reader.On("GetInt", "min_submit").Return(0) - reader.On("GetInt", "min_confirmation").Return(0) - reader.On("GetInt", "max_txn_query").Return(0) - reader.On("GetInt", "query_sleep_time").Return(0) - reader.On("GetInt", "confirmation_chain_length").Return(0) - reader.On("GetStringSlice", "preferred_blobbers").Return(nil) - reader.On("GetString", "signature_scheme").Return("") - reader.On("GetString", "chain_id").Return("") - - return reader + return mockDefaultReader() }, run: func(r *require.Assertions, cfg Config) { r.Equal(50, cfg.MinConfirmation) @@ -152,18 +132,7 @@ func TestLoadConfig(t *testing.T) { setup: func(t *testing.T) Reader { - reader := &mocks.Reader{} - reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") - reader.On("GetInt", "min_submit").Return(0) - reader.On("GetInt", "min_confirmation").Return(0) - reader.On("GetInt", "max_txn_query").Return(0) - reader.On("GetInt", "query_sleep_time").Return(0) - reader.On("GetInt", "confirmation_chain_length").Return(0) - reader.On("GetStringSlice", "preferred_blobbers").Return(nil) - reader.On("GetString", "signature_scheme").Return("") - reader.On("GetString", "chain_id").Return("") - - return reader + return mockDefaultReader() }, run: func(r *require.Assertions, cfg Config) { r.Equal(5, cfg.QuerySleepTime) @@ -173,18 +142,7 @@ func TestLoadConfig(t *testing.T) { setup: func(t *testing.T) Reader { - reader := &mocks.Reader{} - reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") - reader.On("GetInt", "min_submit").Return(0) - reader.On("GetInt", "min_confirmation").Return(0) - reader.On("GetInt", "max_txn_query").Return(0) - reader.On("GetInt", "query_sleep_time").Return(0) - reader.On("GetInt", "confirmation_chain_length").Return(0) - reader.On("GetStringSlice", "preferred_blobbers").Return(nil) - reader.On("GetString", "signature_scheme").Return("") - reader.On("GetString", "chain_id").Return("") - - return reader + return mockDefaultReader() }, run: func(r *require.Assertions, cfg Config) { r.Equal(5, cfg.MaxTxnQuery) @@ -193,19 +151,7 @@ func TestLoadConfig(t *testing.T) { name: "Test_Config_Confirmation_Chain_Length_Less_Than_1", setup: func(t *testing.T) Reader { - - reader := &mocks.Reader{} - reader.On("GetString", "block_worker").Return("https://127.0.0.1:9091/dns") - reader.On("GetInt", "min_submit").Return(0) - reader.On("GetInt", "min_confirmation").Return(0) - reader.On("GetInt", "max_txn_query").Return(0) - reader.On("GetInt", "query_sleep_time").Return(0) - reader.On("GetInt", "confirmation_chain_length").Return(0) - reader.On("GetStringSlice", "preferred_blobbers").Return(nil) - reader.On("GetString", "signature_scheme").Return("") - reader.On("GetString", "chain_id").Return("") - - return reader + return mockDefaultReader() }, run: func(r *require.Assertions, cfg Config) { r.Equal(3, cfg.ConfirmationChainLength) From 9e95de50567895a8f6be09f4be82d81185e388e1 Mon Sep 17 00:00:00 2001 From: Lz Date: Sat, 14 Aug 2021 09:37:37 +0800 Subject: [PATCH 15/21] fix(conf):#195 fixed memory leak issue --- core/resty/resty.go | 6 ++++++ core/resty/result.go | 1 + 2 files changed, 7 insertions(+) diff --git a/core/resty/resty.go b/core/resty/resty.go index aecd5ea8f..2868686c9 100644 --- a/core/resty/resty.go +++ b/core/resty/resty.go @@ -131,6 +131,12 @@ func (r *Resty) httpDo(req *http.Request) { // Wait wait all of requests to done func (r *Resty) Wait() []error { + defer func() { + // call cancelFunc, aovid to memory leak issue + if r.cancelFunc != nil { + r.cancelFunc() + } + }() errs := make([]error, 0, r.qty) done := 0 diff --git a/core/resty/result.go b/core/resty/result.go index 49b095993..9fb1841bb 100644 --- a/core/resty/result.go +++ b/core/resty/result.go @@ -2,6 +2,7 @@ package resty import "net/http" +// Result result of a http request type Result struct { Request *http.Request Response *http.Response From a9f4200e9f161a31e06e08ac19a8726691c80635 Mon Sep 17 00:00:00 2001 From: Lz Date: Sat, 14 Aug 2021 11:17:40 +0800 Subject: [PATCH 16/21] fix(conf):#195 close reponse.Body for avoid to memory leak --- core/resty/resty.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/resty/resty.go b/core/resty/resty.go index 2868686c9..126264f47 100644 --- a/core/resty/resty.go +++ b/core/resty/resty.go @@ -102,11 +102,22 @@ func (r *Resty) httpDo(req *http.Request) { var err error if r.retry > 0 { - for i := 0; i < r.retry; i++ { + for i := 1; ; i++ { resp, err = r.client.Do(req) if resp != nil && resp.StatusCode == 200 { break } + // close body ReadClose to release resource before retrying it + if resp != nil && resp.Body != nil { + // don't close it if it is latest retry + if i < r.retry { + resp.Body.Close() + } + } + + if i == r.retry { + break + } } } else { resp, err = r.client.Do(req.WithContext(r.ctx)) From ba8587553343d51e78cba8c6915f06c1ed36d01f Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 16 Aug 2021 15:47:01 +0800 Subject: [PATCH 17/21] fix(transaction):#195 update http reqeust with resty --- core/resty/resty.go | 2 +- core/resty/vars.go | 12 +++ core/transaction/entity.go | 156 ++++++++++++++++++++++++++----------- core/transaction/vars.go | 3 + core/util/rand.go | 44 +++++++++++ core/util/rand_test.go | 31 ++++++++ go.mod | 3 +- go.sum | 5 +- 8 files changed, 204 insertions(+), 52 deletions(-) create mode 100644 core/resty/vars.go diff --git a/core/resty/resty.go b/core/resty/resty.go index 126264f47..34ff76f55 100644 --- a/core/resty/resty.go +++ b/core/resty/resty.go @@ -40,7 +40,7 @@ type Client interface { } // Handle handler of http response -type Handle func(*http.Request, *http.Response, context.CancelFunc, error) error +type Handle func(req *http.Request, resp *http.Response, cf context.CancelFunc, err error) error // Option set restry option type Option func(*Resty) diff --git a/core/resty/vars.go b/core/resty/vars.go new file mode 100644 index 000000000..1bf97d019 --- /dev/null +++ b/core/resty/vars.go @@ -0,0 +1,12 @@ +package resty + +import "time" + +var ( + // DefaultDialTimeout default timeout of a dialer + DefaultDialTimeout = 5 * time.Second + // DefaultRequestTimeout default time out of a http request + DefaultRequestTimeout = 10 * time.Second + // DefaultRetry retry times if a request is failed with 5xx status code + DefaultRetry = 3 +) diff --git a/core/transaction/entity.go b/core/transaction/entity.go index 51c996acb..9318bc726 100644 --- a/core/transaction/entity.go +++ b/core/transaction/entity.go @@ -1,8 +1,12 @@ package transaction import ( + "context" "encoding/json" "fmt" + "io/ioutil" + "net" + "net/http" "strconv" "strings" "sync" @@ -10,6 +14,7 @@ import ( "github.com/0chain/errors" "github.com/0chain/gosdk/core/common" "github.com/0chain/gosdk/core/encryption" + "github.com/0chain/gosdk/core/resty" "github.com/0chain/gosdk/core/util" ) @@ -206,77 +211,136 @@ func sendTransactionToURL(url string, txn *Transaction, wg *sync.WaitGroup) ([]b // VerifyTransaction query transaction status from sharders, and verify it by mininal confirmation func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) { + if cfg == nil { + return nil, ErrConfigIsNotInitialized + } + numSharders := len(sharders) if numSharders == 0 { return nil, ErrNoAvailableSharder } + minNumConfirmation := cfg.MinConfirmation / 100 * numSharders + + rand := util.NewRand(numSharders) + + selectedSharders := make([]string, minNumConfirmation+1) + + // random pick minNumConfirmation+1 first + for i := 0; i <= minNumConfirmation; i++ { + n, err := rand.Next() + + if err != nil { + break + } + + selectedSharders = append(selectedSharders, sharders[n]) + } + numSuccess := 0 + var retTxn *Transaction //leave first item for ErrTooLessConfirmation var msgList = make([]string, 1, numSharders) - for _, sharder := range sharders { - url := fmt.Sprintf("%v/%v%v", sharder, TXN_VERIFY_URL, txnHash) - req, err := util.NewHTTPGetRequest(url) - if err != nil { + urls := make([]string, len(selectedSharders)) + + for _, sharder := range selectedSharders { + + urls = append(urls, fmt.Sprintf("%v/%v%v", sharder, TXN_VERIFY_URL, txnHash)) + } + + header := map[string]string{ + "Content-Type": "application/json; charset=utf-8", + "Access-Control-Allow-Origin": "*", + } + + transport := &http.Transport{ + Dial: (&net.Dialer{ + Timeout: resty.DefaultDialTimeout, + }).Dial, + TLSHandshakeTimeout: resty.DefaultDialTimeout, + } + r := resty.New(transport, func(req *http.Request, resp *http.Response, cf context.CancelFunc, err error) error { + url := req.URL.String() + + if err != nil { //network issue msgList = append(msgList, err.Error()+": ", url) - continue + return err + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { //network issue + msgList = append(msgList, err.Error()+": "+url) + return err } - response, err := req.Get() + + if resp.StatusCode != 200 { + msgList = append(msgList, strconv.Itoa(resp.StatusCode)+": "+url) + return errors.Throw(ErrInvalidRequest, strconv.Itoa(resp.StatusCode)+": "+resp.Status) + } + + var objmap map[string]json.RawMessage + err = json.Unmarshal(body, &objmap) if err != nil { - msgList = append(msgList, err.Error()+": ", url) - continue - } else { - if response.StatusCode != 200 { - msgList = append(msgList, strconv.Itoa(response.StatusCode)+": "+response.Body+" "+url) - continue - } + msgList = append(msgList, "json: "+string(body)) + return err + } + txnRawJSON, ok := objmap["txn"] - contents := response.Body - var objmap map[string]json.RawMessage - err = json.Unmarshal([]byte(contents), &objmap) + // txn data is found, success + if ok { + txn := &Transaction{} + err = json.Unmarshal(txnRawJSON, txn) if err != nil { - msgList = append(msgList, "json: "+contents) - continue + msgList = append(msgList, "json: "+string(txnRawJSON)) + return err } - txnRawJSON, ok := objmap["txn"] - - // txn data is found, success - if ok { - txn := &Transaction{} - err = json.Unmarshal(txnRawJSON, txn) - if err != nil { - msgList = append(msgList, "json: "+string(txnRawJSON)) - continue - } - if len(txn.Signature) > 0 { - retTxn = txn - } - numSuccess++ + if len(txn.Signature) > 0 { + retTxn = txn + } + numSuccess++ + } else { + // txn data is not found, but get block_hash, success + if _, ok := objmap["block_hash"]; ok { + numSuccess++ } else { - // txn data is not found, but get block_hash, success - if _, ok := objmap["block_hash"]; ok { - numSuccess++ - } else { - // txn and block_hash - msgList = append(msgList, fmt.Sprintf("Sharder does not have the block summary with url: %s, contents: %s", url, contents)) - } - + // txn and block_hash + msgList = append(msgList, fmt.Sprintf("Sharder does not have the block summary with url: %s, contents: %s", url, contents)) } } - } - consensus := int(float64(numSuccess) / float64(numSharders) * 100) + return nil + }, + resty.WithTimeout(resty.DefaultRequestTimeout), + resty.WithRetry(resty.DefaultRetry), + resty.WithHeader(header)) + + for { + r.DoGet(context.TODO(), urls...) + + r.Wait() + + if numSuccess >= minNumConfirmation { + break + } + + // pick more one sharder to query transaction + n, err := rand.Next() + + if errors.Is(err, util.ErrNoItem) { + break + } + + urls = []string{fmt.Sprintf("%v/%v%v", sharders[n], TXN_VERIFY_URL, txnHash)} - if cfg == nil { - return nil, ErrConfigIsNotInitialized } - if consensus > 0 && consensus >= cfg.MinConfirmation { + + if numSuccess > 0 && numSuccess >= minNumConfirmation { if retTxn == nil { return nil, errors.Throw(ErrNoTxnDetail, strings.Join(msgList, "\r\n")) @@ -285,7 +349,7 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) return retTxn, nil } - msgList[0] = fmt.Sprintf("want %v, but got %v ", cfg.MinConfirmation, consensus) + msgList[0] = fmt.Sprintf("min_confirmation is %v%, but got %v/%v sharders", cfg.MinConfirmation, numSuccess, numSharders) return nil, errors.Throw(ErrTooLessConfirmation, strings.Join(msgList, "\r\n")) diff --git a/core/transaction/vars.go b/core/transaction/vars.go index 55025dbd5..3949316bf 100644 --- a/core/transaction/vars.go +++ b/core/transaction/vars.go @@ -17,8 +17,11 @@ func SetConfig(c *conf.Config) { } var ( + ErrInvalidRequest = errors.New("[txn] invalid request") + // ErrNoAvailableSharder no any available sharder ErrNoAvailableSharder = errors.New("[txn] there is no any available sharder") + // ErrNoTxnDetail No transaction detail was found on any of the sharders ErrNoTxnDetail = errors.New("[txn] no transaction detail was found on any of the sharders") diff --git a/core/util/rand.go b/core/util/rand.go index d763ea3c0..f4076b9ff 100644 --- a/core/util/rand.go +++ b/core/util/rand.go @@ -1,6 +1,7 @@ package util import ( + "errors" "math/rand" "time" ) @@ -69,3 +70,46 @@ func GetRandom(in []string, n int) []string { } return out } + +var ( + randGen = rand.New(rand.NewSource(time.Now().UnixNano())) + // ErrNoItem there is no item anymore + ErrNoItem = errors.New("rand: there is no item anymore") +) + +// Rand a progressive rand +type Rand struct { + items []int +} + +// Next get next random item +func (r *Rand) Next() (int, error) { + it := -1 + if len(r.items) > 0 { + i := randGen.Intn(len(r.items)) + + it = r.items[i] + + copy(r.items[i:], r.items[i+1:]) + r.items = r.items[:len(r.items)-1] + + return it, nil + } + + return -1, ErrNoItem + +} + +// NewRand create a ProgressiveRand instance +func NewRand(max int) Rand { + r := Rand{ + items: make([]int, max), + } + + for i := 0; i < max; i++ { + r.items[i] = i + } + + return r + +} diff --git a/core/util/rand_test.go b/core/util/rand_test.go index d53fee4ce..e4379f515 100644 --- a/core/util/rand_test.go +++ b/core/util/rand_test.go @@ -2,6 +2,8 @@ package util import ( "testing" + + "github.com/stretchr/testify/require" ) func TestGetRandomSlice(t *testing.T) { @@ -15,3 +17,32 @@ func TestGetRandomSlice(t *testing.T) { t.Fatalf("Getrandom() failed") } } + +func TestRand(t *testing.T) { + s := []string{"a", "b", "c", "d", "e", "f", "h", "i", "j", "k"} + + r := NewRand(len(s)) + + selected := make(map[int]string) + + for i := 0; i < len(s); i++ { + index, err := r.Next() + + require.Equal(t, nil, err) + + _, ok := selected[index] + + require.Equal(t, false, ok) + + selected[index] = s[index] + } + + for i := 0; i < len(s); i++ { + require.Equal(t, s[i], selected[i]) + } + + _, err := r.Next() + + require.Equal(t, ErrNoItem, err) + +} diff --git a/go.mod b/go.mod index 53ada5477..16dd1b3fd 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,13 @@ module github.com/0chain/gosdk require ( - github.com/0chain/errors v1.0.1 + github.com/0chain/errors v1.0.2 github.com/ethereum/go-ethereum v1.10.3 github.com/h2non/filetype v1.0.9 github.com/herumi/bls-go-binary v0.0.0-20191119080710-898950e1a520 github.com/klauspost/reedsolomon v1.9.11 github.com/lithammer/shortuuid/v3 v3.0.7 github.com/miguelmota/go-ethereum-hdwallet v0.0.1 - github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.1.2 github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 5a6c434b3..333c54296 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,8 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/0chain/errors v1.0.1 h1:e1jyKmYtF5jQdFOeEAjdfyLe5D46HrNO46Z97tWvEh8= -github.com/0chain/errors v1.0.1/go.mod h1:5t76jLb56TKfg/K2VD+eUMmNZJ42QsIRI8KzWuztwU4= +github.com/0chain/errors v1.0.2 h1:IIUMeh/qFlqDcyHesjU92CpRMVz9dIQWAtZooqrYinA= +github.com/0chain/errors v1.0.2/go.mod h1:5t76jLb56TKfg/K2VD+eUMmNZJ42QsIRI8KzWuztwU4= 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= @@ -450,7 +450,6 @@ github.com/miguelmota/go-ethereum-hdwallet v0.0.1 h1:DWqgZtKWTGcHR5QsprMJItZiJ2x github.com/miguelmota/go-ethereum-hdwallet v0.0.1/go.mod h1:iowKavXnc0NVNiv/UKYYBo3SjADph5PUvYQTjOIV9as= 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/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= From 07a755d58dd3bfdb5866c64c782e3a1d75a0e169 Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 16 Aug 2021 16:24:38 +0800 Subject: [PATCH 18/21] fix(error):0chain/errors#195 migrate errors --- core/transaction/entity.go | 2 +- core/util/merkle_tree.go | 4 +-- core/zcncrypto/ed255190chain.go | 2 +- zboxcore/encoder/erasurecode.go | 3 +- zboxcore/encryption/pre.go | 3 +- zboxcore/sdk/allocation.go | 24 ++++++------- zboxcore/sdk/attributesworker.go | 3 +- zboxcore/sdk/blockdownloadworker.go | 6 ++-- zboxcore/sdk/copyworker.go | 3 +- zboxcore/sdk/deleteworker.go | 5 +-- zboxcore/sdk/downloadworker.go | 6 ++-- zboxcore/sdk/listworker.go | 5 +-- zboxcore/sdk/renameworker.go | 3 +- zboxcore/sdk/sdk.go | 20 +++++------ zboxcore/sdk/sync.go | 4 +-- zboxcore/sdk/uploadworker.go | 6 ++-- zboxcore/zboxutil/util.go | 3 +- zcncore/mswallet.go | 8 ++--- zcncore/transaction.go | 56 ++++++++++++++--------------- zcncore/transactionauth.go | 4 +-- zcncore/wallet.go | 22 ++++++------ 21 files changed, 99 insertions(+), 93 deletions(-) diff --git a/core/transaction/entity.go b/core/transaction/entity.go index 9318bc726..8629731d0 100644 --- a/core/transaction/entity.go +++ b/core/transaction/entity.go @@ -309,7 +309,7 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) numSuccess++ } else { // txn and block_hash - msgList = append(msgList, fmt.Sprintf("Sharder does not have the block summary with url: %s, contents: %s", url, contents)) + msgList = append(msgList, fmt.Sprintf("Sharder does not have the block summary with url: %s, contents: %s", url, string(body))) } } diff --git a/core/util/merkle_tree.go b/core/util/merkle_tree.go index ba80cf5ec..f665bda2c 100644 --- a/core/util/merkle_tree.go +++ b/core/util/merkle_tree.go @@ -2,8 +2,6 @@ package util import ( "fmt" - - "github.com/0chain/errors" ) /*MerkleTree - A data structure that implements MerkleTreeI interface */ @@ -82,7 +80,7 @@ func (mt *MerkleTree) GetTree() []string { func (mt *MerkleTree) SetTree(leavesCount int, tree []string) error { size, levels := mt.computeSize(leavesCount) if size != len(tree) { - return errors.New(fmt.Sprintf("Merkle tree with leaves %v should have size %v but only %v is given", leavesCount, size, len(tree))) + return fmt.Errorf("Merkle tree with leaves %v should have size %v but only %v is given", leavesCount, size, len(tree)) } mt.levels = levels mt.tree = tree diff --git a/core/zcncrypto/ed255190chain.go b/core/zcncrypto/ed255190chain.go index 0652ec8fe..0840373b5 100644 --- a/core/zcncrypto/ed255190chain.go +++ b/core/zcncrypto/ed255190chain.go @@ -59,7 +59,7 @@ func (ed *ED255190chainScheme) GenerateKeys() (*Wallet, error) { //GenerateKeysWithEth - not implemented func (ed *ED255190chainScheme) GenerateKeysWithEth(mnemonic, password string) (*Wallet, error) { - return nil, errors.New("Not supported for this scheme") + return nil, errors.New("chain_scheme_unsupported", "Not supported for this scheme") } func (ed *ED255190chainScheme) RecoverKeys(mnemonic string) (*Wallet, error) { diff --git a/zboxcore/encoder/erasurecode.go b/zboxcore/encoder/erasurecode.go index 9a11de1dc..3a58aa3d9 100644 --- a/zboxcore/encoder/erasurecode.go +++ b/zboxcore/encoder/erasurecode.go @@ -4,7 +4,8 @@ import ( "bufio" "bytes" - "github.com/0chain/errors" + "errors" + . "github.com/0chain/gosdk/zboxcore/logger" "github.com/klauspost/reedsolomon" diff --git a/zboxcore/encryption/pre.go b/zboxcore/encryption/pre.go index dd58ec0cf..41cb4cbe8 100644 --- a/zboxcore/encryption/pre.go +++ b/zboxcore/encryption/pre.go @@ -11,7 +11,8 @@ import ( "encoding/json" "strings" - "github.com/0chain/errors" + "errors" + "go.dedis.ch/kyber/v3" "go.dedis.ch/kyber/v3/group/edwards25519" ) diff --git a/zboxcore/sdk/allocation.go b/zboxcore/sdk/allocation.go index 17a6bce84..2dbe765d5 100644 --- a/zboxcore/sdk/allocation.go +++ b/zboxcore/sdk/allocation.go @@ -29,7 +29,7 @@ import ( ) var ( - noBLOBBERS = errors.New("No Blobbers set in this allocation") + noBLOBBERS = errors.New("no_blobber", "No Blobbers set in this allocation") notInitialized = errors.New("sdk_not_initialized", "Please call InitStorageSDK Init and use GetAllocation to get the allocation object") ) @@ -414,7 +414,7 @@ func (a *Allocation) uploadOrUpdateFile(localpath string, } if !repairRequired { - return errors.New("Repair not required") + return errors.New("", "Repair not required") } file, _ := ioutil.ReadFile(localpath) @@ -422,7 +422,7 @@ func (a *Allocation) uploadOrUpdateFile(localpath string, hash.Write(file) contentHash := hex.EncodeToString(hash.Sum(nil)) if contentHash != fileRef.ActualFileHash { - return errors.New("Content hash doesn't match") + return errors.New("", "Content hash doesn't match") } uploadReq.filemeta.Hash = fileRef.ActualFileHash @@ -431,7 +431,7 @@ func (a *Allocation) uploadOrUpdateFile(localpath string, } if !uploadReq.IsFullConsensusSupported() { - return errors.New(fmt.Sprintf("allocation requires [%v] blobbers, which is greater than the maximum permitted number of [%v]. reduce number of data or parity shards and try again", uploadReq.fullconsensus, uploadReq.GetMaxBlobbersSupported())) + return fmt.Errorf("allocation requires [%v] blobbers, which is greater than the maximum permitted number of [%v]. reduce number of data or parity shards and try again", uploadReq.fullconsensus, uploadReq.GetMaxBlobbersSupported()) } go func() { @@ -458,7 +458,7 @@ func (a *Allocation) RepairRequired(remotepath string) (zboxutil.Uint128, bool, listReq.remotefilepath = remotepath found, fileRef, _ := listReq.getFileConsensusFromBlobbers() if fileRef == nil { - return found, false, fileRef, errors.New("File not found for the given remotepath") + return found, false, fileRef, errors.New("", "File not found for the given remotepath") } uploadMask := zboxutil.NewUint128(1).Lsh(uint64(len(a.Blobbers))).Sub64(1) @@ -486,13 +486,13 @@ func (a *Allocation) downloadFile(localPath string, remotePath string, contentMo } if stat, err := os.Stat(localPath); err == nil { if !stat.IsDir() { - return errors.New(fmt.Sprintf("Local path is not a directory '%s'", localPath)) + return fmt.Errorf("Local path is not a directory '%s'", localPath) } localPath = strings.TrimRight(localPath, "/") _, rFile := filepath.Split(remotePath) localPath = fmt.Sprintf("%s/%s", localPath, rFile) if _, err := os.Stat(localPath); err == nil { - return errors.New(fmt.Sprintf("Local file already exists '%s'", localPath)) + return fmt.Errorf("Local file already exists '%s'", localPath) } } lPath, _ := filepath.Split(localPath) @@ -906,11 +906,11 @@ func (a *Allocation) RevokeShare(path string, refereeClientID string) error { wg.Wait() if len(success) == len(a.Blobbers) { if len(notFound) == len(a.Blobbers) { - return errors.New("share not found") + return errors.New("", "share not found") } return nil } - return errors.New("consensus not reached") + return errors.New("", "consensus not reached") } func (a *Allocation) GetAuthTicket( @@ -1035,7 +1035,7 @@ func (a *Allocation) UploadAuthTicketToBlobber(authticketB64 string, clientEncPu fullconsensus: float32(a.DataShards + a.ParityShards), } if !consensus.isConsensusOk() { - return errors.New("consensus not reached") + return errors.New("invalid_consensus", "consensus not reached") } return nil } @@ -1103,13 +1103,13 @@ func (a *Allocation) downloadFromAuthTicket(localPath string, authTicket string, } if stat, err := os.Stat(localPath); err == nil { if !stat.IsDir() { - return errors.New(fmt.Sprintf("Local path is not a directory '%s'", localPath)) + return fmt.Errorf("Local path is not a directory '%s'", localPath) } localPath = strings.TrimRight(localPath, "/") _, rFile := filepath.Split(remoteFilename) localPath = fmt.Sprintf("%s/%s", localPath, rFile) if _, err := os.Stat(localPath); err == nil { - return errors.New(fmt.Sprintf("Local file already exists '%s'", localPath)) + return fmt.Errorf("Local file already exists '%s'", localPath) } } if len(a.Blobbers) <= 1 { diff --git a/zboxcore/sdk/attributesworker.go b/zboxcore/sdk/attributesworker.go index e2d97072d..2f90676ad 100644 --- a/zboxcore/sdk/attributesworker.go +++ b/zboxcore/sdk/attributesworker.go @@ -10,7 +10,8 @@ import ( "sync" "time" - "github.com/0chain/errors" + "errors" + "github.com/0chain/gosdk/zboxcore/fileref" "github.com/0chain/gosdk/zboxcore/allocationchange" diff --git a/zboxcore/sdk/blockdownloadworker.go b/zboxcore/sdk/blockdownloadworker.go index 680c24e24..4704eadd1 100644 --- a/zboxcore/sdk/blockdownloadworker.go +++ b/zboxcore/sdk/blockdownloadworker.go @@ -129,7 +129,7 @@ func (req *BlockDownloadRequest) downloadBlobberBlock() { if req.blobber.IsSkip() { req.result <- &downloadBlock{Success: false, idx: req.blobberIdx, - err: errors.New("skip blobber by previous errors")} + err: errors.New("", "skip blobber by previous errors")} return } @@ -236,7 +236,7 @@ func (req *BlockDownloadRequest) downloadBlobberBlock() { Logger.Info("Will be retrying download") setBlobberReadCtr(req.blobber, rspData.LatestRM.ReadCounter) shouldRetry = true - return errors.New("Need to retry the download") + return errors.New("", "Need to retry the download") } } else { @@ -244,7 +244,7 @@ func (req *BlockDownloadRequest) downloadBlobberBlock() { if err != nil { return err } - err = errors.New(fmt.Sprintf("Response Error: %s", string(resp_body))) + err = fmt.Errorf("Response Error: %s", string(resp_body)) if strings.Contains(err.Error(), "not_enough_tokens") { shouldRetry, retry = false, 3 // don't repeat req.blobber.SetSkip(true) diff --git a/zboxcore/sdk/copyworker.go b/zboxcore/sdk/copyworker.go index de4ded866..0f8a0f21d 100644 --- a/zboxcore/sdk/copyworker.go +++ b/zboxcore/sdk/copyworker.go @@ -10,7 +10,8 @@ import ( "sync" "time" - "github.com/0chain/errors" + "errors" + "github.com/0chain/gosdk/zboxcore/fileref" "github.com/0chain/gosdk/zboxcore/allocationchange" diff --git a/zboxcore/sdk/deleteworker.go b/zboxcore/sdk/deleteworker.go index ac0e20851..bf44b6f5d 100644 --- a/zboxcore/sdk/deleteworker.go +++ b/zboxcore/sdk/deleteworker.go @@ -13,7 +13,8 @@ import ( "sync" "time" - "github.com/0chain/errors" + "errors" + "github.com/0chain/gosdk/zboxcore/allocationchange" "github.com/0chain/gosdk/zboxcore/blockchain" "github.com/0chain/gosdk/zboxcore/fileref" @@ -120,7 +121,7 @@ func (req *DeleteRequest) ProcessDelete() error { req.wg.Wait() if !req.isConsensusOk() { - return errors.New(fmt.Sprintf("Delete failed: Success_rate:%2f, expected:%2f", req.getConsensusRate(), req.getConsensusRequiredForOk())) + return fmt.Errorf("Delete failed: Success_rate:%2f, expected:%2f", req.getConsensusRate(), req.getConsensusRequiredForOk()) } req.consensus = 0 diff --git a/zboxcore/sdk/downloadworker.go b/zboxcore/sdk/downloadworker.go index 6b1c310ab..173c9fc40 100644 --- a/zboxcore/sdk/downloadworker.go +++ b/zboxcore/sdk/downloadworker.go @@ -194,7 +194,7 @@ func (req *DownloadRequest) processDownload(ctx context.Context) { req.downloadMask, fileRef, _ = listReq.getFileConsensusFromBlobbers() if req.downloadMask.Equals64(0) || fileRef == nil { if req.statusCallback != nil { - req.statusCallback.Error(req.allocationID, remotePathCallback, OpDownload, errors.New("No minimum consensus for file meta data of file")) + req.statusCallback.Error(req.allocationID, remotePathCallback, OpDownload, errors.New("", "No minimum consensus for file meta data of file")) } return } @@ -265,7 +265,7 @@ func (req *DownloadRequest) processDownload(ctx context.Context) { req.isDownloadCanceled = false os.Remove(req.localpath) if req.statusCallback != nil { - req.statusCallback.Error(req.allocationID, remotePathCallback, OpDownload, errors.New("Download aborted by user")) + req.statusCallback.Error(req.allocationID, remotePathCallback, OpDownload, errors.New("","Download aborted by user")) } return } @@ -303,7 +303,7 @@ func (req *DownloadRequest) processDownload(ctx context.Context) { if calcHash != expectedHash { os.Remove(req.localpath) if req.statusCallback != nil { - req.statusCallback.Error(req.allocationID, remotePathCallback, OpDownload, errors.New("File content didn't match with uploaded file")) + req.statusCallback.Error(req.allocationID, remotePathCallback, OpDownload, errors.New("","File content didn't match with uploaded file")) } return } diff --git a/zboxcore/sdk/listworker.go b/zboxcore/sdk/listworker.go index 8c977fb6b..5fab52792 100644 --- a/zboxcore/sdk/listworker.go +++ b/zboxcore/sdk/listworker.go @@ -120,9 +120,10 @@ func (req *ListRequest) getListInfoFromBlobber(blobber *blockchain.StorageNode, return errors.Wrap(err, "error getting the dir tree from list response:") } return nil - } else { - return errors.New(fmt.Sprintf("error from server list response: %s", s.String())) } + + return fmt.Errorf("error from server list response: %s", s.String()) + }) } diff --git a/zboxcore/sdk/renameworker.go b/zboxcore/sdk/renameworker.go index 8459935c7..282639421 100644 --- a/zboxcore/sdk/renameworker.go +++ b/zboxcore/sdk/renameworker.go @@ -10,7 +10,8 @@ import ( "sync" "time" - "github.com/0chain/errors" + "errors" + "github.com/0chain/gosdk/zboxcore/fileref" "github.com/0chain/gosdk/zboxcore/allocationchange" diff --git a/zboxcore/sdk/sdk.go b/zboxcore/sdk/sdk.go index 3ca0c1e07..2cc5fac0c 100644 --- a/zboxcore/sdk/sdk.go +++ b/zboxcore/sdk/sdk.go @@ -191,7 +191,7 @@ func GetReadPoolInfo(clientID string) (info *AllocationPoolStats, err error) { return nil, errors.Wrap(err, "error requesting read pool info") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("", "empty response") } info = new(AllocationPoolStats) @@ -335,7 +335,7 @@ func GetStakePoolInfo(blobberID string) (info *StakePoolInfo, err error) { return nil, errors.Wrap(err, "error requesting stake pool info:") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("", "empty response") } info = new(StakePoolInfo) @@ -368,7 +368,7 @@ func GetStakePoolUserInfo(clientID string) (info *StakePoolUserInfo, err error) return nil, errors.Wrap(err, "error requesting stake pool user info:") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("", "empty response") } info = new(StakePoolUserInfo) @@ -490,7 +490,7 @@ func GetWritePoolInfo(clientID string) (info *AllocationPoolStats, err error) { return nil, errors.Wrap(err, "error requesting read pool info:") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("", "empty response") } info = new(AllocationPoolStats) @@ -575,7 +575,7 @@ func GetChallengePoolInfo(allocID string) (info *ChallengePoolInfo, err error) { return nil, errors.Wrap(err, "error requesting challenge pool info:") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("", "empty response") } info = new(ChallengePoolInfo) @@ -600,7 +600,7 @@ func GetMptData(key string) ([]byte, error) { return nil, errors.Wrap(err, "error requesting mpt key data:") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("", "empty response") } return b, nil @@ -667,7 +667,7 @@ func GetStorageSCConfig() (conf *StorageSCConfig, err error) { return nil, errors.Wrap(err, "error requesting storage SC configs:") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("", "empty response") } conf = new(StorageSCConfig) @@ -676,7 +676,7 @@ func GetStorageSCConfig() (conf *StorageSCConfig, err error) { } if conf.ReadPool == nil || conf.WritePool == nil || conf.StakePool == nil { - return nil, errors.New("invalid confg: missing read/write/stake pool configs") + return nil, errors.New("", "invalid confg: missing read/write/stake pool configs") } return } @@ -704,7 +704,7 @@ func GetBlobbers() (bs []*Blobber, err error) { return nil, errors.Wrap(err, "error requesting blobbers:") } if len(b) == 0 { - return nil, errors.New("empty response") + return nil, errors.New("","empty response") } type nodes struct { @@ -735,7 +735,7 @@ func GetBlobber(blobberID string) (blob *Blobber, err error) { return nil, errors.Wrap(err, "requesting blobber:") } if len(b) == 0 { - return nil, errors.New("empty response from sharders") + return nil, errors.New("","empty response from sharders") } blob = new(Blobber) if err = json.Unmarshal(b, blob); err != nil { diff --git a/zboxcore/sdk/sync.go b/zboxcore/sdk/sync.go index 01c2f5829..05633c9f5 100644 --- a/zboxcore/sdk/sync.go +++ b/zboxcore/sdk/sync.go @@ -279,11 +279,11 @@ func (a *Allocation) GetAllocationDiff(lastSyncCachePath string, localRootPath s } content, err := ioutil.ReadFile(lastSyncCachePath) if err != nil { - return lFdiff, errors.New("can't read cache file.") + return lFdiff, errors.New("", "can't read cache file.") } err = json.Unmarshal(content, &prevRemoteFileMap) if err != nil { - return lFdiff, errors.New("invalid cache content.") + return lFdiff, errors.New("", "invalid cache content.") } } } diff --git a/zboxcore/sdk/uploadworker.go b/zboxcore/sdk/uploadworker.go index b9f3b362d..1f86ae3f0 100644 --- a/zboxcore/sdk/uploadworker.go +++ b/zboxcore/sdk/uploadworker.go @@ -288,7 +288,7 @@ func (req *UploadRequest) prepareUpload( } if resp.StatusCode != http.StatusOK { Logger.Error(blobber.Baseurl, " Upload error response: ", resp.StatusCode, string(respbody)) - req.err = errors.New(string(respbody)) + req.err = errors.New("", string(respbody)) return err } var r uploadResult @@ -300,7 +300,7 @@ func (req *UploadRequest) prepareUpload( } if r.Filename != formData.Filename || r.ShardSize != shardSize || r.Hash != formData.Hash || r.MerkleRoot != formData.MerkleRoot { - err = errors.New(fmt.Sprintf(blobber.Baseurl, "Unexpected upload response data", string(respbody))) + err = fmt.Errorf(blobber.Baseurl, "Unexpected upload response data", string(respbody)) Logger.Error(err) req.err = err return err @@ -428,7 +428,7 @@ func (req *UploadRequest) completePush() error { } req.wg.Wait() if !req.isConsensusOk() { - return errors.New(fmt.Sprintf("Upload failed: Consensus_rate:%f, expected:%f", req.getConsensusRate(), req.getConsensusRequiredForOk())) + return fmt.Errorf("Upload failed: Consensus_rate:%f, expected:%f", req.getConsensusRate(), req.getConsensusRequiredForOk()) } return nil } diff --git a/zboxcore/zboxutil/util.go b/zboxcore/zboxutil/util.go index e14ccd42c..fa008686f 100644 --- a/zboxcore/zboxutil/util.go +++ b/zboxcore/zboxutil/util.go @@ -12,7 +12,8 @@ import ( "path/filepath" "strings" - "github.com/0chain/errors" + "errors" + "github.com/0chain/gosdk/core/util" "github.com/0chain/gosdk/zboxcore/blockchain" "github.com/h2non/filetype" diff --git a/zcncore/mswallet.go b/zcncore/mswallet.go index dee2e8173..c8d0cfd89 100644 --- a/zcncore/mswallet.go +++ b/zcncore/mswallet.go @@ -56,7 +56,7 @@ type MSTransfer struct { func (msw *MSWallet) Marshal() (string, error) { msws, err := json.Marshal(msw) if err != nil { - return "", errors.New("Invalid Wallet") + return "", errors.New("", "Invalid Wallet") } return string(msws), nil } @@ -70,7 +70,7 @@ type MSVoteCallback interface { func CreateMSWallet(t, n int) (string, string, []string, error) { id := 0 if _config.chain.SignatureScheme != "bls0chain" { - return "", "", nil, errors.New("encryption scheme for this blockchain is not bls0chain") + return "", "", nil, errors.New("", "encryption scheme for this blockchain is not bls0chain") } @@ -141,11 +141,11 @@ func RegisterWallet(walletString string, cb WalletCallback) { func CreateMSVote(proposal, grpClientID, signerWalletstr, toClientID string, token int64) (string, error) { if proposal == "" || grpClientID == "" || toClientID == "" || signerWalletstr == "" { - return "", errors.New("proposal or groupClient or signer wallet or toClientID cannot be empty") + return "", errors.New("", "proposal or groupClient or signer wallet or toClientID cannot be empty") } if token < 1 { - return "", errors.New("Token cannot be less than 1") + return "", errors.New("", "Token cannot be less than 1") } signerWallet, err := GetWallet(signerWalletstr) diff --git a/zcncore/transaction.go b/zcncore/transaction.go index 747319fcf..d244604bb 100644 --- a/zcncore/transaction.go +++ b/zcncore/transaction.go @@ -26,11 +26,11 @@ var ( ) var ( - errNetwork = errors.New("network error. host not reachable") - errUserRejected = errors.New("rejected by user") - errAuthVerifyFailed = errors.New("verfication failed for auth response") - errAuthTimeout = errors.New("auth timed out") - errAddSignature = errors.New("error adding signature") + errNetwork = errors.New("", "network error. host not reachable") + errUserRejected = errors.New("", "rejected by user") + errAuthVerifyFailed = errors.New("", "verfication failed for auth response") + errAuthTimeout = errors.New("", "auth timed out") + errAddSignature = errors.New("", "error adding signature") ) // TransactionCallback needs to be implemented by the caller for transaction related APIs @@ -164,7 +164,7 @@ func signWithWallet(hash string, wi interface{}) (string, error) { if !ok { fmt.Printf("Error in casting to wallet") - return "", errors.New("error in casting to wallet") + return "", errors.New("", "error in casting to wallet") } sigScheme := zcncrypto.NewSignatureScheme(_config.chain.SignatureScheme) sigScheme.SetPrivateKey(w.Keys[0].PrivateKey) @@ -261,7 +261,7 @@ func (t *Transaction) submitTxn() { } rate := consensus * 100 / float32(len(randomMiners)) if rate < consensusThresh { - t.completeTxn(StatusError, "", errors.New(fmt.Sprintf("submit transaction failed. %s", tFailureRsp))) + t.completeTxn(StatusError, "", fmt.Errorf("submit transaction failed. %s", tFailureRsp)) return } time.Sleep(3 * time.Second) @@ -285,7 +285,7 @@ func NewTransaction(cb TransactionCallback, txnFee int64) (TransactionScheme, er } if _config.isSplitWallet { if _config.authUrl == "" { - return nil, errors.New("auth url not set") + return nil, errors.New("", "auth url not set") } Logger.Info("New transaction interface with auth") return newTransactionWithAuth(cb, txnFee) @@ -296,7 +296,7 @@ func NewTransaction(cb TransactionCallback, txnFee int64) (TransactionScheme, er func (t *Transaction) SetTransactionCallback(cb TransactionCallback) error { if t.txnStatus != StatusUnknown { - return errors.New("transaction already exists. cannot set transaction hash.") + return errors.New("", "transaction already exists. cannot set transaction hash.") } t.txnCb = cb return nil @@ -304,7 +304,7 @@ func (t *Transaction) SetTransactionCallback(cb TransactionCallback) error { func (t *Transaction) SetTransactionFee(txnFee int64) error { if t.txnStatus != StatusUnknown { - return errors.New("transaction already exists. cannot set transaction fee.") + return errors.New("", "transaction already exists. cannot set transaction fee.") } t.txn.TransactionFee = txnFee return nil @@ -399,7 +399,7 @@ func (t *Transaction) ExecuteSmartContract(address, methodName, jsoninput string func (t *Transaction) SetTransactionHash(hash string) error { if t.txnStatus != StatusUnknown { - return errors.New("transaction already exists. cannot set transaction hash.") + return errors.New("", "transaction already exists. cannot set transaction hash.") } t.txnHash = hash return nil @@ -466,17 +466,17 @@ func getBlockHeaderFromTransactionConfirmation(txnHash string, cfmBlock map[stri return nil, errors.Wrap(err, "txn confirmation parse error.") } if cfm.Transaction == nil { - return nil, errors.New(fmt.Sprintf("missing transaction %s in block confirmation", txnHash)) + return nil, fmt.Errorf("missing transaction %s in block confirmation", txnHash) } if txnHash != cfm.Transaction.Hash { - return nil, errors.New(fmt.Sprintf("invalid transaction hash. Expected: %s. Received: %s", txnHash, cfm.Transaction.Hash)) + return nil, fmt.Errorf("invalid transaction hash. Expected: %s. Received: %s", txnHash, cfm.Transaction.Hash) } if !util.VerifyMerklePath(cfm.Transaction.Hash, cfm.MerkleTreePath, cfm.MerkleTreeRoot) { - return nil, errors.New("txn merkle validation failed.") + return nil, errors.New("", "txn merkle validation failed.") } txnRcpt := transaction.NewTransactionReceipt(cfm.Transaction) if !util.VerifyMerklePath(txnRcpt.GetHash(), cfm.ReceiptMerkleTreePath, cfm.ReceiptMerkleTreeRoot) { - return nil, errors.New("txn receipt cmerkle validation failed.") + return nil, errors.New("", "txn receipt cmerkle validation failed.") } prevBlockHash := cfm.PreviousBlockHash block.MinerId = cfm.MinerID @@ -490,10 +490,10 @@ func getBlockHeaderFromTransactionConfirmation(txnHash string, cfmBlock map[stri if isBlockExtends(prevBlockHash, block) { return block, nil } else { - return nil, errors.New("block hash verification failed in confirmation") + return nil, errors.New("", "block hash verification failed in confirmation") } } - return nil, errors.New("txn confirmation not found.") + return nil, errors.New("", "txn confirmation not found.") } func getTransactionConfirmation(numSharders int, txnHash string) (*blockHeader, map[string]json.RawMessage, *blockHeader, error) { @@ -541,7 +541,7 @@ func getTransactionConfirmation(numSharders int, txnHash string) (*blockHeader, } } if maxConfirmation == 0 { - return nil, confirmation, &lfb, errors.New("transaction not found") + return nil, confirmation, &lfb, errors.New("", "transaction not found") } return blockHdr, confirmation, &lfb, nil } @@ -581,7 +581,7 @@ func GetLatestFinalized(ctx context.Context, numSharders int) (b *block.Header, } if maxConsensus == 0 { - return nil, errors.New("block info not found") + return nil, errors.New("", "block info not found") } return @@ -628,7 +628,7 @@ func GetLatestFinalizedMagicBlock(ctx context.Context, numSharders int) (m *bloc } if maxConsensus == 0 { - return nil, errors.New("magic block info not found") + return nil, errors.New("", "magic block info not found") } return @@ -721,7 +721,7 @@ func GetBlockByRound(ctx context.Context, numSharders int, round int64) (b *bloc } if maxConsensus == 0 { - return nil, errors.New("round info not found") + return nil, errors.New("", "round info not found") } return @@ -771,7 +771,7 @@ func GetMagicBlockByNumber(ctx context.Context, numSharders int, number int64) ( } if maxConsensus == 0 { - return nil, errors.New("magic block info not found") + return nil, errors.New("", "magic block info not found") } return @@ -823,7 +823,7 @@ func getBlockInfoByRound(numSharders int, round int64, content string) (*blockHe } } if maxConsensus == 0 { - return nil, errors.New("round info not found.") + return nil, errors.New("", "round info not found.") } return &blkHdr, nil } @@ -884,12 +884,12 @@ func (t *Transaction) isTransactionExpired(lfbCreationTime, currentTime int64) b } func (t *Transaction) Verify() error { if t.txnHash == "" && t.txnStatus == StatusUnknown { - return errors.New("invalid transaction. cannot be verified.") + return errors.New("", "invalid transaction. cannot be verified.") } if t.txnHash == "" && t.txnStatus == StatusSuccess { h := t.GetTransactionHash() if h == "" { - return errors.New("invalid transaction. cannot be verified.") + return errors.New("", "invalid transaction. cannot be verified.") } } // If transaction is verify only start from current time @@ -909,14 +909,14 @@ func (t *Transaction) Verify() error { confirmBlock, confirmation, lfb, err = getTransactionConfirmation(getMinShardersVerify(), t.txnHash) if err != nil { if t.isTransactionExpired(lfb.CreationDate, tn) { - t.completeVerify(StatusError, "", errors.New(`{"error": "verify transaction failed"}`)) + t.completeVerify(StatusError, "", errors.New("", `{"error": "verify transaction failed"}`)) return } continue } } else { if t.isTransactionExpired(lfb.CreationDate, tn) { - t.completeVerify(StatusError, "", errors.New(`{"error": "verify transaction failed"}`)) + t.completeVerify(StatusError, "", errors.New("", `{"error": "verify transaction failed"}`)) return } continue @@ -926,7 +926,7 @@ func (t *Transaction) Verify() error { if valid { output, err := json.Marshal(confirmation) if err != nil { - t.completeVerify(StatusError, "", errors.New(`{"error": "transaction confirmation json marshal error"`)) + t.completeVerify(StatusError, "", errors.New("", `{"error": "transaction confirmation json marshal error"`)) return } t.completeVerify(StatusSuccess, string(output), nil) diff --git a/zcncore/transactionauth.go b/zcncore/transactionauth.go index 3d67c170f..374798891 100644 --- a/zcncore/transactionauth.go +++ b/zcncore/transactionauth.go @@ -93,7 +93,7 @@ func verifyFn(signature, msgHash, publicKey string) (bool, error) { v.SetPublicKey(publicKey) ok, err := v.Verify(signature, msgHash) if err != nil || ok == false { - return false, errors.New(`{"error": "signature_mismatch"}`) + return false, errors.New("", `{"error": "signature_mismatch"}`) } return true, nil } @@ -353,7 +353,7 @@ func (ta *TransactionWithAuth) UnlockTokens(poolID string) error { //RegisterMultiSig register a multisig wallet with the SC. func (ta *TransactionWithAuth) RegisterMultiSig(walletstr string, mswallet string) error { - return errors.New("not implemented") + return errors.New("", "not implemented") } // diff --git a/zcncore/wallet.go b/zcncore/wallet.go index 96c3aa86b..f726d2f52 100644 --- a/zcncore/wallet.go +++ b/zcncore/wallet.go @@ -200,14 +200,14 @@ func init() { } func checkSdkInit() error { if !_config.isConfigured || len(_config.chain.Miners) < 1 || len(_config.chain.Sharders) < 1 { - return errors.New("SDK not initialized") + return errors.New("", "SDK not initialized") } return nil } func checkWalletConfig() error { if !_config.isValidWallet || _config.wallet.ClientID == "" { Logger.Error("wallet info not found. returning error.") - return errors.New("wallet info not found. set wallet info") + return errors.New("", "wallet info not found. set wallet info") } return nil } @@ -294,7 +294,7 @@ func Init(c string) error { if err == nil { // Check signature scheme is supported if _config.chain.SignatureScheme != "ed25519" && _config.chain.SignatureScheme != "bls0chain" { - return errors.New("invalid/unsupported signature scheme") + return errors.New("", "invalid/unsupported signature scheme") } err := UpdateNetworkDetails() @@ -342,7 +342,7 @@ func WithConfirmationChainLength(m int) func(c *ChainConfig) error { // InitZCNSDK initializes the SDK with miner, sharder and signature scheme provided. func InitZCNSDK(blockWorker string, signscheme string, configs ...func(*ChainConfig) error) error { if signscheme != "ed25519" && signscheme != "bls0chain" { - return errors.New("invalid/unsupported signature scheme") + return errors.New("", "invalid/unsupported signature scheme") } _config.chain.BlockWorker = blockWorker _config.chain.SignatureScheme = signscheme @@ -388,7 +388,7 @@ func GetNetworkJSON() string { // It also registers the wallet again to block chain. func CreateWallet(statusCb WalletCallback) error { if len(_config.chain.Miners) < 1 || len(_config.chain.Sharders) < 1 { - return errors.New("SDK not initialized") + return errors.New("", "SDK not initialized") } go func() { sigScheme := zcncrypto.NewSignatureScheme(_config.chain.SignatureScheme) @@ -410,7 +410,7 @@ func CreateWallet(statusCb WalletCallback) error { // It also registers the wallet again to block chain. func RecoverWallet(mnemonic string, statusCb WalletCallback) error { if zcncrypto.IsMnemonicValid(mnemonic) != true { - return errors.New("Invalid mnemonic") + return errors.New("", "Invalid mnemonic") } go func() { sigScheme := zcncrypto.NewSignatureScheme(_config.chain.SignatureScheme) @@ -431,7 +431,7 @@ func RecoverWallet(mnemonic string, statusCb WalletCallback) error { // Split keys from the primary master key func SplitKeys(privateKey string, numSplits int) (string, error) { if _config.chain.SignatureScheme != "bls0chain" { - return "", errors.New("signature key doesn't support split key") + return "", errors.New("", "signature key doesn't support split key") } sigScheme := zcncrypto.NewBLS0ChainScheme() err := sigScheme.SetPrivateKey(privateKey) @@ -489,7 +489,7 @@ func RegisterToMiners(wallet *zcncrypto.Wallet, statusCb WalletCallback) error { } rate := consensus * 100 / float32(len(_config.chain.Miners)) if rate < consensusThresh { - return errors.New(fmt.Sprintf("Register consensus not met. Consensus: %f, Expected: %f", rate, consensusThresh)) + return fmt.Errorf("Register consensus not met. Consensus: %f, Expected: %f", rate, consensusThresh) } w, err := wallet.Marshal() if err != nil { @@ -551,10 +551,10 @@ func SetWalletInfo(w string, splitKeyWallet bool) error { // SetAuthUrl will be called by app to set zauth URL to SDK. func SetAuthUrl(url string) error { if !_config.isSplitWallet { - return errors.New("wallet type is not split key") + return errors.New("", "wallet type is not split key") } if url == "" { - return errors.New("invalid auth url") + return errors.New("", "invalid auth url") } _config.authUrl = strings.TrimRight(url, "/") return nil @@ -641,7 +641,7 @@ func getBalanceFromSharders(clientID string) (int64, string, error) { } rate := consensus * 100 / float32(len(_config.chain.Sharders)) if rate < consensusThresh { - return 0, winError, errors.New("get balance failed. consensus not reached") + return 0, winError, errors.New("", "get balance failed. consensus not reached") } return winBalance, winInfo, nil } From f46a8d7b83e2f7075f201ab65feacb05b2a2e42b Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 16 Aug 2021 17:07:07 +0800 Subject: [PATCH 19/21] fix(transaction):#195 fixed random issue --- core/transaction/entity.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/transaction/entity.go b/core/transaction/entity.go index 8629731d0..50568958f 100644 --- a/core/transaction/entity.go +++ b/core/transaction/entity.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "math" "net" "net/http" "strconv" @@ -221,11 +222,11 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) return nil, ErrNoAvailableSharder } - minNumConfirmation := cfg.MinConfirmation / 100 * numSharders + minNumConfirmation := int(math.Ceil(float64(cfg.MinConfirmation*numSharders) / 100)) rand := util.NewRand(numSharders) - selectedSharders := make([]string, minNumConfirmation+1) + selectedSharders := make([]string, 0, minNumConfirmation+1) // random pick minNumConfirmation+1 first for i := 0; i <= minNumConfirmation; i++ { @@ -245,10 +246,9 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) //leave first item for ErrTooLessConfirmation var msgList = make([]string, 1, numSharders) - urls := make([]string, len(selectedSharders)) + urls := make([]string, 0, len(selectedSharders)) for _, sharder := range selectedSharders { - urls = append(urls, fmt.Sprintf("%v/%v%v", sharder, TXN_VERIFY_URL, txnHash)) } @@ -267,18 +267,18 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) url := req.URL.String() if err != nil { //network issue - msgList = append(msgList, err.Error()+": ", url) + msgList = append(msgList, err.Error()) return err } body, err := ioutil.ReadAll(resp.Body) if err != nil { //network issue - msgList = append(msgList, err.Error()+": "+url) + msgList = append(msgList, url+": "+err.Error()) return err } if resp.StatusCode != 200 { - msgList = append(msgList, strconv.Itoa(resp.StatusCode)+": "+url) + msgList = append(msgList, url+": ["+strconv.Itoa(resp.StatusCode)+"] "+string(body)) return errors.Throw(ErrInvalidRequest, strconv.Itoa(resp.StatusCode)+": "+resp.Status) } @@ -349,7 +349,7 @@ func VerifyTransaction(txnHash string, sharders []string) (*Transaction, error) return retTxn, nil } - msgList[0] = fmt.Sprintf("min_confirmation is %v%, but got %v/%v sharders", cfg.MinConfirmation, numSuccess, numSharders) + msgList[0] = fmt.Sprintf("min_confirmation is %v%%, but got %v/%v sharders", cfg.MinConfirmation, numSuccess, numSharders) return nil, errors.Throw(ErrTooLessConfirmation, strings.Join(msgList, "\r\n")) From 15f2dc527f192566fa3a5d7f6a20e10d12b2a2ae Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 16 Aug 2021 17:38:13 +0800 Subject: [PATCH 20/21] fix(transaction):#195 fixed unit test --- core/resty/resty.go | 17 +++++++++++------ zboxcore/sdk/allocation.go | 2 +- zboxcore/sdk/allocation_test.go | 17 ++++++++++++----- zboxcore/sdk/filemetaworker_test.go | 3 ++- zboxcore/sdk/filestatsworker_test.go | 2 +- zboxcore/sdk/listworker_test.go | 2 +- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/core/resty/resty.go b/core/resty/resty.go index 34ff76f55..33d288988 100644 --- a/core/resty/resty.go +++ b/core/resty/resty.go @@ -22,16 +22,21 @@ func New(transport *http.Transport, handle Handle, opts ...Option) *Resty { r.transport = &http.Transport{} } + r.client = CreateClient(r.transport, r.timeout) + + return r +} + +// CreateClient a function that create a client instance +var CreateClient = func(t *http.Transport, timeout time.Duration) Client { client := &http.Client{ - Transport: r.transport, + Transport: t, } - if r.timeout > 0 { - client.Timeout = r.timeout + if timeout > 0 { + client.Timeout = timeout } - r.client = client - - return r + return client } // Client http client diff --git a/zboxcore/sdk/allocation.go b/zboxcore/sdk/allocation.go index 2dbe765d5..316bc08ed 100644 --- a/zboxcore/sdk/allocation.go +++ b/zboxcore/sdk/allocation.go @@ -29,7 +29,7 @@ import ( ) var ( - noBLOBBERS = errors.New("no_blobber", "No Blobbers set in this allocation") + noBLOBBERS = errors.New("", "No Blobbers set in this allocation") notInitialized = errors.New("sdk_not_initialized", "Please call InitStorageSDK Init and use GetAllocation to get the allocation object") ) diff --git a/zboxcore/sdk/allocation_test.go b/zboxcore/sdk/allocation_test.go index c86b5e2a8..217c99cd0 100644 --- a/zboxcore/sdk/allocation_test.go +++ b/zboxcore/sdk/allocation_test.go @@ -12,12 +12,14 @@ import ( "strings" "sync" "testing" + "time" "github.com/0chain/gosdk/zboxcore/encryption" "github.com/0chain/errors" "github.com/0chain/gosdk/core/common" "github.com/0chain/gosdk/core/conf" + "github.com/0chain/gosdk/core/resty" "github.com/0chain/gosdk/core/transaction" "github.com/0chain/gosdk/core/util" @@ -2673,6 +2675,13 @@ func TestAllocation_CommitFolderChange(t *testing.T) { var mockClient = mocks.HttpClient{} util.Client = &mockClient + resty.CreateClient = func(t *http.Transport, timeout time.Duration) resty.Client { + return &mockClient + } + + transaction.SetConfig(&conf.Config{ + MinConfirmation: 50, + }) client := zclient.GetClient() client.Wallet = &zcncrypto.Wallet{ @@ -2683,7 +2692,7 @@ func TestAllocation_CommitFolderChange(t *testing.T) { setupHttpResponse := func(t *testing.T, name string, httpMethod string, statusCode int, body []byte) { mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool { return req.Method == httpMethod && - strings.HasPrefix(req.URL.Path, name) + strings.Index(req.URL.String(), name) > -1 })).Return(&http.Response{ StatusCode: statusCode, Body: ioutil.NopCloser(bytes.NewReader([]byte(body))), @@ -2719,8 +2728,6 @@ func TestAllocation_CommitFolderChange(t *testing.T) { name: "Test_Sharder_Verify_Txn_Failed", setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) { - transaction.SetConfig(&conf.Config{}) - body, err := json.Marshal(&transaction.Transaction{ Hash: mockHash, }) @@ -2780,8 +2787,8 @@ func TestAllocation_CommitFolderChange(t *testing.T) { } a.InitAllocation() sdkInitialized = true - blockchain.SetMiners([]string{tt.name + "mockMiners"}) - blockchain.SetSharders([]string{tt.name + "mockSharders"}) + blockchain.SetMiners([]string{"http://" + tt.name + "mockMiners"}) + blockchain.SetSharders([]string{"http://" + tt.name + "mockSharders"}) if tt.setup != nil { if teardown := tt.setup(t, tt.name, a); teardown != nil { defer teardown(t) diff --git a/zboxcore/sdk/filemetaworker_test.go b/zboxcore/sdk/filemetaworker_test.go index f36650efd..a63894576 100644 --- a/zboxcore/sdk/filemetaworker_test.go +++ b/zboxcore/sdk/filemetaworker_test.go @@ -15,6 +15,7 @@ import ( "testing" "github.com/0chain/errors" + "github.com/0chain/gosdk/core/zcncrypto" "github.com/0chain/gosdk/zboxcore/blockchain" zclient "github.com/0chain/gosdk/zboxcore/client" @@ -70,7 +71,7 @@ func TestListRequest_getFileMetaInfoFromBlobber(t *testing.T) { })).Return(&http.Response{ Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), StatusCode: p.respStatusCode, - }, errors.New(mockErrorMessage)) + }, errors.New("", mockErrorMessage)) }, wantErr: true, errMsg: mockErrorMessage, diff --git a/zboxcore/sdk/filestatsworker_test.go b/zboxcore/sdk/filestatsworker_test.go index d6c8a8703..fbc1f7c29 100644 --- a/zboxcore/sdk/filestatsworker_test.go +++ b/zboxcore/sdk/filestatsworker_test.go @@ -74,7 +74,7 @@ func TestListRequest_getFileStatsInfoFromBlobber(t *testing.T) { })).Return(&http.Response{ Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), StatusCode: p.respStatusCode, - }, errors.New(mockErrorMessage)) + }, errors.New("", mockErrorMessage)) }, wantErr: true, errMsg: mockErrorMessage, diff --git a/zboxcore/sdk/listworker_test.go b/zboxcore/sdk/listworker_test.go index ad288ff11..173fc107d 100644 --- a/zboxcore/sdk/listworker_test.go +++ b/zboxcore/sdk/listworker_test.go @@ -80,7 +80,7 @@ func TestListRequest_getListInfoFromBlobber(t *testing.T) { })).Return(&http.Response{ Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), StatusCode: p.respStatusCode, - }, errors.New(mockErrorMessage)) + }, errors.New("", mockErrorMessage)) }, wantErr: true, errMsg: mockErrorMessage, From c6532fe31173efde3012b0e665267f4c8e58af9b Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 16 Aug 2021 17:47:26 +0800 Subject: [PATCH 21/21] fix(error):0chain/errors#195 migrate errors --- core/zcncrypto/ed255190chain.go | 2 +- zboxcore/sdk/allocation.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/zcncrypto/ed255190chain.go b/core/zcncrypto/ed255190chain.go index 0840373b5..a7822d98d 100644 --- a/core/zcncrypto/ed255190chain.go +++ b/core/zcncrypto/ed255190chain.go @@ -59,7 +59,7 @@ func (ed *ED255190chainScheme) GenerateKeys() (*Wallet, error) { //GenerateKeysWithEth - not implemented func (ed *ED255190chainScheme) GenerateKeysWithEth(mnemonic, password string) (*Wallet, error) { - return nil, errors.New("chain_scheme_unsupported", "Not supported for this scheme") + return nil, errors.New("", "Not supported for this scheme") } func (ed *ED255190chainScheme) RecoverKeys(mnemonic string) (*Wallet, error) { diff --git a/zboxcore/sdk/allocation.go b/zboxcore/sdk/allocation.go index 316bc08ed..17d7f6c79 100644 --- a/zboxcore/sdk/allocation.go +++ b/zboxcore/sdk/allocation.go @@ -1035,7 +1035,7 @@ func (a *Allocation) UploadAuthTicketToBlobber(authticketB64 string, clientEncPu fullconsensus: float32(a.DataShards + a.ParityShards), } if !consensus.isConsensusOk() { - return errors.New("invalid_consensus", "consensus not reached") + return errors.New("", "consensus not reached") } return nil }