github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/account/manager.go (about)

     1  package account
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"path/filepath"
     8  	"sync"
     9  
    10  	acct "github.com/sixexorg/magnetic-ring/account/keystore"
    11  	"github.com/sixexorg/magnetic-ring/common"
    12  	"github.com/sixexorg/magnetic-ring/config"
    13  	"github.com/sixexorg/magnetic-ring/crypto"
    14  	"github.com/sixexorg/magnetic-ring/crypto/cipher"
    15  	"github.com/sixexorg/magnetic-ring/errors"
    16  	"github.com/sixexorg/magnetic-ring/log"
    17  )
    18  
    19  type NormalAccountImpl struct {
    20  	PrivKey crypto.PrivateKey
    21  	Addr    common.Address
    22  }
    23  
    24  func (acct *NormalAccountImpl) Sign(hash []byte) (sig []byte, err error) {
    25  	priv := acct.PrivKey
    26  	return priv.Sign(hash[:])
    27  }
    28  
    29  func (acct *NormalAccountImpl) Verify(hash, sig []byte) (bool, error) {
    30  	pub := acct.PublicKey()
    31  	return pub.Verify(hash, sig)
    32  }
    33  
    34  func (acct *NormalAccountImpl) Address() common.Address {
    35  	return acct.Addr
    36  }
    37  
    38  func (acct *NormalAccountImpl) PublicKey() crypto.PublicKey {
    39  	return acct.PrivKey.Public()
    40  }
    41  
    42  type MultipleAccountImpl struct {
    43  	Addr *common.Address
    44  	Maus MultiAccountUnits
    45  }
    46  
    47  func (mai *MultipleAccountImpl) PublicKey() crypto.PublicKey {
    48  	return nil
    49  }
    50  
    51  func (mai *MultipleAccountImpl) ExistPubkey(pubKey crypto.PublicKey) bool {
    52  
    53  	for _, arr := range mai.Maus {
    54  		for _, ele := range arr.Pubkeys {
    55  			if bytes.Compare(pubKey.Bytes(), ele.Bytes()) == 0 {
    56  				return true
    57  			}
    58  		}
    59  	}
    60  
    61  	return false
    62  }
    63  
    64  func (mai *MultipleAccountImpl) OnlyPubkey() crypto.PublicKey {
    65  	if len(mai.Maus) != 1 {
    66  		return nil
    67  	}
    68  	if len(mai.Maus[0].Pubkeys) != 1 {
    69  		return nil
    70  	}
    71  	return mai.Maus[0].Pubkeys[0]
    72  }
    73  
    74  func (acct *MultipleAccountImpl) Address() common.Address {
    75  	return *acct.Addr
    76  }
    77  
    78  func (acct *MultipleAccountImpl) Sign(hash []byte) (sig []byte, err error) {
    79  	return nil, errors.SIG_ERR_NOT_SUPPORT
    80  }
    81  
    82  func (acct *MultipleAccountImpl) Verify(hash, sig []byte) (bool, error) {
    83  
    84  	return false, errors.SIG_ERR_NOT_SUPPORT
    85  }
    86  
    87  type AccountManagerImpl struct {
    88  	// keystore
    89  	ks *acct.Keystore
    90  
    91  	// key save path
    92  	keydir string
    93  
    94  	//multi addr save path
    95  	multiAddrDir string
    96  
    97  	// account slice
    98  	accounts []*account
    99  
   100  	mutex sync.Mutex
   101  
   102  	acctMulMap  map[string]MultiMap
   103  	accMulMutex sync.Mutex
   104  }
   105  
   106  type MultiMap map[string]MultipleAccountImpl
   107  
   108  func NewManager() (*AccountManagerImpl, error) {
   109  	m := new(AccountManagerImpl)
   110  	m.ks = acct.DefaultKS
   111  	tmpKeyDir, err := filepath.Abs(config.DefaultKeyDir)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	m.keydir = tmpKeyDir
   116  
   117  	mulTmpDir, err := filepath.Abs(config.DefaultMultiAddrDir)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	m.multiAddrDir = mulTmpDir
   122  	m.acctMulMap = make(map[string]MultiMap)
   123  	if err := m.refreshAccounts(); err != nil {
   124  		return nil, err
   125  	}
   126  	if err := m.refreshMulTmplts(); err != nil {
   127  		return nil, err
   128  	}
   129  	return m, nil
   130  }
   131  
   132  func (am *AccountManagerImpl) GenerateNormalAccount(password string) (NormalAccount, error) {
   133  
   134  	privk, err := crypto.GenerateKey()
   135  
   136  	if err != nil {
   137  		log.Error("generate key err", err)
   138  		return nil, err
   139  	}
   140  	na := new(NormalAccountImpl)
   141  	na.PrivKey = privk
   142  
   143  	bytes := na.PublicKey().Bytes()
   144  	hash := common.Sha256Ripemd160(bytes)
   145  	na.Addr = common.BytesToAddress(hash, common.NormalAddress)
   146  
   147  	passphrase := []byte(password)
   148  	addr, err := am.setKeyStore(privk, passphrase, common.NormalAddress)
   149  	if err != nil {
   150  		return nil, err
   151  	}
   152  
   153  	path, err := am.exportFile(addr, passphrase, false)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	am.updateAccount(addr, path)
   159  
   160  	return na, nil
   161  }
   162  
   163  func (am *AccountManagerImpl) CreateTraAccount(password string) (NormalAccount, error) {
   164  
   165  	privk, err := crypto.GenerateKey()
   166  
   167  	if err != nil {
   168  		log.Error("generate key err", err)
   169  		return nil, err
   170  	}
   171  	na := new(NormalAccountImpl)
   172  	na.PrivKey = privk
   173  
   174  	bytes := na.PublicKey().Bytes()
   175  	hash := common.Sha256Ripemd160(bytes)
   176  	na.Addr = common.BytesToAddress(hash, common.NormalAddress)
   177  
   178  	passphrase := []byte(password)
   179  	addr, err := am.setKeyStore(privk, passphrase, common.NormalAddress)
   180  	if err != nil {
   181  		return nil, err
   182  	}
   183  
   184  	path, err := am.exportFile(addr, passphrase, false)
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	am.updateAccount(addr, path)
   190  
   191  	return na, nil
   192  }
   193  
   194  func (am *AccountManagerImpl) OneKeyToAddress(pubk crypto.PublicKey) (common.Address, error) {
   195  	mult := MultiAccountUnit{1, []crypto.PublicKey{pubk}}
   196  
   197  	muls := make(MultiAccountUnits, 1)
   198  	muls[0] = mult
   199  
   200  	return muls.Address()
   201  }
   202  
   203  func (am *AccountManagerImpl) ImportKeyNormal(prvk, password string) (NormalAccount, error) {
   204  	privk, err := crypto.HexToPrivateKey(prvk)
   205  
   206  	if err != nil {
   207  		log.Error("Hex To Private Key err", "error", err)
   208  		return nil, err
   209  	}
   210  	na := new(NormalAccountImpl)
   211  	na.PrivKey = privk
   212  
   213  
   214  	mult := MultiAccountUnit{1, []crypto.PublicKey{privk.Public()}}
   215  
   216  	muls := make(MultiAccountUnits, 1)
   217  	muls[0] = mult
   218  
   219  	muladdr, err := muls.Address()
   220  
   221  	if err != nil {
   222  		log.Error("create multiple account err", "units.Address", err)
   223  		return nil, err
   224  	}
   225  	muladdrstr := muladdr.ToString()
   226  	fmt.Printf("muladdrstr=%s\n", muladdrstr)
   227  
   228  	paswphrase := []byte(password)
   229  	err = am.setOneKeyStore(privk, paswphrase, muladdr)
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  
   234  	path, err := am.exportFile(muladdr, paswphrase, false)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  
   239  	am.updateAccount(muladdr, path)
   240  
   241  	mulpath := filepath.Join(am.multiAddrDir, muladdr.ToString(), muladdr.ToString())
   242  
   243  	mulac := new(MultipleAccountImpl)
   244  	mulac.Addr = &muladdr
   245  	mulac.Maus = muls
   246  
   247  	am.accMulMutex.Lock()
   248  
   249  	if mulmap, ok := am.acctMulMap[muladdr.ToString()]; !ok {
   250  		mulmap = make(MultiMap)
   251  	} else {
   252  		mulmap[muladdr.ToString()] = *mulac
   253  	}
   254  
   255  	am.accMulMutex.Unlock()
   256  
   257  	//rawbuf := new(bytes.Buffer)
   258  
   259  	mpk := new(MulPack)
   260  	mpk.Mulstr = muladdr.ToString()
   261  	mpk.Tmplt = muls.ToObj()
   262  
   263  	rawbuf, err := json.Marshal(mpk)
   264  	//err = rlp.Encode(rawbuf,mpk)
   265  
   266  	if err != nil {
   267  		return nil, err
   268  	}
   269  
   270  	if err := common.FileWrite(mulpath, rawbuf, false); err != nil {
   271  		log.Error("create multiple account err", "common.FileWrite", err)
   272  		return nil, err
   273  	}
   274  
   275  	return na, nil
   276  }
   277  
   278  func (am *AccountManagerImpl) ImportKeyNode(prvk, password string) (NormalAccount, error) {
   279  	privk, err := crypto.HexToPrivateKey(prvk)
   280  
   281  	if err != nil {
   282  		log.Error("Hex To Private Key err", "error", err)
   283  		return nil, err
   284  	}
   285  	na := new(NodeAccountImpl)
   286  	na.PrivKey = privk
   287  
   288  	bytes := na.PublicKey().Bytes()
   289  	hash := common.Sha256Ripemd160(bytes)
   290  	na.Addr = common.BytesToAddress(hash, common.NodeAddress)
   291  
   292  	passphrase := []byte(password)
   293  	addr, err := am.setKeyStore(privk, passphrase, common.NodeAddress)
   294  	if err != nil {
   295  		return nil, err
   296  	}
   297  
   298  	path, err := am.exportFile(addr, passphrase, false)
   299  	if err != nil {
   300  		return nil, err
   301  	}
   302  
   303  	am.updateAccount(addr, path)
   304  
   305  	return na, nil
   306  }
   307  
   308  func (am *AccountManagerImpl) GenerateNodeAccount(password string) (NodeAccount, error) {
   309  
   310  	privk, err := crypto.GenerateKey()
   311  
   312  	if err != nil {
   313  		log.Error("generate key err", err)
   314  		return nil, err
   315  	}
   316  	na := new(NodeAccountImpl)
   317  	na.PrivKey = privk
   318  
   319  	bytes := na.PublicKey().Bytes()
   320  	hash := common.Sha256Ripemd160(bytes)
   321  	na.Addr = common.BytesToAddress(hash, common.NodeAddress)
   322  
   323  	passphrase := []byte(password)
   324  	addr, err := am.setKeyStore(privk, passphrase, common.NodeAddress)
   325  	if err != nil {
   326  		return nil, err
   327  	}
   328  
   329  	path, err := am.exportFile(addr, passphrase, false)
   330  	if err != nil {
   331  		return nil, err
   332  	}
   333  
   334  	am.updateAccount(addr, path)
   335  
   336  	return na, nil
   337  }
   338  
   339  func (am *AccountManagerImpl) CreateMultipleAccount(addr common.Address, units MultiAccountUnits) (MultipleAccount, error) {
   340  
   341  	muladdr, err := units.Address()
   342  
   343  	if err != nil {
   344  		log.Error("create multiple account err", "units.Address", err)
   345  		return nil, err
   346  	}
   347  
   348  	mulpath := filepath.Join(am.multiAddrDir, addr.ToString(), muladdr.ToString())
   349  
   350  	mulac := new(MultipleAccountImpl)
   351  	mulac.Addr = &muladdr
   352  	mulac.Maus = units
   353  
   354  	am.accMulMutex.Lock()
   355  
   356  	if mulmap, ok := am.acctMulMap[addr.ToString()]; !ok {
   357  		mulmap = make(MultiMap)
   358  	} else {
   359  		mulmap[muladdr.ToString()] = *mulac
   360  	}
   361  
   362  	am.accMulMutex.Unlock()
   363  
   364  	//rawbuf := new(bytes.Buffer)
   365  
   366  	mpk := new(MulPack)
   367  	mpk.Mulstr = muladdr.ToString()
   368  	mpk.Tmplt = units.ToObj()
   369  
   370  	rawbuf, err := json.Marshal(mpk)
   371  	//err = rlp.Encode(rawbuf,mpk)
   372  
   373  	if err != nil {
   374  		return nil, err
   375  	}
   376  
   377  	if err := common.FileWrite(mulpath, rawbuf, false); err != nil {
   378  		log.Error("create multiple account err", "common.FileWrite", err)
   379  		return nil, err
   380  	}
   381  
   382  	return mulac, err
   383  }
   384  
   385  func (am *AccountManagerImpl) GetNormalAccount(addr common.Address, password string) (NormalAccount, error) {
   386  	passphrase := []byte(password)
   387  
   388  	addrstr := addr.ToString()
   389  	res, err := am.ks.ContainsAlias(addrstr)
   390  	if err != nil || res == false {
   391  		err = am.loadFile(addr, passphrase)
   392  		if err != nil {
   393  			fmt.Printf("👠 fu ck\n")
   394  			return nil, err
   395  		}
   396  	}
   397  
   398  	privk, err := am.ks.GetKey(addr.ToString(), passphrase)
   399  	if err != nil {
   400  		fmt.Printf("👠 fu2ck,address=%s\n",addr.ToString())
   401  		return nil, err
   402  	}
   403  
   404  	na := new(NormalAccountImpl)
   405  	na.PrivKey = privk
   406  	bytes := na.PublicKey().Bytes()
   407  	hash := common.Sha256Ripemd160(bytes)
   408  	na.Addr = common.BytesToAddress(hash, common.NormalAddress)
   409  	return na, err
   410  }
   411  
   412  //func (am *AccountManagerImpl) GetMultipleAccount(addr, multiAddr common.Address, selfPass string) (MultipleAccount, error) {
   413  //
   414  //	//fmt.Printf("watch addr=%s\n", addr.ToString())
   415  //	//fmt.Printf("watch mult=%s\n", multiAddr.ToString())
   416  //	passphrase := []byte(selfPass)
   417  //
   418  //	res, err := am.ks.ContainsAlias(addr.ToString())
   419  //	if err != nil || res == false {
   420  //		err = am.loadFile(addr, passphrase)
   421  //		if err != nil {
   422  //			return nil, err
   423  //		}
   424  //	}
   425  //
   426  //	_, err = am.ks.GetKey(addr.ToString(), passphrase)
   427  //
   428  //	if err != nil {
   429  //		log.Info("GetMultipleAccount err", "AccountManagerImpl.ks.GetKey", err)
   430  //		return nil, err
   431  //	}
   432  //
   433  //	addrstr := addr.ToString()
   434  //	multstr := multiAddr.ToString()
   435  //
   436  //	am.accMulMutex.Lock()
   437  //	defer am.accMulMutex.Unlock()
   438  //
   439  //	rt, ok := am.acctMulMap[addrstr]
   440  //
   441  //	if !ok {
   442  //		return nil, errors.ERR_ACCT_MULADDR_NOT_FOUND
   443  //	}
   444  //
   445  //	fnrt, ok := rt[multstr]
   446  //
   447  //	if !ok {
   448  //		return nil, errors.ERR_ACCT_MULADDR_NOT_FOUND
   449  //
   450  //	}
   451  //	return &fnrt, nil
   452  //}
   453  
   454  func (am *AccountManagerImpl) GetMultipleAccount(addr, multiAddr common.Address) (MultipleAccount, error) {
   455  	addrstr := addr.ToString()
   456  	multstr := multiAddr.ToString()
   457  
   458  	am.accMulMutex.Lock()
   459  	defer am.accMulMutex.Unlock()
   460  
   461  	rt, ok := am.acctMulMap[addrstr]
   462  
   463  	if !ok {
   464  		return nil, errors.ERR_ACCT_MULADDR_NOT_FOUND
   465  	}
   466  
   467  	fnrt, ok := rt[multstr]
   468  
   469  	if !ok {
   470  		return nil, errors.ERR_ACCT_MULADDR_NOT_FOUND
   471  
   472  	}
   473  	return &fnrt, nil
   474  }
   475  
   476  func (am *AccountManagerImpl) DeleteNormalAccount(addr common.Address, password string) error {
   477  	passphrase := []byte(password)
   478  	err := am.ks.Delete(addr.ToString(), passphrase)
   479  	return err
   480  }
   481  
   482  func (am *AccountManagerImpl) DeleteMultipleAccount(addr, multiAddr common.Address, selfPass string) error {
   483  	_, err := am.ks.GetKey(addr.ToString(), []byte(selfPass))
   484  	if err != nil {
   485  		return err
   486  	}
   487  
   488  	am.accMulMutex.Lock()
   489  
   490  	delete(am.acctMulMap[addr.ToString()], multiAddr.ToString())
   491  
   492  	am.accMulMutex.Unlock()
   493  
   494  	return nil
   495  }
   496  
   497  func (m *AccountManagerImpl) Load(keyjson, passphrase []byte) (common.Address, error) {
   498  	//var account account
   499  	empty := common.Address{}
   500  	cipher := cipher.NewCipher()
   501  	data, err := cipher.DecryptKey(keyjson, passphrase)
   502  	if err != nil {
   503  		return empty, err
   504  	}
   505  	defer common.ZeroBytes(data)
   506  
   507  	priv, err := crypto.ToPrivateKey(data)
   508  	if err != nil {
   509  		return empty, err
   510  	}
   511  	//defer priv.Clear()
   512  
   513  	addr, err := m.setKeyStore(priv, passphrase, common.NormalAddress)
   514  	if err != nil {
   515  		return empty, err
   516  	}
   517  
   518  	if _, err := m.getAccount(addr); err != nil {
   519  		m.mutex.Lock()
   520  		acc := &account{addr: addr}
   521  		m.accounts = append(m.accounts, acc)
   522  		m.mutex.Unlock()
   523  	}
   524  	return addr, nil
   525  }
   526  
   527  func (m *AccountManagerImpl) setKeyStore(priv crypto.PrivateKey, passphrase []byte, addrType common.AddressType) (common.Address, error) {
   528  	empty := common.Address{}
   529  	//pub := priv.Public().Bytes()
   530  
   531  	//hash := common.Sha256Ripemd160(pub)
   532  	//
   533  	//addr := common.BytesToAddress(hash, addrType)
   534  
   535  	addr,err := m.OneKeyToAddress(priv.Public())
   536  	if err != nil {
   537  		return addr,err
   538  	}
   539  
   540  	// set key to keystore
   541  	err = m.ks.SetKey(addr.ToString(), priv, passphrase)
   542  	if err != nil {
   543  		return empty, err
   544  	}
   545  
   546  	return addr, nil
   547  }
   548  
   549  func (m *AccountManagerImpl) setOneKeyStore(priv crypto.PrivateKey, passphrase []byte, addr common.Address) error {
   550  	//empty := common.Address{}
   551  	//pub := priv.Public().Bytes()
   552  
   553  	//hash := common.Sha256Ripemd160(pub)
   554  
   555  	//addr := common.BytesToAddress(hash, addrType)
   556  
   557  	// set key to keystore
   558  	err := m.ks.SetKey(addr.ToString(), priv, passphrase)
   559  	if err != nil {
   560  		return err
   561  	}
   562  
   563  	return nil
   564  }
   565  
   566  func (m *AccountManagerImpl) Export(addr common.Address, passphrase []byte) ([]byte, error) {
   567  	key, err := m.ks.GetKey(addr.ToString(), passphrase)
   568  	if err != nil {
   569  		return nil, err
   570  	}
   571  	//defer key.Clear()
   572  
   573  	data := key.Bytes()
   574  	defer common.ZeroBytes(data)
   575  
   576  	cipher := cipher.NewCipher()
   577  	if err != nil {
   578  		return nil, err
   579  	}
   580  
   581  	out, err := cipher.EncryptKey(addr.ToString(), data, passphrase)
   582  	if err != nil {
   583  		return nil, err
   584  	}
   585  	return out, nil
   586  }
   587  
   588  type LeagueAccountImpl struct {
   589  	Addr common.Address
   590  }
   591  
   592  func (la *LeagueAccountImpl) Address() common.Address {
   593  	return la.Addr
   594  }
   595  
   596  func (am *AccountManagerImpl) CreateOneKeyAccount(password []byte) (MultipleAccount, error) {
   597  	privk, err := crypto.GenerateKey()
   598  
   599  	if err != nil {
   600  		log.Error("generate key err", err)
   601  		return nil, err
   602  	}
   603  
   604  	mult := MultiAccountUnit{1, []crypto.PublicKey{privk.Public()}}
   605  
   606  	muls := make(MultiAccountUnits, 1)
   607  	muls[0] = mult
   608  
   609  	muladdr, err := muls.Address()
   610  
   611  	if err != nil {
   612  		log.Error("create multiple account err", "units.Address", err)
   613  		return nil, err
   614  	}
   615  
   616  	err = am.setOneKeyStore(privk, password, muladdr)
   617  	if err != nil {
   618  		return nil, err
   619  	}
   620  
   621  	path, err := am.exportFile(muladdr, password, false)
   622  	if err != nil {
   623  		return nil, err
   624  	}
   625  
   626  	am.updateAccount(muladdr, path)
   627  
   628  	mulpath := filepath.Join(am.multiAddrDir, muladdr.ToString(), muladdr.ToString())
   629  
   630  	mulac := new(MultipleAccountImpl)
   631  	mulac.Addr = &muladdr
   632  	mulac.Maus = muls
   633  
   634  	am.accMulMutex.Lock()
   635  
   636  	if mulmap, ok := am.acctMulMap[muladdr.ToString()]; !ok {
   637  		mulmap = make(MultiMap)
   638  	} else {
   639  		mulmap[muladdr.ToString()] = *mulac
   640  	}
   641  
   642  	am.accMulMutex.Unlock()
   643  
   644  	//rawbuf := new(bytes.Buffer)
   645  
   646  	mpk := new(MulPack)
   647  	mpk.Mulstr = muladdr.ToString()
   648  	mpk.Tmplt = muls.ToObj()
   649  
   650  	rawbuf, err := json.Marshal(mpk)
   651  	//err = rlp.Encode(rawbuf,mpk)
   652  
   653  	if err != nil {
   654  		return nil, err
   655  	}
   656  
   657  	if err := common.FileWrite(mulpath, rawbuf, false); err != nil {
   658  		log.Error("create multiple account err", "common.FileWrite", err)
   659  		return nil, err
   660  	}
   661  
   662  	return mulac, err
   663  }
   664  
   665  
   666  func (am *AccountManagerImpl) CreateBoxAccount(password []byte,privKeyHex string) (MultipleAccount, error) {
   667  	privk, err := crypto.HexToPrivateKey(privKeyHex)
   668  
   669  	if err != nil {
   670  		log.Error("generate key err", err)
   671  		return nil, err
   672  	}
   673  
   674  	fmt.Printf("private key for test:%s\n", privk.Hex())
   675  
   676  	mult := MultiAccountUnit{1, []crypto.PublicKey{privk.Public()}}
   677  
   678  	muls := make(MultiAccountUnits, 1)
   679  	muls[0] = mult
   680  
   681  	muladdr, err := muls.Address()
   682  
   683  	if err != nil {
   684  		log.Error("create multiple account err", "units.Address", err)
   685  		return nil, err
   686  	}
   687  
   688  	err = am.setOneKeyStore(privk, password, muladdr)
   689  	if err != nil {
   690  		return nil, err
   691  	}
   692  
   693  	path, err := am.exportFile(muladdr, password, false)
   694  	if err != nil {
   695  		return nil, err
   696  	}
   697  
   698  	am.updateAccount(muladdr, path)
   699  
   700  	mulpath := filepath.Join(am.multiAddrDir, muladdr.ToString(), muladdr.ToString())
   701  
   702  	mulac := new(MultipleAccountImpl)
   703  	mulac.Addr = &muladdr
   704  	mulac.Maus = muls
   705  
   706  	am.accMulMutex.Lock()
   707  
   708  	if mulmap, ok := am.acctMulMap[muladdr.ToString()]; !ok {
   709  		mulmap = make(MultiMap)
   710  	} else {
   711  		mulmap[muladdr.ToString()] = *mulac
   712  	}
   713  
   714  	am.accMulMutex.Unlock()
   715  
   716  	//rawbuf := new(bytes.Buffer)
   717  
   718  	mpk := new(MulPack)
   719  	mpk.Mulstr = muladdr.ToString()
   720  	mpk.Tmplt = muls.ToObj()
   721  
   722  	rawbuf, err := json.Marshal(mpk)
   723  	//err = rlp.Encode(rawbuf,mpk)
   724  
   725  	if err != nil {
   726  		return nil, err
   727  	}
   728  
   729  	if err := common.FileWrite(mulpath, rawbuf, false); err != nil {
   730  		log.Error("create multiple account err", "common.FileWrite", err)
   731  		return nil, err
   732  	}
   733  
   734  	return mulac, err
   735  }