diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 54e3d7b0..25b41170 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -43,7 +43,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -54,7 +54,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v3 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -68,4 +68,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v3 diff --git a/README.md b/README.md index 6d94fc00..9f10b883 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The next generation of the Qitmeer network implementation with the plug-able VMs under the MeerDAG consensus. ### Installation -***make sure you have go-lang version `1.19.x` or above (`1.20.x` is recommended) installed on the system to build.*** +***make sure you have go-lang version `1.21.x` or above (`1.22.x` is recommended) installed on the system to build.*** * Build from source ```bash diff --git a/cmd/miner/common/rpc.go b/cmd/miner/common/rpc.go deleted file mode 100644 index 702d7410..00000000 --- a/cmd/miner/common/rpc.go +++ /dev/null @@ -1,134 +0,0 @@ -package common - -import ( - "bytes" - "crypto/tls" - "crypto/x509" - "encoding/json" - "github.com/Qitmeer/qng/cmd/miner/common/socks" - "github.com/Qitmeer/qng/rpc/client/cmds" - "io/ioutil" - "net" - "net/http" - "strings" - "time" -) - -type RpcClient struct { - Cfg *GlobalConfig - GbtID int64 - SubmitID int64 -} - -// newHTTPClient returns a new HTTP client that is configured according to the -// proxy and TLS settings in the associated connection configuration. -func (rpc *RpcClient) newHTTPClient() (*http.Client, error) { - // Configure proxy if needed. - var dial func(network, addr string) (net.Conn, error) - if rpc.Cfg.OptionConfig.Proxy != "" { - proxy := &socks.Proxy{ - Addr: rpc.Cfg.OptionConfig.Proxy, - Username: rpc.Cfg.OptionConfig.ProxyUser, - Password: rpc.Cfg.OptionConfig.ProxyPass, - } - dial = func(network, addr string) (net.Conn, error) { - c, err := proxy.Dial(network, addr) - if err != nil { - return nil, err - } - return c, nil - } - } - - // Configure TLS if needed. - var tlsConfig *tls.Config - if !rpc.Cfg.SoloConfig.NoTLS && rpc.Cfg.SoloConfig.RPCCert != "" { - pem, err := ioutil.ReadFile(rpc.Cfg.SoloConfig.RPCCert) - if err != nil { - return nil, err - } - - pool := x509.NewCertPool() - pool.AppendCertsFromPEM(pem) - tlsConfig = &tls.Config{ - RootCAs: pool, - InsecureSkipVerify: rpc.Cfg.SoloConfig.NoTLS, - } - } else { - tlsConfig = &tls.Config{ - InsecureSkipVerify: rpc.Cfg.SoloConfig.NoTLS, - } - } - - // Create and return the new HTTP client potentially configured with a - // proxy and TLS. - client := http.Client{ - Transport: &http.Transport{ - Dial: dial, - TLSClientConfig: tlsConfig, - DialContext: (&net.Dialer{ - Timeout: time.Duration(rpc.Cfg.OptionConfig.Timeout) * time.Second, - KeepAlive: time.Duration(rpc.Cfg.OptionConfig.Timeout) * time.Second, - DualStack: true, - }).DialContext, - }, - } - return &client, nil -} - -func (rpc *RpcClient) RpcResult(method string, params []interface{}, id string) []byte { - protocol := "http" - if !rpc.Cfg.SoloConfig.NoTLS { - protocol = "https" - } - req, err := cmds.NewRequest(id, method, params) - url := rpc.Cfg.SoloConfig.RPCServer - if !strings.Contains(rpc.Cfg.SoloConfig.RPCServer, "://") { - url = protocol + "://" + url - } - bodyB, err := json.Marshal(req) - if err != nil { - MinerLoger.Error("request failed ", "error", err) - return nil - } - bodyBuff := bytes.NewBuffer(bodyB) - httpRequest, err := http.NewRequest("POST", url, bodyBuff) - if err != nil { - MinerLoger.Error("rpc connect failed ", "error", err) - return nil - } - httpRequest.Close = true - httpRequest.Header.Set("Content-Type", "application/json") - // Configure basic access authorization. - httpRequest.SetBasicAuth(rpc.Cfg.SoloConfig.RPCUser, rpc.Cfg.SoloConfig.RPCPassword) - - // Create the new HTTP client that is configured according to the user- - // specified options and submit the request. - httpClient, err := rpc.newHTTPClient() - if err != nil { - MinerLoger.Error("rpc auth faild ", "error", err) - return nil - } - defer httpClient.CloseIdleConnections() - httpClient.Timeout = time.Duration(rpc.Cfg.OptionConfig.Timeout) * time.Second - httpResponse, err := httpClient.Do(httpRequest) - if err != nil { - MinerLoger.Error("rpc request faild ", "error", err) - return nil - } - defer func() { - _ = httpResponse.Body.Close() - }() - body, err := ioutil.ReadAll(httpResponse.Body) - if err != nil { - MinerLoger.Error("error reading json reply", "error", err) - return nil - } - - if httpResponse.StatusCode != 200 { - time.Sleep(30 * time.Second) - MinerLoger.Error("error http response", "status", httpResponse.Status, "body", string(body), "wait sec", 30) - return nil - } - return body -} diff --git a/cmd/miner/core/robot.go b/cmd/miner/core/robot.go index c295c0a7..97508b70 100644 --- a/cmd/miner/core/robot.go +++ b/cmd/miner/core/robot.go @@ -5,9 +5,10 @@ package core import ( "context" - "github.com/Qitmeer/qng/cmd/miner/common" "strings" "sync" + + "github.com/Qitmeer/qng/cmd/miner/common" ) //var devicesTypesForMining = cl.DeviceTypeAll @@ -30,13 +31,12 @@ type MinerRobot struct { Quit context.Context Work *Work ClDevices []string - Rpc *common.RpcClient Pool bool SubmitStr chan string UseDevices []string } -//init GPU device +// init GPU device func (this *MinerRobot) InitDevice() { this.UseDevices = []string{} if this.Cfg.OptionConfig.UseDevices != "" { diff --git a/cmd/miner/core/work.go b/cmd/miner/core/work.go index d3098841..a1de1e1f 100644 --- a/cmd/miner/core/work.go +++ b/cmd/miner/core/work.go @@ -5,9 +5,10 @@ package core import ( "context" + "sync" + "github.com/Qitmeer/qng/cmd/miner/common" "github.com/Qitmeer/qng/core/types" - "sync" ) const SYMBOL_PMEER = "MEER" @@ -19,10 +20,9 @@ type BaseWork interface { PoolSubmit(subm string) error } -//standard work template +// standard work template type Work struct { Cfg *common.GlobalConfig - Rpc *common.RpcClient Clean bool sync.Mutex Quit context.Context diff --git a/cmd/miner/main.go b/cmd/miner/main.go index 0711d6d6..ad5065d9 100644 --- a/cmd/miner/main.go +++ b/cmd/miner/main.go @@ -5,20 +5,21 @@ package main import ( "context" - "github.com/Qitmeer/qng/cmd/miner/common" - "github.com/Qitmeer/qng/cmd/miner/core" - qitmeer "github.com/Qitmeer/qng/cmd/miner/symbols/lib" "log" "os" "os/signal" "runtime" "strings" "time" + + "github.com/Qitmeer/qng/cmd/miner/common" + "github.com/Qitmeer/qng/cmd/miner/core" + qitmeer "github.com/Qitmeer/qng/cmd/miner/symbols/lib" ) var robotminer core.Robot -//init the config file +// init the config file func init() { cfg, _, err := common.LoadConfig() if err != nil { @@ -50,7 +51,7 @@ func main() { common.MinerLoger.Info("All services exited") } -//get current coin miner +// get current coin miner func GetRobot(cfg *common.GlobalConfig) core.Robot { switch strings.ToUpper(cfg.NecessaryConfig.Symbol) { case core.SYMBOL_PMEER: @@ -58,7 +59,6 @@ func GetRobot(cfg *common.GlobalConfig) core.Robot { r.Cfg = cfg r.NeedGBT = make(chan struct{}, 1) r.Started = uint32(time.Now().Unix()) - r.Rpc = &common.RpcClient{Cfg: cfg} r.SubmitStr = make(chan string) r.PendingBlocks = map[string]qitmeer.PendingBlock{} return r diff --git a/cmd/miner/symbols/lib/pow_meer_cpu.go b/cmd/miner/symbols/lib/pow_meer_cpu.go index 0e974629..26239bb4 100644 --- a/cmd/miner/symbols/lib/pow_meer_cpu.go +++ b/cmd/miner/symbols/lib/pow_meer_cpu.go @@ -111,7 +111,7 @@ func (this *MeerCrypto) Mine(wg *sync.WaitGroup) { } hData := make([]byte, 128) copy(hData[0:types.MaxBlockHeaderPayload-pow.PROOFDATA_LENGTH], this.header.BlockData()) - nonce++ + nonce = common.RandUint64() this.AllDiffOneShares++ b := make([]byte, 8) binary.LittleEndian.PutUint64(b, nonce) diff --git a/cmd/miner/symbols/lib/robot.go b/cmd/miner/symbols/lib/robot.go index 56c4c0d8..344f771b 100644 --- a/cmd/miner/symbols/lib/robot.go +++ b/cmd/miner/symbols/lib/robot.go @@ -103,7 +103,6 @@ func (this *QitmeerRobot) Run(ctx context.Context) { common.MinerLoger.Info(fmt.Sprintf("[%s miner] start", connectName)) this.Work = QitmeerWork{} this.Work.Cfg = this.Cfg - this.Work.Rpc = this.Rpc this.Work.stra = this.Stratu this.Work.Quit = this.Quit this.Work.WorkLock = sync.Mutex{} @@ -223,7 +222,6 @@ func (this *QitmeerRobot) SubmitWork() { this.SubmitLock.Unlock() continue } - this.Work.LastSubmit = time.Now() var err error var txID string @@ -266,6 +264,7 @@ func (this *QitmeerRobot) SubmitWork() { continue } else { if !this.Pool { // solo + this.Work.LastSubmit = time.Now() this.PendingBlocks[txID] = PendingBlock{ CoinbaseHash: txID, BlockHash: blockHash, diff --git a/cmd/miner/symbols/lib/work.go b/cmd/miner/symbols/lib/work.go index 4db8011f..d4d5571d 100644 --- a/cmd/miner/symbols/lib/work.go +++ b/cmd/miner/symbols/lib/work.go @@ -22,6 +22,7 @@ import ( var ErrSameWork = fmt.Errorf("Same work, Had Submitted!") var ErrLimitWork = fmt.Errorf("Submission interval Limited") +var hasSubmits = map[string]bool{} type QitmeerWork struct { core.Work @@ -34,6 +35,8 @@ type QitmeerWork struct { WorkLock sync.Mutex WsClient *client.Client LastSubmit time.Time + GbtID int64 + SubmitID int64 } func (this *QitmeerWork) GetPowType() pow.PowType { @@ -72,7 +75,7 @@ func (this *QitmeerWork) Get() bool { continue } if this.Block != nil && this.Block.ParentRoot == header.ParentRoot && - (time.Now().Unix()-this.GetWorkTime) < int64(this.Cfg.OptionConfig.Timeout)*10 { + (time.Now().Unix()-this.GetWorkTime) < int64(this.Cfg.OptionConfig.TaskInterval)/1000 { common.MinerLoger.Warn("GetRemoteGBT Repeat", "old block parent root", this.Block.ParentRoot, "current", header.ParentRoot) //not has new work return false @@ -83,14 +86,14 @@ func (this *QitmeerWork) Get() bool { // BuildBlock func (this *QitmeerWork) BuildBlock(header *types.BlockHeader) bool { - this.Rpc.GbtID++ + this.GbtID++ this.Block = &BlockHeader{} this.Block.ParentRoot = header.ParentRoot this.Block.WorkData = header.BlockData() this.Block.Target = fmt.Sprintf("%064x", pow.CompactToBig(header.Difficulty)) - this.Block.GBTID = this.Rpc.GbtID - common.LatestGBTID = this.Rpc.GbtID - common.MinerLoger.Debug(fmt.Sprintf("getRemoteBlockTemplate , target :%s , GBTID:%d", this.Block.Target, this.Rpc.GbtID)) + this.Block.GBTID = this.GbtID + common.LatestGBTID = this.GbtID + common.MinerLoger.Debug(fmt.Sprintf("getRemoteBlockTemplate , target :%s , GBTID:%d", this.Block.Target, this.GbtID)) this.GetWorkTime = time.Now().Unix() return true } @@ -99,17 +102,21 @@ func (this *QitmeerWork) BuildBlock(header *types.BlockHeader) bool { func (this *QitmeerWork) Submit(header *types.BlockHeader, gbtID string) (string, int, error) { this.Lock() defer this.Unlock() + if v, ok := hasSubmits[header.ParentRoot.String()]; ok && v { + return "", 0, ErrSameWork + } + gbtIDInt64, _ := strconv.ParseInt(gbtID, 10, 64) - if this.Rpc.GbtID != gbtIDInt64 { - common.MinerLoger.Debug(fmt.Sprintf("gbt old , target :%d , current:%d", this.Rpc.GbtID, gbtIDInt64)) + if this.GbtID != gbtIDInt64 { + common.MinerLoger.Debug(fmt.Sprintf("gbt old , target :%d , current:%d", this.GbtID, gbtIDInt64)) return "", 0, ErrSameWork } - this.Rpc.SubmitID++ + this.SubmitID++ - id := fmt.Sprintf("miner_submit_gbtID:%s_id:%d", gbtID, this.Rpc.SubmitID) + id := fmt.Sprintf("miner_submit_gbtID:%s_id:%d", gbtID, this.SubmitID) res, err := this.WsClient.SubmitBlockHeader(header) if err != nil { - common.MinerLoger.Error("[submit error] " + id + " " + err.Error()) + common.MinerLoger.Error("[submit error] parent root", header.ParentRoot.String(), id) if strings.Contains(err.Error(), "The tips of block is expired") { return "", 0, ErrSameWork } @@ -121,6 +128,7 @@ func (this *QitmeerWork) Submit(header *types.BlockHeader, gbtID string) (string } return "", 0, errors.New("[submit data failed]" + err.Error()) } + hasSubmits[header.ParentRoot.String()] = true return res.CoinbaseTxID, int(res.Height), err } diff --git a/core/shutdown/tracker.go b/core/shutdown/tracker.go index 2054814f..d9df66c6 100644 --- a/core/shutdown/tracker.go +++ b/core/shutdown/tracker.go @@ -2,7 +2,6 @@ package shutdown import ( "fmt" - "io/ioutil" "os" "path" ) @@ -24,6 +23,10 @@ func (t *Tracker) Check() error { if len(bhbs) <= 0 { return nil } + max_file_size := 512 + if len(bhbs) > max_file_size*1024 { // 512 kb + return fmt.Errorf("file size large than %d kb : %s", max_file_size, t.filePath) + } err = fmt.Errorf("Illegal withdrawal at block:%s, you can cleanup your block data base by '--cleanup'.", string(bhbs)) log.Error(err.Error()) return err @@ -72,7 +75,7 @@ func ReadFile(path string) ([]byte, error) { } } - ba, err := ioutil.ReadFile(path) + ba, err := os.ReadFile(path) if err != nil { return nil, err } diff --git a/rpc/client/example/go.mod b/rpc/client/example/go.mod index 21e5b718..07081e65 100644 --- a/rpc/client/example/go.mod +++ b/rpc/client/example/go.mod @@ -1,6 +1,6 @@ module rpcclient -go 1.18 +go 1.22.3 replace github.com/Qitmeer/qng => ../../../ @@ -13,9 +13,9 @@ require ( github.com/dchest/blake256 v1.1.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/jrick/logrotate v1.0.0 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pkg/errors v0.9.1 // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/sys v0.19.0 // indirect ) diff --git a/rpc/client/example/go.sum b/rpc/client/example/go.sum index e9316135..7f98c767 100644 --- a/rpc/client/example/go.sum +++ b/rpc/client/example/go.sum @@ -5,6 +5,7 @@ github.com/Qitmeer/crypto/cryptonight v0.0.0-20201028030128-6ed4040ca34a/go.mod github.com/aead/skein v0.0.0-20160722084837-9365ae6e95d2 h1:q5TSngwXJdajCyZPQR+eKyRRgI3/ZXC/Nq1ZxZ4Zxu8= github.com/aead/skein v0.0.0-20160722084837-9365ae6e95d2/go.mod h1:4JBZEId5BaLqvA2DGU53phvwkn2WpeLhNSF79/uKBPs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= github.com/dchest/blake256 v1.1.0 h1:4AuEhGPT/3TTKFhTfBpZ8hgZE7wJpawcYaEawwsbtqM= github.com/dchest/blake256 v1.1.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= @@ -13,25 +14,29 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=