signer/rules: use goja and remove otto (#20599)

* signer: replace otto with goja

* go.mod: remove Otto
pull/20609/head
Guillaume Ballet 5 years ago committed by GitHub
parent a903912b96
commit 594e038e75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      go.mod
  2. 2
      go.sum
  3. 52
      signer/rules/rules.go
  4. 2
      signer/rules/rules_test.go

@ -49,7 +49,6 @@ require (
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150 github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150
github.com/rjeczalik/notify v0.9.1 github.com/rjeczalik/notify v0.9.1
github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4

@ -167,8 +167,6 @@ github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150 h1:ZeU+auZj1iNzN
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
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/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE=
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20=

@ -22,12 +22,12 @@ import (
"os" "os"
"strings" "strings"
"github.com/dop251/goja"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/rules/deps" "github.com/ethereum/go-ethereum/signer/rules/deps"
"github.com/ethereum/go-ethereum/signer/storage" "github.com/ethereum/go-ethereum/signer/storage"
"github.com/robertkrimen/otto"
) )
var ( var (
@ -36,13 +36,13 @@ var (
// consoleOutput is an override for the console.log and console.error methods to // consoleOutput is an override for the console.log and console.error methods to
// stream the output into the configured output stream instead of stdout. // stream the output into the configured output stream instead of stdout.
func consoleOutput(call otto.FunctionCall) otto.Value { func consoleOutput(call goja.FunctionCall) goja.Value {
output := []string{"JS:> "} output := []string{"JS:> "}
for _, argument := range call.ArgumentList { for _, argument := range call.Arguments {
output = append(output, fmt.Sprintf("%v", argument)) output = append(output, fmt.Sprintf("%v", argument))
} }
fmt.Fprintln(os.Stderr, strings.Join(output, " ")) fmt.Fprintln(os.Stderr, strings.Join(output, " "))
return otto.Value{} return goja.Undefined()
} }
// rulesetUI provides an implementation of UIClientAPI that evaluates a javascript // rulesetUI provides an implementation of UIClientAPI that evaluates a javascript
@ -70,45 +70,47 @@ func (r *rulesetUI) Init(javascriptRules string) error {
r.jsRules = javascriptRules r.jsRules = javascriptRules
return nil return nil
} }
func (r *rulesetUI) execute(jsfunc string, jsarg interface{}) (otto.Value, error) { func (r *rulesetUI) execute(jsfunc string, jsarg interface{}) (goja.Value, error) {
// Instantiate a fresh vm engine every time // Instantiate a fresh vm engine every time
vm := otto.New() vm := goja.New()
// Set the native callbacks // Set the native callbacks
consoleObj, _ := vm.Get("console") consoleObj := vm.NewObject()
consoleObj.Object().Set("log", consoleOutput) consoleObj.Set("log", consoleOutput)
consoleObj.Object().Set("error", consoleOutput) consoleObj.Set("error", consoleOutput)
vm.Set("console", consoleObj)
vm.Set("storage", struct{}{}) storageObj := vm.NewObject()
storageObj, _ := vm.Get("storage") storageObj.Set("put", func(call goja.FunctionCall) goja.Value {
storageObj.Object().Set("put", func(call otto.FunctionCall) otto.Value {
key, val := call.Argument(0).String(), call.Argument(1).String() key, val := call.Argument(0).String(), call.Argument(1).String()
if val == "" { if val == "" {
r.storage.Del(key) r.storage.Del(key)
} else { } else {
r.storage.Put(key, val) r.storage.Put(key, val)
} }
return otto.NullValue() return goja.Null()
}) })
storageObj.Object().Set("get", func(call otto.FunctionCall) otto.Value { storageObj.Set("get", func(call goja.FunctionCall) goja.Value {
goval, _ := r.storage.Get(call.Argument(0).String()) goval, _ := r.storage.Get(call.Argument(0).String())
jsval, _ := otto.ToValue(goval) jsval := vm.ToValue(goval)
return jsval return jsval
}) })
vm.Set("storage", storageObj)
// Load bootstrap libraries // Load bootstrap libraries
script, err := vm.Compile("bignumber.js", BigNumber_JS) script, err := goja.Compile("bignumber.js", string(BigNumber_JS), true)
if err != nil { if err != nil {
log.Warn("Failed loading libraries", "err", err) log.Warn("Failed loading libraries", "err", err)
return otto.UndefinedValue(), err return goja.Undefined(), err
} }
vm.Run(script) vm.RunProgram(script)
// Run the actual rule implementation // Run the actual rule implementation
_, err = vm.Run(r.jsRules) _, err = vm.RunString(r.jsRules)
if err != nil { if err != nil {
log.Warn("Execution failed", "err", err) log.Warn("Execution failed", "err", err)
return otto.UndefinedValue(), err return goja.Undefined(), err
} }
// And the actual call // And the actual call
@ -119,7 +121,7 @@ func (r *rulesetUI) execute(jsfunc string, jsarg interface{}) (otto.Value, error
jsonbytes, err := json.Marshal(jsarg) jsonbytes, err := json.Marshal(jsarg)
if err != nil { if err != nil {
log.Warn("failed marshalling data", "data", jsarg) log.Warn("failed marshalling data", "data", jsarg)
return otto.UndefinedValue(), err return goja.Undefined(), err
} }
// Now, we call foobar(JSON.parse(<jsondata>)). // Now, we call foobar(JSON.parse(<jsondata>)).
var call string var call string
@ -128,7 +130,7 @@ func (r *rulesetUI) execute(jsfunc string, jsarg interface{}) (otto.Value, error
} else { } else {
call = fmt.Sprintf("%v()", jsfunc) call = fmt.Sprintf("%v()", jsfunc)
} }
return vm.Run(call) return vm.RunString(call)
} }
func (r *rulesetUI) checkApproval(jsfunc string, jsarg []byte, err error) (bool, error) { func (r *rulesetUI) checkApproval(jsfunc string, jsarg []byte, err error) (bool, error) {
@ -140,11 +142,7 @@ func (r *rulesetUI) checkApproval(jsfunc string, jsarg []byte, err error) (bool,
log.Info("error occurred during execution", "error", err) log.Info("error occurred during execution", "error", err)
return false, err return false, err
} }
result, err := v.ToString() result := v.ToString().String()
if err != nil {
log.Info("error occurred during response unmarshalling", "error", err)
return false, err
}
if result == "Approve" { if result == "Approve" {
log.Info("Op approved") log.Info("Op approved")
return true, nil return true, nil

@ -337,7 +337,7 @@ func TestStorage(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Unexpected error %v", err) t.Errorf("Unexpected error %v", err)
} }
retval, err := v.ToString() retval := v.ToString().String()
if err != nil { if err != nil {
t.Errorf("Unexpected error %v", err) t.Errorf("Unexpected error %v", err)

Loading…
Cancel
Save