diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63fb7e63f..ef0045df8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,10 +32,10 @@ jobs: cd contracts/validator/src yarn npx hardhat test - - name: Set up Go 1.14.x + - name: Set up Go 1.21.x uses: actions/setup-go@v4 with: - go-version: "1.14.x" # The Go version to download (if necessary) and use. + go-version: "1.21.x" # The Go version to download (if necessary) and use. - name: Run tests run: | make test diff --git a/.github/workflows/pr_test.yml b/.github/workflows/pr_test.yml index 60b1dae6e..485a9dff8 100644 --- a/.github/workflows/pr_test.yml +++ b/.github/workflows/pr_test.yml @@ -28,10 +28,10 @@ jobs: cd contracts/validator/src yarn npx hardhat test - - name: Set up Go 1.14.x + - name: Set up Go 1.21.x uses: actions/setup-go@v4 with: - go-version: "1.14.x" # The Go version to download (if necessary) and use. + go-version: "1.21.x" # The Go version to download (if necessary) and use. - name: Run tests run: | make test diff --git a/Makefile b/Makefile index 2e1ba6cf9..c9147c38a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ GOBIN = $(shell pwd)/build/bin GOFMT = gofmt -GO ?= 1.13.1 +GO ?= 1.21.3 GO_PACKAGES = . GO_FILES := $(shell find $(shell go list -f '{{.Dir}}' $(GO_PACKAGES)) -name \*.go) diff --git a/build/ci.go b/build/ci.go index 862fd020b..602dd1bda 100644 --- a/build/ci.go +++ b/build/ci.go @@ -114,9 +114,9 @@ func doInstall(cmdline []string) { var minor int fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor) - if minor < 9 { + if minor < 21 { log.Println("You have Go version", runtime.Version()) - log.Println("XDC requires at least Go version 1.9 and cannot") + log.Println("XDC requires at least Go version 1.21 and cannot") log.Println("be compiled with an earlier version. Please upgrade your Go installation.") os.Exit(1) } diff --git a/cmd/XDC/consolecmd_test.go b/cmd/XDC/consolecmd_test.go index 2b1deb66e..4e3ae07bc 100644 --- a/cmd/XDC/consolecmd_test.go +++ b/cmd/XDC/consolecmd_test.go @@ -52,7 +52,9 @@ func TestConsoleWelcome(t *testing.T) { XDC.SetTemplateFunc("goarch", func() string { return runtime.GOARCH }) XDC.SetTemplateFunc("gover", runtime.Version) XDC.SetTemplateFunc("XDCver", func() string { return params.Version }) - XDC.SetTemplateFunc("niltime", func() string { return time.Unix(1559211559, 0).Format(time.RFC1123) }) + XDC.SetTemplateFunc("niltime", func() string { + return time.Unix(1559211559, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)") + }) XDC.SetTemplateFunc("apis", func() string { return ipcAPIs }) // Verify the actual welcome message to the required template @@ -137,7 +139,9 @@ func testAttachWelcome(t *testing.T, XDC *testXDC, endpoint, apis string) { attach.SetTemplateFunc("gover", runtime.Version) attach.SetTemplateFunc("XDCver", func() string { return params.Version }) attach.SetTemplateFunc("etherbase", func() string { return XDC.Etherbase }) - attach.SetTemplateFunc("niltime", func() string { return time.Unix(1559211559, 0).Format(time.RFC1123) }) + attach.SetTemplateFunc("niltime", func() string { + return time.Unix(1559211559, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)") + }) attach.SetTemplateFunc("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") }) attach.SetTemplateFunc("datadir", func() string { return XDC.Datadir }) attach.SetTemplateFunc("apis", func() string { return apis }) diff --git a/common/sort/slice.go b/common/sort/slice.go new file mode 100644 index 000000000..a158c93a6 --- /dev/null +++ b/common/sort/slice.go @@ -0,0 +1,190 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sort + +import "reflect" + +// any is an alias for interface{} and is equivalent to interface{} in all ways. +type any = interface{} + +// lessSwap is a pair of Less and Swap function for use with the +// auto-generated func-optimized variant of sort.go in +// zfuncversion.go. +type lessSwap struct { + Less func(i, j int) bool + Swap func(i, j int) +} + +// Slice sorts the slice x given the provided less function. +// It panics if x is not a slice. +// +// The sort is not guaranteed to be stable: equal elements +// may be reversed from their original order. +// For a stable sort, use SliceStable. +// +// The less function must satisfy the same requirements as +// the Interface type's Less method. +func Slice(x any, less func(i, j int) bool) { + rv := reflect.ValueOf(x) + swap := reflect.Swapper(x) + length := rv.Len() + quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length)) +} + +// maxDepth returns a threshold at which quicksort should switch +// to heapsort. It returns 2*ceil(lg(n+1)). +func maxDepth(n int) int { + var depth int + for i := n; i > 0; i >>= 1 { + depth++ + } + return depth * 2 +} + +// Auto-generated variant of sort.go:quickSort +func quickSort_func(data lessSwap, a, b, maxDepth int) { + for b-a > 12 { + if maxDepth == 0 { + heapSort_func(data, a, b) + return + } + maxDepth-- + mlo, mhi := doPivot_func(data, a, b) + if mlo-a < b-mhi { + quickSort_func(data, a, mlo, maxDepth) + a = mhi + } else { + quickSort_func(data, mhi, b, maxDepth) + b = mlo + } + } + if b-a > 1 { + for i := a + 6; i < b; i++ { + if data.Less(i, i-6) { + data.Swap(i, i-6) + } + } + insertionSort_func(data, a, b) + } +} + +// Auto-generated variant of sort.go:heapSort +func heapSort_func(data lessSwap, a, b int) { + first := a + lo := 0 + hi := b - a + for i := (hi - 1) / 2; i >= 0; i-- { + siftDown_func(data, i, hi, first) + } + for i := hi - 1; i >= 0; i-- { + data.Swap(first, first+i) + siftDown_func(data, lo, i, first) + } +} + +// Auto-generated variant of sort.go:doPivot +func doPivot_func(data lessSwap, lo, hi int) (midlo, midhi int) { + m := int(uint(lo+hi) >> 1) + if hi-lo > 40 { + s := (hi - lo) / 8 + medianOfThree_func(data, lo, lo+s, lo+2*s) + medianOfThree_func(data, m, m-s, m+s) + medianOfThree_func(data, hi-1, hi-1-s, hi-1-2*s) + } + medianOfThree_func(data, lo, m, hi-1) + pivot := lo + a, c := lo+1, hi-1 + for ; a < c && data.Less(a, pivot); a++ { + } + b := a + for { + for ; b < c && !data.Less(pivot, b); b++ { + } + for ; b < c && data.Less(pivot, c-1); c-- { + } + if b >= c { + break + } + data.Swap(b, c-1) + b++ + c-- + } + protect := hi-c < 5 + if !protect && hi-c < (hi-lo)/4 { + dups := 0 + if !data.Less(pivot, hi-1) { + data.Swap(c, hi-1) + c++ + dups++ + } + if !data.Less(b-1, pivot) { + b-- + dups++ + } + if !data.Less(m, pivot) { + data.Swap(m, b-1) + b-- + dups++ + } + protect = dups > 1 + } + if protect { + for { + for ; a < b && !data.Less(b-1, pivot); b-- { + } + for ; a < b && data.Less(a, pivot); a++ { + } + if a >= b { + break + } + data.Swap(a, b-1) + a++ + b-- + } + } + data.Swap(pivot, b-1) + return b - 1, c +} + +// Auto-generated variant of sort.go:insertionSort +func insertionSort_func(data lessSwap, a, b int) { + for i := a + 1; i < b; i++ { + for j := i; j > a && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} + +// Auto-generated variant of sort.go:siftDown +func siftDown_func(data lessSwap, lo, hi, first int) { + root := lo + for { + child := 2*root + 1 + if child >= hi { + break + } + if child+1 < hi && data.Less(first+child, first+child+1) { + child++ + } + if !data.Less(first+root, first+child) { + return + } + data.Swap(first+root, first+child) + root = child + } +} + +// Auto-generated variant of sort.go:medianOfThree +func medianOfThree_func(data lessSwap, m1, m0, m2 int) { + if data.Less(m1, m0) { + data.Swap(m1, m0) + } + if data.Less(m2, m1) { + data.Swap(m2, m1) + if data.Less(m1, m0) { + data.Swap(m1, m0) + } + } +} diff --git a/consensus/XDPoS/utils/utils.go b/consensus/XDPoS/utils/utils.go index 409f00d5d..cb5c591d7 100644 --- a/consensus/XDPoS/utils/utils.go +++ b/consensus/XDPoS/utils/utils.go @@ -68,10 +68,10 @@ func CompareSignersLists(list1 []common.Address, list2 []common.Address) bool { } sort.Slice(l1, func(i, j int) bool { - return l1[i].String() <= l1[j].String() + return bytes.Compare(l1[i][:], l1[j][:]) == -1 }) sort.Slice(l2, func(i, j int) bool { - return l2[i].String() <= l2[j].String() + return bytes.Compare(l2[i][:], l2[j][:]) == -1 }) return reflect.DeepEqual(l1, l2) } diff --git a/console/bridge.go b/console/bridge.go index bb89aed0a..dbd4bae88 100644 --- a/console/bridge.go +++ b/console/bridge.go @@ -20,13 +20,15 @@ import ( "encoding/json" "fmt" "io" + "reflect" "strings" "time" "github.com/XinFinOrg/XDC-Subnet/accounts/usbwallet" - "github.com/XinFinOrg/XDC-Subnet/log" + "github.com/XinFinOrg/XDC-Subnet/common/hexutil" + "github.com/XinFinOrg/XDC-Subnet/internal/jsre" "github.com/XinFinOrg/XDC-Subnet/rpc" - "github.com/robertkrimen/otto" + "github.com/dop251/goja" ) // bridge is a collection of JavaScript utility methods to bride the .js runtime @@ -46,10 +48,18 @@ func newBridge(client *rpc.Client, prompter UserPrompter, printer io.Writer) *br } } +func getJeth(vm *goja.Runtime) *goja.Object { + jeth := vm.Get("jeth") + if jeth == nil { + panic(vm.ToValue("jeth object does not exist")) + } + return jeth.ToObject(vm) +} + // NewAccount is a wrapper around the personal.newAccount RPC method that uses a // non-echoing password prompt to acquire the passphrase and executes the original // RPC method (saved in jeth.newAccount) with it to actually execute the RPC call. -func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) { +func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) { var ( password string confirm string @@ -57,57 +67,93 @@ func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) { ) switch { // No password was specified, prompt the user for it - case len(call.ArgumentList) == 0: + case len(call.Arguments) == 0: if password, err = b.prompter.PromptPassword("Passphrase: "); err != nil { - throwJSException(err.Error()) + return nil, err } if confirm, err = b.prompter.PromptPassword("Repeat passphrase: "); err != nil { - throwJSException(err.Error()) + return nil, err } if password != confirm { - throwJSException("passphrases don't match!") + return nil, fmt.Errorf("passwords don't match!") } - // A single string password was specified, use that - case len(call.ArgumentList) == 1 && call.Argument(0).IsString(): - password, _ = call.Argument(0).ToString() - - // Otherwise fail with some error + case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil: + password = call.Argument(0).ToString().String() default: - throwJSException("expected 0 or 1 string argument") + return nil, fmt.Errorf("expected 0 or 1 string argument") } // Password acquired, execute the call and return - ret, err := call.Otto.Call("jeth.newAccount", nil, password) + newAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("newAccount")) + if !callable { + return nil, fmt.Errorf("jeth.newAccount is not callable") + } + ret, err := newAccount(goja.Null(), call.VM.ToValue(password)) if err != nil { - throwJSException(err.Error()) + return nil, err } - return ret + return ret, nil } // OpenWallet is a wrapper around personal.openWallet which can interpret and // react to certain error messages, such as the Trezor PIN matrix request. -func (b *bridge) OpenWallet(call otto.FunctionCall) (response otto.Value) { - // Make sure we have an wallet specified to open - if !call.Argument(0).IsString() { - throwJSException("first argument must be the wallet URL to open") +func (b *bridge) OpenWallet(call jsre.Call) (goja.Value, error) { + // Make sure we have a wallet specified to open + if call.Argument(0).ToObject(call.VM).ClassName() != "String" { + return nil, fmt.Errorf("first argument must be the wallet URL to open") } wallet := call.Argument(0) - var passwd otto.Value - if call.Argument(1).IsUndefined() || call.Argument(1).IsNull() { - passwd, _ = otto.ToValue("") + var passwd goja.Value + if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { + passwd = call.VM.ToValue("") } else { passwd = call.Argument(1) } // Open the wallet and return if successful in itself - val, err := call.Otto.Call("jeth.openWallet", nil, wallet, passwd) + openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) + if !callable { + return nil, fmt.Errorf("jeth.openWallet is not callable") + } + val, err := openWallet(goja.Null(), wallet, passwd) if err == nil { - return val + return val, nil + } + + // Wallet open failed, report error unless it's a PIN or PUK entry + switch { + case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()): + val, err = b.readPinAndReopenWallet(call) + if err == nil { + return val, nil + } + val, err = b.readPassphraseAndReopenWallet(call) + if err != nil { + return nil, err + } + + default: + // Unknown error occurred, drop to the user + return nil, err + } + return val, nil +} + +func (b *bridge) readPassphraseAndReopenWallet(call jsre.Call) (goja.Value, error) { + wallet := call.Argument(0) + input, err := b.prompter.PromptPassword("Please enter your passphrase: ") + if err != nil { + return nil, err } - // Wallet open failed, report error unless it's a PIN entry - if !strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()) { - throwJSException(err.Error()) + openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) + if !callable { + return nil, fmt.Errorf("jeth.openWallet is not callable") } + return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) +} + +func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) { + wallet := call.Argument(0) // Trezor PIN matrix input requested, display the matrix to the user and fetch the data fmt.Fprintf(b.printer, "Look at the device for number positions\n\n") fmt.Fprintf(b.printer, "7 | 8 | 9\n") @@ -116,158 +162,154 @@ func (b *bridge) OpenWallet(call otto.FunctionCall) (response otto.Value) { fmt.Fprintf(b.printer, "--+---+--\n") fmt.Fprintf(b.printer, "1 | 2 | 3\n\n") - if input, err := b.prompter.PromptPassword("Please enter current PIN: "); err != nil { - throwJSException(err.Error()) - } else { - passwd, _ = otto.ToValue(input) + input, err := b.prompter.PromptPassword("Please enter current PIN: ") + if err != nil { + return nil, err } - if val, err = call.Otto.Call("jeth.openWallet", nil, wallet, passwd); err != nil { - throwJSException(err.Error()) + openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) + if !callable { + return nil, fmt.Errorf("jeth.openWallet is not callable") } - return val + return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) } // UnlockAccount is a wrapper around the personal.unlockAccount RPC method that // uses a non-echoing password prompt to acquire the passphrase and executes the // original RPC method (saved in jeth.unlockAccount) with it to actually execute // the RPC call. -func (b *bridge) UnlockAccount(call otto.FunctionCall) (response otto.Value) { - // Make sure we have an account specified to unlock - if !call.Argument(0).IsString() { - throwJSException("first argument must be the account to unlock") +func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) { + // Make sure we have an account specified to unlock. + if call.Argument(0).ExportType().Kind() != reflect.String { + return nil, fmt.Errorf("first argument must be the account to unlock") } account := call.Argument(0) - // If password is not given or is the null value, prompt the user for it - var passwd otto.Value - - if call.Argument(1).IsUndefined() || call.Argument(1).IsNull() { + // If password is not given or is the null value, prompt the user for it. + var passwd goja.Value + if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { fmt.Fprintf(b.printer, "Unlock account %s\n", account) - if input, err := b.prompter.PromptPassword("Passphrase: "); err != nil { - throwJSException(err.Error()) - } else { - passwd, _ = otto.ToValue(input) + input, err := b.prompter.PromptPassword("Passphrase: ") + if err != nil { + return nil, err } + passwd = call.VM.ToValue(input) } else { - if !call.Argument(1).IsString() { - throwJSException("password must be a string") + if call.Argument(1).ExportType().Kind() != reflect.String { + return nil, fmt.Errorf("password must be a string") } passwd = call.Argument(1) } - // Third argument is the duration how long the account must be unlocked. - duration := otto.NullValue() - if call.Argument(2).IsDefined() && !call.Argument(2).IsNull() { - if !call.Argument(2).IsNumber() { - throwJSException("unlock duration must be a number") + + // Third argument is the duration how long the account should be unlocked. + duration := goja.Null() + if !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) { + if !isNumber(call.Argument(2)) { + return nil, fmt.Errorf("unlock duration must be a number") } duration = call.Argument(2) } - // Send the request to the backend and return - val, err := call.Otto.Call("jeth.unlockAccount", nil, account, passwd, duration) - if err != nil { - throwJSException(err.Error()) + + // Send the request to the backend and return. + unlockAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount")) + if !callable { + return nil, fmt.Errorf("jeth.unlockAccount is not callable") } - return val + return unlockAccount(goja.Null(), account, passwd, duration) } // Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password // prompt to acquire the passphrase and executes the original RPC method (saved in // jeth.sign) with it to actually execute the RPC call. -func (b *bridge) Sign(call otto.FunctionCall) (response otto.Value) { +func (b *bridge) Sign(call jsre.Call) (goja.Value, error) { var ( message = call.Argument(0) account = call.Argument(1) passwd = call.Argument(2) ) - if !message.IsString() { - throwJSException("first argument must be the message to sign") + if message.ExportType().Kind() != reflect.String { + return nil, fmt.Errorf("first argument must be the message to sign") } - if !account.IsString() { - throwJSException("second argument must be the account to sign with") + if account.ExportType().Kind() != reflect.String { + return nil, fmt.Errorf("second argument must be the account to sign with") } // if the password is not given or null ask the user and ensure password is a string - if passwd.IsUndefined() || passwd.IsNull() { + if goja.IsUndefined(passwd) || goja.IsNull(passwd) { fmt.Fprintf(b.printer, "Give password for account %s\n", account) - if input, err := b.prompter.PromptPassword("Passphrase: "); err != nil { - throwJSException(err.Error()) - } else { - passwd, _ = otto.ToValue(input) + input, err := b.prompter.PromptPassword("Password: ") + if err != nil { + return nil, err } - } - if !passwd.IsString() { - throwJSException("third argument must be the password to unlock the account") + passwd = call.VM.ToValue(input) + } else if passwd.ExportType().Kind() != reflect.String { + return nil, fmt.Errorf("third argument must be the password to unlock the account") } // Send the request to the backend and return - val, err := call.Otto.Call("jeth.sign", nil, message, account, passwd) - if err != nil { - throwJSException(err.Error()) + sign, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount")) + if !callable { + return nil, fmt.Errorf("jeth.unlockAccount is not callable") } - return val + return sign(goja.Null(), message, account, passwd) } // Sleep will block the console for the specified number of seconds. -func (b *bridge) Sleep(call otto.FunctionCall) (response otto.Value) { - if call.Argument(0).IsNumber() { - sleep, _ := call.Argument(0).ToInteger() - time.Sleep(time.Duration(sleep) * time.Second) - return otto.TrueValue() +func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) { + if !isNumber(call.Argument(0)) { + return nil, fmt.Errorf("usage: sleep()") } - return throwJSException("usage: sleep()") + sleep := call.Argument(0).ToFloat() + time.Sleep(time.Duration(sleep * float64(time.Second))) + return call.VM.ToValue(true), nil } // SleepBlocks will block the console for a specified number of new blocks optionally // until the given timeout is reached. -func (b *bridge) SleepBlocks(call otto.FunctionCall) (response otto.Value) { +func (b *bridge) SleepBlocks(call jsre.Call) (goja.Value, error) { + // Parse the input parameters for the sleep. var ( blocks = int64(0) sleep = int64(9999999999999999) // indefinitely ) - // Parse the input parameters for the sleep - nArgs := len(call.ArgumentList) + nArgs := len(call.Arguments) if nArgs == 0 { - throwJSException("usage: sleepBlocks([, max sleep in seconds])") + return nil, fmt.Errorf("usage: sleepBlocks([, max sleep in seconds])") } if nArgs >= 1 { - if call.Argument(0).IsNumber() { - blocks, _ = call.Argument(0).ToInteger() - } else { - throwJSException("expected number as first argument") + if !isNumber(call.Argument(0)) { + return nil, fmt.Errorf("expected number as first argument") } + blocks = call.Argument(0).ToInteger() } if nArgs >= 2 { - if call.Argument(1).IsNumber() { - sleep, _ = call.Argument(1).ToInteger() - } else { - throwJSException("expected number as second argument") + if isNumber(call.Argument(1)) { + return nil, fmt.Errorf("expected number as second argument") } + sleep = call.Argument(1).ToInteger() } - // go through the console, this will allow web3 to call the appropriate - // callbacks if a delayed response or notification is received. - blockNumber := func() int64 { - result, err := call.Otto.Run("eth.blockNumber") + + // Poll the current block number until either it or a timeout is reached. + var ( + deadline = time.Now().Add(time.Duration(sleep) * time.Second) + lastNumber = ^hexutil.Uint64(0) + ) + for time.Now().Before(deadline) { + var number hexutil.Uint64 + err := b.client.Call(&number, "eth_blockNumber") if err != nil { - throwJSException(err.Error()) + return nil, err } - block, err := result.ToInteger() - if err != nil { - throwJSException(err.Error()) + if number != lastNumber { + lastNumber = number + blocks-- } - return block - } - // Poll the current block number until either it ot a timeout is reached - targetBlockNr := blockNumber() + blocks - deadline := time.Now().Add(time.Duration(sleep) * time.Second) - - for time.Now().Before(deadline) { - if blockNumber() >= targetBlockNr { - return otto.TrueValue() + if blocks <= 0 { + break } time.Sleep(time.Second) } - return otto.FalseValue() + return call.VM.ToValue(true), nil } type jsonrpcCall struct { @@ -277,15 +319,15 @@ type jsonrpcCall struct { } // Send implements the web3 provider "send" method. -func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) { +func (b *bridge) Send(call jsre.Call) (goja.Value, error) { // Remarshal the request into a Go value. - JSON, _ := call.Otto.Object("JSON") - reqVal, err := JSON.Call("stringify", call.Argument(0)) + reqVal, err := call.Argument(0).ToObject(call.VM).MarshalJSON() if err != nil { - throwJSException(err.Error()) + return nil, err } + var ( - rawReq = reqVal.String() + rawReq = string(reqVal) dec = json.NewDecoder(strings.NewReader(rawReq)) reqs []jsonrpcCall batch bool @@ -301,10 +343,12 @@ func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) { } // Execute the requests. - resps, _ := call.Otto.Object("new Array()") + var resps []*goja.Object for _, req := range reqs { - resp, _ := call.Otto.Object(`({"jsonrpc":"2.0"})`) + resp := call.VM.NewObject() + resp.Set("jsonrpc", "2.0") resp.Set("id", req.Id) + var result json.RawMessage err = b.client.Call(&result, req.Method, req.Params...) switch err := err.(type) { @@ -312,9 +356,14 @@ func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) { if result == nil { // Special case null because it is decoded as an empty // raw message for some reason. - resp.Set("result", otto.NullValue()) + resp.Set("result", goja.Null()) } else { - resultVal, err := JSON.Call("parse", string(result)) + JSON := call.VM.Get("JSON").ToObject(call.VM) + parse, callable := goja.AssertFunction(JSON.Get("parse")) + if !callable { + return nil, fmt.Errorf("JSON.parse is not a function") + } + resultVal, err := parse(goja.Null(), call.VM.ToValue(string(result))) if err != nil { setError(resp, -32603, err.Error()) } else { @@ -326,33 +375,38 @@ func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) { default: setError(resp, -32603, err.Error()) } - resps.Call("push", resp) + resps = append(resps, resp) } // Return the responses either to the callback (if supplied) // or directly as the return value. + var result goja.Value if batch { - response = resps.Value() + result = call.VM.ToValue(resps) } else { - response, _ = resps.Get("0") + result = resps[0] } - if fn := call.Argument(1); fn.Class() == "Function" { - fn.Call(otto.NullValue(), otto.NullValue(), response) - return otto.UndefinedValue() + if fn, isFunc := goja.AssertFunction(call.Argument(1)); isFunc { + fn(goja.Null(), goja.Null(), result) + return goja.Undefined(), nil } - return response + return result, nil } -func setError(resp *otto.Object, code int, msg string) { +func setError(resp *goja.Object, code int, msg string) { resp.Set("error", map[string]interface{}{"code": code, "message": msg}) } -// throwJSException panics on an otto.Value. The Otto VM will recover from the -// Go panic and throw msg as a JavaScript error. -func throwJSException(msg interface{}) otto.Value { - val, err := otto.ToValue(msg) - if err != nil { - log.Error("Failed to serialize JavaScript exception", "exception", msg, "err", err) +// isNumber returns true if input value is a JS number. +func isNumber(v goja.Value) bool { + k := v.ExportType().Kind() + return k >= reflect.Int && k <= reflect.Float64 +} + +func getObject(vm *goja.Runtime, name string) *goja.Object { + v := vm.Get(name) + if v == nil { + return nil } - panic(val) + return v.ToObject(vm) } diff --git a/console/console.go b/console/console.go index e9b2158a3..a7da0643b 100644 --- a/console/console.go +++ b/console/console.go @@ -29,11 +29,12 @@ import ( "syscall" "github.com/XinFinOrg/XDC-Subnet/internal/jsre" + "github.com/XinFinOrg/XDC-Subnet/internal/jsre/deps" "github.com/XinFinOrg/XDC-Subnet/internal/web3ext" "github.com/XinFinOrg/XDC-Subnet/rpc" + "github.com/dop251/goja" "github.com/mattn/go-colorable" "github.com/peterh/liner" - "github.com/robertkrimen/otto" ) var ( @@ -84,6 +85,7 @@ func New(config Config) (*Console, error) { if config.Printer == nil { config.Printer = colorable.NewColorableStdout() } + // Initialize the console and return console := &Console{ client: config.Client, @@ -105,120 +107,141 @@ func New(config Config) (*Console, error) { // init retrieves the available APIs from the remote RPC provider and initializes // the console's JavaScript namespaces based on the exposed modules. func (c *Console) init(preload []string) error { - // Initialize the JavaScript <-> Go RPC bridge + c.initConsoleObject() + + // Initialize the JavaScript <-> Go RPC bridge. bridge := newBridge(c.client, c.prompter, c.printer) - c.jsre.Set("jeth", struct{}{}) + if err := c.initWeb3(bridge); err != nil { + return err + } + if err := c.initExtensions(); err != nil { + return err + } + + // Add bridge overrides for web3.js functionality. + c.jsre.Do(func(vm *goja.Runtime) { + c.initAdmin(vm, bridge) + c.initPersonal(vm, bridge) + }) + + // Preload JavaScript files. + for _, path := range preload { + if err := c.jsre.Exec(path); err != nil { + failure := err.Error() + if gojaErr, ok := err.(*goja.Exception); ok { + failure = gojaErr.String() + } + return fmt.Errorf("%s: %v", path, failure) + } + } - jethObj, _ := c.jsre.Get("jeth") - jethObj.Object().Set("send", bridge.Send) - jethObj.Object().Set("sendAsync", bridge.Send) + // Configure the input prompter for history and tab completion. + if c.prompter != nil { + if content, err := ioutil.ReadFile(c.histPath); err != nil { + c.prompter.SetHistory(nil) + } else { + c.history = strings.Split(string(content), "\n") + c.prompter.SetHistory(c.history) + } + c.prompter.SetWordCompleter(c.AutoCompleteInput) + } + return nil +} - consoleObj, _ := c.jsre.Get("console") - consoleObj.Object().Set("log", c.consoleOutput) - consoleObj.Object().Set("error", c.consoleOutput) +func (c *Console) initConsoleObject() { + c.jsre.Do(func(vm *goja.Runtime) { + console := vm.NewObject() + console.Set("log", c.consoleOutput) + console.Set("error", c.consoleOutput) + vm.Set("console", console) + }) +} - // Load all the internal utility JavaScript libraries - if err := c.jsre.Compile("bignumber.js", jsre.BigNumber_JS); err != nil { +func (c *Console) initWeb3(bridge *bridge) error { + bnJS := string(deps.MustAsset("bignumber.js")) + web3JS := string(deps.MustAsset("web3.js")) + if err := c.jsre.Compile("bignumber.js", bnJS); err != nil { return fmt.Errorf("bignumber.js: %v", err) } - if err := c.jsre.Compile("web3.js", jsre.Web3_JS); err != nil { + if err := c.jsre.Compile("web3.js", web3JS); err != nil { return fmt.Errorf("web3.js: %v", err) } if _, err := c.jsre.Run("var Web3 = require('web3');"); err != nil { return fmt.Errorf("web3 require: %v", err) } - if _, err := c.jsre.Run("var web3 = new Web3(jeth);"); err != nil { - return fmt.Errorf("web3 provider: %v", err) - } - // Load the supported APIs into the JavaScript runtime environment + var err error + c.jsre.Do(func(vm *goja.Runtime) { + transport := vm.NewObject() + transport.Set("send", jsre.MakeCallback(vm, bridge.Send)) + transport.Set("sendAsync", jsre.MakeCallback(vm, bridge.Send)) + vm.Set("_consoleWeb3Transport", transport) + _, err = vm.RunString("var web3 = new Web3(_consoleWeb3Transport)") + }) + return err +} + +// initExtensions loads and registers web3.js extensions. +func (c *Console) initExtensions() error { + // Compute aliases from server-provided modules. apis, err := c.client.SupportedModules() if err != nil { return fmt.Errorf("api modules: %v", err) } - flatten := "var eth = web3.eth; var personal = web3.personal; " + aliases := map[string]struct{}{"eth": {}, "personal": {}} for api := range apis { if api == "web3" { - continue // manually mapped or ignore + continue } + aliases[api] = struct{}{} if file, ok := web3ext.Modules[api]; ok { - // Load our extension for the module. - if err = c.jsre.Compile(fmt.Sprintf("%s.js", api), file); err != nil { + if err = c.jsre.Compile(api+".js", file); err != nil { return fmt.Errorf("%s.js: %v", api, err) } - flatten += fmt.Sprintf("var %s = web3.%s; ", api, api) - } else if obj, err := c.jsre.Run("web3." + api); err == nil && obj.IsObject() { - // Enable web3.js built-in extension if available. - flatten += fmt.Sprintf("var %s = web3.%s; ", api, api) } } - if _, err = c.jsre.Run(flatten); err != nil { - return fmt.Errorf("namespace flattening: %v", err) - } - // Initialize the global name register (disabled for now) - //c.jsre.Run(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `); registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`) - // If the console is in interactive mode, instrument password related methods to query the user - if c.prompter != nil { - // Retrieve the account management object to instrument - personal, err := c.jsre.Get("personal") - if err != nil { - return err - } - // Override the openWallet, unlockAccount, newAccount and sign methods since - // these require user interaction. Assign these method in the Console the - // original web3 callbacks. These will be called by the jeth.* methods after - // they got the password from the user and send the original web3 request to - // the backend. - if obj := personal.Object(); obj != nil { // make sure the personal api is enabled over the interface - if _, err = c.jsre.Run(`jeth.openWallet = personal.openWallet;`); err != nil { - return fmt.Errorf("personal.openWallet: %v", err) - } - if _, err = c.jsre.Run(`jeth.unlockAccount = personal.unlockAccount;`); err != nil { - return fmt.Errorf("personal.unlockAccount: %v", err) - } - if _, err = c.jsre.Run(`jeth.newAccount = personal.newAccount;`); err != nil { - return fmt.Errorf("personal.newAccount: %v", err) - } - if _, err = c.jsre.Run(`jeth.sign = personal.sign;`); err != nil { - return fmt.Errorf("personal.sign: %v", err) - } - obj.Set("openWallet", bridge.OpenWallet) - obj.Set("unlockAccount", bridge.UnlockAccount) - obj.Set("newAccount", bridge.NewAccount) - obj.Set("sign", bridge.Sign) - } - } - // The admin.sleep and admin.sleepBlocks are offered by the console and not by the RPC layer. - admin, err := c.jsre.Get("admin") - if err != nil { - return err - } - if obj := admin.Object(); obj != nil { // make sure the admin api is enabled over the interface - obj.Set("sleepBlocks", bridge.SleepBlocks) - obj.Set("sleep", bridge.Sleep) - obj.Set("clearHistory", c.clearHistory) - } - // Preload any JavaScript files before starting the console - for _, path := range preload { - if err := c.jsre.Exec(path); err != nil { - failure := err.Error() - if ottoErr, ok := err.(*otto.Error); ok { - failure = ottoErr.String() + // Apply aliases. + c.jsre.Do(func(vm *goja.Runtime) { + web3 := getObject(vm, "web3") + for name := range aliases { + if v := web3.Get(name); v != nil { + vm.Set(name, v) } - return fmt.Errorf("%s: %v", path, failure) } + }) + return nil +} + +// initAdmin creates additional admin APIs implemented by the bridge. +func (c *Console) initAdmin(vm *goja.Runtime, bridge *bridge) { + if admin := getObject(vm, "admin"); admin != nil { + admin.Set("sleepBlocks", jsre.MakeCallback(vm, bridge.SleepBlocks)) + admin.Set("sleep", jsre.MakeCallback(vm, bridge.Sleep)) + admin.Set("clearHistory", c.clearHistory) } - // Configure the console's input prompter for scrollback and tab completion - if c.prompter != nil { - if content, err := ioutil.ReadFile(c.histPath); err != nil { - c.prompter.SetHistory(nil) - } else { - c.history = strings.Split(string(content), "\n") - c.prompter.SetHistory(c.history) - } - c.prompter.SetWordCompleter(c.AutoCompleteInput) +} + +// initPersonal redirects account-related API methods through the bridge. +// +// If the console is in interactive mode and the 'personal' API is available, override +// the openWallet, unlockAccount, newAccount and sign methods since these require user +// interaction. The original web3 callbacks are stored in 'jeth'. These will be called +// by the bridge after the prompt and send the original web3 request to the backend. +func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) { + personal := getObject(vm, "personal") + if personal == nil || c.prompter == nil { + return } - return nil + jeth := vm.NewObject() + vm.Set("jeth", jeth) + jeth.Set("openWallet", personal.Get("openWallet")) + jeth.Set("unlockAccount", personal.Get("unlockAccount")) + jeth.Set("newAccount", personal.Get("newAccount")) + jeth.Set("sign", personal.Get("sign")) + personal.Set("openWallet", jsre.MakeCallback(vm, bridge.OpenWallet)) + personal.Set("unlockAccount", jsre.MakeCallback(vm, bridge.UnlockAccount)) + personal.Set("newAccount", jsre.MakeCallback(vm, bridge.NewAccount)) + personal.Set("sign", jsre.MakeCallback(vm, bridge.Sign)) } func (c *Console) clearHistory() { @@ -233,13 +256,13 @@ func (c *Console) clearHistory() { // consoleOutput is an override for the console.log and console.error methods to // stream the output into the configured output stream instead of stdout. -func (c *Console) consoleOutput(call otto.FunctionCall) otto.Value { - output := []string{} - for _, argument := range call.ArgumentList { +func (c *Console) consoleOutput(call goja.FunctionCall) goja.Value { + var output []string + for _, argument := range call.Arguments { output = append(output, fmt.Sprintf("%v", argument)) } fmt.Fprintln(c.printer, strings.Join(output, " ")) - return otto.Value{} + return goja.Null() } // AutoCompleteInput is a pre-assembled word completer to be used by the user @@ -294,13 +317,13 @@ func (c *Console) Welcome() { // Evaluate executes code and pretty prints the result to the specified output // stream. -func (c *Console) Evaluate(statement string) error { +func (c *Console) Evaluate(statement string) { defer func() { if r := recover(); r != nil { fmt.Fprintf(c.printer, "[native] error: %v\n", r) } }() - return c.jsre.Evaluate(statement, c.printer) + c.jsre.Evaluate(statement, c.printer) } // Interactive starts an interactive user session, where input is propted from diff --git a/console/console_test.go b/console/console_test.go index b21b7848e..5c0c20503 100644 --- a/console/console_test.go +++ b/console/console_test.go @@ -262,7 +262,7 @@ func TestPrettyError(t *testing.T) { defer tester.Close(t) tester.console.Evaluate("throw 'hello'") - want := jsre.ErrorColor("hello") + "\n" + want := jsre.ErrorColor("hello") + "\n\tat :1:7(1)\n\n" if output := tester.output.String(); output != want { t.Fatalf("pretty error mismatch: have %s, want %s", output, want) } diff --git a/core/blockchain.go b/core/blockchain.go index bb11fed34..0931f9976 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -24,7 +24,6 @@ import ( "io" "math/big" "os" - "sort" "sync" "sync/atomic" "time" @@ -36,6 +35,7 @@ import ( "github.com/XinFinOrg/XDC-Subnet/common" "github.com/XinFinOrg/XDC-Subnet/common/mclock" + "github.com/XinFinOrg/XDC-Subnet/common/sort" "github.com/XinFinOrg/XDC-Subnet/consensus" "github.com/XinFinOrg/XDC-Subnet/consensus/XDPoS" "github.com/XinFinOrg/XDC-Subnet/consensus/XDPoS/utils" diff --git a/docker/Dockerfile b/docker/Dockerfile index 42e75b515..cc6551110 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,13 +1,14 @@ -FROM golang:1.14 as builder +FROM golang:1.21 as builder RUN apt-get update && apt-get install -y git build-essential COPY . /builder +RUN go env -w GOFLAGS="-buildvcs=false" RUN cd /builder && make XDC && make bootnode && make puppeth # The actual image for subnet containers -FROM golang:1.14 +FROM golang:1.21 RUN apt-get update && apt-get install -y git build-essential diff --git a/go.mod b/go.mod index 2e20b231f..12e0335e4 100644 --- a/go.mod +++ b/go.mod @@ -1,60 +1,80 @@ module github.com/XinFinOrg/XDC-Subnet -go 1.14 +go 1.21 require ( bazil.org/fuse v0.0.0-20180421153158-65cc252bf669 - github.com/VictoriaMetrics/fastcache v1.5.7 - github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb + github.com/VictoriaMetrics/fastcache v1.12.1 + github.com/aristanetworks/goarista v0.0.0-20231019142648-8c6f0862ab98 github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 github.com/cespare/cp v1.1.1 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf + github.com/dop251/goja v0.0.0-20200106141417-aaec0e7bde29 github.com/edsrzf/mmap-go v1.0.0 - github.com/elastic/gosigar v0.10.5 // indirect - github.com/ethereum/go-ethereum v1.9.9 - github.com/fatih/color v1.6.0 + github.com/ethereum/go-ethereum v1.9.11 + github.com/fatih/color v1.13.0 github.com/gizak/termui v2.2.0+incompatible github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 - github.com/go-stack/stack v1.8.0 - github.com/golang/protobuf v1.3.2 - github.com/golang/snappy v0.0.1 + github.com/go-stack/stack v1.8.1 + github.com/golang/protobuf v1.5.3 + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/gorilla/websocket v1.4.2 github.com/hashicorp/golang-lru v0.5.3 - github.com/huin/goupnp v1.0.0 + github.com/huin/goupnp v1.3.0 github.com/influxdata/influxdb v1.7.9 - github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 + github.com/jackpal/go-nat-pmp v1.0.2 github.com/julienschmidt/httprouter v1.3.0 github.com/karalabe/hid v1.0.0 - github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e // indirect - github.com/maruel/ut v1.0.2 // indirect - github.com/mattn/go-colorable v0.1.0 - github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect + github.com/mattn/go-colorable v0.1.13 github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 - github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77 // indirect - github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c - github.com/onsi/ginkgo v1.10.3 // indirect - github.com/onsi/gomega v1.7.1 // indirect + github.com/olekukonko/tablewriter v0.0.5 github.com/pborman/uuid v1.2.0 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 - github.com/pkg/errors v0.8.1 + github.com/pkg/errors v0.9.1 github.com/prometheus/prometheus v1.7.2-0.20170814170113-3101606756c5 github.com/rjeczalik/notify v0.9.2 - github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d - github.com/rs/cors v1.6.0 + github.com/rs/cors v1.7.0 github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 - github.com/stretchr/testify v1.7.0 - github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d - golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59 - golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 - golang.org/x/sync v0.0.0-20190423024810-112230192c58 - golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8 - golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9 - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 + github.com/stretchr/testify v1.8.4 + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + golang.org/x/crypto v0.15.0 + golang.org/x/net v0.17.0 + golang.org/x/sync v0.4.0 + golang.org/x/sys v0.14.0 + golang.org/x/tools v0.14.0 + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 gopkg.in/urfave/cli.v1 v1.20.0 - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dlclark/regexp2 v1.10.0 // indirect + github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa // indirect + github.com/go-ole/go-ole v1.2.5 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e // indirect + github.com/maruel/ut v1.0.2 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect + github.com/naoina/go-stringutil v0.1.0 // indirect + github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect + github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/term v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/go.sum b/go.sum index 58d2d89b6..0e4048ac1 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,5 @@ bazil.org/fuse v0.0.0-20180421153158-65cc252bf669 h1:FNCRpXiquG1aoyqcIWVFmpTSKVcx2bQD38uZZeGtdlw= bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 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= @@ -15,41 +14,36 @@ github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.5.3/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v49daAVERr0H3CuscE= -github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= -github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks= -github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= -github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb h1:gXDS2cX8AS8KbnP32J6XMSjzC1FhHEdHfUUCy018VrA= -github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns= -github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc= +github.com/aristanetworks/goarista v0.0.0-20231019142648-8c6f0862ab98 h1:7buXGE+m4OPjyo8rUJgA8RmARNMq+m99JJLR+Z+ZWN0= +github.com/aristanetworks/goarista v0.0.0-20231019142648-8c6f0862ab98/go.mod h1:DLTg9Gp4FAXF5EpqYBQnUeBbRsNLY7b2HR94TE5XQtE= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.0.1-0.20190104013014-3767db7a7e18/go.mod h1:HD5P3vAIAh+Y2GAxg0PrPN1P8WkepXGpjbUPDHJqqKM= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -58,26 +52,27 @@ github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsP github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= +github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf h1:sh8rkQZavChcmakYiSlqu2425CHyFXLZZnvm7PDpU8M= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/dop251/goja v0.0.0-20200106141417-aaec0e7bde29 h1:Ewd9K+mC725sITA12QQHRqWj78NU4t7EhlFVVgdlzJg= +github.com/dop251/goja v0.0.0-20200106141417-aaec0e7bde29/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa h1:XKAhUk/dtp+CV0VO6mhG2V7jA9vbcGcnYF/Ay9NjZrY= github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= -github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo= -github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= -github.com/ethereum/go-ethereum v1.9.9 h1:jnoBvjH8aMH++iH14XmiJdAsnRcmZUM+B5fsnEZBVE0= -github.com/ethereum/go-ethereum v1.9.9/go.mod h1:a9TqabFudpDu1nucId+k9S8R9whYaHnGBLKFouA5EAo= +github.com/ethereum/go-ethereum v1.9.11 h1:Z0jugPDfuI5qsPY1XgBGVwikpdFK/ANqP7MrYvkmk+A= +github.com/ethereum/go-ethereum v1.9.11/go.mod h1:7oC0Ni6dosMv5pxMigm6s0hN8g4haJMBnqmmo0D9YfQ= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.6.0 h1:66qjqZk8kalYAvDRtM1AdAJQI0tj4Wrue3Eq3B3pmFU= -github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gizak/termui v2.2.0+incompatible h1:qvZU9Xll/Xd/Xr/YO+HfBKXhy8a8/94ao6vV9DSXzUE= github.com/gizak/termui v2.2.0+incompatible/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA= @@ -85,151 +80,153 @@ github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7a github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2-0.20190517061210-b285ee9cfc6c/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= -github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb v1.7.9 h1:uSeBTNO4rBkbp1Be5FKRsAmglM9nlx25TzVQRQt1An4= github.com/influxdata/influxdb v1.7.9/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= -github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/karalabe/hid v1.0.0 h1:+/CIMNXhSU/zIJgnIvBD2nKHxS/bnRHhhs9xBryLpPo= github.com/karalabe/hid v1.0.0/go.mod h1:Vr51f8rUOLYrfrWDFlV12GGQgM5AT8sVh+2fY4MPeu8= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e h1:e2z/lz9pvtRrEOgKWaLW2Dw02Nqd3/fqv0qWTQ8ByZE= github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI= github.com/maruel/ut v1.0.2 h1:mQTlQk3jubTbdTcza+hwoZQWhzcvE4L6K6RTtAFlA1k= github.com/maruel/ut v1.0.2/go.mod h1:RV8PwPD9dd2KFlnlCc/DB2JVvkXmyaalfc5xvmSrRSs= -github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +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-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77 h1:gKl78uP/I7JZ56OFtRf7nc4m1icV38hwV0In5pEGzeA= github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc= -github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/prometheus v1.7.2-0.20170814170113-3101606756c5 h1:K2PKeDFZidfjUWpXk05Gbxhwm8Rnz1l4O+u/bbbcCvc= github.com/prometheus/prometheus v1.7.2-0.20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= -github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d h1:ouzpe+YhpIfnjR40gSkJHWsvXmB6TiPKqMtMpfyU9DE= -github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= -github.com/rs/cors v1.6.0/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= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.0.1-0.20190317074736-539464a789e9/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= @@ -238,92 +235,91 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8 github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= -github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= -github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= -github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= -github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= -github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59 h1:PyXRxSVbvzDGuqYXjHndV7xDzJ7w2K8KD9Ef8GB7KOE= -golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc= -golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8 h1:41hwlulw1prEMBxLQSlMSux1zxJf07B3WPsdjJlKZxE= -golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9 h1:m9xhlkk2j+sO9WjAgNfTtl505MN7ZkuW69nOcBlp9qY= -golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/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= -gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= -gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= -gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951 h1:DMTcQRFbEH62YPRWwOI647s2e5mHda3oBPMHfrLs2bw= gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951/go.mod h1:owOxCRGGeAx1uugABik6K9oeNu1cgxP/R9ItzLDxNWA= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 h1:hhsSf/5z74Ck/DJYc+R8zpq8KGm7uJvpdLRQED/IedA= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= -gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA= -gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -331,10 +327,11 @@ gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 72129befe..259bc39a8 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -22,7 +22,6 @@ import ( "errors" "fmt" "math/big" - "sort" "strings" "time" @@ -37,6 +36,7 @@ import ( "github.com/XinFinOrg/XDC-Subnet/common" "github.com/XinFinOrg/XDC-Subnet/common/hexutil" "github.com/XinFinOrg/XDC-Subnet/common/math" + "github.com/XinFinOrg/XDC-Subnet/common/sort" "github.com/XinFinOrg/XDC-Subnet/consensus/XDPoS" "github.com/XinFinOrg/XDC-Subnet/consensus/XDPoS/utils" "github.com/XinFinOrg/XDC-Subnet/consensus/ethash" diff --git a/internal/jsre/completion.go b/internal/jsre/completion.go index 7f484bbbb..2c105184c 100644 --- a/internal/jsre/completion.go +++ b/internal/jsre/completion.go @@ -20,35 +20,43 @@ import ( "sort" "strings" - "github.com/robertkrimen/otto" + "github.com/dop251/goja" ) // CompleteKeywords returns potential continuations for the given line. Since line is // evaluated, callers need to make sure that evaluating line does not have side effects. func (jsre *JSRE) CompleteKeywords(line string) []string { var results []string - jsre.Do(func(vm *otto.Otto) { + jsre.Do(func(vm *goja.Runtime) { results = getCompletions(vm, line) }) return results } -func getCompletions(vm *otto.Otto, line string) (results []string) { +func getCompletions(vm *goja.Runtime, line string) (results []string) { parts := strings.Split(line, ".") - objRef := "this" - prefix := line - if len(parts) > 1 { - objRef = strings.Join(parts[0:len(parts)-1], ".") - prefix = parts[len(parts)-1] + if len(parts) == 0 { + return nil } - obj, _ := vm.Object(objRef) - if obj == nil { - return nil + // Find the right-most fully named object in the line. e.g. if line = "x.y.z" + // and "x.y" is an object, obj will reference "x.y". + obj := vm.GlobalObject() + for i := 0; i < len(parts)-1; i++ { + v := obj.Get(parts[i]) + if v == nil { + return nil // No object was found + } + obj = v.ToObject(vm) } + + // Go over the keys of the object and retain the keys matching prefix. + // Example: if line = "x.y.z" and "x.y" exists and has keys "zebu", "zebra" + // and "platypus", then "x.y.zebu" and "x.y.zebra" will be added to results. + prefix := parts[len(parts)-1] iterOwnAndConstructorKeys(vm, obj, func(k string) { if strings.HasPrefix(k, prefix) { - if objRef == "this" { + if len(parts) == 1 { results = append(results, k) } else { results = append(results, strings.Join(parts[:len(parts)-1], ".")+"."+k) @@ -59,9 +67,9 @@ func getCompletions(vm *otto.Otto, line string) (results []string) { // Append opening parenthesis (for functions) or dot (for objects) // if the line itself is the only completion. if len(results) == 1 && results[0] == line { - obj, _ := vm.Object(line) + obj := obj.Get(parts[len(parts)-1]) if obj != nil { - if obj.Class() == "Function" { + if _, isfunc := goja.AssertFunction(obj); isfunc { results[0] += "(" } else { results[0] += "." diff --git a/internal/jsre/completion_test.go b/internal/jsre/completion_test.go index ccbd73dcc..2d05547d1 100644 --- a/internal/jsre/completion_test.go +++ b/internal/jsre/completion_test.go @@ -39,6 +39,10 @@ func TestCompleteKeywords(t *testing.T) { input string want []string }{ + { + input: "St", + want: []string{"String"}, + }, { input: "x", want: []string{"x."}, diff --git a/internal/jsre/jsre.go b/internal/jsre/jsre.go index 76652d4f9..5e8845006 100644 --- a/internal/jsre/jsre.go +++ b/internal/jsre/jsre.go @@ -28,7 +28,7 @@ import ( "github.com/XinFinOrg/XDC-Subnet/common" "github.com/XinFinOrg/XDC-Subnet/internal/jsre/deps" - "github.com/robertkrimen/otto" + "github.com/dop251/goja" ) var ( @@ -36,20 +36,26 @@ var ( Web3_JS = deps.MustAsset("web3.js") ) -/* -JSRE is a generic JS runtime environment embedding the otto JS interpreter. -It provides some helper functions to -- load code from files -- run code snippets -- require libraries -- bind native go objects -*/ +// JSRE is a JS runtime environment embedding the goja interpreter. +// It provides helper functions to load code from files, run code snippets +// and bind native go objects to JS. +// +// The runtime runs all code on a dedicated event loop and does not expose the underlying +// goja runtime directly. To use the runtime, call JSRE.Do. When binding a Go function, +// use the Call type to gain access to the runtime. type JSRE struct { assetPath string output io.Writer evalQueue chan *evalReq stopEventLoop chan bool closed chan struct{} + vm *goja.Runtime +} + +// Call is the argument type of Go functions which are callable from JS. +type Call struct { + goja.FunctionCall + VM *goja.Runtime } // jsTimer is a single timer instance with a callback function @@ -57,12 +63,12 @@ type jsTimer struct { timer *time.Timer duration time.Duration interval bool - call otto.FunctionCall + call goja.FunctionCall } // evalReq is a serialized vm execution request processed by runEventLoop. type evalReq struct { - fn func(vm *otto.Otto) + fn func(vm *goja.Runtime) done chan bool } @@ -74,9 +80,10 @@ func New(assetPath string, output io.Writer) *JSRE { closed: make(chan struct{}), evalQueue: make(chan *evalReq), stopEventLoop: make(chan bool), + vm: goja.New(), } go re.runEventLoop() - re.Set("loadScript", re.loadScript) + re.Set("loadScript", MakeCallback(re.vm, re.loadScript)) re.Set("inspect", re.prettyPrintJS) return re } @@ -99,21 +106,20 @@ func randomSource() *rand.Rand { // serialized way and calls timer callback functions at the appropriate time. // Exported functions always access the vm through the event queue. You can -// call the functions of the otto vm directly to circumvent the queue. These +// call the functions of the goja vm directly to circumvent the queue. These // functions should be used if and only if running a routine that was already // called from JS through an RPC call. -func (self *JSRE) runEventLoop() { - defer close(self.closed) +func (re *JSRE) runEventLoop() { + defer close(re.closed) - vm := otto.New() r := randomSource() - vm.SetRandomSource(r.Float64) + re.vm.SetRandSource(r.Float64) registry := map[*jsTimer]*jsTimer{} ready := make(chan *jsTimer) - newTimer := func(call otto.FunctionCall, interval bool) (*jsTimer, otto.Value) { - delay, _ := call.Argument(1).ToInteger() + newTimer := func(call goja.FunctionCall, interval bool) (*jsTimer, goja.Value) { + delay := call.Argument(1).ToInteger() if 0 >= delay { delay = 1 } @@ -128,47 +134,43 @@ func (self *JSRE) runEventLoop() { ready <- timer }) - value, err := call.Otto.ToValue(timer) - if err != nil { - panic(err) - } - return timer, value + return timer, re.vm.ToValue(timer) } - setTimeout := func(call otto.FunctionCall) otto.Value { + setTimeout := func(call goja.FunctionCall) goja.Value { _, value := newTimer(call, false) return value } - setInterval := func(call otto.FunctionCall) otto.Value { + setInterval := func(call goja.FunctionCall) goja.Value { _, value := newTimer(call, true) return value } - clearTimeout := func(call otto.FunctionCall) otto.Value { - timer, _ := call.Argument(0).Export() + clearTimeout := func(call goja.FunctionCall) goja.Value { + timer := call.Argument(0).Export() if timer, ok := timer.(*jsTimer); ok { timer.timer.Stop() delete(registry, timer) } - return otto.UndefinedValue() + return goja.Undefined() } - vm.Set("_setTimeout", setTimeout) - vm.Set("_setInterval", setInterval) - vm.Run(`var setTimeout = function(args) { + re.vm.Set("_setTimeout", setTimeout) + re.vm.Set("_setInterval", setInterval) + re.vm.RunString(`var setTimeout = function(args) { if (arguments.length < 1) { throw TypeError("Failed to execute 'setTimeout': 1 argument required, but only 0 present."); } return _setTimeout.apply(this, arguments); }`) - vm.Run(`var setInterval = function(args) { + re.vm.RunString(`var setInterval = function(args) { if (arguments.length < 1) { throw TypeError("Failed to execute 'setInterval': 1 argument required, but only 0 present."); } return _setInterval.apply(this, arguments); }`) - vm.Set("clearTimeout", clearTimeout) - vm.Set("clearInterval", clearTimeout) + re.vm.Set("clearTimeout", clearTimeout) + re.vm.Set("clearInterval", clearTimeout) var waitForCallbacks bool @@ -178,8 +180,8 @@ loop: case timer := <-ready: // execute callback, remove/reschedule the timer var arguments []interface{} - if len(timer.call.ArgumentList) > 2 { - tmp := timer.call.ArgumentList[2:] + if len(timer.call.Arguments) > 2 { + tmp := timer.call.Arguments[2:] arguments = make([]interface{}, 2+len(tmp)) for i, value := range tmp { arguments[i+2] = value @@ -187,11 +189,12 @@ loop: } else { arguments = make([]interface{}, 1) } - arguments[0] = timer.call.ArgumentList[0] - _, err := vm.Call(`Function.call.call`, nil, arguments...) - if err != nil { - fmt.Println("js error:", err, arguments) + arguments[0] = timer.call.Arguments[0] + call, isFunc := goja.AssertFunction(timer.call.Arguments[0]) + if !isFunc { + panic(re.vm.ToValue("js error: timer/timeout callback is not a function")) } + call(goja.Null(), timer.call.Arguments...) _, inreg := registry[timer] // when clearInterval is called from within the callback don't reset it if timer.interval && inreg { @@ -202,14 +205,14 @@ loop: break loop } } - case req := <-self.evalQueue: + case req := <-re.evalQueue: // run the code, send the result back - req.fn(vm) + req.fn(re.vm) close(req.done) if waitForCallbacks && (len(registry) == 0) { break loop } - case waitForCallbacks = <-self.stopEventLoop: + case waitForCallbacks = <-re.stopEventLoop: if !waitForCallbacks || (len(registry) == 0) { break loop } @@ -223,93 +226,59 @@ loop: } // Do executes the given function on the JS event loop. -func (self *JSRE) Do(fn func(*otto.Otto)) { +func (re *JSRE) Do(fn func(*goja.Runtime)) { done := make(chan bool) req := &evalReq{fn, done} - self.evalQueue <- req + re.evalQueue <- req <-done } // stops the event loop before exit, optionally waits for all timers to expire -func (self *JSRE) Stop(waitForCallbacks bool) { +func (re *JSRE) Stop(waitForCallbacks bool) { select { - case <-self.closed: - case self.stopEventLoop <- waitForCallbacks: - <-self.closed + case <-re.closed: + case re.stopEventLoop <- waitForCallbacks: + <-re.closed } } // Exec(file) loads and runs the contents of a file // if a relative path is given, the jsre's assetPath is used -func (self *JSRE) Exec(file string) error { - code, err := ioutil.ReadFile(common.AbsolutePath(self.assetPath, file)) +func (re *JSRE) Exec(file string) error { + code, err := ioutil.ReadFile(common.AbsolutePath(re.assetPath, file)) if err != nil { return err } - var script *otto.Script - self.Do(func(vm *otto.Otto) { - script, err = vm.Compile(file, code) - if err != nil { - return - } - _, err = vm.Run(script) - }) - return err -} - -// Bind assigns value v to a variable in the JS environment -// This method is deprecated, use Set. -func (self *JSRE) Bind(name string, v interface{}) error { - return self.Set(name, v) + return re.Compile(file, string(code)) } // Run runs a piece of JS code. -func (self *JSRE) Run(code string) (v otto.Value, err error) { - self.Do(func(vm *otto.Otto) { v, err = vm.Run(code) }) - return v, err -} - -// Get returns the value of a variable in the JS environment. -func (self *JSRE) Get(ns string) (v otto.Value, err error) { - self.Do(func(vm *otto.Otto) { v, err = vm.Get(ns) }) +func (re *JSRE) Run(code string) (v goja.Value, err error) { + re.Do(func(vm *goja.Runtime) { v, err = vm.RunString(code) }) return v, err } // Set assigns value v to a variable in the JS environment. -func (self *JSRE) Set(ns string, v interface{}) (err error) { - self.Do(func(vm *otto.Otto) { err = vm.Set(ns, v) }) +func (re *JSRE) Set(ns string, v interface{}) (err error) { + re.Do(func(vm *goja.Runtime) { vm.Set(ns, v) }) return err } -// loadScript executes a JS script from inside the currently executing JS code. -func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value { - file, err := call.Argument(0).ToString() - if err != nil { - // TODO: throw exception - return otto.FalseValue() - } - file = common.AbsolutePath(self.assetPath, file) - source, err := ioutil.ReadFile(file) - if err != nil { - // TODO: throw exception - return otto.FalseValue() - } - if _, err := compileAndRun(call.Otto, file, source); err != nil { - // TODO: throw exception - fmt.Println("err:", err) - return otto.FalseValue() - } - // TODO: return evaluation result - return otto.TrueValue() +// MakeCallback turns the given function into a function that's callable by JS. +func MakeCallback(vm *goja.Runtime, fn func(Call) (goja.Value, error)) goja.Value { + return vm.ToValue(func(call goja.FunctionCall) goja.Value { + result, err := fn(Call{call, vm}) + if err != nil { + panic(vm.NewGoError(err)) + } + return result + }) } -// Evaluate executes code and pretty prints the result to the specified output -// stream. -func (self *JSRE) Evaluate(code string, w io.Writer) error { - var fail error - - self.Do(func(vm *otto.Otto) { - val, err := vm.Run(code) +// Evaluate executes code and pretty prints the result to the specified output stream. +func (re *JSRE) Evaluate(code string, w io.Writer) { + re.Do(func(vm *goja.Runtime) { + val, err := vm.RunString(code) if err != nil { prettyError(vm, err, w) } else { @@ -317,19 +286,33 @@ func (self *JSRE) Evaluate(code string, w io.Writer) error { } fmt.Fprintln(w) }) - return fail } // Compile compiles and then runs a piece of JS code. -func (self *JSRE) Compile(filename string, src interface{}) (err error) { - self.Do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) }) +func (re *JSRE) Compile(filename string, src string) (err error) { + re.Do(func(vm *goja.Runtime) { _, err = compileAndRun(vm, filename, src) }) return err } -func compileAndRun(vm *otto.Otto, filename string, src interface{}) (otto.Value, error) { - script, err := vm.Compile(filename, src) +// loadScript loads and executes a JS file. +func (re *JSRE) loadScript(call Call) (goja.Value, error) { + file := call.Argument(0).ToString().String() + file = common.AbsolutePath(re.assetPath, file) + source, err := ioutil.ReadFile(file) + if err != nil { + return nil, fmt.Errorf("Could not read file %s: %v", file, err) + } + value, err := compileAndRun(re.vm, file, string(source)) + if err != nil { + return nil, fmt.Errorf("Error while compiling or running script: %v", err) + } + return value, nil +} + +func compileAndRun(vm *goja.Runtime, filename string, src string) (goja.Value, error) { + script, err := goja.Compile(filename, src, false) if err != nil { - return otto.Value{}, err + return goja.Null(), err } - return vm.Run(script) + return vm.RunProgram(script) } diff --git a/internal/jsre/jsre_test.go b/internal/jsre/jsre_test.go index bcb6e0dd2..bc38f7a44 100644 --- a/internal/jsre/jsre_test.go +++ b/internal/jsre/jsre_test.go @@ -20,25 +20,24 @@ import ( "io/ioutil" "os" "path" + "reflect" "testing" "time" - "github.com/robertkrimen/otto" + "github.com/dop251/goja" ) -type testNativeObjectBinding struct{} +type testNativeObjectBinding struct { + vm *goja.Runtime +} type msg struct { Msg string } -func (no *testNativeObjectBinding) TestMethod(call otto.FunctionCall) otto.Value { - m, err := call.Argument(0).ToString() - if err != nil { - return otto.UndefinedValue() - } - v, _ := call.Otto.ToValue(&msg{m}) - return v +func (no *testNativeObjectBinding) TestMethod(call goja.FunctionCall) goja.Value { + m := call.Argument(0).ToString().String() + return no.vm.ToValue(&msg{m}) } func newWithTestJS(t *testing.T, testjs string) (*JSRE, string) { @@ -51,7 +50,8 @@ func newWithTestJS(t *testing.T, testjs string) (*JSRE, string) { t.Fatal("cannot create test.js:", err) } } - return New(dir, os.Stdout), dir + jsre := New(dir, os.Stdout) + return jsre, dir } func TestExec(t *testing.T) { @@ -66,11 +66,11 @@ func TestExec(t *testing.T) { if err != nil { t.Errorf("expected no error, got %v", err) } - if !val.IsString() { + if val.ExportType().Kind() != reflect.String { t.Errorf("expected string value, got %v", val) } exp := "testMsg" - got, _ := val.ToString() + got := val.ToString().String() if exp != got { t.Errorf("expected '%v', got '%v'", exp, got) } @@ -90,11 +90,11 @@ func TestNatto(t *testing.T) { if err != nil { t.Errorf("expected no error, got %v", err) } - if !val.IsString() { + if val.ExportType().Kind() != reflect.String { t.Errorf("expected string value, got %v", val) } exp := "testMsg" - got, _ := val.ToString() + got := val.ToString().String() if exp != got { t.Errorf("expected '%v', got '%v'", exp, got) } @@ -105,7 +105,7 @@ func TestBind(t *testing.T) { jsre := New("", os.Stdout) defer jsre.Stop(false) - jsre.Bind("no", &testNativeObjectBinding{}) + jsre.Set("no", &testNativeObjectBinding{vm: jsre.vm}) _, err := jsre.Run(`no.TestMethod("testMsg")`) if err != nil { @@ -125,11 +125,11 @@ func TestLoadScript(t *testing.T) { if err != nil { t.Errorf("expected no error, got %v", err) } - if !val.IsString() { + if val.ExportType().Kind() != reflect.String { t.Errorf("expected string value, got %v", val) } exp := "testMsg" - got, _ := val.ToString() + got := val.ToString().String() if exp != got { t.Errorf("expected '%v', got '%v'", exp, got) } diff --git a/internal/jsre/pretty.go b/internal/jsre/pretty.go index 16fa91b67..4171e0090 100644 --- a/internal/jsre/pretty.go +++ b/internal/jsre/pretty.go @@ -19,12 +19,13 @@ package jsre import ( "fmt" "io" + "reflect" "sort" "strconv" "strings" + "github.com/dop251/goja" "github.com/fatih/color" - "github.com/robertkrimen/otto" ) const ( @@ -52,29 +53,29 @@ var boringKeys = map[string]bool{ } // prettyPrint writes value to standard output. -func prettyPrint(vm *otto.Otto, value otto.Value, w io.Writer) { +func prettyPrint(vm *goja.Runtime, value goja.Value, w io.Writer) { ppctx{vm: vm, w: w}.printValue(value, 0, false) } // prettyError writes err to standard output. -func prettyError(vm *otto.Otto, err error, w io.Writer) { +func prettyError(vm *goja.Runtime, err error, w io.Writer) { failure := err.Error() - if ottoErr, ok := err.(*otto.Error); ok { - failure = ottoErr.String() + if gojaErr, ok := err.(*goja.Exception); ok { + failure = gojaErr.String() } fmt.Fprint(w, ErrorColor("%s", failure)) } -func (re *JSRE) prettyPrintJS(call otto.FunctionCall) otto.Value { - for _, v := range call.ArgumentList { - prettyPrint(call.Otto, v, re.output) +func (re *JSRE) prettyPrintJS(call goja.FunctionCall) goja.Value { + for _, v := range call.Arguments { + prettyPrint(re.vm, v, re.output) fmt.Fprintln(re.output) } - return otto.UndefinedValue() + return goja.Undefined() } type ppctx struct { - vm *otto.Otto + vm *goja.Runtime w io.Writer } @@ -82,35 +83,47 @@ func (ctx ppctx) indent(level int) string { return strings.Repeat(indentString, level) } -func (ctx ppctx) printValue(v otto.Value, level int, inArray bool) { +func (ctx ppctx) printValue(v goja.Value, level int, inArray bool) { + if goja.IsNull(v) || goja.IsUndefined(v) { + fmt.Fprint(ctx.w, SpecialColor(v.String())) + return + } + kind := v.ExportType().Kind() switch { - case v.IsObject(): - ctx.printObject(v.Object(), level, inArray) - case v.IsNull(): - fmt.Fprint(ctx.w, SpecialColor("null")) - case v.IsUndefined(): - fmt.Fprint(ctx.w, SpecialColor("undefined")) - case v.IsString(): - s, _ := v.ToString() - fmt.Fprint(ctx.w, StringColor("%q", s)) - case v.IsBoolean(): - b, _ := v.ToBoolean() - fmt.Fprint(ctx.w, SpecialColor("%t", b)) - case v.IsNaN(): - fmt.Fprint(ctx.w, NumberColor("NaN")) - case v.IsNumber(): - s, _ := v.ToString() - fmt.Fprint(ctx.w, NumberColor("%s", s)) + case kind == reflect.Bool: + fmt.Fprint(ctx.w, SpecialColor("%t", v.ToBoolean())) + case kind == reflect.String: + fmt.Fprint(ctx.w, StringColor("%q", v.String())) + case kind >= reflect.Int && kind <= reflect.Complex128: + fmt.Fprint(ctx.w, NumberColor("%s", v.String())) default: - fmt.Fprint(ctx.w, "") + if obj, ok := v.(*goja.Object); ok { + ctx.printObject(obj, level, inArray) + } else { + fmt.Fprintf(ctx.w, "", v) + } } } -func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) { - switch obj.Class() { +// SafeGet attempt to get the value associated to `key`, and +// catches the panic that goja creates if an error occurs in +// key. +func SafeGet(obj *goja.Object, key string) (ret goja.Value) { + defer func() { + if r := recover(); r != nil { + ret = goja.Undefined() + } + }() + ret = obj.Get(key) + + return ret +} + +func (ctx ppctx) printObject(obj *goja.Object, level int, inArray bool) { + switch obj.ClassName() { case "Array", "GoArray": - lv, _ := obj.Get("length") - len, _ := lv.ToInteger() + lv := obj.Get("length") + len := lv.ToInteger() if len == 0 { fmt.Fprintf(ctx.w, "[]") return @@ -121,8 +134,8 @@ func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) { } fmt.Fprint(ctx.w, "[") for i := int64(0); i < len; i++ { - el, err := obj.Get(strconv.FormatInt(i, 10)) - if err == nil { + el := obj.Get(strconv.FormatInt(i, 10)) + if el != nil { ctx.printValue(el, level+1, true) } if i < len-1 { @@ -149,7 +162,7 @@ func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) { } fmt.Fprintln(ctx.w, "{") for i, k := range keys { - v, _ := obj.Get(k) + v := SafeGet(obj, k) fmt.Fprintf(ctx.w, "%s%s: ", ctx.indent(level+1), k) ctx.printValue(v, level+1, false) if i < len(keys)-1 { @@ -163,29 +176,25 @@ func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) { fmt.Fprintf(ctx.w, "%s}", ctx.indent(level)) case "Function": - // Use toString() to display the argument list if possible. - if robj, err := obj.Call("toString"); err != nil { - fmt.Fprint(ctx.w, FunctionColor("function()")) - } else { - desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n") - desc = strings.Replace(desc, " (", "(", 1) - fmt.Fprint(ctx.w, FunctionColor("%s", desc)) - } + robj := obj.ToString() + desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n") + desc = strings.Replace(desc, " (", "(", 1) + fmt.Fprint(ctx.w, FunctionColor("%s", desc)) case "RegExp": fmt.Fprint(ctx.w, StringColor("%s", toString(obj))) default: - if v, _ := obj.Get("toString"); v.IsFunction() && level <= maxPrettyPrintLevel { - s, _ := obj.Call("toString") - fmt.Fprintf(ctx.w, "<%s %s>", obj.Class(), s.String()) + if level <= maxPrettyPrintLevel { + s := obj.ToString().String() + fmt.Fprintf(ctx.w, "<%s %s>", obj.ClassName(), s) } else { - fmt.Fprintf(ctx.w, "<%s>", obj.Class()) + fmt.Fprintf(ctx.w, "<%s>", obj.ClassName()) } } } -func (ctx ppctx) fields(obj *otto.Object) []string { +func (ctx ppctx) fields(obj *goja.Object) []string { var ( vals, methods []string seen = make(map[string]bool) @@ -195,11 +204,22 @@ func (ctx ppctx) fields(obj *otto.Object) []string { return } seen[k] = true - if v, _ := obj.Get(k); v.IsFunction() { - methods = append(methods, k) - } else { + + key := SafeGet(obj, k) + if key == nil { + // The value corresponding to that key could not be found + // (typically because it is backed by an RPC call that is + // not supported by this instance. Add it to the list of + // values so that it appears as `undefined` to the user. vals = append(vals, k) + } else { + if _, callable := goja.AssertFunction(key); callable { + methods = append(methods, k) + } else { + vals = append(vals, k) + } } + } iterOwnAndConstructorKeys(ctx.vm, obj, add) sort.Strings(vals) @@ -207,13 +227,13 @@ func (ctx ppctx) fields(obj *otto.Object) []string { return append(vals, methods...) } -func iterOwnAndConstructorKeys(vm *otto.Otto, obj *otto.Object, f func(string)) { +func iterOwnAndConstructorKeys(vm *goja.Runtime, obj *goja.Object, f func(string)) { seen := make(map[string]bool) iterOwnKeys(vm, obj, func(prop string) { seen[prop] = true f(prop) }) - if cp := constructorPrototype(obj); cp != nil { + if cp := constructorPrototype(vm, obj); cp != nil { iterOwnKeys(vm, cp, func(prop string) { if !seen[prop] { f(prop) @@ -222,10 +242,17 @@ func iterOwnAndConstructorKeys(vm *otto.Otto, obj *otto.Object, f func(string)) } } -func iterOwnKeys(vm *otto.Otto, obj *otto.Object, f func(string)) { - Object, _ := vm.Object("Object") - rv, _ := Object.Call("getOwnPropertyNames", obj.Value()) - gv, _ := rv.Export() +func iterOwnKeys(vm *goja.Runtime, obj *goja.Object, f func(string)) { + Object := vm.Get("Object").ToObject(vm) + getOwnPropertyNames, isFunc := goja.AssertFunction(Object.Get("getOwnPropertyNames")) + if !isFunc { + panic(vm.ToValue("Object.getOwnPropertyNames isn't a function")) + } + rv, err := getOwnPropertyNames(goja.Null(), obj) + if err != nil { + panic(vm.ToValue(fmt.Sprintf("Error getting object properties: %v", err))) + } + gv := rv.Export() switch gv := gv.(type) { case []interface{}: for _, v := range gv { @@ -240,32 +267,35 @@ func iterOwnKeys(vm *otto.Otto, obj *otto.Object, f func(string)) { } } -func (ctx ppctx) isBigNumber(v *otto.Object) bool { +func (ctx ppctx) isBigNumber(v *goja.Object) bool { // Handle numbers with custom constructor. - if v, _ := v.Get("constructor"); v.Object() != nil { - if strings.HasPrefix(toString(v.Object()), "function BigNumber") { + if obj := v.Get("constructor").ToObject(ctx.vm); obj != nil { + if strings.HasPrefix(toString(obj), "function BigNumber") { return true } } // Handle default constructor. - BigNumber, _ := ctx.vm.Object("BigNumber.prototype") + BigNumber := ctx.vm.Get("BigNumber").ToObject(ctx.vm) if BigNumber == nil { return false } - bv, _ := BigNumber.Call("isPrototypeOf", v) - b, _ := bv.ToBoolean() - return b + prototype := BigNumber.Get("prototype").ToObject(ctx.vm) + isPrototypeOf, callable := goja.AssertFunction(prototype.Get("isPrototypeOf")) + if !callable { + return false + } + bv, _ := isPrototypeOf(prototype, v) + return bv.ToBoolean() } -func toString(obj *otto.Object) string { - s, _ := obj.Call("toString") - return s.String() +func toString(obj *goja.Object) string { + return obj.ToString().String() } -func constructorPrototype(obj *otto.Object) *otto.Object { - if v, _ := obj.Get("constructor"); v.Object() != nil { - if v, _ = v.Object().Get("prototype"); v.Object() != nil { - return v.Object() +func constructorPrototype(vm *goja.Runtime, obj *goja.Object) *goja.Object { + if v := obj.Get("constructor"); v != nil { + if v := v.ToObject(vm).Get("prototype"); v != nil { + return v.ToObject(vm) } } return nil