github.com/turingchain2020/turingchain@v1.1.21/account/execaccount.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package account
     6  
     7  import (
     8  	"github.com/turingchain2020/turingchain/client"
     9  	"github.com/turingchain2020/turingchain/common/address"
    10  	"github.com/turingchain2020/turingchain/types"
    11  )
    12  
    13  // LoadExecAccount Load exec account from address and exec
    14  func (acc *DB) LoadExecAccount(addr, execaddr string) *types.Account {
    15  	value, err := acc.db.Get(acc.execAccountKey(addr, execaddr))
    16  	if err != nil {
    17  		return &types.Account{Addr: addr}
    18  	}
    19  	var acc1 types.Account
    20  	err = types.Decode(value, &acc1)
    21  	if err != nil {
    22  		panic(err) //数据库已经损坏
    23  	}
    24  	return &acc1
    25  }
    26  
    27  // LoadExecAccountQueue load exec account from statedb
    28  func (acc *DB) LoadExecAccountQueue(api client.QueueProtocolAPI, addr, execaddr string) (*types.Account, error) {
    29  	header, err := api.GetLastHeader()
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	return acc.LoadExecAccountHistoryQueue(api, addr, execaddr, header.GetStateHash())
    34  }
    35  
    36  // SaveExecAccount save exec account data to db
    37  func (acc *DB) SaveExecAccount(execaddr string, acc1 *types.Account) {
    38  	set := acc.GetExecKVSet(execaddr, acc1)
    39  	for i := 0; i < len(set); i++ {
    40  		err := acc.db.Set(set[i].GetKey(), set[i].Value)
    41  		if err != nil {
    42  			panic(err)
    43  		}
    44  	}
    45  }
    46  
    47  // GetExecKVSet 将执行账户数据转为数据库存储kv
    48  func (acc *DB) GetExecKVSet(execaddr string, acc1 *types.Account) (kvset []*types.KeyValue) {
    49  	value := types.Encode(acc1)
    50  	kvset = append(kvset, &types.KeyValue{
    51  		Key:   acc.execAccountKey(acc1.Addr, execaddr),
    52  		Value: value,
    53  	})
    54  	return kvset
    55  }
    56  
    57  func (acc *DB) execAccountKey(address, execaddr string) (key []byte) {
    58  	key = make([]byte, 0, len(acc.execAccountKeyPerfix)+len(execaddr)+len(address)+1)
    59  	key = append(key, acc.execAccountKeyPerfix...)
    60  	key = append(key, []byte(execaddr)...)
    61  	key = append(key, []byte(":")...)
    62  	key = append(key, []byte(address)...)
    63  	return key
    64  }
    65  
    66  // TransferToExec transfer coins from address to exec address
    67  func (acc *DB) TransferToExec(from, to string, amount int64) (*types.Receipt, error) {
    68  	receipt, err := acc.Transfer(from, to, amount)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	receipt2, err := acc.ExecDeposit(from, to, amount)
    73  	if err != nil {
    74  		//存款不应该出任何问题
    75  		panic(err)
    76  	}
    77  	return acc.mergeReceipt(receipt, receipt2), nil
    78  }
    79  
    80  // TransferWithdraw 撤回转帐
    81  func (acc *DB) TransferWithdraw(from, to string, amount int64) (*types.Receipt, error) {
    82  	//先判断可以取款
    83  	if err := acc.CheckTransfer(to, from, amount); err != nil {
    84  		return nil, err
    85  	}
    86  	receipt, err := acc.ExecWithdraw(to, from, amount)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	//然后执行transfer
    91  	receipt2, err := acc.Transfer(to, from, amount)
    92  	if err != nil {
    93  		panic(err) //在withdraw
    94  	}
    95  	return acc.mergeReceipt(receipt, receipt2), nil
    96  }
    97  
    98  //ExecFrozen 执行冻结资金,四个操作中 Deposit 自动完成,不需要模块外的函数来调用
    99  func (acc *DB) ExecFrozen(addr, execaddr string, amount int64) (*types.Receipt, error) {
   100  	if addr == execaddr {
   101  		return nil, types.ErrSendSameToRecv
   102  	}
   103  	if !types.CheckAmount(amount) {
   104  		return nil, types.ErrAmount
   105  	}
   106  	acc1 := acc.LoadExecAccount(addr, execaddr)
   107  	if acc1.Balance-amount < 0 {
   108  		alog.Error("ExecFrozen", "balance", acc1.Balance, "amount", amount)
   109  		return nil, types.ErrNoBalance
   110  	}
   111  	copyacc := *acc1
   112  	acc1.Balance -= amount
   113  	acc1.Frozen += amount
   114  	receiptBalance := &types.ReceiptExecAccountTransfer{
   115  		ExecAddr: execaddr,
   116  		Prev:     &copyacc,
   117  		Current:  acc1,
   118  	}
   119  	acc.SaveExecAccount(execaddr, acc1)
   120  	ty := int32(types.TyLogExecFrozen)
   121  	return acc.execReceipt(ty, acc1, receiptBalance), nil
   122  }
   123  
   124  // ExecActive 执行激活资金
   125  func (acc *DB) ExecActive(addr, execaddr string, amount int64) (*types.Receipt, error) {
   126  	if addr == execaddr {
   127  		return nil, types.ErrSendSameToRecv
   128  	}
   129  	if !types.CheckAmount(amount) {
   130  		return nil, types.ErrAmount
   131  	}
   132  	acc1 := acc.LoadExecAccount(addr, execaddr)
   133  	if acc1.Frozen-amount < 0 {
   134  		return nil, types.ErrNoBalance
   135  	}
   136  	copyacc := *acc1
   137  	acc1.Balance += amount
   138  	acc1.Frozen -= amount
   139  	receiptBalance := &types.ReceiptExecAccountTransfer{
   140  		ExecAddr: execaddr,
   141  		Prev:     &copyacc,
   142  		Current:  acc1,
   143  	}
   144  	acc.SaveExecAccount(execaddr, acc1)
   145  	ty := int32(types.TyLogExecActive)
   146  	return acc.execReceipt(ty, acc1, receiptBalance), nil
   147  }
   148  
   149  // ExecTransfer 执行转帐
   150  func (acc *DB) ExecTransfer(from, to, execaddr string, amount int64) (*types.Receipt, error) {
   151  	if from == to {
   152  		return nil, types.ErrSendSameToRecv
   153  	}
   154  	if !types.CheckAmount(amount) {
   155  		return nil, types.ErrAmount
   156  	}
   157  	accFrom := acc.LoadExecAccount(from, execaddr)
   158  	accTo := acc.LoadExecAccount(to, execaddr)
   159  
   160  	if accFrom.GetBalance()-amount < 0 {
   161  		return nil, types.ErrNoBalance
   162  	}
   163  	copyaccFrom := *accFrom
   164  	copyaccTo := *accTo
   165  
   166  	accFrom.Balance -= amount
   167  	accTo.Balance += amount
   168  
   169  	receiptBalanceFrom := &types.ReceiptExecAccountTransfer{
   170  		ExecAddr: execaddr,
   171  		Prev:     &copyaccFrom,
   172  		Current:  accFrom,
   173  	}
   174  	receiptBalanceTo := &types.ReceiptExecAccountTransfer{
   175  		ExecAddr: execaddr,
   176  		Prev:     &copyaccTo,
   177  		Current:  accTo,
   178  	}
   179  
   180  	acc.SaveExecAccount(execaddr, accFrom)
   181  	acc.SaveExecAccount(execaddr, accTo)
   182  	return acc.execReceipt2(accFrom, accTo, receiptBalanceFrom, receiptBalanceTo), nil
   183  }
   184  
   185  // ExecTransferFrozen 从自己冻结的钱里面扣除,转移到别人的活动钱包里面去
   186  func (acc *DB) ExecTransferFrozen(from, to, execaddr string, amount int64) (*types.Receipt, error) {
   187  	if from == to {
   188  		return nil, types.ErrSendSameToRecv
   189  	}
   190  	if !types.CheckAmount(amount) {
   191  		return nil, types.ErrAmount
   192  	}
   193  	accFrom := acc.LoadExecAccount(from, execaddr)
   194  	accTo := acc.LoadExecAccount(to, execaddr)
   195  	b := accFrom.GetFrozen() - amount
   196  	if b < 0 {
   197  		return nil, types.ErrNoBalance
   198  	}
   199  	copyaccFrom := *accFrom
   200  	copyaccTo := *accTo
   201  
   202  	accFrom.Frozen -= amount
   203  	accTo.Balance += amount
   204  
   205  	receiptBalanceFrom := &types.ReceiptExecAccountTransfer{
   206  		ExecAddr: execaddr,
   207  		Prev:     &copyaccFrom,
   208  		Current:  accFrom,
   209  	}
   210  	receiptBalanceTo := &types.ReceiptExecAccountTransfer{
   211  		ExecAddr: execaddr,
   212  		Prev:     &copyaccTo,
   213  		Current:  accTo,
   214  	}
   215  
   216  	acc.SaveExecAccount(execaddr, accFrom)
   217  	acc.SaveExecAccount(execaddr, accTo)
   218  	return acc.execReceipt2(accFrom, accTo, receiptBalanceFrom, receiptBalanceTo), nil
   219  }
   220  
   221  // ExecAddress 根据执行器名称获取执行器地址
   222  func (acc *DB) ExecAddress(name string) string {
   223  	return address.ExecAddress(name)
   224  }
   225  
   226  // ExecDepositFrozen 执行增发coins到具体的地址,并冻结
   227  func (acc *DB) ExecDepositFrozen(addr, execaddr string, amount int64) (*types.Receipt, error) {
   228  	if addr == execaddr {
   229  		return nil, types.ErrSendSameToRecv
   230  	}
   231  	//issue coins to exec addr
   232  	receipt1, err := acc.ExecIssueCoins(execaddr, amount)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  	receipt2, err := acc.execDepositFrozen(addr, execaddr, amount)
   237  	if err != nil {
   238  		return nil, err
   239  	}
   240  	return acc.mergeReceipt(receipt1, receipt2), nil
   241  }
   242  
   243  // ExecIssueCoins 增发coins到具体的挖矿合约
   244  func (acc *DB) ExecIssueCoins(execaddr string, amount int64) (*types.Receipt, error) {
   245  	cfg := acc.cfg
   246  	//这个函数只有挖矿的合约才能调用
   247  	allow := false
   248  	for _, exec := range cfg.GetMinerExecs() {
   249  		if acc.ExecAddress(cfg.ExecName(exec)) == execaddr {
   250  			allow = true
   251  			break
   252  		}
   253  	}
   254  	if !allow {
   255  		return nil, types.ErrNotAllowDeposit
   256  	}
   257  	receipt, err := acc.depositBalance(execaddr, amount)
   258  	if err != nil {
   259  		return nil, err
   260  	}
   261  	return receipt, nil
   262  }
   263  
   264  func (acc *DB) execDepositFrozen(addr, execaddr string, amount int64) (*types.Receipt, error) {
   265  	if addr == execaddr {
   266  		return nil, types.ErrSendSameToRecv
   267  	}
   268  	if !types.CheckAmount(amount) {
   269  		return nil, types.ErrAmount
   270  	}
   271  	acc1 := acc.LoadExecAccount(addr, execaddr)
   272  	copyacc := *acc1
   273  	acc1.Frozen += amount
   274  	receiptBalance := &types.ReceiptExecAccountTransfer{
   275  		ExecAddr: execaddr,
   276  		Prev:     &copyacc,
   277  		Current:  acc1,
   278  	}
   279  	acc.SaveExecAccount(execaddr, acc1)
   280  	ty := int32(types.TyLogExecDeposit)
   281  	return acc.execReceipt(ty, acc1, receiptBalance), nil
   282  }
   283  
   284  // ExecDeposit  在当前addr的execaddr地址中存款
   285  func (acc *DB) ExecDeposit(addr, execaddr string, amount int64) (*types.Receipt, error) {
   286  	if addr == execaddr {
   287  		return nil, types.ErrSendSameToRecv
   288  	}
   289  	if !types.CheckAmount(amount) {
   290  		return nil, types.ErrAmount
   291  	}
   292  	acc1 := acc.LoadExecAccount(addr, execaddr)
   293  	copyacc := *acc1
   294  	acc1.Balance += amount
   295  	receiptBalance := &types.ReceiptExecAccountTransfer{
   296  		ExecAddr: execaddr,
   297  		Prev:     &copyacc,
   298  		Current:  acc1,
   299  	}
   300  	//alog.Debug("execDeposit", "addr", addr, "execaddr", execaddr, "account", acc)
   301  	acc.SaveExecAccount(execaddr, acc1)
   302  	ty := int32(types.TyLogExecDeposit)
   303  	return acc.execReceipt(ty, acc1, receiptBalance), nil
   304  }
   305  
   306  // ExecWithdraw 执行撤回转帐
   307  func (acc *DB) ExecWithdraw(execaddr, addr string, amount int64) (*types.Receipt, error) {
   308  	if addr == execaddr {
   309  		return nil, types.ErrSendSameToRecv
   310  	}
   311  	if !types.CheckAmount(amount) {
   312  		return nil, types.ErrAmount
   313  	}
   314  	acc1 := acc.LoadExecAccount(addr, execaddr)
   315  	if acc1.Balance-amount < 0 {
   316  		return nil, types.ErrNoBalance
   317  	}
   318  	copyacc := *acc1
   319  	acc1.Balance -= amount
   320  	receiptBalance := &types.ReceiptExecAccountTransfer{
   321  		ExecAddr: execaddr,
   322  		Prev:     &copyacc,
   323  		Current:  acc1,
   324  	}
   325  	acc.SaveExecAccount(execaddr, acc1)
   326  	ty := int32(types.TyLogExecWithdraw)
   327  	return acc.execReceipt(ty, acc1, receiptBalance), nil
   328  }
   329  
   330  func (acc *DB) execReceipt(ty int32, acc1 *types.Account, r *types.ReceiptExecAccountTransfer) *types.Receipt {
   331  	log1 := &types.ReceiptLog{
   332  		Ty:  ty,
   333  		Log: types.Encode(r),
   334  	}
   335  	kv := acc.GetExecKVSet(r.ExecAddr, acc1)
   336  	return &types.Receipt{
   337  		Ty:   types.ExecOk,
   338  		KV:   kv,
   339  		Logs: []*types.ReceiptLog{log1},
   340  	}
   341  }
   342  
   343  func (acc *DB) execReceipt2(acc1, acc2 *types.Account, r1, r2 *types.ReceiptExecAccountTransfer) *types.Receipt {
   344  	ty := int32(types.TyLogExecTransfer)
   345  	log1 := &types.ReceiptLog{
   346  		Ty:  ty,
   347  		Log: types.Encode(r1),
   348  	}
   349  	log2 := &types.ReceiptLog{
   350  		Ty:  ty,
   351  		Log: types.Encode(r2),
   352  	}
   353  	kv := acc.GetExecKVSet(r1.ExecAddr, acc1)
   354  	kv = append(kv, acc.GetExecKVSet(r2.ExecAddr, acc2)...)
   355  	return &types.Receipt{
   356  		Ty:   types.ExecOk,
   357  		KV:   kv,
   358  		Logs: []*types.ReceiptLog{log1, log2},
   359  	}
   360  }
   361  
   362  func (acc *DB) mergeReceipt(receipt, receipt2 *types.Receipt) *types.Receipt {
   363  	receipt.Logs = append(receipt.Logs, receipt2.Logs...)
   364  	receipt.KV = append(receipt.KV, receipt2.KV...)
   365  	return receipt
   366  }
   367  
   368  // LoadExecAccountHistoryQueue  载入当前statehash,载入执行账户数据
   369  func (acc *DB) LoadExecAccountHistoryQueue(api client.QueueProtocolAPI, addr, execaddr string, stateHash []byte) (*types.Account, error) {
   370  	get := types.StoreGet{StateHash: stateHash}
   371  	get.Keys = append(get.Keys, acc.execAccountKey(addr, execaddr))
   372  	values, err := api.StoreGet(&get)
   373  	if err != nil {
   374  		return nil, err
   375  	}
   376  	if len(values.Values) <= 0 {
   377  		return nil, types.ErrNotFound
   378  	}
   379  	value := values.Values[0]
   380  	if value == nil {
   381  		return &types.Account{Addr: addr}, nil
   382  	}
   383  
   384  	var acc1 types.Account
   385  	err = types.Decode(value, &acc1)
   386  	if err != nil {
   387  		return nil, err
   388  	}
   389  
   390  	return &acc1, nil
   391  }