Commit 69245823 authored by linj's avatar linj Committed by linj

impl unfreeze.exec

parent 12f5fdc8
...@@ -3,200 +3,30 @@ package executor ...@@ -3,200 +3,30 @@ package executor
import ( import (
"time" "time"
"gitlab.33.cn/chain33/chain33/account"
"gitlab.33.cn/chain33/chain33/common"
dbm "gitlab.33.cn/chain33/chain33/common/db" dbm "gitlab.33.cn/chain33/chain33/common/db"
uf "gitlab.33.cn/chain33/chain33/plugin/dapp/unfreeze/types" pty "gitlab.33.cn/chain33/chain33/plugin/dapp/unfreeze/types"
"gitlab.33.cn/chain33/chain33/system/dapp"
"gitlab.33.cn/chain33/chain33/types" "gitlab.33.cn/chain33/chain33/types"
) )
type action struct {
coinsAccount *account.DB
db dbm.KV
txhash []byte
fromaddr string
blocktime int64
height int64
index int32
execaddr string
}
func newAction(u *Unfreeze, tx *types.Transaction, index int32) *action {
hash := tx.Hash()
fromaddr := tx.From()
return &action{u.GetCoinsAccount(), u.GetStateDB(), hash, fromaddr,
u.GetBlockTime(), u.GetHeight(), index, dapp.ExecAddress(string(tx.Execer))}
}
//创建解冻交易
func (a *action) UnfreezeCreate(create *uf.UnfreezeCreate) (*types.Receipt, error) {
//构造ID - txHash
var unfreezeID string = "unfreezeID_" + common.ToHex(a.txhash)
tokenAccDB, err := account.NewAccountDB(create.AssetExec, create.AssetSymbol, a.db)
if err != nil {
return nil, err
}
receipt, err := tokenAccDB.ExecFrozen(a.fromaddr, a.execaddr, create.TotalCount)
if err != nil {
uflog.Error("unfreeze create ", "addr", a.fromaddr, "execaddr", a.execaddr, "ExecFrozen amount", create.TotalCount)
return nil, err
}
var logs []*types.ReceiptLog
var kv []*types.KeyValue
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
unfreeze := &uf.Unfreeze{
UnfreezeID: unfreezeID,
StartTime: create.StartTime,
AssetExec: create.AssetExec,
AssetSymbol: create.AssetSymbol,
TotalCount: create.TotalCount,
Initiator: a.fromaddr,
Beneficiary: create.Beneficiary,
Means: create.Means,
// TODO set option
}
a.saveStateDB(unfreeze)
k := []byte(unfreezeID)
v := types.Encode(unfreeze)
kv = append(kv, &types.KeyValue{k, v})
receiptLog := a.getUnfreezeLog(unfreeze)
logs = append(logs, receiptLog)
return &types.Receipt{types.ExecOk, kv, logs}, nil
}
//提取解冻币
func (a *action) UnfreezeWithdraw(withdraw *uf.UnfreezeWithdraw) (*types.Receipt, error) {
value, err := a.db.Get(key(withdraw.UnfreezeID))
if err != nil {
uflog.Error("unfreeze withdraw ", "execaddr", a.execaddr, "err", err)
return nil, err
}
var unfreeze uf.Unfreeze
err = types.Decode(value, &unfreeze)
if err != nil {
uflog.Error("unfreeze withdraw ", "execaddr", a.execaddr, "err", err)
return nil, err
}
var logs []*types.ReceiptLog
var kv []*types.KeyValue
_, available, err := getWithdrawAvailable(unfreeze, a.blocktime)
if err != nil {
uflog.Error("unfreeze withdraw ", "execaddr", a.execaddr, "err", err)
return nil, err
}
tokenAccDB, err := account.NewAccountDB(unfreeze.AssetExec, unfreeze.AssetSymbol, a.db)
if err != nil {
return nil, err
}
receipt, err := tokenAccDB.ExecTransferFrozen(unfreeze.Initiator, a.fromaddr, a.execaddr, available)
if err != nil {
uflog.Error("unfreeze withdraw ", "execaddr", a.execaddr, "err", err)
return nil, err
}
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
//unfreeze.WithdrawTimes += int32(reaTimes)
unfreeze.Remaining -= available
a.saveStateDB(&unfreeze)
receiptLog := a.getUnfreezeLog(&unfreeze)
logs = append(logs, receiptLog)
k := []byte(withdraw.UnfreezeID)
v := types.Encode(&unfreeze)
kv = append(kv, &types.KeyValue{k, v})
return &types.Receipt{types.ExecOk, kv, logs}, nil
}
//中止定期解冻
func (a *action) UnfreezeTerminate(terminate *uf.UnfreezeTerminate) (*types.Receipt, error) {
value, err := a.db.Get(key(terminate.UnfreezeID))
if err != nil {
uflog.Error("unfreeze terminate ", "execaddr", a.execaddr, "err", err)
return nil, err
}
var unfreeze uf.Unfreeze
err = types.Decode(value, &unfreeze)
if err != nil {
uflog.Error("unfreeze terminate ", "execaddr", a.execaddr, "err", err)
return nil, err
}
if a.fromaddr != unfreeze.Initiator {
uflog.Error("unfreeze terminate ", "execaddr", a.execaddr, "err", uf.ErrUnfreezeID)
return nil, uf.ErrUnfreezeID
}
if unfreeze.Remaining <= 0 {
uflog.Error("unfreeze terminate ", "execaddr", a.execaddr, "err", uf.ErrUnfreezeEmptied)
return nil, uf.ErrUnfreezeEmptied
}
tokenAccDB, err := account.NewAccountDB(unfreeze.AssetExec, unfreeze.AssetSymbol, a.db)
if err != nil {
return nil, err
}
receipt, err := tokenAccDB.ExecActive(unfreeze.Initiator, a.execaddr, unfreeze.Remaining)
if err != nil {
uflog.Error("unfreeze terminate ", "addr", unfreeze.Initiator, "execaddr", a.execaddr, "err", err)
return nil, err
}
var logs []*types.ReceiptLog
var kv []*types.KeyValue
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
unfreeze.Remaining = 0
a.saveStateDB(&unfreeze)
receiptLog := a.getUnfreezeLog(&unfreeze)
logs = append(logs, receiptLog)
k := []byte(terminate.UnfreezeID)
v := types.Encode(&unfreeze)
kv = append(kv, &types.KeyValue{k, v})
return &types.Receipt{types.ExecOk, kv, logs}, nil
}
func (a *action) saveStateDB(unfreeze *uf.Unfreeze) {
a.db.Set(key(unfreeze.GetUnfreezeID()), types.Encode(unfreeze))
}
func key(id string) (keys []byte) {
keys = append(keys, []byte("mavl-"+uf.UnfreezeX+"-")...)
keys = append(keys, []byte(id)...)
return keys
}
func (a *action) getUnfreezeLog(unfreeze *uf.Unfreeze) *types.ReceiptLog {
log := &types.ReceiptLog{}
log.Ty = uf.TyLogCreateUnfreeze
r := &uf.ReceiptUnfreeze{}
r.UnfreezeID = unfreeze.UnfreezeID
r.Initiator = unfreeze.Initiator
r.Beneficiary = unfreeze.Beneficiary
r.TokenName = unfreeze.AssetSymbol // TODO exec
log.Log = types.Encode(r)
return log
}
//查询可提币状态 //查询可提币状态
func QueryUnfreezeWithdraw(stateDB dbm.KV, param *uf.QueryUnfreezeWithdraw) (types.Message, error) { func QueryUnfreezeWithdraw(stateDB dbm.KV, param *pty.QueryUnfreezeWithdraw) (types.Message, error) {
//查询提币次数 //查询提币次数
//计算当前可否提币 //计算当前可否提币
unfreezeID := param.UnfreezeID unfreezeID := param.UnfreezeID
value, err := stateDB.Get(key(unfreezeID)) value, err := stateDB.Get([]byte(unfreezeID))
if err != nil { if err != nil {
uflog.Error("QueryWithdraw ", "unfreezeID", unfreezeID, "err", err) uflog.Error("QueryWithdraw ", "unfreezeID", unfreezeID, "err", err)
return nil, err return nil, err
} }
var unfreeze uf.Unfreeze var unfreeze pty.Unfreeze
err = types.Decode(value, &unfreeze) err = types.Decode(value, &unfreeze)
if err != nil { if err != nil {
uflog.Error("QueryWithdraw ", "unfreezeID", unfreezeID, "err", err) uflog.Error("QueryWithdraw ", "unfreezeID", unfreezeID, "err", err)
return nil, err return nil, err
} }
currentTime := time.Now().Unix() // TODO currentTime := time.Now().Unix()
reply := &uf.ReplyQueryUnfreezeWithdraw{UnfreezeID: unfreezeID} reply := &pty.ReplyQueryUnfreezeWithdraw{UnfreezeID: unfreezeID}
_, available, err := getWithdrawAvailable(unfreeze, currentTime) available, err := getWithdrawAvailable(&unfreeze, currentTime)
if err != nil { if err != nil {
reply.AvailableAmount = 0 reply.AvailableAmount = 0
} else { } else {
...@@ -205,40 +35,15 @@ func QueryUnfreezeWithdraw(stateDB dbm.KV, param *uf.QueryUnfreezeWithdraw) (typ ...@@ -205,40 +35,15 @@ func QueryUnfreezeWithdraw(stateDB dbm.KV, param *uf.QueryUnfreezeWithdraw) (typ
return reply, nil return reply, nil
} }
func getWithdrawAvailable(unfreeze uf.Unfreeze, calcTime int64) (int64, int64, error) { func getWithdrawAvailable(unfreeze *pty.Unfreeze, calcTime int64) (int64, error) {
return 1, 1, nil // TODO impl means, err := newMeans(unfreeze.Means)
/* if err != nil {
expectTimes := (calcTime + unfreeze.Period - unfreeze.StartTime) / unfreeze.Period return 0, err
reaTimes := expectTimes - int64(unfreeze.WithdrawTimes)
if reaTimes <= 0 {
return 0, 0, uf.ErrUnfreezeBeforeDue
}
if unfreeze.Remaining <= 0 {
return 0, 0, uf.ErrUnfreezeEmptied
} }
frozen, err := means.calcFrozen(unfreeze, calcTime)
var available int64 if err != nil {
switch unfreeze.Means { return 0, err
case 1: // 百分比
for i := int64(0); i < reaTimes; i++ {
if tmp := unfreeze.Remaining * unfreeze.Amount / 10000; tmp == 0 {
available = unfreeze.Remaining
break
} else {
available += tmp
}
}
case 2: // 固额
for i := int64(0); i < reaTimes; i++ {
if unfreeze.Remaining <= unfreeze.Amount {
available = unfreeze.Remaining
break
}
available += unfreeze.Amount
}
default:
return 0, 0, uf.ErrUnfreezeMeans
} }
return reaTimes, available, nil _, amount := withdraw(unfreeze, frozen)
*/ return amount, nil
} }
package executor package executor
import ( import (
uf "gitlab.33.cn/chain33/chain33/plugin/dapp/unfreeze/types" "gitlab.33.cn/chain33/chain33/account"
pty "gitlab.33.cn/chain33/chain33/plugin/dapp/unfreeze/types"
"gitlab.33.cn/chain33/chain33/system/dapp"
"gitlab.33.cn/chain33/chain33/types" "gitlab.33.cn/chain33/chain33/types"
) )
func (u *Unfreeze) Exec_Create(payload *uf.UnfreezeCreate, tx *types.Transaction, index int32) (*types.Receipt, error) { func (u *Unfreeze) Exec_Create(payload *pty.UnfreezeCreate, tx *types.Transaction, index int32) (*types.Receipt, error) {
action := newAction(u, tx, index) if payload.AssetSymbol == "" || payload.AssetSymbol == "" || payload.TotalCount <= 0 || payload.Means == "" {
return action.UnfreezeCreate(payload) return nil, types.ErrInvalidParam
}
unfreeze, err := u.newEntity(payload, tx)
if err != nil {
uflog.Error("unfreeze create entity", "addr", tx.From(), "payload", payload)
return nil, err
}
receipt1, err := u.create(unfreeze)
if err != nil {
uflog.Error("unfreeze create order", "addr", tx.From(), "unfreeze", unfreeze)
return nil, err
}
acc, err := account.NewAccountDB(payload.AssetExec, payload.AssetSymbol, u.GetStateDB())
if err != nil {
uflog.Error("unfreeze create new account", "addr", tx.From(), "execAddr",
dapp.ExecAddress(string(tx.Execer)), "exec", payload.AssetExec, "symbol", payload.AssetSymbol)
return nil, err
}
receipt, err := acc.ExecFrozen(unfreeze.Initiator, dapp.ExecAddress(string(tx.Execer)), payload.TotalCount)
if err != nil {
uflog.Error("unfreeze create exec frozen", "addr", tx.From(), "execAddr", dapp.ExecAddress(string(tx.Execer)),
"ExecFrozen amount", payload.TotalCount, "exec", payload.AssetExec, "symbol", payload.AssetSymbol)
return nil, err
}
return MergeReceipt(receipt, receipt1)
}
func (u *Unfreeze) Exec_Withdraw(payload *pty.UnfreezeWithdraw, tx *types.Transaction, index int32) (*types.Receipt, error) {
value, err := u.GetStateDB().Get([]byte(payload.UnfreezeID))
if err != nil {
uflog.Error("unfreeze withdraw get", "id", payload.UnfreezeID, "err", err)
return nil, err
}
var unfreeze pty.Unfreeze
err = types.Decode(value, &unfreeze)
if err != nil {
uflog.Error("unfreeze withdraw decode", "err", err)
return nil, err
}
if unfreeze.Beneficiary != tx.From() {
uflog.Error("unfreeze withdraw no privilege", "beneficiary", unfreeze.Beneficiary, "txFrom", tx.From())
return nil, pty.ErrNoPrivilege
}
amount, receipt1, err := u.withdraw(&unfreeze)
if err != nil {
uflog.Error("unfreeze withdraw withdraw", "err", err, "unfreeze", unfreeze)
return nil, err
}
acc, err := account.NewAccountDB(unfreeze.AssetExec, unfreeze.AssetSymbol, u.GetStateDB())
if err != nil {
return nil, err
}
execAddr := dapp.ExecAddress(string(tx.Execer))
receipt, err := acc.ExecTransferFrozen(unfreeze.Initiator, tx.From(), execAddr, amount)
if err != nil {
uflog.Error("unfreeze withdraw transfer", "execaddr", execAddr, "err", err)
return nil, err
}
return MergeReceipt(receipt, receipt1)
}
func (u *Unfreeze) Exec_Terminate(payload *pty.UnfreezeTerminate, tx *types.Transaction, index int32) (*types.Receipt, error) {
value, err := u.GetStateDB().Get([]byte(payload.UnfreezeID))
if err != nil {
uflog.Error("unfreeze terminate get", "id", payload.UnfreezeID, "err", err)
return nil, err
}
var unfreeze pty.Unfreeze
err = types.Decode(value, &unfreeze)
if err != nil {
uflog.Error("unfreeze terminate decode", "err", err)
return nil, err
}
if tx.From() != unfreeze.Initiator {
uflog.Error("unfreeze terminate no privilege", "err", pty.ErrUnfreezeID, "initiator",
unfreeze.Initiator, "from", tx.From())
return nil, pty.ErrUnfreezeID
}
amount, receipt1, err := u.terminator(&unfreeze)
if err != nil {
uflog.Error("unfreeze terminate ", "err", err, "unfreeze", unfreeze)
return nil, err
}
acc, err := account.NewAccountDB(unfreeze.AssetExec, unfreeze.AssetSymbol, u.GetStateDB())
if err != nil {
return nil, err
}
execAddr := dapp.ExecAddress(string(tx.Execer))
receipt, err := acc.ExecActive(unfreeze.Initiator, execAddr, amount)
if err != nil {
uflog.Error("unfreeze terminate ", "addr", unfreeze.Initiator, "execaddr", execAddr, "err", err)
return nil, err
}
return MergeReceipt(receipt, receipt1)
}
func (u *Unfreeze) newEntity(payload *pty.UnfreezeCreate, tx *types.Transaction) (*pty.Unfreeze, error) {
id := unfreezeID(string(tx.Hash()))
unfreeze := &pty.Unfreeze{
UnfreezeID: string(id),
StartTime: payload.StartTime,
AssetExec: payload.AssetExec,
AssetSymbol: payload.AssetSymbol,
TotalCount: payload.TotalCount,
Initiator: tx.From(),
Beneficiary: payload.Beneficiary,
Means: payload.Means,
}
means, err := newMeans(payload.Means)
if err != nil {
return nil, err
}
unfreeze, err = means.setOpt(unfreeze, payload)
if err != nil {
return nil, err
}
return unfreeze, nil
}
// 创建解冻交易
func (u *Unfreeze) create(unfreeze *pty.Unfreeze) (*types.Receipt, error) {
k := []byte(unfreeze.UnfreezeID)
v := types.Encode(unfreeze)
err := u.GetStateDB().Set(k, v)
if err != nil {
return nil, err
}
receiptLog := getUnfreezeLog(nil, unfreeze)
return &types.Receipt{KV: []*types.KeyValue{{k, v}}, Logs: []*types.ReceiptLog{receiptLog}}, nil
} }
func (u *Unfreeze) Exec_Withdraw(payload *uf.UnfreezeWithdraw, tx *types.Transaction, index int32) (*types.Receipt, error) { func MergeReceipt(r1 *types.Receipt, r2 *types.Receipt) (*types.Receipt, error) {
action := newAction(u, tx, index) r1.Logs = append(r1.Logs, r2.Logs...)
return action.UnfreezeWithdraw(payload) r1.KV = append(r1.KV, r2.KV...)
r1.Ty = types.ExecOk
return r1, nil
} }
func (u *Unfreeze) Exec_Terminate(payload *uf.UnfreezeTerminate, tx *types.Transaction, index int32) (*types.Receipt, error) { func getUnfreezeLog(prev, cur *pty.Unfreeze) *types.ReceiptLog {
action := newAction(u, tx, index) log := &types.ReceiptLog{}
return action.UnfreezeTerminate(payload) log.Ty = pty.TyLogCreateUnfreeze
r := &pty.ReceiptUnfreeze{Prev: prev, Cur: cur}
log.Log = types.Encode(r)
return log
}
// 提取解冻币
func (u *Unfreeze) withdraw(unfreeze *pty.Unfreeze) (int64, *types.Receipt, error) {
means, err := newMeans(unfreeze.Means)
if err != nil {
return 0, nil, err
}
frozen, err := means.calcFrozen(unfreeze, u.GetBlockTime())
if err != nil {
return 0, nil, err
}
unfreezeOld := *unfreeze
unfreeze, amount := withdraw(unfreeze, frozen)
receiptLog := getUnfreezeLog(&unfreezeOld, unfreeze)
k := []byte(unfreeze.UnfreezeID)
v := types.Encode(unfreeze)
err = u.GetStateDB().Set(k, v)
if err != nil {
return 0, nil, err
}
return amount, &types.Receipt{Ty: types.ExecOk, KV: []*types.KeyValue{{k, v}},
Logs: []*types.ReceiptLog{receiptLog}}, nil
}
// 中止定期解冻
func (u *Unfreeze) terminator(unfreeze *pty.Unfreeze) (int64, *types.Receipt, error) {
if unfreeze.Remaining <= 0 {
return 0, nil, pty.ErrUnfreezeEmptied
}
unfreezeOld := *unfreeze
amount := unfreeze.Remaining
unfreeze.Remaining = 0
receiptLog := getUnfreezeLog(&unfreezeOld, unfreeze)
k := []byte(unfreeze.UnfreezeID)
v := types.Encode(unfreeze)
err := u.GetStateDB().Set(k, v)
if err != nil {
return 0, nil, err
}
return amount, &types.Receipt{Ty: types.ExecOk, KV: []*types.KeyValue{{k, v}},
Logs: []*types.ReceiptLog{receiptLog}}, nil
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment