mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43:47 +00:00
signer/rules: implement dispatching to next handler
This commit is contained in:
parent
99dd0a1b58
commit
3ade6cb242
2 changed files with 82 additions and 21 deletions
|
|
@ -19,6 +19,7 @@ package rules
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/ethereum/go-ethereum/cmd/signer/core"
|
||||||
"github.com/ethereum/go-ethereum/cmd/signer/rules/deps"
|
"github.com/ethereum/go-ethereum/cmd/signer/rules/deps"
|
||||||
"github.com/ethereum/go-ethereum/cmd/signer/storage"
|
"github.com/ethereum/go-ethereum/cmd/signer/storage"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
|
@ -26,7 +27,6 @@ import (
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/ethereum/go-ethereum/cmd/signer/core"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -47,14 +47,15 @@ func consoleOutput(call otto.FunctionCall) otto.Value {
|
||||||
// rulesetUi provides an implementation of SignerUI that evaluates a javascript
|
// rulesetUi provides an implementation of SignerUI that evaluates a javascript
|
||||||
// file for each defined UI-method
|
// file for each defined UI-method
|
||||||
type rulesetUi struct {
|
type rulesetUi struct {
|
||||||
vm *otto.Otto // The JS vm
|
vm *otto.Otto // The JS vm
|
||||||
next core.SignerUI // The next handler, for manual processing
|
next core.SignerUI // The next handler, for manual processing
|
||||||
storage storage.Storage
|
storage storage.Storage
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRuleEvaluator() (*rulesetUi, error) {
|
func NewRuleEvaluator(next core.SignerUI) (*rulesetUi, error) {
|
||||||
c := &rulesetUi{
|
c := &rulesetUi{
|
||||||
vm: otto.New(),
|
vm: otto.New(),
|
||||||
|
next: next,
|
||||||
storage: storage.NewEphemeralStorage(),
|
storage: storage.NewEphemeralStorage(),
|
||||||
}
|
}
|
||||||
consoleObj, _ := c.vm.Get("console")
|
consoleObj, _ := c.vm.Get("console")
|
||||||
|
|
@ -81,32 +82,38 @@ func (r *rulesetUi) Init(javascriptRules string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) checkApproval(jsfunc string, jsarg []byte, err error) error {
|
func (r *rulesetUi) checkApproval(jsfunc string, jsarg []byte, err error) (bool, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
v, err := r.vm.Call(jsfunc, nil, string(jsarg))
|
v, err := r.vm.Call(jsfunc, nil, string(jsarg))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("error occurred during execution", "error", err)
|
log.Info("error occurred during execution", "error", err)
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
result, err := v.ToString()
|
result, err := v.ToString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("error occurred during response unmarshalling", "error", err)
|
log.Info("error occurred during response unmarshalling", "error", err)
|
||||||
return err
|
return false, err
|
||||||
|
|
||||||
}
|
}
|
||||||
if result == "Approve" {
|
if result == "Approve" {
|
||||||
log.Info("Op approved")
|
log.Info("Op approved")
|
||||||
return nil
|
return true, nil
|
||||||
|
} else if result == "Reject" {
|
||||||
|
log.Info("Op rejected")
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("rejected")
|
return false, fmt.Errorf("Unknown response")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
|
func (r *rulesetUi) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
approved, err := r.checkApproval("ApproveTx", jsonreq, err)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Rule-based approval error, going to manual", "error", "err")
|
||||||
|
return r.next.ApproveTx(request)
|
||||||
|
}
|
||||||
|
if approved {
|
||||||
return core.SignTxResponse{Transaction: request.Transaction, Approved: true, Password: ""}, nil
|
return core.SignTxResponse{Transaction: request.Transaction, Approved: true, Password: ""}, nil
|
||||||
}
|
}
|
||||||
return core.SignTxResponse{Approved: false}, err
|
return core.SignTxResponse{Approved: false}, err
|
||||||
|
|
@ -114,7 +121,12 @@ func (r *rulesetUi) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse,
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
|
func (r *rulesetUi) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
approved, err := r.checkApproval("ApproveSignData", jsonreq, err)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Rule-based approval error, going to manual", "error", "err")
|
||||||
|
return r.next.ApproveSignData(request)
|
||||||
|
}
|
||||||
|
if approved {
|
||||||
return core.SignDataResponse{Approved: true, Password: ""}, nil
|
return core.SignDataResponse{Approved: true, Password: ""}, nil
|
||||||
}
|
}
|
||||||
return core.SignDataResponse{Approved: false, Password: ""}, err
|
return core.SignDataResponse{Approved: false, Password: ""}, err
|
||||||
|
|
@ -122,7 +134,12 @@ func (r *rulesetUi) ApproveSignData(request *core.SignDataRequest) (core.SignDat
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
|
func (r *rulesetUi) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
approved, err := r.checkApproval("ApproveExport", jsonreq, err)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Rule-based approval error, going to manual", "error", "err")
|
||||||
|
return r.next.ApproveExport(request)
|
||||||
|
}
|
||||||
|
if approved {
|
||||||
return core.ExportResponse{Approved: true}, nil
|
return core.ExportResponse{Approved: true}, nil
|
||||||
}
|
}
|
||||||
return core.ExportResponse{Approved: false}, err
|
return core.ExportResponse{Approved: false}, err
|
||||||
|
|
@ -136,7 +153,12 @@ func (r *rulesetUi) ApproveImport(request *core.ImportRequest) (core.ImportRespo
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
|
func (r *rulesetUi) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveListing", jsonreq, err); err == nil {
|
approved, err := r.checkApproval("ApproveListing", jsonreq, err)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Rule-based approval error, going to manual", "error", "err")
|
||||||
|
return r.next.ApproveListing(request)
|
||||||
|
}
|
||||||
|
if approved {
|
||||||
return core.ListResponse{Accounts: request.Accounts}, nil
|
return core.ListResponse{Accounts: request.Accounts}, nil
|
||||||
}
|
}
|
||||||
return core.ListResponse{}, err
|
return core.ListResponse{}, err
|
||||||
|
|
@ -157,8 +179,8 @@ func (r *rulesetUi) ShowInfo(message string) {
|
||||||
log.Info(message)
|
log.Info(message)
|
||||||
r.next.ShowInfo(message)
|
r.next.ShowInfo(message)
|
||||||
}
|
}
|
||||||
func (r *rulesetUi) OnApprovedTx(tx ethapi.SignTransactionResult) {
|
|
||||||
|
|
||||||
|
func (r *rulesetUi) OnApprovedTx(tx ethapi.SignTransactionResult) {
|
||||||
jsonTx, err := json.Marshal(tx)
|
jsonTx, err := json.Marshal(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("failed marshalling transaction", "tx", tx)
|
log.Warn("failed marshalling transaction", "tx", tx)
|
||||||
|
|
@ -169,5 +191,4 @@ func (r *rulesetUi) OnApprovedTx(tx ethapi.SignTransactionResult) {
|
||||||
fmt.Printf("Error in onapprove %v", err)
|
fmt.Printf("Error in onapprove %v", err)
|
||||||
log.Warn("error occurred during execution", "error", err)
|
log.Warn("error occurred during execution", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,46 @@ func hexAddr(a string) common.Address { return common.BytesToAddress(common.Hex2
|
||||||
func mixAddr(a string) (*common.MixedcaseAddress, error) {
|
func mixAddr(a string) (*common.MixedcaseAddress, error) {
|
||||||
return common.NewMixedcaseAddressFromString(a)
|
return common.NewMixedcaseAddressFromString(a)
|
||||||
}
|
}
|
||||||
|
type alwaysDenyUi struct{}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
|
||||||
|
return core.SignTxResponse{request.Transaction, false, ""}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
|
||||||
|
return core.SignDataResponse{false, ""}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
|
||||||
|
return core.ExportResponse{false}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ApproveImport(request *core.ImportRequest) (core.ImportResponse, error) {
|
||||||
|
return core.ImportResponse{false, "", ""}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
|
||||||
|
return core.ListResponse{nil}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ApproveNewAccount(request *core.NewAccountRequest) (core.NewAccountResponse, error) {
|
||||||
|
return core.NewAccountResponse{false, ""}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ShowError(message string) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) ShowInfo(message string) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alwaysDenyUi) OnApprovedTx(tx ethapi.SignTransactionResult) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
func initRuleEngine(js string) (*rulesetUi, error) {
|
func initRuleEngine(js string) (*rulesetUi, error) {
|
||||||
r, err := NewRuleEvaluator()
|
r, err := NewRuleEvaluator(&alwaysDenyUi{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to create js engine: %v", err)
|
return nil, fmt.Errorf("Failed to create js engine: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -154,10 +191,13 @@ func TestMissingFunc(t *testing.T) {
|
||||||
t.Error("Expected error")
|
t.Error("Expected error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.checkApproval("MissingMethod", nil, nil) == nil {
|
approved, err := r.checkApproval("MissingMethod", nil, nil);
|
||||||
t.Errorf("Expected error to resolve to 'Reject'")
|
if err == nil {
|
||||||
|
t.Errorf("Expected missing method to yield error'")
|
||||||
|
}
|
||||||
|
if approved{
|
||||||
|
t.Errorf("Expected missing method to cause non-approval")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Err %v", err)
|
fmt.Printf("Err %v", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue