github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/signer/rules/rules.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2018 Go Ethereum作者
    10  //此文件是Go以太坊的一部分。
    11  //
    12  //Go以太坊是免费软件:您可以重新发布和/或修改它
    13  //根据GNU通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊的分布希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU通用公共许可证了解更多详细信息。
    21  //
    22  //你应该已经收到一份GNU通用公共许可证的副本
    23  //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package rules
    26  
    27  import (
    28  	"encoding/json"
    29  	"fmt"
    30  	"os"
    31  	"strings"
    32  
    33  	"github.com/ethereum/go-ethereum/common"
    34  	"github.com/ethereum/go-ethereum/internal/ethapi"
    35  	"github.com/ethereum/go-ethereum/log"
    36  	"github.com/ethereum/go-ethereum/signer/core"
    37  	"github.com/ethereum/go-ethereum/signer/rules/deps"
    38  	"github.com/ethereum/go-ethereum/signer/storage"
    39  	"github.com/robertkrimen/otto"
    40  )
    41  
    42  var (
    43  	BigNumber_JS = deps.MustAsset("bignumber.js")
    44  )
    45  
    46  //consoleoutput是console.log和console.error方法的重写,用于
    47  //将输出流传输到配置的输出流,而不是stdout。
    48  func consoleOutput(call otto.FunctionCall) otto.Value {
    49  	output := []string{"JS:> "}
    50  	for _, argument := range call.ArgumentList {
    51  		output = append(output, fmt.Sprintf("%v", argument))
    52  	}
    53  	fmt.Fprintln(os.Stdout, strings.Join(output, " "))
    54  	return otto.Value{}
    55  }
    56  
    57  //rulesetui提供了一个signerui的实现,它评估一个javascript
    58  //每个定义的UI方法的文件
    59  type rulesetUI struct {
    60  next        core.SignerUI //下一个处理程序,用于手动处理
    61  	storage     storage.Storage
    62  	credentials storage.Storage
    63  jsRules     string //使用的规则
    64  }
    65  
    66  func NewRuleEvaluator(next core.SignerUI, jsbackend, credentialsBackend storage.Storage) (*rulesetUI, error) {
    67  	c := &rulesetUI{
    68  		next:        next,
    69  		storage:     jsbackend,
    70  		credentials: credentialsBackend,
    71  		jsRules:     "",
    72  	}
    73  
    74  	return c, nil
    75  }
    76  
    77  func (r *rulesetUI) Init(javascriptRules string) error {
    78  	r.jsRules = javascriptRules
    79  	return nil
    80  }
    81  func (r *rulesetUI) execute(jsfunc string, jsarg interface{}) (otto.Value, error) {
    82  
    83  //每次实例化一个新的VM引擎
    84  	vm := otto.New()
    85  //设置本机回调
    86  	consoleObj, _ := vm.Get("console")
    87  	consoleObj.Object().Set("log", consoleOutput)
    88  	consoleObj.Object().Set("error", consoleOutput)
    89  	vm.Set("storage", r.storage)
    90  
    91  //加载引导程序库
    92  	script, err := vm.Compile("bignumber.js", BigNumber_JS)
    93  	if err != nil {
    94  		log.Warn("Failed loading libraries", "err", err)
    95  		return otto.UndefinedValue(), err
    96  	}
    97  	vm.Run(script)
    98  
    99  //运行实际规则实现
   100  	_, err = vm.Run(r.jsRules)
   101  	if err != nil {
   102  		log.Warn("Execution failed", "err", err)
   103  		return otto.UndefinedValue(), err
   104  	}
   105  
   106  //和实际通话
   107  //所有调用都是对象,其中参数是该对象中的键。
   108  //为了在JS和Go之间提供额外的隔离,我们在Go端将其序列化为JSON,
   109  //并在JS端对其进行反序列化。
   110  
   111  	jsonbytes, err := json.Marshal(jsarg)
   112  	if err != nil {
   113  		log.Warn("failed marshalling data", "data", jsarg)
   114  		return otto.UndefinedValue(), err
   115  	}
   116  //现在,我们称之为foobar(json.parse(<jsondata>)。
   117  	var call string
   118  	if len(jsonbytes) > 0 {
   119  		call = fmt.Sprintf("%v(JSON.parse(%v))", jsfunc, string(jsonbytes))
   120  	} else {
   121  		call = fmt.Sprintf("%v()", jsfunc)
   122  	}
   123  	return vm.Run(call)
   124  }
   125  
   126  func (r *rulesetUI) checkApproval(jsfunc string, jsarg []byte, err error) (bool, error) {
   127  	if err != nil {
   128  		return false, err
   129  	}
   130  	v, err := r.execute(jsfunc, string(jsarg))
   131  	if err != nil {
   132  		log.Info("error occurred during execution", "error", err)
   133  		return false, err
   134  	}
   135  	result, err := v.ToString()
   136  	if err != nil {
   137  		log.Info("error occurred during response unmarshalling", "error", err)
   138  		return false, err
   139  	}
   140  	if result == "Approve" {
   141  		log.Info("Op approved")
   142  		return true, nil
   143  	} else if result == "Reject" {
   144  		log.Info("Op rejected")
   145  		return false, nil
   146  	}
   147  	return false, fmt.Errorf("Unknown response")
   148  }
   149  
   150  func (r *rulesetUI) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
   151  	jsonreq, err := json.Marshal(request)
   152  	approved, err := r.checkApproval("ApproveTx", jsonreq, err)
   153  	if err != nil {
   154  		log.Info("Rule-based approval error, going to manual", "error", err)
   155  		return r.next.ApproveTx(request)
   156  	}
   157  
   158  	if approved {
   159  		return core.SignTxResponse{
   160  				Transaction: request.Transaction,
   161  				Approved:    true,
   162  				Password:    r.lookupPassword(request.Transaction.From.Address()),
   163  			},
   164  			nil
   165  	}
   166  	return core.SignTxResponse{Approved: false}, err
   167  }
   168  
   169  func (r *rulesetUI) lookupPassword(address common.Address) string {
   170  	return r.credentials.Get(strings.ToLower(address.String()))
   171  }
   172  
   173  func (r *rulesetUI) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
   174  	jsonreq, err := json.Marshal(request)
   175  	approved, err := r.checkApproval("ApproveSignData", jsonreq, err)
   176  	if err != nil {
   177  		log.Info("Rule-based approval error, going to manual", "error", err)
   178  		return r.next.ApproveSignData(request)
   179  	}
   180  	if approved {
   181  		return core.SignDataResponse{Approved: true, Password: r.lookupPassword(request.Address.Address())}, nil
   182  	}
   183  	return core.SignDataResponse{Approved: false, Password: ""}, err
   184  }
   185  
   186  func (r *rulesetUI) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
   187  	jsonreq, err := json.Marshal(request)
   188  	approved, err := r.checkApproval("ApproveExport", jsonreq, err)
   189  	if err != nil {
   190  		log.Info("Rule-based approval error, going to manual", "error", err)
   191  		return r.next.ApproveExport(request)
   192  	}
   193  	if approved {
   194  		return core.ExportResponse{Approved: true}, nil
   195  	}
   196  	return core.ExportResponse{Approved: false}, err
   197  }
   198  
   199  func (r *rulesetUI) ApproveImport(request *core.ImportRequest) (core.ImportResponse, error) {
   200  //这不能由规则处理,需要设置密码
   201  //发送到下一个
   202  	return r.next.ApproveImport(request)
   203  }
   204  
   205  func (r *rulesetUI) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
   206  	jsonreq, err := json.Marshal(request)
   207  	approved, err := r.checkApproval("ApproveListing", jsonreq, err)
   208  	if err != nil {
   209  		log.Info("Rule-based approval error, going to manual", "error", err)
   210  		return r.next.ApproveListing(request)
   211  	}
   212  	if approved {
   213  		return core.ListResponse{Accounts: request.Accounts}, nil
   214  	}
   215  	return core.ListResponse{}, err
   216  }
   217  
   218  func (r *rulesetUI) ApproveNewAccount(request *core.NewAccountRequest) (core.NewAccountResponse, error) {
   219  //这不能由规则处理,需要设置密码
   220  //发送到下一个
   221  	return r.next.ApproveNewAccount(request)
   222  }
   223  
   224  func (r *rulesetUI) ShowError(message string) {
   225  	log.Error(message)
   226  	r.next.ShowError(message)
   227  }
   228  
   229  func (r *rulesetUI) ShowInfo(message string) {
   230  	log.Info(message)
   231  	r.next.ShowInfo(message)
   232  }
   233  func (r *rulesetUI) OnSignerStartup(info core.StartupInfo) {
   234  	jsonInfo, err := json.Marshal(info)
   235  	if err != nil {
   236  		log.Warn("failed marshalling data", "data", info)
   237  		return
   238  	}
   239  	r.next.OnSignerStartup(info)
   240  	_, err = r.execute("OnSignerStartup", string(jsonInfo))
   241  	if err != nil {
   242  		log.Info("error occurred during execution", "error", err)
   243  	}
   244  }
   245  
   246  func (r *rulesetUI) OnApprovedTx(tx ethapi.SignTransactionResult) {
   247  	jsonTx, err := json.Marshal(tx)
   248  	if err != nil {
   249  		log.Warn("failed marshalling transaction", "tx", tx)
   250  		return
   251  	}
   252  	_, err = r.execute("OnApprovedTx", string(jsonTx))
   253  	if err != nil {
   254  		log.Info("error occurred during execution", "error", err)
   255  	}
   256  }