diff --git a/geth/api/api.go b/geth/api/api.go index cda6a8e97..30ae24dce 100644 --- a/geth/api/api.go +++ b/geth/api/api.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/status-im/status-go/geth/common" + "github.com/status-im/status-go/geth/jail" "github.com/status-im/status-go/geth/log" "github.com/status-im/status-go/geth/params" "github.com/status-im/status-go/geth/transactions" @@ -41,7 +42,7 @@ func (api *StatusAPI) AccountManager() common.AccountManager { } // JailManager returns reference to jail -func (api *StatusAPI) JailManager() common.JailManager { +func (api *StatusAPI) JailManager() jail.Manager { return api.b.JailManager() } diff --git a/geth/api/backend.go b/geth/api/backend.go index de8882c08..5d8b447ea 100644 --- a/geth/api/backend.go +++ b/geth/api/backend.go @@ -28,7 +28,7 @@ type StatusBackend struct { nodeManager *node.NodeManager accountManager common.AccountManager txQueueManager *transactions.Manager - jailManager common.JailManager + jailManager jail.Manager newNotification common.NotificationConstructor connectionState ConnectionState } @@ -63,7 +63,7 @@ func (b *StatusBackend) AccountManager() common.AccountManager { } // JailManager returns reference to jail -func (b *StatusBackend) JailManager() common.JailManager { +func (b *StatusBackend) JailManager() jail.Manager { return b.jailManager } diff --git a/geth/common/types.go b/geth/common/types.go index cb14226aa..783537055 100644 --- a/geth/common/types.go +++ b/geth/common/types.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/node" whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" - "github.com/robertkrimen/otto" "github.com/status-im/status-go/geth/params" "github.com/status-im/status-go/geth/rpc" "github.com/status-im/status-go/static" @@ -172,53 +171,6 @@ type SendTxArgs struct { Input hexutil.Bytes `json:"input"` } -// JailCell represents single jail cell, which is basically a JavaScript VM. -// It's designed to be a transparent wrapper around otto.VM's methods. -type JailCell interface { - // Set a value inside VM. - Set(string, interface{}) error - // Get a value from VM. - Get(string) (otto.Value, error) - // GetObjectValue returns the given name's otto.Value from the given otto.Value v. Should only be needed in tests. - GetObjectValue(otto.Value, string) (otto.Value, error) - // Run an arbitrary JS code. Input maybe string or otto.Script. - Run(interface{}) (otto.Value, error) - // Call an arbitrary JS function by name and args. - Call(item string, this interface{}, args ...interface{}) (otto.Value, error) - // Stop stops background execution of cell. - Stop() error -} - -// JailManager defines methods for managing jailed environments -type JailManager interface { - // Call executes given JavaScript function w/i a jail cell context identified by the chatID. - Call(chatID, this, args string) string - - // CreateCell creates a new jail cell. - CreateCell(chatID string) (JailCell, error) - - // Parse creates a new jail cell context, with the given chatID as identifier. - // New context executes provided JavaScript code, right after the initialization. - // DEPRECATED in favour of CreateAndInitCell. - Parse(chatID, js string) string - - // CreateAndInitCell creates a new jail cell and initialize it - // with web3 and other handlers. - CreateAndInitCell(chatID string, code ...string) string - - // Cell returns an existing instance of JailCell. - Cell(chatID string) (JailCell, error) - - // Execute allows to run arbitrary JS code within a cell. - Execute(chatID, code string) string - - // SetBaseJS allows to setup initial JavaScript to be loaded on each jail.CreateAndInitCell(). - SetBaseJS(js string) - - // Stop stops all background activity of jail - Stop() -} - // APIResponse generic response from API type APIResponse struct { Error string `json:"error"` diff --git a/geth/common/types_mock.go b/geth/common/types_mock.go index 394cdb846..853eb9070 100644 --- a/geth/common/types_mock.go +++ b/geth/common/types_mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: geth/common/types.go +// Source: types.go // Package common is a generated GoMock package. package common @@ -13,7 +13,6 @@ import ( node "github.com/ethereum/go-ethereum/node" whisperv5 "github.com/ethereum/go-ethereum/whisper/whisperv5" gomock "github.com/golang/mock/gomock" - otto "github.com/robertkrimen/otto" params "github.com/status-im/status-go/geth/params" rpc "github.com/status-im/status-go/geth/rpc" reflect "reflect" @@ -382,229 +381,3 @@ func (m *MockAccountManager) AddressToDecryptedAccount(address, password string) func (mr *MockAccountManagerMockRecorder) AddressToDecryptedAccount(address, password interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressToDecryptedAccount", reflect.TypeOf((*MockAccountManager)(nil).AddressToDecryptedAccount), address, password) } - -// MockJailCell is a mock of JailCell interface -type MockJailCell struct { - ctrl *gomock.Controller - recorder *MockJailCellMockRecorder -} - -// MockJailCellMockRecorder is the mock recorder for MockJailCell -type MockJailCellMockRecorder struct { - mock *MockJailCell -} - -// NewMockJailCell creates a new mock instance -func NewMockJailCell(ctrl *gomock.Controller) *MockJailCell { - mock := &MockJailCell{ctrl: ctrl} - mock.recorder = &MockJailCellMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockJailCell) EXPECT() *MockJailCellMockRecorder { - return m.recorder -} - -// Set mocks base method -func (m *MockJailCell) Set(arg0 string, arg1 interface{}) error { - ret := m.ctrl.Call(m, "Set", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// Set indicates an expected call of Set -func (mr *MockJailCellMockRecorder) Set(arg0, arg1 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockJailCell)(nil).Set), arg0, arg1) -} - -// Get mocks base method -func (m *MockJailCell) Get(arg0 string) (otto.Value, error) { - ret := m.ctrl.Call(m, "Get", arg0) - ret0, _ := ret[0].(otto.Value) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get -func (mr *MockJailCellMockRecorder) Get(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockJailCell)(nil).Get), arg0) -} - -// GetObjectValue mocks base method -func (m *MockJailCell) GetObjectValue(arg0 otto.Value, arg1 string) (otto.Value, error) { - ret := m.ctrl.Call(m, "GetObjectValue", arg0, arg1) - ret0, _ := ret[0].(otto.Value) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetObjectValue indicates an expected call of GetObjectValue -func (mr *MockJailCellMockRecorder) GetObjectValue(arg0, arg1 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetObjectValue", reflect.TypeOf((*MockJailCell)(nil).GetObjectValue), arg0, arg1) -} - -// Run mocks base method -func (m *MockJailCell) Run(arg0 interface{}) (otto.Value, error) { - ret := m.ctrl.Call(m, "Run", arg0) - ret0, _ := ret[0].(otto.Value) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Run indicates an expected call of Run -func (mr *MockJailCellMockRecorder) Run(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockJailCell)(nil).Run), arg0) -} - -// Call mocks base method -func (m *MockJailCell) Call(item string, this interface{}, args ...interface{}) (otto.Value, error) { - varargs := []interface{}{item, this} - for _, a := range args { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Call", varargs...) - ret0, _ := ret[0].(otto.Value) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Call indicates an expected call of Call -func (mr *MockJailCellMockRecorder) Call(item, this interface{}, args ...interface{}) *gomock.Call { - varargs := append([]interface{}{item, this}, args...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockJailCell)(nil).Call), varargs...) -} - -// Stop mocks base method -func (m *MockJailCell) Stop() error { - ret := m.ctrl.Call(m, "Stop") - ret0, _ := ret[0].(error) - return ret0 -} - -// Stop indicates an expected call of Stop -func (mr *MockJailCellMockRecorder) Stop() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockJailCell)(nil).Stop)) -} - -// MockJailManager is a mock of JailManager interface -type MockJailManager struct { - ctrl *gomock.Controller - recorder *MockJailManagerMockRecorder -} - -// MockJailManagerMockRecorder is the mock recorder for MockJailManager -type MockJailManagerMockRecorder struct { - mock *MockJailManager -} - -// NewMockJailManager creates a new mock instance -func NewMockJailManager(ctrl *gomock.Controller) *MockJailManager { - mock := &MockJailManager{ctrl: ctrl} - mock.recorder = &MockJailManagerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockJailManager) EXPECT() *MockJailManagerMockRecorder { - return m.recorder -} - -// Call mocks base method -func (m *MockJailManager) Call(chatID, this, args string) string { - ret := m.ctrl.Call(m, "Call", chatID, this, args) - ret0, _ := ret[0].(string) - return ret0 -} - -// Call indicates an expected call of Call -func (mr *MockJailManagerMockRecorder) Call(chatID, this, args interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockJailManager)(nil).Call), chatID, this, args) -} - -// CreateCell mocks base method -func (m *MockJailManager) CreateCell(chatID string) (JailCell, error) { - ret := m.ctrl.Call(m, "CreateCell", chatID) - ret0, _ := ret[0].(JailCell) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateCell indicates an expected call of CreateCell -func (mr *MockJailManagerMockRecorder) CreateCell(chatID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCell", reflect.TypeOf((*MockJailManager)(nil).CreateCell), chatID) -} - -// Parse mocks base method -func (m *MockJailManager) Parse(chatID, js string) string { - ret := m.ctrl.Call(m, "Parse", chatID, js) - ret0, _ := ret[0].(string) - return ret0 -} - -// Parse indicates an expected call of Parse -func (mr *MockJailManagerMockRecorder) Parse(chatID, js interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Parse", reflect.TypeOf((*MockJailManager)(nil).Parse), chatID, js) -} - -// CreateAndInitCell mocks base method -func (m *MockJailManager) CreateAndInitCell(chatID string, code ...string) string { - varargs := []interface{}{chatID} - for _, a := range code { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "CreateAndInitCell", varargs...) - ret0, _ := ret[0].(string) - return ret0 -} - -// CreateAndInitCell indicates an expected call of CreateAndInitCell -func (mr *MockJailManagerMockRecorder) CreateAndInitCell(chatID interface{}, code ...interface{}) *gomock.Call { - varargs := append([]interface{}{chatID}, code...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAndInitCell", reflect.TypeOf((*MockJailManager)(nil).CreateAndInitCell), varargs...) -} - -// Cell mocks base method -func (m *MockJailManager) Cell(chatID string) (JailCell, error) { - ret := m.ctrl.Call(m, "Cell", chatID) - ret0, _ := ret[0].(JailCell) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Cell indicates an expected call of Cell -func (mr *MockJailManagerMockRecorder) Cell(chatID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Cell", reflect.TypeOf((*MockJailManager)(nil).Cell), chatID) -} - -// Execute mocks base method -func (m *MockJailManager) Execute(chatID, code string) string { - ret := m.ctrl.Call(m, "Execute", chatID, code) - ret0, _ := ret[0].(string) - return ret0 -} - -// Execute indicates an expected call of Execute -func (mr *MockJailManagerMockRecorder) Execute(chatID, code interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Execute", reflect.TypeOf((*MockJailManager)(nil).Execute), chatID, code) -} - -// SetBaseJS mocks base method -func (m *MockJailManager) SetBaseJS(js string) { - m.ctrl.Call(m, "SetBaseJS", js) -} - -// SetBaseJS indicates an expected call of SetBaseJS -func (mr *MockJailManagerMockRecorder) SetBaseJS(js interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBaseJS", reflect.TypeOf((*MockJailManager)(nil).SetBaseJS), js) -} - -// Stop mocks base method -func (m *MockJailManager) Stop() { - m.ctrl.Call(m, "Stop") -} - -// Stop indicates an expected call of Stop -func (mr *MockJailManagerMockRecorder) Stop() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockJailManager)(nil).Stop)) -} diff --git a/geth/jail/cell.go b/geth/jail/cell.go index 82a040e95..608ed2ea6 100644 --- a/geth/jail/cell.go +++ b/geth/jail/cell.go @@ -15,9 +15,64 @@ import ( const timeout = 5 * time.Second +// Manager defines methods for managing jailed environments +type Manager interface { + // Call executes given JavaScript function w/i a jail cell context identified by the chatID. + Call(chatID, this, args string) string + + // CreateCell creates a new jail cell. + CreateCell(chatID string) (JSCell, error) + + // Parse creates a new jail cell context, with the given chatID as identifier. + // New context executes provided JavaScript code, right after the initialization. + // DEPRECATED in favour of CreateAndInitCell. + Parse(chatID, js string) string + + // CreateAndInitCell creates a new jail cell and initialize it + // with web3 and other handlers. + CreateAndInitCell(chatID string, code ...string) string + + // Cell returns an existing instance of JSCell. + Cell(chatID string) (JSCell, error) + + // Execute allows to run arbitrary JS code within a cell. + Execute(chatID, code string) string + + // SetBaseJS allows to setup initial JavaScript to be loaded on each jail.CreateAndInitCell(). + SetBaseJS(js string) + + // Stop stops all background activity of jail + Stop() +} + +// JSValue is a wrapper around an otto.Value. +type JSValue struct { + value otto.Value +} + +// Value returns the underlying otto.Value from a JSValue. This value IS NOT THREADSAFE. +func (v *JSValue) Value() otto.Value { + return v.value +} + +// JSCell represents single jail cell, which is basically a JavaScript VM. +// It's designed to be a transparent wrapper around otto.VM's methods. +type JSCell interface { + // Set a value inside VM. + Set(string, interface{}) error + // Get a value from VM. + Get(string) (JSValue, error) + // Run an arbitrary JS code. Input maybe string or otto.Script. + Run(interface{}) (JSValue, error) + // Call an arbitrary JS function by name and args. + Call(item string, this interface{}, args ...interface{}) (JSValue, error) + // Stop stops background execution of cell. + Stop() error +} + // Cell represents a single jail cell, which is basically a JavaScript VM. type Cell struct { - *vm.VM + jsvm *vm.VM id string cancel context.CancelFunc @@ -40,7 +95,7 @@ func NewCell(id string) (*Cell, error) { ctx, cancel := context.WithCancel(context.Background()) loopStopped := make(chan struct{}) cell := Cell{ - VM: vm, + jsvm: vm, id: id, cancel: cancel, loop: lo, @@ -110,4 +165,54 @@ func (c *Cell) CallAsync(fn otto.Value, args ...interface{}) error { case <-timer.C: return errors.New("Timeout") } + +} + +// Set calls Set on the underlying JavaScript VM. +func (c *Cell) Set(key string, val interface{}) error { + return c.jsvm.Set(key, val) +} + +// Get calls Get on the underlying JavaScript VM and returns +// a wrapper around the otto.Value. +func (c *Cell) Get(key string) (JSValue, error) { + v, err := c.jsvm.Get(key) + if err != nil { + return JSValue{}, err + } + JSValue := JSValue{value: v} + return JSValue, nil +} + +// GetObjectValue calls GetObjectValue on the underlying JavaScript VM and returns +// a wrapper around the otto.Value. +func (c *Cell) GetObjectValue(v otto.Value, name string) (JSValue, error) { + v, err := c.jsvm.GetObjectValue(v, name) + if err != nil { + return JSValue{}, err + } + JSValue := JSValue{value: v} + return JSValue, nil +} + +// Run calls Run on the underlying JavaScript VM and returns +// a wrapper around the otto.Value. +func (c *Cell) Run(src interface{}) (JSValue, error) { + v, err := c.jsvm.Run(src) + if err != nil { + return JSValue{}, err + } + JSValue := JSValue{value: v} + return JSValue, nil +} + +// Call calls Call on the underlying JavaScript VM and returns +// a wrapper around the otto.Value. +func (c *Cell) Call(item string, this interface{}, args ...interface{}) (JSValue, error) { + v, err := c.jsvm.Call(item, this, args...) + if err != nil { + return JSValue{}, err + } + JSValue := JSValue{value: v} + return JSValue, nil } diff --git a/geth/jail/cell_mock.go b/geth/jail/cell_mock.go new file mode 100644 index 000000000..691d6e9fa --- /dev/null +++ b/geth/jail/cell_mock.go @@ -0,0 +1,223 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: cell.go + +// Package jail is a generated GoMock package. +package jail + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockManager is a mock of Manager interface +type MockManager struct { + ctrl *gomock.Controller + recorder *MockManagerMockRecorder +} + +// MockManagerMockRecorder is the mock recorder for MockManager +type MockManagerMockRecorder struct { + mock *MockManager +} + +// NewMockManager creates a new mock instance +func NewMockManager(ctrl *gomock.Controller) *MockManager { + mock := &MockManager{ctrl: ctrl} + mock.recorder = &MockManagerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockManager) EXPECT() *MockManagerMockRecorder { + return m.recorder +} + +// Call mocks base method +func (m *MockManager) Call(chatID, this, args string) string { + ret := m.ctrl.Call(m, "Call", chatID, this, args) + ret0, _ := ret[0].(string) + return ret0 +} + +// Call indicates an expected call of Call +func (mr *MockManagerMockRecorder) Call(chatID, this, args interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockManager)(nil).Call), chatID, this, args) +} + +// CreateCell mocks base method +func (m *MockManager) CreateCell(chatID string) (JSCell, error) { + ret := m.ctrl.Call(m, "CreateCell", chatID) + ret0, _ := ret[0].(JSCell) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateCell indicates an expected call of CreateCell +func (mr *MockManagerMockRecorder) CreateCell(chatID interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCell", reflect.TypeOf((*MockManager)(nil).CreateCell), chatID) +} + +// Parse mocks base method +func (m *MockManager) Parse(chatID, js string) string { + ret := m.ctrl.Call(m, "Parse", chatID, js) + ret0, _ := ret[0].(string) + return ret0 +} + +// Parse indicates an expected call of Parse +func (mr *MockManagerMockRecorder) Parse(chatID, js interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Parse", reflect.TypeOf((*MockManager)(nil).Parse), chatID, js) +} + +// CreateAndInitCell mocks base method +func (m *MockManager) CreateAndInitCell(chatID string, code ...string) string { + varargs := []interface{}{chatID} + for _, a := range code { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateAndInitCell", varargs...) + ret0, _ := ret[0].(string) + return ret0 +} + +// CreateAndInitCell indicates an expected call of CreateAndInitCell +func (mr *MockManagerMockRecorder) CreateAndInitCell(chatID interface{}, code ...interface{}) *gomock.Call { + varargs := append([]interface{}{chatID}, code...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAndInitCell", reflect.TypeOf((*MockManager)(nil).CreateAndInitCell), varargs...) +} + +// Cell mocks base method +func (m *MockManager) Cell(chatID string) (JSCell, error) { + ret := m.ctrl.Call(m, "Cell", chatID) + ret0, _ := ret[0].(JSCell) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Cell indicates an expected call of Cell +func (mr *MockManagerMockRecorder) Cell(chatID interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Cell", reflect.TypeOf((*MockManager)(nil).Cell), chatID) +} + +// Execute mocks base method +func (m *MockManager) Execute(chatID, code string) string { + ret := m.ctrl.Call(m, "Execute", chatID, code) + ret0, _ := ret[0].(string) + return ret0 +} + +// Execute indicates an expected call of Execute +func (mr *MockManagerMockRecorder) Execute(chatID, code interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Execute", reflect.TypeOf((*MockManager)(nil).Execute), chatID, code) +} + +// SetBaseJS mocks base method +func (m *MockManager) SetBaseJS(js string) { + m.ctrl.Call(m, "SetBaseJS", js) +} + +// SetBaseJS indicates an expected call of SetBaseJS +func (mr *MockManagerMockRecorder) SetBaseJS(js interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBaseJS", reflect.TypeOf((*MockManager)(nil).SetBaseJS), js) +} + +// Stop mocks base method +func (m *MockManager) Stop() { + m.ctrl.Call(m, "Stop") +} + +// Stop indicates an expected call of Stop +func (mr *MockManagerMockRecorder) Stop() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockManager)(nil).Stop)) +} + +// MockJSCell is a mock of JSCell interface +type MockJSCell struct { + ctrl *gomock.Controller + recorder *MockJSCellMockRecorder +} + +// MockJSCellMockRecorder is the mock recorder for MockJSCell +type MockJSCellMockRecorder struct { + mock *MockJSCell +} + +// NewMockJSCell creates a new mock instance +func NewMockJSCell(ctrl *gomock.Controller) *MockJSCell { + mock := &MockJSCell{ctrl: ctrl} + mock.recorder = &MockJSCellMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockJSCell) EXPECT() *MockJSCellMockRecorder { + return m.recorder +} + +// Set mocks base method +func (m *MockJSCell) Set(arg0 string, arg1 interface{}) error { + ret := m.ctrl.Call(m, "Set", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Set indicates an expected call of Set +func (mr *MockJSCellMockRecorder) Set(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockJSCell)(nil).Set), arg0, arg1) +} + +// Get mocks base method +func (m *MockJSCell) Get(arg0 string) (JSValue, error) { + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(JSValue) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get +func (mr *MockJSCellMockRecorder) Get(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockJSCell)(nil).Get), arg0) +} + +// Run mocks base method +func (m *MockJSCell) Run(arg0 interface{}) (JSValue, error) { + ret := m.ctrl.Call(m, "Run", arg0) + ret0, _ := ret[0].(JSValue) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Run indicates an expected call of Run +func (mr *MockJSCellMockRecorder) Run(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockJSCell)(nil).Run), arg0) +} + +// Call mocks base method +func (m *MockJSCell) Call(item string, this interface{}, args ...interface{}) (JSValue, error) { + varargs := []interface{}{item, this} + for _, a := range args { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Call", varargs...) + ret0, _ := ret[0].(JSValue) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Call indicates an expected call of Call +func (mr *MockJSCellMockRecorder) Call(item, this interface{}, args ...interface{}) *gomock.Call { + varargs := append([]interface{}{item, this}, args...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockJSCell)(nil).Call), varargs...) +} + +// Stop mocks base method +func (m *MockJSCell) Stop() error { + ret := m.ctrl.Call(m, "Stop") + ret0, _ := ret[0].(error) + return ret0 +} + +// Stop indicates an expected call of Stop +func (mr *MockJSCellMockRecorder) Stop() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockJSCell)(nil).Stop)) +} diff --git a/geth/jail/cell_test.go b/geth/jail/cell_test.go index 34f81f559..c20be40cb 100644 --- a/geth/jail/cell_test.go +++ b/geth/jail/cell_test.go @@ -172,7 +172,7 @@ func (s *CellTestSuite) TestCellFetchErrorRace() { case e := <-errCh: name, err := cell.GetObjectValue(e, "name") s.NoError(err) - s.Equal("Error", name.String()) + s.Equal("Error", name.Value().String()) _, err = cell.GetObjectValue(e, "message") s.NoError(err) case <-time.After(5 * time.Second): @@ -240,7 +240,7 @@ func (s *CellTestSuite) TestCellCallAsync() { fn, err := s.cell.Get("testCallAsync") s.NoError(err) - err = s.cell.CallAsync(fn, "success") + err = s.cell.CallAsync(fn.Value(), "success") s.NoError(err) s.Equal("success", <-datac) } diff --git a/geth/jail/handlers.go b/geth/jail/handlers.go index 1b9d9f736..af8cd2c48 100644 --- a/geth/jail/handlers.go +++ b/geth/jail/handlers.go @@ -29,7 +29,7 @@ func registerWeb3Provider(jail *Jail, cell *Cell) error { "isConnected": createIsConnectedHandler(jail), } - return cell.Set("jeth", jeth) + return cell.jsvm.Set("jeth", jeth) } // registerStatusSignals creates an object called "statusSignals". @@ -39,7 +39,7 @@ func registerStatusSignals(cell *Cell) error { "sendSignal": createSendSignalHandler(cell), } - return cell.Set("statusSignals", statusSignals) + return cell.jsvm.Set("statusSignals", statusSignals) } // createSendHandler returns jeth.send(). @@ -48,7 +48,7 @@ func createSendHandler(jail *Jail, cell *Cell) func(call otto.FunctionCall) otto // As it's a sync call, it's called already from a thread-safe context, // thus using otto.Otto directly. Otherwise, it would try to acquire a lock again // and result in a deadlock. - vm := cell.VM.UnsafeVM() + vm := cell.jsvm.UnsafeVM() request, err := vm.Call("JSON.stringify", nil, call.Argument(0)) if err != nil { @@ -75,7 +75,7 @@ func createSendAsyncHandler(jail *Jail, cell *Cell) func(call otto.FunctionCall) // As it's a sync call, it's called already from a thread-safe context, // thus using otto.Otto directly. Otherwise, it would try to acquire a lock again // and result in a deadlock. - unsafeVM := cell.VM.UnsafeVM() + unsafeVM := cell.jsvm.UnsafeVM() request, err := unsafeVM.Call("JSON.stringify", nil, call.Argument(0)) if err != nil { @@ -85,7 +85,7 @@ func createSendAsyncHandler(jail *Jail, cell *Cell) func(call otto.FunctionCall) go func() { // As it's an async call, it's not called from a thread-safe context, // thus using a thread-safe vm.VM. - vm := cell.VM + vm := cell.jsvm callback := call.Argument(1) response, err := jail.sendRPCCall(request.String()) @@ -146,7 +146,7 @@ func createSendSignalHandler(cell *Cell) func(otto.FunctionCall) otto.Value { // As it's a sync call, it's called already from a thread-safe context, // thus using otto.Otto directly. Otherwise, it would try to acquire a lock again // and result in a deadlock. - vm := cell.VM.UnsafeVM() + vm := cell.jsvm.UnsafeVM() value, err := wrapResultInValue(vm, otto.TrueValue()) if err != nil { diff --git a/geth/jail/handlers_test.go b/geth/jail/handlers_test.go index fa520b83d..36af2bfa6 100644 --- a/geth/jail/handlers_test.go +++ b/geth/jail/handlers_test.go @@ -59,7 +59,7 @@ func (s *HandlersTestSuite) TestWeb3SendHandlerSuccess() { // web3.eth.syncing is an arbitrary web3 sync RPC call. value, err := cell.Run("web3.eth.syncing") s.NoError(err) - result, err := value.ToBoolean() + result, err := value.Value().ToBoolean() s.NoError(err) s.True(result) } @@ -155,7 +155,7 @@ func (s *HandlersTestSuite) TestWeb3IsConnectedHandler() { // When result is true. value, err := cell.Run("web3.isConnected()") s.NoError(err) - valueBoolean, err := value.ToBoolean() + valueBoolean, err := value.Value().ToBoolean() s.NoError(err) s.True(valueBoolean) @@ -163,7 +163,7 @@ func (s *HandlersTestSuite) TestWeb3IsConnectedHandler() { s.responseFixture = `{"json-rpc":"2.0","id":10,"result":false}` value, err = cell.Run("web3.isConnected()") s.NoError(err) - valueBoolean, err = value.ToBoolean() + valueBoolean, err = value.Value().ToBoolean() s.NoError(err) s.False(valueBoolean) } @@ -180,9 +180,9 @@ func (s *HandlersTestSuite) TestSendSignalHandler() { value, err := cell.Run(`statusSignals.sendSignal("test signal message")`) s.NoError(err) - result, err := cell.GetObjectValue(value, "result") + result, err := cell.GetObjectValue(value.Value(), "result") s.NoError(err) - resultBool, err := result.ToBoolean() + resultBool, err := result.Value().ToBoolean() s.NoError(err) s.True(resultBool) } diff --git a/geth/jail/jail.go b/geth/jail/jail.go index e88ce487c..fc50ab430 100644 --- a/geth/jail/jail.go +++ b/geth/jail/jail.go @@ -8,7 +8,6 @@ import ( "sync" "github.com/robertkrimen/otto" - "github.com/status-im/status-go/geth/common" "github.com/status-im/status-go/geth/rpc" "github.com/status-im/status-go/static" ) @@ -113,7 +112,7 @@ func (j *Jail) obtainCell(chatID string, expectNew bool) (cell *Cell, err error) // CreateCell creates a new cell. It returns an error // if a cell with a given ID already exists. -func (j *Jail) CreateCell(chatID string) (common.JailCell, error) { +func (j *Jail) CreateCell(chatID string) (JSCell, error) { return j.obtainCell(chatID, true) } @@ -158,7 +157,7 @@ func (j *Jail) createAndInitCell(chatID string, extraCode ...string) (*Cell, str return nil, "", err } - response = newJailResultResponse(formatOttoValue(result)) + response = newJailResultResponse(formatOttoValue(result.Value())) } return cell, response, nil @@ -213,7 +212,7 @@ func (j *Jail) cell(chatID string) (*Cell, error) { // Cell returns a cell by chatID. If it does not exist, error is returned. // Required by the Backend. -func (j *Jail) Cell(chatID string) (common.JailCell, error) { +func (j *Jail) Cell(chatID string) (JSCell, error) { return j.cell(chatID) } @@ -229,7 +228,7 @@ func (j *Jail) Execute(chatID, code string) string { return newJailErrorResponse(err) } - return value.String() + return value.Value().String() } // Call executes the `call` function within a cell with chatID. @@ -251,7 +250,7 @@ func (j *Jail) Call(chatID, commandPath, args string) string { return newJailErrorResponse(err) } - return newJailResultResponse(value) + return newJailResultResponse(value.Value()) } // RPCClient returns an rpc.Client. diff --git a/geth/jail/jail_test.go b/geth/jail/jail_test.go index db4df448e..d49ccf273 100644 --- a/geth/jail/jail_test.go +++ b/geth/jail/jail_test.go @@ -69,7 +69,7 @@ func (s *JailTestSuite) TestJailInitCell() { // web3 should be available value, err := cell.Run("web3.fromAscii('ethereum')") s.NoError(err) - s.Equal(`0x657468657265756d`, value.String()) + s.Equal(`0x657468657265756d`, value.Value().String()) } func (s *JailTestSuite) TestJailStop() { @@ -115,11 +115,11 @@ func (s *JailTestSuite) TestCreateAndInitCell() { value, err := cell.Get("testCreateAndInitCell1") s.NoError(err) - s.Equal(`true`, value.String()) + s.Equal(`true`, value.Value().String()) value, err = cell.Get("testCreateAndInitCell2") s.NoError(err) - s.Equal(`true`, value.String()) + s.Equal(`true`, value.Value().String()) } func (s *JailTestSuite) TestPublicCreateAndInitCell() { @@ -208,12 +208,12 @@ func (s *JailTestSuite) TestGetObjectValue() { testCreateAndInitCell1, err := cell.Get("testCreateAndInitCell1") s.NoError(err) - s.True(testCreateAndInitCell1.IsObject()) - value, err := cell.GetObjectValue(testCreateAndInitCell1, "obj") + s.True(testCreateAndInitCell1.Value().IsObject()) + value, err := cell.GetObjectValue(testCreateAndInitCell1.Value(), "obj") s.NoError(err) - s.Equal("objValue", value.String()) + s.Equal("objValue", value.Value().String()) value, err = cell.Get("testCreateAndInitCell2") s.NoError(err) - s.Equal(`true`, value.String()) + s.Equal(`true`, value.Value().String()) } diff --git a/t/e2e/jail/jail_rpc_test.go b/t/e2e/jail/jail_rpc_test.go index 24db996f0..cef284b10 100644 --- a/t/e2e/jail/jail_rpc_test.go +++ b/t/e2e/jail/jail_rpc_test.go @@ -11,6 +11,7 @@ import ( gethcommon "github.com/ethereum/go-ethereum/common" "github.com/status-im/status-go/geth/common" + "github.com/status-im/status-go/geth/jail" "github.com/status-im/status-go/geth/params" "github.com/status-im/status-go/geth/signal" "github.com/status-im/status-go/geth/transactions" @@ -26,7 +27,7 @@ func TestJailRPCTestSuite(t *testing.T) { type JailRPCTestSuite struct { e2e.BackendTestSuite - jail common.JailManager + jail jail.Manager } func (s *JailRPCTestSuite) SetupTest() { @@ -61,7 +62,7 @@ func (s *JailRPCTestSuite) TestJailRPCSend() { value, err := cell.Get("sendResult") s.NoError(err, "cannot obtain result of balance check operation") - balance, err := value.ToFloat() + balance, err := value.Value().ToFloat() s.NoError(err) s.T().Logf("Balance of %.2f ETH found on '%s' account", balance, TestConfig.Account1.Address) @@ -87,7 +88,7 @@ func (s *JailRPCTestSuite) TestIsConnected() { responseValue, err := cell.Get("responseValue") s.NoError(err, "cannot obtain result of isConnected()") - response, err := responseValue.ToBoolean() + response, err := responseValue.Value().ToBoolean() s.NoError(err, "cannot parse result") s.True(response) } @@ -177,12 +178,12 @@ func (s *JailRPCTestSuite) TestContractDeployment() { errorValue, err := cell.Get("errorValue") s.NoError(err) - s.Equal("null", errorValue.String()) + s.Equal("null", errorValue.Value().String()) responseValue, err := cell.Get("responseValue") s.NoError(err) - response, err := responseValue.ToString() + response, err := responseValue.Value().ToString() s.NoError(err) expectedResponse := txHash.Hex() @@ -335,7 +336,7 @@ func (s *JailRPCTestSuite) TestJailVMPersistence() { totalOtto, err := cell.Get("total") s.NoError(err) - total, err := totalOtto.ToFloat() + total, err := totalOtto.Value().ToFloat() s.NoError(err) s.T().Log(total) diff --git a/t/e2e/jail/jail_test.go b/t/e2e/jail/jail_test.go index 810ae48ca..698b4d828 100644 --- a/t/e2e/jail/jail_test.go +++ b/t/e2e/jail/jail_test.go @@ -10,7 +10,6 @@ import ( "testing" "time" - "github.com/status-im/status-go/geth/common" "github.com/status-im/status-go/geth/jail" "github.com/status-im/status-go/geth/node" "github.com/status-im/status-go/geth/signal" @@ -33,7 +32,7 @@ func TestJailTestSuite(t *testing.T) { type JailTestSuite struct { e2e.NodeManagerTestSuite - Jail common.JailManager + Jail jail.Manager } func (s *JailTestSuite) SetupTest() { @@ -192,7 +191,7 @@ func (s *JailTestSuite) TestEventSignal() { responseValue, err := cell.Get("responseValue") s.NoError(err, "cannot obtain result of localStorage.set()") - response, err := responseValue.ToString() + response, err := responseValue.Value().ToString() s.NoError(err, "cannot parse result") expectedResponse := `{"result":true}` diff --git a/t/e2e/whisper/whisper_jail_test.go b/t/e2e/whisper/whisper_jail_test.go index 3d62ce104..f46d3ca05 100644 --- a/t/e2e/whisper/whisper_jail_test.go +++ b/t/e2e/whisper/whisper_jail_test.go @@ -1,12 +1,13 @@ package whisper import ( + "runtime" "testing" "time" "github.com/ethereum/go-ethereum/crypto" whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" - "github.com/status-im/status-go/geth/common" + "github.com/status-im/status-go/geth/jail" "github.com/status-im/status-go/static" e2e "github.com/status-im/status-go/t/e2e" . "github.com/status-im/status-go/t/utils" @@ -35,7 +36,7 @@ type WhisperJailTestSuite struct { Timeout time.Duration WhisperAPI *whisper.PublicWhisperAPI - Jail common.JailManager + Jail jail.Manager } func (s *WhisperJailTestSuite) StartTestBackend(opts ...e2e.TestNodeOption) { @@ -65,6 +66,11 @@ func (s *WhisperJailTestSuite) TestJailWhisper() { r := s.Require() + // Increase number of OS threads that can run go code simultaneously. + // Some test cases (namely test 3) require a higher number of parallel + // go routines to successfully complete without hanging. + runtime.GOMAXPROCS(3) + keyPairID1, err := s.AddKeyPair(TestConfig.Account1.Address, TestConfig.Account1.Password) r.NoError(err) @@ -295,9 +301,11 @@ func (s *WhisperJailTestSuite) TestJailWhisper() { s.Jail.CreateAndInitCell(chatID, makeTopicCode) - cell, err := s.Jail.Cell(chatID) + jailCell, err := s.Jail.Cell(chatID) r.NoError(err, "cannot get VM") + cell := jailCell.(*jail.Cell) + // Run JS code that setups filters and sends messages. _, err = cell.Run(tc.code) r.NoError(err) @@ -323,12 +331,12 @@ func (s *WhisperJailTestSuite) TestJailWhisper() { for { filter, err := cell.Get("filter") r.NoError(err, "cannot get filter") - filterID, err := cell.GetObjectValue(filter, "filterId") + filterID, err := cell.GetObjectValue(filter.Value(), "filterId") r.NoError(err, "cannot get filterId") select { case <-done: - ok, err := s.WhisperAPI.DeleteMessageFilter(filterID.String()) + ok, err := s.WhisperAPI.DeleteMessageFilter(filterID.Value().String()) r.NoError(err) r.True(ok) break poll_loop @@ -338,18 +346,18 @@ func (s *WhisperJailTestSuite) TestJailWhisper() { } // FilterID is not assigned yet. - if filterID.IsNull() { + if filterID.Value().IsNull() { continue } payload, err := cell.Get("payload") r.NoError(err, "cannot get payload") - messages, err := s.WhisperAPI.GetFilterMessages(filterID.String()) + messages, err := s.WhisperAPI.GetFilterMessages(filterID.Value().String()) r.NoError(err) for _, m := range messages { - r.Equal(payload.String(), string(m.Payload)) + r.Equal(payload.Value().String(), string(m.Payload)) close(done) } }