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: ©acc, 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: ©acc, 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: ©accFrom, 172 Current: accFrom, 173 } 174 receiptBalanceTo := &types.ReceiptExecAccountTransfer{ 175 ExecAddr: execaddr, 176 Prev: ©accTo, 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: ©accFrom, 208 Current: accFrom, 209 } 210 receiptBalanceTo := &types.ReceiptExecAccountTransfer{ 211 ExecAddr: execaddr, 212 Prev: ©accTo, 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: ©acc, 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: ©acc, 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: ©acc, 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 }