github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/contracts/statute/service.go (about)

     1  package statute
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  	"math/big"
     9  	"time"
    10  
    11  	chieflib "github.com/SmartMeshFoundation/Spectrum/contracts/chief/lib"
    12  
    13  	"github.com/SmartMeshFoundation/Spectrum/accounts"
    14  	"github.com/SmartMeshFoundation/Spectrum/accounts/abi/bind"
    15  	"github.com/SmartMeshFoundation/Spectrum/common"
    16  	"github.com/SmartMeshFoundation/Spectrum/contracts"
    17  	"github.com/SmartMeshFoundation/Spectrum/contracts/statute/anmaplib"
    18  	"github.com/SmartMeshFoundation/Spectrum/contracts/statute/meshboxlib"
    19  	"github.com/SmartMeshFoundation/Spectrum/core/types"
    20  	"github.com/SmartMeshFoundation/Spectrum/eth"
    21  	"github.com/SmartMeshFoundation/Spectrum/log"
    22  	"github.com/SmartMeshFoundation/Spectrum/node"
    23  	"github.com/SmartMeshFoundation/Spectrum/p2p"
    24  	"github.com/SmartMeshFoundation/Spectrum/params"
    25  	"github.com/SmartMeshFoundation/Spectrum/rpc"
    26  )
    27  
    28  type AnmapService interface {
    29  	BindInfo(addr common.Address, blockNumber *big.Int, blockHash *common.Hash) (from common.Address, nodeids []common.Address, err error)
    30  	Bind(from, nodeAddr common.Address, sigHex string) (common.Hash, error)
    31  	Unbind(from, nodeAddr common.Address, sigHex string) (common.Hash, error)
    32  }
    33  
    34  type MeshboxService interface {
    35  	ExistAddress(addr common.Address) (*big.Int, error)
    36  }
    37  
    38  type StatuteService struct {
    39  	accman        *accounts.Manager
    40  	anmap_0_0_1   *anmaplib.Anmap
    41  	meshbox_0_0_1 *meshboxlib.MeshBox
    42  	meshbox_0_0_2 *meshboxlib.MeshBox_0_0_2
    43  	poc_1         *chieflib.POC_1_0_0
    44  	ipcpath       string
    45  	server        *p2p.Server // peers and nodekey ...
    46  	quit          chan int
    47  	ethereum      *eth.Ethereum
    48  }
    49  
    50  var statuteService *StatuteService
    51  
    52  func NewStatuteService(ctx *node.ServiceContext) (node.Service, error) {
    53  	var ethereum *eth.Ethereum
    54  	err := ctx.Service(&ethereum)
    55  	if err != nil {
    56  		log.Error("NewStatuteService", "err", err)
    57  	}
    58  	ipcpath := params.GetIPCPath()
    59  	statuteService = &StatuteService{
    60  		accman:   ctx.AccountManager,
    61  		quit:     make(chan int),
    62  		ipcpath:  ipcpath,
    63  		ethereum: ethereum,
    64  	}
    65  	go statuteService.loop()
    66  	return statuteService, nil
    67  }
    68  
    69  func (self *StatuteService) startMeshbox(vsn string, backend *eth.ContractBackend) {
    70  	defer func() {
    71  		if r := recover(); r != nil {
    72  			log.Warn("ignore_this_err", r)
    73  		}
    74  	}()
    75  	var period = params.TribePeriod()
    76  	for {
    77  		var cn = self.ethereum.BlockChain().CurrentBlock().Number()
    78  		if params.IsReadyMeshbox(cn) {
    79  			mn, maddr := params.MeshboxInfo(cn, vsn)
    80  			if maddr != common.HexToAddress("") {
    81  				switch vsn {
    82  				case "0.0.1":
    83  					contract, err := meshboxlib.NewMeshBox(maddr, backend)
    84  					if err != nil {
    85  						panic(err)
    86  					}
    87  					statuteService.meshbox_0_0_1 = contract
    88  				case "0.0.2":
    89  					contract, err := meshboxlib.NewMeshBox_0_0_2(maddr, backend)
    90  					if err != nil {
    91  						panic(err)
    92  					}
    93  					statuteService.meshbox_0_0_2 = contract
    94  				}
    95  				close(params.InitMeshbox)
    96  				log.Info("<<Meshbox.Start>> success ", "period", period, "vsn", vsn, "cn", cn.Int64(), "tn", mn.Int64())
    97  				return
    98  			} else {
    99  				//} else if cn.Cmp(mn) >= 0 {
   100  				log.Info("<<Meshbox.Start>> cancel ", "period", period, "vsn", vsn, "cn", cn, "tn", mn)
   101  				return
   102  			}
   103  		}
   104  		<-time.After(time.Duration(period) * time.Second)
   105  	}
   106  }
   107  
   108  func (self *StatuteService) startAnmap(vsn string, backend *eth.ContractBackend) {
   109  	defer func() {
   110  		if r := recover(); r != nil {
   111  			log.Warn("ignore_this_err", r)
   112  		}
   113  	}()
   114  	var period = params.TribePeriod()
   115  	for {
   116  		var cn = self.ethereum.BlockChain().CurrentBlock().Number()
   117  		if params.IsReadyAnmap(cn) {
   118  			mn, maddr := params.AnmapInfo(cn, vsn)
   119  			if maddr != common.HexToAddress("") {
   120  				switch vsn {
   121  				case "0.0.1":
   122  					contract, err := anmaplib.NewAnmap(maddr, backend)
   123  					if err != nil {
   124  						panic(err)
   125  					}
   126  					statuteService.anmap_0_0_1 = contract
   127  				}
   128  				close(params.InitAnmap)
   129  				log.Info("<<Anmap.Start>> success ", "period", period, "vsn", vsn, "cn", cn.Int64(), "tn", mn.Int64())
   130  				return
   131  			} else if cn.Cmp(mn) >= 0 {
   132  				log.Info("<<Anmap.Start>> cancel ", "period", period, "vsn", vsn, "cn", cn.Int64(), "tn", mn.Int64())
   133  				return
   134  			}
   135  		}
   136  		<-time.After(time.Duration(period) * time.Second)
   137  	}
   138  }
   139  
   140  func (self *StatuteService) Protocols() []p2p.Protocol { return nil }
   141  func (self *StatuteService) APIs() []rpc.API           { return nil }
   142  func (self *StatuteService) Start(server *p2p.Server) error {
   143  	var be = eth.NewContractBackend(self.ethereum.ApiBackend)
   144  	go self.startMeshbox("0.0.1", be)
   145  	go self.startMeshbox("0.0.2", be)
   146  	go self.startAnmap("0.0.1", be)
   147  	if true {
   148  		//poc contract service
   149  		var err error
   150  		self.poc_1, err = chieflib.NewPOC_1_0_0(params.POCInfo(), be)
   151  		if err != nil {
   152  			panic(err)
   153  		}
   154  	}
   155  
   156  	self.server = server
   157  	return nil
   158  }
   159  
   160  func (self *StatuteService) Stop() error {
   161  	close(self.quit)
   162  	return nil
   163  }
   164  
   165  // ===============================================================================
   166  // biz functions
   167  // ===============================================================================
   168  
   169  func GetAnmapService() (AnmapService, error) {
   170  	log.Debug("<<GetAnmapService>>")
   171  	select {
   172  	case <-params.InitMeshbox:
   173  		return statuteService, nil
   174  	default:
   175  		return nil, errors.New("anmap wait init")
   176  	}
   177  }
   178  
   179  func GetMeshboxService() (MeshboxService, error) {
   180  	log.Debug("<<GetMeshboxService>>")
   181  	select {
   182  	case <-params.InitMeshbox:
   183  		return statuteService, nil
   184  	default:
   185  		return nil, errors.New("meshbox wait init")
   186  	}
   187  }
   188  
   189  func sigSplit(sigHex string) (R, S [32]byte, V uint8) {
   190  	bR, err := hex.DecodeString(sigHex[:64])
   191  	bS, err := hex.DecodeString(sigHex[64:128])
   192  	if err != nil {
   193  		log.Error("sigSplit ", "sigHex", sigHex, "err", err)
   194  	}
   195  	copy(R[:], bR)
   196  	copy(S[:], bS)
   197  	V = 27
   198  	switch sigHex[128:] {
   199  	case "01":
   200  		V = 28
   201  	}
   202  	return
   203  }
   204  
   205  func (self *StatuteService) BindInfo(addr common.Address, blockNumber *big.Int, blockHash *common.Hash) (from common.Address, nodeids []common.Address, err error) {
   206  	chash := self.ethereum.BlockChain().CurrentBlock().Hash()
   207  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
   208  	defer cancel()
   209  	opts := new(bind.CallOptsWithNumber)
   210  	opts.Context = ctx
   211  	if blockHash != nil {
   212  		opts.Hash = blockHash
   213  	}
   214  
   215  	if blockNumber != nil {
   216  		opts.Number = blockNumber
   217  	}
   218  	if blockNumber == nil && blockHash == nil {
   219  		opts.Hash = &chash
   220  	}
   221  	vo, err := self.anmap_0_0_1.BindInfo(opts, addr)
   222  
   223  	// anmap.sol bindInfo func has a problum , an/na return diff nodeids so query again
   224  	if err == nil && len(vo.Nids) == 1 && vo.From != addr {
   225  		vo, err = self.anmap_0_0_1.BindInfo(opts, vo.From)
   226  	}
   227  
   228  	from = vo.From
   229  	nodeids = vo.Nids
   230  
   231  	return
   232  }
   233  
   234  func (self *StatuteService) Bind(from, nodeAddr common.Address, sigHex string) (common.Hash, error) {
   235  	a := accounts.Account{Address: from}
   236  	w, err := self.accman.Find(a)
   237  	if err != nil {
   238  		return common.Hash{}, err
   239  	}
   240  	opts := &bind.TransactOpts{
   241  		From: from,
   242  		Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) {
   243  			return w.SignTx(a, tx, params.ChainID())
   244  		},
   245  	}
   246  	//client   *ethclient.Client
   247  	client, err := contracts.GetEthclientInstance()
   248  	if err != nil {
   249  		return common.Hash{}, err
   250  	}
   251  	//if params.ChiefTxNonce > 0 {
   252  	pnonce, perr := client.PendingNonceAt(context.Background(), from)
   253  	if perr != nil {
   254  		log.Debug("<<StatuteService_Bind>> === nonce_err", "err", perr)
   255  	} else {
   256  		log.Debug("<<StatuteService_Bind>> === nonce", "nonce", pnonce)
   257  		opts.Nonce = new(big.Int).SetUint64(pnonce)
   258  	}
   259  
   260  	r, s, v := sigSplit(sigHex)
   261  	tx, err := self.anmap_0_0_1.Bind(opts, nodeAddr, v, r, s)
   262  	log.Info("<<StatuteService.Bind>>", "err", err, "tx", tx)
   263  	if err != nil {
   264  		return common.HexToHash("0x"), err
   265  	}
   266  	return tx.Hash(), nil
   267  }
   268  
   269  func (self *StatuteService) Unbind(from, nodeAddr common.Address, sigHex string) (common.Hash, error) {
   270  	a := accounts.Account{Address: from}
   271  	w, err := self.accman.Find(a)
   272  	if err != nil {
   273  		log.Error("Unbindb find", "err", err)
   274  	}
   275  	opts := &bind.TransactOpts{
   276  		From: from,
   277  		Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) {
   278  			return w.SignTx(a, tx, params.ChainID())
   279  		},
   280  	}
   281  	//client   *ethclient.Client
   282  	client, err := contracts.GetEthclientInstance()
   283  	if err != nil {
   284  		return common.Hash{}, err
   285  	}
   286  	//if params.ChiefTxNonce > 0 {
   287  	pnonce, perr := client.PendingNonceAt(context.Background(), from)
   288  	if perr != nil {
   289  		log.Debug("<<StatuteService_Bind>> === nonce_err", "err", perr)
   290  	} else {
   291  		log.Debug("<<StatuteService_Bind>> === nonce", "nonce", pnonce)
   292  		opts.Nonce = new(big.Int).SetUint64(pnonce)
   293  	}
   294  
   295  	r, s, v := sigSplit(sigHex)
   296  	tx, err := self.anmap_0_0_1.UnbindBySig(opts, nodeAddr, v, r, s)
   297  	log.Info("<<StatuteService.Unbind>>", "err", err, "tx", tx)
   298  	if err != nil {
   299  		return common.HexToHash("0x"), err
   300  	}
   301  	return tx.Hash(), nil
   302  }
   303  
   304  func (self *StatuteService) getBalance(mbox params.Mbox) {
   305  	success := params.MBoxSuccess{Success: true}
   306  	addr := mbox.Params["addr"].(common.Address)
   307  	sdb, err := self.ethereum.BlockChain().State()
   308  	if err != nil {
   309  		log.Error("BlockChain().State()", "err", err)
   310  	}
   311  	success.Entity = map[string]interface{}{"addr": addr, "balance": sdb.GetBalance(addr)}
   312  	mbox.Rtn <- success
   313  }
   314  
   315  /*
   316  args:
   317  	addr
   318  	hash : blockHash
   319  */
   320  func (self *StatuteService) bindInfo(mbox params.Mbox) {
   321  	success := params.MBoxSuccess{Success: true}
   322  	var (
   323  		addr        common.Address
   324  		blockHash   *common.Hash
   325  		blockNumber *big.Int
   326  	)
   327  	addr = mbox.Params["addr"].(common.Address)
   328  	// hash and number can not nil
   329  	if h, ok := mbox.Params["hash"]; ok {
   330  		bh := h.(common.Hash)
   331  		blockHash = &bh
   332  		_block := self.ethereum.BlockChain().GetBlockByHash(*blockHash)
   333  		log.Debug("<<StatuteService_bindInfo>>", "hash", blockHash.Hex())
   334  		if _block == nil {
   335  			blockHash = nil
   336  		}
   337  	}
   338  	if n, ok := mbox.Params["number"]; ok {
   339  		blockNumber = n.(*big.Int)
   340  	}
   341  	f, n, err := self.BindInfo(addr, blockNumber, blockHash)
   342  	if err != nil {
   343  		success.Success = false
   344  		success.Entity = err
   345  	} else {
   346  		success.Entity = map[string]interface{}{"from": f, "nodeids": n}
   347  	}
   348  	mbox.Rtn <- success
   349  }
   350  
   351  /*
   352  args:
   353  	from
   354  	nodeid
   355  	sigHex
   356  */
   357  func (self *StatuteService) bind(mbox params.Mbox) {
   358  	success := params.MBoxSuccess{Success: true}
   359  	var (
   360  		from, nodeid common.Address
   361  		sigHex       string
   362  	)
   363  	from = mbox.Params["from"].(common.Address)
   364  	nodeid = mbox.Params["nodeid"].(common.Address)
   365  	sigHex = mbox.Params["sigHex"].(string)
   366  	log.Info("mbox.params", "from", from.Hex(), "nodeid", nodeid, "sigHex", sigHex)
   367  	txHash, err := self.Bind(from, nodeid, sigHex)
   368  	if err != nil {
   369  		success.Success = false
   370  		success.Entity = err
   371  	} else {
   372  		success.Entity = txHash.Hex()
   373  	}
   374  	mbox.Rtn <- success
   375  }
   376  
   377  /*
   378  from common.Address, sigHex string
   379  */
   380  func (self *StatuteService) pocDeposit(mbox params.Mbox) {
   381  	success := params.MBoxSuccess{Success: true}
   382  	var (
   383  		from   common.Address
   384  		sigHex string
   385  		err    error
   386  		tx     *types.Transaction
   387  	)
   388  	defer func() {
   389  		if err != nil {
   390  			success.Success = false
   391  			success.Entity = err
   392  		} else {
   393  			success.Entity = tx.Hash().String()
   394  		}
   395  		mbox.Rtn <- success
   396  	}()
   397  	from = mbox.Params["from"].(common.Address)
   398  	sigHex = mbox.Params["sigHex"].(string)
   399  	log.Info("mbox.params", "from", from.Hex(), "sigHex", sigHex, "pocaddr", params.POCInfo())
   400  
   401  	a := accounts.Account{Address: from}
   402  	w, err := self.accman.Find(a)
   403  	if err != nil {
   404  		return
   405  	}
   406  	//client   *ethclient.Client
   407  	client, err := contracts.GetEthclientInstance()
   408  	if err != nil {
   409  		return
   410  	}
   411  	poc, err := chieflib.NewPOC_1_0_0(params.POCInfo(), client)
   412  	if err != nil {
   413  		return
   414  	}
   415  	//质押最小金额
   416  	min, err := poc.MinDepositAmount(nil)
   417  	if err != nil {
   418  		log.Error(fmt.Sprintf("query min deposit err %s,poc addr=%s", err, params.POCInfo().String()))
   419  		return
   420  	}
   421  	sdb, err := self.ethereum.BlockChain().State()
   422  	if err != nil {
   423  		return
   424  	}
   425  	balance := sdb.GetBalance(from)
   426  	if balance.Cmp(min) <= 0 {
   427  		err = fmt.Errorf("addr %s doesn't have enough balance, need=%s, have=%s", from.String(), min, balance)
   428  	}
   429  	opts := &bind.TransactOpts{
   430  		From: from,
   431  		Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) {
   432  			return w.SignTx(a, tx, params.ChainID())
   433  		},
   434  		Value: min,
   435  	}
   436  	//if params.ChiefTxNonce > 0 {
   437  	pnonce, perr := client.PendingNonceAt(context.Background(), from)
   438  	if perr != nil {
   439  		log.Debug("<<StatuteService_PocDeposit>> === nonce_err", "err", perr)
   440  	} else {
   441  		log.Debug("<<StatuteService_PocDeposit>> === nonce", "nonce", pnonce)
   442  		opts.Nonce = new(big.Int).SetUint64(pnonce)
   443  	}
   444  
   445  	r, s, v := sigSplit(sigHex)
   446  	tx, err = poc.Deposit(opts, r, s, v)
   447  	log.Info("<<StatuteService.PocDeposit>>", "err", err, "tx", tx)
   448  	return
   449  }
   450  
   451  func (self *StatuteService) pocStartAndStopAndWithdrawAndWithdrawSurplus(mbox params.Mbox, method string) {
   452  	success := params.MBoxSuccess{Success: true}
   453  	var (
   454  		from   common.Address
   455  		nodeID common.Address
   456  		err    error
   457  		tx     *types.Transaction
   458  	)
   459  	defer func() {
   460  		if err != nil {
   461  			success.Success = false
   462  			success.Entity = err
   463  		} else {
   464  			success.Entity = tx.Hash().String()
   465  		}
   466  		mbox.Rtn <- success
   467  	}()
   468  	from = mbox.Params["from"].(common.Address)
   469  	nodeID = mbox.Params["nodeid"].(common.Address)
   470  	log.Info("mbox.params", "from", from.Hex(), "nodeid", nodeID, "pocaddr", params.POCInfo())
   471  
   472  	a := accounts.Account{Address: from}
   473  	w, err := self.accman.Find(a)
   474  	if err != nil {
   475  		return
   476  	}
   477  	opts := &bind.TransactOpts{
   478  		From: from,
   479  		Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) {
   480  			return w.SignTx(a, tx, params.ChainID())
   481  		},
   482  	}
   483  	//client   *ethclient.Client
   484  	client, err := contracts.GetEthclientInstance()
   485  	if err != nil {
   486  		return
   487  	}
   488  	//if params.ChiefTxNonce > 0 {
   489  	pnonce, perr := client.PendingNonceAt(context.Background(), from)
   490  	if perr != nil {
   491  		log.Debug("<<StatuteService_pocStartAndStopAndWithdrawAndWithdrawSurplus>> === nonce_err", "err", perr)
   492  	} else {
   493  		log.Debug("<<StatuteService_pocStartAndStopAndWithdrawAndWithdrawSurplus>> === nonce", "nonce", pnonce)
   494  		opts.Nonce = new(big.Int).SetUint64(pnonce)
   495  	}
   496  	switch method {
   497  	case params.POC_METHOD_START:
   498  		tx, err = self.poc_1.Start(opts, nodeID)
   499  	case params.POC_METHOD_STOP:
   500  		tx, err = self.poc_1.Stop(opts, nodeID)
   501  	case params.POC_METHOD_WITHDRAW:
   502  		tx, err = self.poc_1.Withdraw(opts, nodeID)
   503  	case params.POC_METHOD_WITHDRAW_SURPLUS:
   504  		tx, err = self.poc_1.WithdrawSurplus(opts, nodeID)
   505  	default:
   506  		panic(method)
   507  	}
   508  	log.Info("<<StatuteService>>", "method", method, "err", err, "tx", tx)
   509  	return
   510  }
   511  
   512  func (self *StatuteService) pocGetAll(mbox params.Mbox) {
   513  	var (
   514  		blockNumber *big.Int     = nil
   515  		blockHash   *common.Hash = nil
   516  	)
   517  	// hash and number can not nil
   518  	if h, ok := mbox.Params["hash"]; ok {
   519  		bh := h.(common.Hash)
   520  		blockHash = &bh
   521  	}
   522  	if n, ok := mbox.Params["number"]; ok {
   523  		blockNumber = n.(*big.Int)
   524  	}
   525  	log.Debug("=>TribeService.pocGetAll", "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   526  	success := params.MBoxSuccess{Success: true}
   527  	var (
   528  		err error
   529  		ps  *params.PocStatus
   530  	)
   531  	defer func() {
   532  		if err != nil {
   533  			success.Success = false
   534  			success.Entity = err
   535  		} else {
   536  			success.Entity = ps
   537  		}
   538  		mbox.Rtn <- success
   539  	}()
   540  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*60)
   541  	defer cancel()
   542  	opts := &bind.CallOptsWithNumber{}
   543  	opts.Context = ctx
   544  	opts.Hash = blockHash
   545  	minerList, amountList, blockList, ownerList, blackStatusList, err := self.poc_1.GetAll(opts)
   546  	if err != nil {
   547  		return
   548  	}
   549  	ps = &params.PocStatus{
   550  		MinerList:       minerList,
   551  		AmountList:      amountList,
   552  		BlockList:       blockList,
   553  		OwnerList:       ownerList,
   554  		BlackStatusList: blackStatusList,
   555  	}
   556  	log.Debug("<<StatuteService.pocGetAll>>")
   557  	return
   558  }
   559  
   560  /*
   561  args:
   562  	from
   563  	nodeid
   564  	sigHex
   565  */
   566  func (self *StatuteService) unbind(mbox params.Mbox) {
   567  	success := params.MBoxSuccess{Success: true}
   568  	var (
   569  		from, nodeid common.Address
   570  		sigHex       string
   571  	)
   572  	from = mbox.Params["from"].(common.Address)
   573  	nodeid = mbox.Params["nodeid"].(common.Address)
   574  	sigHex = mbox.Params["sigHex"].(string)
   575  	log.Info("mbox.params", "from", from.Hex(), "nodeid", nodeid, "sigHex", sigHex)
   576  	txHash, err := self.Unbind(from, nodeid, sigHex)
   577  	if err != nil {
   578  		success.Success = false
   579  		success.Entity = err
   580  	} else {
   581  		success.Entity = txHash.Hex()
   582  	}
   583  	mbox.Rtn <- success
   584  }
   585  
   586  func (self *StatuteService) ExistAddress(addr common.Address) (*big.Int, error) {
   587  	log.Debug("<<StatuteService.ExistAddress>>")
   588  	select {
   589  	case <-params.InitMeshbox:
   590  		var (
   591  			num  = self.ethereum.BlockChain().CurrentHeader().Number
   592  			ctx  = context.Background()
   593  			opts = new(bind.CallOptsWithNumber)
   594  			i    *big.Int
   595  		)
   596  		vsn, err := params.MeshboxVsn(num)
   597  		if err != nil {
   598  			return nil, err
   599  		}
   600  		ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
   601  		defer cancel()
   602  		opts.Context = ctx
   603  		switch vsn {
   604  		case "0.0.1":
   605  			i, err = self.meshbox_0_0_1.ExistAddress(opts, addr)
   606  		case "0.0.2":
   607  			i, err = self.meshbox_0_0_2.ExistAddress(opts, addr)
   608  		}
   609  		log.Debug("<<StatuteService.ExistAddress>>", "r", i, "err", err)
   610  		return i, err
   611  	default:
   612  		return nil, errors.New("wait init")
   613  	}
   614  }
   615  
   616  func (self *StatuteService) GetMeshboxList() ([]common.Address, error) {
   617  	log.Debug("<<StatuteService.GetMeshboxList>>")
   618  	select {
   619  	case <-params.InitMeshbox:
   620  		var (
   621  			num  = self.ethereum.BlockChain().CurrentHeader().Number
   622  			ctx  = context.Background()
   623  			opts = new(bind.CallOptsWithNumber)
   624  			mbs  []common.Address
   625  		)
   626  		vsn, err := params.MeshboxVsn(num)
   627  		if err != nil {
   628  			return nil, err
   629  		}
   630  		ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
   631  		defer cancel()
   632  		opts.Context = ctx
   633  		switch vsn {
   634  		case "0.0.2":
   635  			mbs, err = self.meshbox_0_0_2.GetMeshboxList(opts)
   636  		}
   637  		log.Debug("<<StatuteService.GetMeshboxList>>", "err", err)
   638  		return mbs, err
   639  	default:
   640  		return nil, errors.New("wait init")
   641  	}
   642  }
   643  
   644  func (self *StatuteService) existAddress(mbox params.Mbox) {
   645  	success := params.MBoxSuccess{Success: true}
   646  	var addr common.Address
   647  	addr = mbox.Params["addr"].(common.Address)
   648  	log.Debug("mbox.params", "addr", addr.Hex())
   649  	i, err := self.ExistAddress(addr)
   650  	if err != nil {
   651  		success.Success = false
   652  		success.Entity = err
   653  	} else {
   654  		success.Entity = i.Int64()
   655  	}
   656  	mbox.Rtn <- success
   657  }
   658  
   659  func (self *StatuteService) loop() {
   660  	for {
   661  		select {
   662  		case <-self.quit:
   663  			break
   664  		case mbox := <-params.StatuteService:
   665  			switch mbox.Method {
   666  			case "getBalance":
   667  				self.getBalance(mbox)
   668  			case "bindInfo":
   669  				self.bindInfo(mbox)
   670  			case "bind":
   671  				self.bind(mbox)
   672  			case "unbind":
   673  				self.unbind(mbox)
   674  			case "existAddress":
   675  				self.existAddress(mbox)
   676  			case params.POC_METHOD_DEPOSIT:
   677  				self.pocDeposit(mbox)
   678  			case params.POC_METHOD_START:
   679  				fallthrough
   680  			case params.POC_METHOD_STOP:
   681  				fallthrough
   682  			case params.POC_METHOD_WITHDRAW:
   683  				fallthrough
   684  			case params.POC_METHOD_WITHDRAW_SURPLUS:
   685  				self.pocStartAndStopAndWithdrawAndWithdrawSurplus(mbox, mbox.Method)
   686  			case params.POC_METHOD_GET_STATUS:
   687  				self.pocGetAll(mbox)
   688  			}
   689  		}
   690  	}
   691  }