Commit 6a9f1f6f authored by pengjun's avatar pengjun Committed by vipwzw

#627 fix debtceiling & liquidation recovery

parent 233bd4d3
...@@ -449,7 +449,7 @@ func TestCollateralize(t *testing.T) { ...@@ -449,7 +449,7 @@ func TestCollateralize(t *testing.T) {
} }
p8 := &pkt.CollateralizeFeedTx{} p8 := &pkt.CollateralizeFeedTx{}
p8.Price = append(p8.Price, 0.25) p8.Price = append(p8.Price, 0.28)
p8.Volume = append(p8.Volume, 100) p8.Volume = append(p8.Volume, 100)
createTx, err = pkt.CreateRawCollateralizeFeedTx(env.cfg, p8) createTx, err = pkt.CreateRawCollateralizeFeedTx(env.cfg, p8)
if err != nil { if err != nil {
...@@ -478,16 +478,91 @@ func TestCollateralize(t *testing.T) { ...@@ -478,16 +478,91 @@ func TestCollateralize(t *testing.T) {
} }
// query collateralize by status // query collateralize by status
res, err = exec.Query("CollateralizeRecordByStatus", res, err = exec.Query("CollateralizeRecordByStatus",
types.Encode(&pkt.ReqCollateralizeRecordByStatus{CollateralizeId: common.ToHex(collateralizeID), Status: 2}))
assert.Nil(t, err)
assert.NotNil(t, res)
res, err = exec.Query("CollateralizeRecordByStatus",
types.Encode(&pkt.ReqCollateralizeRecordByStatus{CollateralizeId: common.ToHex(collateralizeID), Status: 4}))
assert.Nil(t, res)
p81 := &pkt.CollateralizeFeedTx{}
p81.Price = append(p81.Price, 0.5)
p81.Volume = append(p81.Volume, 100)
createTx, err = pkt.CreateRawCollateralizeFeedTx(env.cfg, p81)
if err != nil {
t.Error("RPC_Default_Process", "err", err)
}
createTx.Execer = []byte(pkt.CollateralizeX)
createTx, err = signTx(createTx, PrivKeyB)
if err != nil {
t.Error("RPC_Default_Process sign", "err", err)
}
exec.SetEnv(env.blockHeight+1, env.blockTime+1, env.difficulty)
receipt, err = exec.Exec(createTx, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
t.Log(receipt)
for _, kv := range receipt.KV {
env.db.Set(kv.Key, kv.Value)
}
receiptData = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx, receiptData, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
env.kvdb.Set(kv.Key, kv.Value)
}
// query collateralize by status
res, err = exec.Query("CollateralizeRecordByStatus",
types.Encode(&pkt.ReqCollateralizeRecordByStatus{CollateralizeId: common.ToHex(collateralizeID), Status: 4}))
assert.Nil(t, err)
assert.NotNil(t, res)
p9 := &pkt.CollateralizeFeedTx{}
p9.Price = append(p9.Price, 0.25)
p9.Volume = append(p9.Volume, 100)
createTx, err = pkt.CreateRawCollateralizeFeedTx(env.cfg, p9)
if err != nil {
t.Error("RPC_Default_Process", "err", err)
}
createTx.Execer = []byte(pkt.CollateralizeX)
createTx, err = signTx(createTx, PrivKeyB)
if err != nil {
t.Error("RPC_Default_Process sign", "err", err)
}
exec.SetEnv(env.blockHeight+1, env.blockTime+1, env.difficulty)
receipt, err = exec.Exec(createTx, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
t.Log(receipt)
for _, kv := range receipt.KV {
env.db.Set(kv.Key, kv.Value)
}
receiptData = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx, receiptData, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
env.kvdb.Set(kv.Key, kv.Value)
}
// query collateralize by status
res, err = exec.Query("CollateralizeRecordByStatus",
types.Encode(&pkt.ReqCollateralizeRecordByStatus{CollateralizeId: common.ToHex(collateralizeID), Status: 3})) types.Encode(&pkt.ReqCollateralizeRecordByStatus{CollateralizeId: common.ToHex(collateralizeID), Status: 3}))
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, res) assert.NotNil(t, res)
res, err = exec.Query("CollateralizeRecordByStatus",
types.Encode(&pkt.ReqCollateralizeRecordByStatus{CollateralizeId: common.ToHex(collateralizeID), Status: 4}))
assert.Nil(t, res)
// expire liquidate // expire liquidate
p9 := &pkt.CollateralizeBorrowTx{ p10 := &pkt.CollateralizeBorrowTx{
CollateralizeID: common.ToHex(collateralizeID), CollateralizeID: common.ToHex(collateralizeID),
Value: 100, Value: 100,
} }
createTx, err = pkt.CreateRawCollateralizeBorrowTx(env.cfg, p9) createTx, err = pkt.CreateRawCollateralizeBorrowTx(env.cfg, p10)
if err != nil { if err != nil {
t.Error("RPC_Default_Process", "err", err) t.Error("RPC_Default_Process", "err", err)
} }
...@@ -513,10 +588,10 @@ func TestCollateralize(t *testing.T) { ...@@ -513,10 +588,10 @@ func TestCollateralize(t *testing.T) {
env.kvdb.Set(kv.Key, kv.Value) env.kvdb.Set(kv.Key, kv.Value)
} }
p10 := &pkt.CollateralizeFeedTx{} p11 := &pkt.CollateralizeFeedTx{}
p10.Price = append(p10.Price, 1) p11.Price = append(p11.Price, 1)
p10.Volume = append(p10.Volume, 100) p11.Volume = append(p11.Volume, 100)
createTx, err = pkt.CreateRawCollateralizeFeedTx(env.cfg, p10) createTx, err = pkt.CreateRawCollateralizeFeedTx(env.cfg, p11)
if err != nil { if err != nil {
t.Error("RPC_Default_Process", "err", err) t.Error("RPC_Default_Process", "err", err)
} }
...@@ -548,11 +623,11 @@ func TestCollateralize(t *testing.T) { ...@@ -548,11 +623,11 @@ func TestCollateralize(t *testing.T) {
assert.NotNil(t, res) assert.NotNil(t, res)
// collateralize retrieve // collateralize retrieve
p11 := &pkt.CollateralizeRetrieveTx{ p12 := &pkt.CollateralizeRetrieveTx{
CollateralizeID: common.ToHex(collateralizeID), CollateralizeID: common.ToHex(collateralizeID),
Balance: 100, Balance: 100,
} }
createTx, err = pkt.CreateRawCollateralizeRetrieveTx(env.cfg, p11) createTx, err = pkt.CreateRawCollateralizeRetrieveTx(env.cfg, p12)
if err != nil { if err != nil {
t.Error("RPC_Default_Process", "err", err) t.Error("RPC_Default_Process", "err", err)
} }
......
...@@ -528,7 +528,7 @@ func (action *Action) CollateralizeBorrow(borrow *pty.CollateralizeBorrow) (*typ ...@@ -528,7 +528,7 @@ func (action *Action) CollateralizeBorrow(borrow *pty.CollateralizeBorrow) (*typ
// 查找对应的借贷ID // 查找对应的借贷ID
collateralize, err := queryCollateralizeByID(action.db, borrow.CollateralizeId) collateralize, err := queryCollateralizeByID(action.db, borrow.CollateralizeId)
if err != nil { if err != nil {
clog.Error("CollateralizeBorrow", "CollateralizeId", borrow.CollateralizeId, "error", err) clog.Error("CollateralizeBorrow.queryCollateralizeByID", "CollateralizeId", borrow.CollateralizeId, "error", err)
return nil, err return nil, err
} }
...@@ -547,8 +547,10 @@ func (action *Action) CollateralizeBorrow(borrow *pty.CollateralizeBorrow) (*typ ...@@ -547,8 +547,10 @@ func (action *Action) CollateralizeBorrow(borrow *pty.CollateralizeBorrow) (*typ
} }
// 借贷金额不超过个人限额 // 借贷金额不超过个人限额
if borrow.GetValue() > coll.DebtCeiling { userBalance, _ := queryCollateralizeUserBalance(action.db, action.localDB, action.fromaddr)
clog.Error("CollateralizeBorrow", "CollID", coll.CollateralizeId, "addr", action.fromaddr, "execaddr", action.execaddr, "borrow value", borrow.GetValue(), "error", pty.ErrCollateralizeExceedDebtCeiling) if borrow.GetValue() + userBalance > coll.DebtCeiling {
clog.Error("CollateralizeBorrow", "CollID", coll.CollateralizeId, "addr", action.fromaddr, "execaddr", action.execaddr,
"borrow value", borrow.GetValue(), "current balance", userBalance, "error", pty.ErrCollateralizeExceedDebtCeiling)
return nil, pty.ErrCollateralizeExceedDebtCeiling return nil, pty.ErrCollateralizeExceedDebtCeiling
} }
...@@ -899,13 +901,17 @@ func (action *Action) systemLiquidation(coll *pty.Collateralize, price int64) (* ...@@ -899,13 +901,17 @@ func (action *Action) systemLiquidation(coll *pty.Collateralize, price int64) (*
for index, borrowRecord := range coll.BorrowRecords { for index, borrowRecord := range coll.BorrowRecords {
if (borrowRecord.LiquidationPrice*PriceWarningRate)/1e4 < price { if (borrowRecord.LiquidationPrice*PriceWarningRate)/1e4 < price {
// 价格恢复,告警记录恢复
if borrowRecord.Status == pty.CollateralizeUserStatusWarning { if borrowRecord.Status == pty.CollateralizeUserStatusWarning {
borrowRecord.PreStatus = borrowRecord.Status borrowRecord.PreStatus = borrowRecord.Status
borrowRecord.Status = pty.CollateralizeUserStatusCreate borrowRecord.Status = pty.CollateralizeUserStatusCreate
log := action.GetFeedReceiptLog(coll, borrowRecord)
logs = append(logs, log)
} }
continue continue
} }
// 价格低于清算线,记录清算
if borrowRecord.LiquidationPrice >= price { if borrowRecord.LiquidationPrice >= price {
getGuarantorAddr, err := getGuarantorAddr(action.db) getGuarantorAddr, err := getGuarantorAddr(action.db)
if err != nil { if err != nil {
...@@ -931,14 +937,20 @@ func (action *Action) systemLiquidation(coll *pty.Collateralize, price int64) (* ...@@ -931,14 +937,20 @@ func (action *Action) systemLiquidation(coll *pty.Collateralize, price int64) (*
coll.InvalidRecords = append(coll.InvalidRecords, borrowRecord) coll.InvalidRecords = append(coll.InvalidRecords, borrowRecord)
coll.BorrowRecords = append(coll.BorrowRecords[:index], coll.BorrowRecords[index+1:]...) coll.BorrowRecords = append(coll.BorrowRecords[:index], coll.BorrowRecords[index+1:]...)
coll.CollBalance -= borrowRecord.CollateralValue coll.CollBalance -= borrowRecord.CollateralValue
} else {
borrowRecord.PreStatus = borrowRecord.Status log := action.GetFeedReceiptLog(coll, borrowRecord)
borrowRecord.Status = pty.CollateralizeUserStatusWarning logs = append(logs, log)
continue
} }
// 价格高于清算线,且还不处于告警状态,记录告警
if borrowRecord.Status != pty.CollateralizeUserStatusWarning {
borrowRecord.PreStatus = borrowRecord.Status
borrowRecord.Status = pty.CollateralizeUserStatusWarning
log := action.GetFeedReceiptLog(coll, borrowRecord) log := action.GetFeedReceiptLog(coll, borrowRecord)
logs = append(logs, log) logs = append(logs, log)
} }
}
// 保存 // 保存
coll.LatestLiquidationPrice = getLatestLiquidationPrice(coll) coll.LatestLiquidationPrice = getLatestLiquidationPrice(coll)
...@@ -961,6 +973,7 @@ func (action *Action) expireLiquidation(coll *pty.Collateralize) (*types.Receipt ...@@ -961,6 +973,7 @@ func (action *Action) expireLiquidation(coll *pty.Collateralize) (*types.Receipt
continue continue
} }
// 超过超时时间,记录清算
if borrowRecord.ExpireTime <= action.blocktime { if borrowRecord.ExpireTime <= action.blocktime {
getGuarantorAddr, err := getGuarantorAddr(action.db) getGuarantorAddr, err := getGuarantorAddr(action.db)
if err != nil { if err != nil {
...@@ -986,14 +999,20 @@ func (action *Action) expireLiquidation(coll *pty.Collateralize) (*types.Receipt ...@@ -986,14 +999,20 @@ func (action *Action) expireLiquidation(coll *pty.Collateralize) (*types.Receipt
coll.InvalidRecords = append(coll.InvalidRecords, borrowRecord) coll.InvalidRecords = append(coll.InvalidRecords, borrowRecord)
coll.BorrowRecords = append(coll.BorrowRecords[:index], coll.BorrowRecords[index+1:]...) coll.BorrowRecords = append(coll.BorrowRecords[:index], coll.BorrowRecords[index+1:]...)
coll.CollBalance -= borrowRecord.CollateralValue coll.CollBalance -= borrowRecord.CollateralValue
} else {
borrowRecord.PreStatus = borrowRecord.Status log := action.GetFeedReceiptLog(coll, borrowRecord)
borrowRecord.Status = pty.CollateralizeUserStatusExpire logs = append(logs, log)
continue
} }
// 还没记录超时告警,记录告警
if borrowRecord.Status != pty.CollateralizeUserStatusExpire {
borrowRecord.PreStatus = borrowRecord.Status
borrowRecord.Status = pty.CollateralizeUserStatusExpire
log := action.GetFeedReceiptLog(coll, borrowRecord) log := action.GetFeedReceiptLog(coll, borrowRecord)
logs = append(logs, log) logs = append(logs, log)
} }
}
// 保存 // 保存
coll.LatestLiquidationPrice = getLatestLiquidationPrice(coll) coll.LatestLiquidationPrice = getLatestLiquidationPrice(coll)
...@@ -1348,14 +1367,12 @@ func queryCollateralizeUserBalanceStatus(db dbm.KV, localdb dbm.KVDB, addr strin ...@@ -1348,14 +1367,12 @@ func queryCollateralizeUserBalanceStatus(db dbm.KV, localdb dbm.KVDB, addr strin
for { for {
rows, err = query.List("addr_status", data, primary, DefaultCount, ListDESC) rows, err = query.List("addr_status", data, primary, DefaultCount, ListDESC)
if err != nil { if err != nil {
clog.Debug("queryCollateralizeRecordByAddr.List", "index", "addr", "error", err)
return -1, err return -1, err
} }
for _, row := range rows { for _, row := range rows {
record, err := queryCollateralizeRecordByID(db, row.Data.(*pty.ReceiptCollateralize).CollateralizeId, row.Data.(*pty.ReceiptCollateralize).RecordId) record, err := queryCollateralizeRecordByID(db, row.Data.(*pty.ReceiptCollateralize).CollateralizeId, row.Data.(*pty.ReceiptCollateralize).RecordId)
if err != nil { if err != nil {
clog.Debug("queryCollateralizeRecordByStatus.queryCollateralizeRecordByID", "error", err)
continue continue
} }
totalBalance += record.DebtValue totalBalance += record.DebtValue
...@@ -1375,21 +1392,27 @@ func queryCollateralizeUserBalance(db dbm.KV, localdb dbm.KVDB, addr string) (in ...@@ -1375,21 +1392,27 @@ func queryCollateralizeUserBalance(db dbm.KV, localdb dbm.KVDB, addr string) (in
balance, err := queryCollateralizeUserBalanceStatus(db, localdb, addr, pty.CollateralizeUserStatusCreate) balance, err := queryCollateralizeUserBalanceStatus(db, localdb, addr, pty.CollateralizeUserStatusCreate)
if err != nil { if err != nil {
if err != types.ErrNotFound {
clog.Error("queryCollateralizeUserBalance", "err", err) clog.Error("queryCollateralizeUserBalance", "err", err)
}
} else { } else {
totalBalance += balance totalBalance += balance
} }
balance, err = queryCollateralizeUserBalanceStatus(db, localdb, addr, pty.CollateralizeUserStatusWarning) balance, err = queryCollateralizeUserBalanceStatus(db, localdb, addr, pty.CollateralizeUserStatusWarning)
if err != nil { if err != nil {
if err != types.ErrNotFound {
clog.Error("queryCollateralizeUserBalance", "err", err) clog.Error("queryCollateralizeUserBalance", "err", err)
}
} else { } else {
totalBalance += balance totalBalance += balance
} }
balance, err = queryCollateralizeUserBalanceStatus(db, localdb, addr, pty.CollateralizeUserStatusExpire) balance, err = queryCollateralizeUserBalanceStatus(db, localdb, addr, pty.CollateralizeUserStatusExpire)
if err != nil { if err != nil {
if err != types.ErrNotFound {
clog.Error("queryCollateralizeUserBalance", "err", err) clog.Error("queryCollateralizeUserBalance", "err", err)
}
} else { } else {
totalBalance += balance totalBalance += balance
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package executor package executor
import ( import (
"github.com/33cn/chain33/common/db/table"
//"github.com/33cn/chain33/common" //"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/collateralize/types" pty "github.com/33cn/plugin/plugin/dapp/collateralize/types"
...@@ -12,6 +13,7 @@ import ( ...@@ -12,6 +13,7 @@ import (
func (c *Collateralize) execLocal(tx *types.Transaction, receipt *types.ReceiptData) (*types.LocalDBSet, error) { func (c *Collateralize) execLocal(tx *types.Transaction, receipt *types.ReceiptData) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{} set := &types.LocalDBSet{}
var collTable, recordTable *table.Table
for _, item := range receipt.Logs { for _, item := range receipt.Logs {
if item.Ty >= pty.TyLogCollateralizeCreate && item.Ty <= pty.TyLogCollateralizeRetrieve { if item.Ty >= pty.TyLogCollateralizeCreate && item.Ty <= pty.TyLogCollateralizeRetrieve {
var collateralizeLog pty.ReceiptCollateralize var collateralizeLog pty.ReceiptCollateralize
...@@ -21,31 +23,37 @@ func (c *Collateralize) execLocal(tx *types.Transaction, receipt *types.ReceiptD ...@@ -21,31 +23,37 @@ func (c *Collateralize) execLocal(tx *types.Transaction, receipt *types.ReceiptD
} }
if item.Ty == pty.TyLogCollateralizeCreate || item.Ty == pty.TyLogCollateralizeRetrieve { if item.Ty == pty.TyLogCollateralizeCreate || item.Ty == pty.TyLogCollateralizeRetrieve {
collTable := pty.NewCollateralizeTable(c.GetLocalDB()) collTable = pty.NewCollateralizeTable(c.GetLocalDB())
err = collTable.Replace(&pty.ReceiptCollateralize{CollateralizeId: collateralizeLog.CollateralizeId, Status: collateralizeLog.Status, err = collTable.Replace(&pty.ReceiptCollateralize{CollateralizeId: collateralizeLog.CollateralizeId, Status: collateralizeLog.Status,
AccountAddr: collateralizeLog.AccountAddr}) AccountAddr: collateralizeLog.AccountAddr})
if err != nil { if err != nil {
return nil, err return nil, err
} }
kvs, err := collTable.Save()
if err != nil {
return nil, err
}
set.KV = append(set.KV, kvs...)
} else { } else {
recordTable := pty.NewRecordTable(c.GetLocalDB()) recordTable = pty.NewRecordTable(c.GetLocalDB())
err = recordTable.Replace(&pty.ReceiptCollateralize{CollateralizeId: collateralizeLog.CollateralizeId, Status: collateralizeLog.Status, err = recordTable.Replace(&pty.ReceiptCollateralize{CollateralizeId: collateralizeLog.CollateralizeId, Status: collateralizeLog.Status,
RecordId: collateralizeLog.RecordId, AccountAddr: collateralizeLog.AccountAddr}) RecordId: collateralizeLog.RecordId, AccountAddr: collateralizeLog.AccountAddr})
if err != nil { if err != nil {
return nil, err return nil, err
} }
kvs, err := recordTable.Save() }
}
}
if collTable != nil {
kvs, err := collTable.Save()
if err != nil { if err != nil {
return nil, err return nil, err
} }
set.KV = append(set.KV, kvs...) set.KV = append(set.KV, kvs...)
} }
if recordTable != nil {
kvs, err := recordTable.Save()
if err != nil {
return nil, err
} }
set.KV = append(set.KV, kvs...)
} }
set.KV = c.AddRollbackKV(tx, []byte(pty.CollateralizeX), set.KV) set.KV = c.AddRollbackKV(tx, []byte(pty.CollateralizeX), set.KV)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package executor package executor
import ( import (
"github.com/33cn/chain33/common/db/table"
//"github.com/33cn/chain33/common" //"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/issuance/types" pty "github.com/33cn/plugin/plugin/dapp/issuance/types"
...@@ -12,6 +13,7 @@ import ( ...@@ -12,6 +13,7 @@ import (
func (c *Issuance) execLocal(tx *types.Transaction, receipt *types.ReceiptData) (*types.LocalDBSet, error) { func (c *Issuance) execLocal(tx *types.Transaction, receipt *types.ReceiptData) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{} set := &types.LocalDBSet{}
var IDtable, recordTable *table.Table
for _, item := range receipt.Logs { for _, item := range receipt.Logs {
if item.Ty >= pty.TyLogIssuanceCreate && item.Ty <= pty.TyLogIssuanceClose { if item.Ty >= pty.TyLogIssuanceCreate && item.Ty <= pty.TyLogIssuanceClose {
var issuanceLog pty.ReceiptIssuance var issuanceLog pty.ReceiptIssuance
...@@ -21,30 +23,36 @@ func (c *Issuance) execLocal(tx *types.Transaction, receipt *types.ReceiptData) ...@@ -21,30 +23,36 @@ func (c *Issuance) execLocal(tx *types.Transaction, receipt *types.ReceiptData)
} }
if item.Ty == pty.TyLogIssuanceCreate || item.Ty == pty.TyLogIssuanceClose { if item.Ty == pty.TyLogIssuanceCreate || item.Ty == pty.TyLogIssuanceClose {
IDtable := pty.NewIssuanceTable(c.GetLocalDB()) IDtable = pty.NewIssuanceTable(c.GetLocalDB())
err = IDtable.Replace(&pty.ReceiptIssuanceID{IssuanceId: issuanceLog.IssuanceId, Status: issuanceLog.Status}) err = IDtable.Replace(&pty.ReceiptIssuanceID{IssuanceId: issuanceLog.IssuanceId, Status: issuanceLog.Status})
if err != nil { if err != nil {
return nil, err return nil, err
} }
kvs, err := IDtable.Save()
if err != nil {
return nil, err
}
set.KV = append(set.KV, kvs...)
} else { } else {
recordTable := pty.NewRecordTable(c.GetLocalDB()) recordTable = pty.NewRecordTable(c.GetLocalDB())
err = recordTable.Replace(&pty.ReceiptIssuance{IssuanceId: issuanceLog.IssuanceId, Status: issuanceLog.Status, err = recordTable.Replace(&pty.ReceiptIssuance{IssuanceId: issuanceLog.IssuanceId, Status: issuanceLog.Status,
DebtId: issuanceLog.DebtId, AccountAddr: issuanceLog.AccountAddr}) DebtId: issuanceLog.DebtId, AccountAddr: issuanceLog.AccountAddr})
if err != nil { if err != nil {
return nil, err return nil, err
} }
kvs, err := recordTable.Save() }
}
}
if IDtable != nil {
kvs, err := IDtable.Save()
if err != nil { if err != nil {
return nil, err return nil, err
} }
set.KV = append(set.KV, kvs...) set.KV = append(set.KV, kvs...)
} }
if recordTable != nil {
kvs, err := recordTable.Save()
if err != nil {
return nil, err
} }
set.KV = append(set.KV, kvs...)
} }
set.KV = c.AddRollbackKV(tx, []byte(pty.IssuanceX), set.KV) set.KV = c.AddRollbackKV(tx, []byte(pty.IssuanceX), set.KV)
......
...@@ -379,7 +379,7 @@ func TestIssuance(t *testing.T) { ...@@ -379,7 +379,7 @@ func TestIssuance(t *testing.T) {
} }
p7 := &pkt.IssuanceFeedTx{} p7 := &pkt.IssuanceFeedTx{}
p7.Price = append(p7.Price, 0.25) p7.Price = append(p7.Price, 0.28)
p7.Volume = append(p7.Volume, 100) p7.Volume = append(p7.Volume, 100)
createTx, err = pkt.CreateRawIssuanceFeedTx(env.cfg, p7) createTx, err = pkt.CreateRawIssuanceFeedTx(env.cfg, p7)
if err != nil { if err != nil {
...@@ -408,16 +408,89 @@ func TestIssuance(t *testing.T) { ...@@ -408,16 +408,89 @@ func TestIssuance(t *testing.T) {
} }
// query issuance by status // query issuance by status
res, err = exec.Query("IssuanceRecordsByStatus", res, err = exec.Query("IssuanceRecordsByStatus",
types.Encode(&pkt.ReqIssuanceRecords{Status: 2}))
assert.Nil(t, err)
assert.NotNil(t, res)
res, err = exec.Query("IssuanceRecordsByStatus",
types.Encode(&pkt.ReqIssuanceRecords{Status: 4}))
assert.Nil(t, res)
p8 := &pkt.IssuanceFeedTx{}
p8.Price = append(p8.Price, 0.5)
p8.Volume = append(p8.Volume, 100)
createTx, err = pkt.CreateRawIssuanceFeedTx(env.cfg, p8)
if err != nil {
t.Error("RPC_Default_Process", "err", err)
}
createTx.Execer = []byte(pkt.IssuanceX)
createTx, err = signTx(createTx, PrivKeyB)
if err != nil {
t.Error("RPC_Default_Process sign", "err", err)
}
exec.SetEnv(env.blockHeight+1, env.blockTime+1, env.difficulty)
receipt, err = exec.Exec(createTx, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
t.Log(receipt)
for _, kv := range receipt.KV {
env.db.Set(kv.Key, kv.Value)
}
receiptData = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx, receiptData, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
env.kvdb.Set(kv.Key, kv.Value)
}
// query issuance by status
res, err = exec.Query("IssuanceRecordsByStatus", types.Encode(&pkt.ReqIssuanceRecords{Status: 4}))
assert.Nil(t, err)
assert.NotNil(t, res)
p81 := &pkt.IssuanceFeedTx{}
p81.Price = append(p81.Price, 0.25)
p81.Volume = append(p81.Volume, 100)
createTx, err = pkt.CreateRawIssuanceFeedTx(env.cfg, p81)
if err != nil {
t.Error("RPC_Default_Process", "err", err)
}
createTx.Execer = []byte(pkt.IssuanceX)
createTx, err = signTx(createTx, PrivKeyB)
if err != nil {
t.Error("RPC_Default_Process sign", "err", err)
}
exec.SetEnv(env.blockHeight+1, env.blockTime+1, env.difficulty)
receipt, err = exec.Exec(createTx, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
t.Log(receipt)
for _, kv := range receipt.KV {
env.db.Set(kv.Key, kv.Value)
}
receiptData = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx, receiptData, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
env.kvdb.Set(kv.Key, kv.Value)
}
// query issuance by status
res, err = exec.Query("IssuanceRecordsByStatus",
types.Encode(&pkt.ReqIssuanceRecords{Status: 3})) types.Encode(&pkt.ReqIssuanceRecords{Status: 3}))
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, res) assert.NotNil(t, res)
res, err = exec.Query("IssuanceRecordsByStatus",
types.Encode(&pkt.ReqIssuanceRecords{Status: 4}))
assert.Nil(t, res)
// expire liquidate // expire liquidate
p8 := &pkt.IssuanceDebtTx{ p9 := &pkt.IssuanceDebtTx{
IssuanceID: common.ToHex(issuanceID), IssuanceID: common.ToHex(issuanceID),
Value: 100, Value: 100,
} }
createTx, err = pkt.CreateRawIssuanceDebtTx(env.cfg, p8) createTx, err = pkt.CreateRawIssuanceDebtTx(env.cfg, p9)
if err != nil { if err != nil {
t.Error("RPC_Default_Process", "err", err) t.Error("RPC_Default_Process", "err", err)
} }
...@@ -443,10 +516,10 @@ func TestIssuance(t *testing.T) { ...@@ -443,10 +516,10 @@ func TestIssuance(t *testing.T) {
env.kvdb.Set(kv.Key, kv.Value) env.kvdb.Set(kv.Key, kv.Value)
} }
p9 := &pkt.IssuanceFeedTx{} p10 := &pkt.IssuanceFeedTx{}
p9.Price = append(p9.Price, 1) p10.Price = append(p10.Price, 1)
p9.Volume = append(p9.Volume, 100) p10.Volume = append(p10.Volume, 100)
createTx, err = pkt.CreateRawIssuanceFeedTx(env.cfg, p9) createTx, err = pkt.CreateRawIssuanceFeedTx(env.cfg, p10)
if err != nil { if err != nil {
t.Error("RPC_Default_Process", "err", err) t.Error("RPC_Default_Process", "err", err)
} }
...@@ -478,10 +551,10 @@ func TestIssuance(t *testing.T) { ...@@ -478,10 +551,10 @@ func TestIssuance(t *testing.T) {
assert.NotNil(t, res) assert.NotNil(t, res)
// issuance close // issuance close
p10 := &pkt.IssuanceCloseTx{ p11 := &pkt.IssuanceCloseTx{
IssuanceID: common.ToHex(issuanceID), IssuanceID: common.ToHex(issuanceID),
} }
createTx, err = pkt.CreateRawIssuanceCloseTx(env.cfg, p10) createTx, err = pkt.CreateRawIssuanceCloseTx(env.cfg, p11)
if err != nil { if err != nil {
t.Error("RPC_Default_Process", "err", err) t.Error("RPC_Default_Process", "err", err)
} }
......
...@@ -514,8 +514,10 @@ func (action *Action) IssuanceDebt(debt *pty.IssuanceDebt) (*types.Receipt, erro ...@@ -514,8 +514,10 @@ func (action *Action) IssuanceDebt(debt *pty.IssuanceDebt) (*types.Receipt, erro
} }
// 借贷金额不超过个人限额 // 借贷金额不超过个人限额
if debt.GetValue() > issu.DebtCeiling { userBalance, _ := queryIssuanceUserBalance(action.db, action.localDB, action.fromaddr)
clog.Error("IssuanceDebt", "CollID", issu.IssuanceId, "addr", action.fromaddr, "execaddr", action.execaddr, "debt value", debt.GetValue(), "error", pty.ErrIssuanceExceedDebtCeiling) if debt.GetValue() + userBalance > issu.DebtCeiling {
clog.Error("IssuanceDebt", "CollID", issu.IssuanceId, "addr", action.fromaddr, "execaddr", action.execaddr,
"debt value", debt.GetValue(), "current balance", userBalance, "error", pty.ErrIssuanceExceedDebtCeiling)
return nil, pty.ErrIssuanceExceedDebtCeiling return nil, pty.ErrIssuanceExceedDebtCeiling
} }
...@@ -706,13 +708,17 @@ func (action *Action) systemLiquidation(issu *pty.Issuance, price int64) (*types ...@@ -706,13 +708,17 @@ func (action *Action) systemLiquidation(issu *pty.Issuance, price int64) (*types
for index, debtRecord := range issu.DebtRecords { for index, debtRecord := range issu.DebtRecords {
if (debtRecord.LiquidationPrice*PriceWarningRate)/1e4 < price { if (debtRecord.LiquidationPrice*PriceWarningRate)/1e4 < price {
// 价格恢复,告警记录恢复
if debtRecord.Status == pty.IssuanceUserStatusWarning { if debtRecord.Status == pty.IssuanceUserStatusWarning {
debtRecord.PreStatus = debtRecord.Status debtRecord.PreStatus = debtRecord.Status
debtRecord.Status = pty.IssuanceUserStatusCreate debtRecord.Status = pty.IssuanceUserStatusCreate
log := action.GetFeedReceiptLog(issu, debtRecord)
logs = append(logs, log)
} }
continue continue
} }
// 价格低于清算线,记录清算
if debtRecord.LiquidationPrice >= price { if debtRecord.LiquidationPrice >= price {
getGuarantorAddr, err := getGuarantorAddr(action.db) getGuarantorAddr, err := getGuarantorAddr(action.db)
if err != nil { if err != nil {
...@@ -737,14 +743,22 @@ func (action *Action) systemLiquidation(issu *pty.Issuance, price int64) (*types ...@@ -737,14 +743,22 @@ func (action *Action) systemLiquidation(issu *pty.Issuance, price int64) (*types
debtRecord.Status = pty.IssuanceUserStatusSystemLiquidate debtRecord.Status = pty.IssuanceUserStatusSystemLiquidate
issu.InvalidRecords = append(issu.InvalidRecords, debtRecord) issu.InvalidRecords = append(issu.InvalidRecords, debtRecord)
issu.DebtRecords = append(issu.DebtRecords[:index], issu.DebtRecords[index+1:]...) issu.DebtRecords = append(issu.DebtRecords[:index], issu.DebtRecords[index+1:]...)
} else {
log := action.GetFeedReceiptLog(issu, debtRecord)
logs = append(logs, log)
continue
}
// 价格高于清算线,且还不处于告警状态,记录告警
if debtRecord.Status != pty.IssuanceUserStatusWarning {
debtRecord.PreStatus = debtRecord.Status debtRecord.PreStatus = debtRecord.Status
debtRecord.Status = pty.IssuanceUserStatusWarning debtRecord.Status = pty.IssuanceUserStatusWarning
}
log := action.GetFeedReceiptLog(issu, debtRecord) log := action.GetFeedReceiptLog(issu, debtRecord)
logs = append(logs, log) logs = append(logs, log)
} }
}
// 保存 // 保存
issu.LatestLiquidationPrice = getLatestLiquidationPrice(issu) issu.LatestLiquidationPrice = getLatestLiquidationPrice(issu)
...@@ -767,6 +781,7 @@ func (action *Action) expireLiquidation(issu *pty.Issuance) (*types.Receipt, err ...@@ -767,6 +781,7 @@ func (action *Action) expireLiquidation(issu *pty.Issuance) (*types.Receipt, err
continue continue
} }
// 超过超时时间,记录清算
if debtRecord.ExpireTime <= action.blocktime { if debtRecord.ExpireTime <= action.blocktime {
getGuarantorAddr, err := getGuarantorAddr(action.db) getGuarantorAddr, err := getGuarantorAddr(action.db)
if err != nil { if err != nil {
...@@ -791,14 +806,20 @@ func (action *Action) expireLiquidation(issu *pty.Issuance) (*types.Receipt, err ...@@ -791,14 +806,20 @@ func (action *Action) expireLiquidation(issu *pty.Issuance) (*types.Receipt, err
debtRecord.Status = pty.IssuanceUserStatusExpireLiquidate debtRecord.Status = pty.IssuanceUserStatusExpireLiquidate
issu.InvalidRecords = append(issu.InvalidRecords, debtRecord) issu.InvalidRecords = append(issu.InvalidRecords, debtRecord)
issu.DebtRecords = append(issu.DebtRecords[:index], issu.DebtRecords[index+1:]...) issu.DebtRecords = append(issu.DebtRecords[:index], issu.DebtRecords[index+1:]...)
} else { log := action.GetFeedReceiptLog(issu, debtRecord)
debtRecord.PreStatus = debtRecord.Status logs = append(logs, log)
debtRecord.Status = pty.IssuanceUserStatusExpire
continue
} }
// 还没记录超时告警,记录告警
if debtRecord.Status != pty.IssuanceUserStatusExpire {
debtRecord.PreStatus = debtRecord.Status
debtRecord.Status = pty.IssuanceUserStatusExpire
log := action.GetFeedReceiptLog(issu, debtRecord) log := action.GetFeedReceiptLog(issu, debtRecord)
logs = append(logs, log) logs = append(logs, log)
} }
}
// 保存 // 保存
issu.LatestLiquidationPrice = getLatestLiquidationPrice(issu) issu.LatestLiquidationPrice = getLatestLiquidationPrice(issu)
...@@ -1097,14 +1118,12 @@ func queryIssuanceUserBalanceStatus(db dbm.KV, localdb dbm.KVDB, addr string, st ...@@ -1097,14 +1118,12 @@ func queryIssuanceUserBalanceStatus(db dbm.KV, localdb dbm.KVDB, addr string, st
for { for {
rows, err = query.List("addr_status", data, primary, DefaultCount, ListDESC) rows, err = query.List("addr_status", data, primary, DefaultCount, ListDESC)
if err != nil { if err != nil {
clog.Debug("queryIssuanceRecordByAddr.List", "index", "addr", "error", err)
return -1, err return -1, err
} }
for _, row := range rows { for _, row := range rows {
record, err := queryIssuanceRecordByID(db, row.Data.(*pty.ReceiptIssuance).IssuanceId, row.Data.(*pty.ReceiptIssuance).DebtId) record, err := queryIssuanceRecordByID(db, row.Data.(*pty.ReceiptIssuance).IssuanceId, row.Data.(*pty.ReceiptIssuance).DebtId)
if err != nil { if err != nil {
clog.Debug("queryIssuanceRecordByStatus.queryIssuanceRecordByID", "error", err)
continue continue
} }
totalBalance += record.DebtValue totalBalance += record.DebtValue
...@@ -1124,21 +1143,27 @@ func queryIssuanceUserBalance(db dbm.KV, localdb dbm.KVDB, addr string) (int64, ...@@ -1124,21 +1143,27 @@ func queryIssuanceUserBalance(db dbm.KV, localdb dbm.KVDB, addr string) (int64,
balance, err := queryIssuanceUserBalanceStatus(db, localdb, addr, pty.IssuanceUserStatusCreate) balance, err := queryIssuanceUserBalanceStatus(db, localdb, addr, pty.IssuanceUserStatusCreate)
if err != nil { if err != nil {
if err != types.ErrNotFound {
clog.Error("queryIssuanceUserBalance", "err", err) clog.Error("queryIssuanceUserBalance", "err", err)
}
} else { } else {
totalBalance += balance totalBalance += balance
} }
balance, err = queryIssuanceUserBalanceStatus(db, localdb, addr, pty.IssuanceUserStatusWarning) balance, err = queryIssuanceUserBalanceStatus(db, localdb, addr, pty.IssuanceUserStatusWarning)
if err != nil { if err != nil {
if err != types.ErrNotFound {
clog.Error("queryIssuanceUserBalance", "err", err) clog.Error("queryIssuanceUserBalance", "err", err)
}
} else { } else {
totalBalance += balance totalBalance += balance
} }
balance, err = queryIssuanceUserBalanceStatus(db, localdb, addr, pty.IssuanceUserStatusExpire) balance, err = queryIssuanceUserBalanceStatus(db, localdb, addr, pty.IssuanceUserStatusExpire)
if err != nil { if err != nil {
if err != types.ErrNotFound {
clog.Error("queryIssuanceUserBalance", "err", err) clog.Error("queryIssuanceUserBalance", "err", err)
}
} else { } else {
totalBalance += balance totalBalance += balance
} }
......
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