otto包

以太坊的命令是通过在js虚拟机上来实现命令的。而在go语言中,有第三方的otto包,可以直接在go语言中实现js命令。而以太坊代码则使用了otto包来实现搭建js命令。
在otto包中,set方法是设置变量的值,get方法是获取变量的值。

  1. // Set the property of the given name to the given value.
  2. func (self Object) Set(name string, value interface{})
  3. // Get the value of the property with the given name.
  4. func (self Object) Get(name string) (Value, error)

Compile是根据输入的路径对js的代码进行编译,返回变量的值。

  1. // Compile will parse the given source and return a Script value or nil and
  2. // an error if there was a problem during compilation.
  3. func (self *Otto) Compile(filename string, src interface{}) (*Script, error)

Run方法会运行相关的js代码,如果有返回值的话会返回。

  1. // Run will run the given source (parsing it first if necessary), returning the resulting value and error (if any)
  2. func (self Otto) Run(src interface{}) (Value, error)

如何编写自己的以太坊命令

接上篇ethapi.api-analysis分析,如果我们需要在相关模块添加相关命令,首先我们需要找到相关命令所对应的api结构体。
各个命令对应的结构体,包的位置如下:

  1. admin PrivateAdminAPI,PublicAdminAPI node/api
  2. debug PrivateDebugAPI eth/api
  3. eth PublicBlockChainAPI ethapi/api
  4. miner PrivateMinerAPI eth/api
  5. net PublicNetAPI ethapi/api
  6. personal PrivateAccountAPI ethapi/api
  7. txpool PublicTxPoolAPI ethapi/api
  8. rpc 所有可调用包集合
  9. web3 所有命令集合

假设我们需要在personal包中添加一个命令,那么我们就在PrivateAccountAPI中添加一个方法:

  1. func (s *PrivateAccountAPI) TestMethod() {
  2. fmt.Print("TestMethod")
  3. }

接下来到internal/web3ext/web3ext.go中,找到personal命令集合,然后添加一条自己的命令:

  1. const Personal_JS = `
  2. web3._extend(
  3. methods: [
  4. new web3._extend.Method({
  5. name : 'testMethod',
  6. call : 'personal_testMethod'
  7. }), //our method
  8. ...

最后到internal/jsre/deps/web3.js中,找到personal方法的定义:

  1. function Personal(web3) {
  2. this._requestManager = web3._requestManager;
  3. var self = this;
  4. methods().forEach(function(method) {
  5. method.attachToObject(self);
  6. method.setRequestManager(self._requestManager);
  7. });
  8. properties().forEach(function(p) {
  9. p.attachToObject(self);
  10. p.setRequestManager(self._requestManager);
  11. });
  12. }
  13. var methods = function () {
  14. ...

然后再methods中添加你定义的方法名:

  1. var methods = function () {
  2. var testMethod = new Method({
  3. name : 'testMethod',
  4. call : 'personal_testMethod'
  5. });
  6. ...

并在最后的return中添加你的方法:

  1. return [
  2. newAccount,
  3. testMethod, //our method
  4. importRawKey,
  5. unlockAccount,
  6. ecRecover,
  7. sign,
  8. sendTransaction,
  9. lockAccount
  10. ];

这之后在启动命令行,我们就可以调用我们的方法了。结果如下:

  1. > personal.testMethod()
  2. TestMethodnull