go-ethereum/XDCxlending/lendingstate/state_lendingbook.go
Daniel Liu fbecb8c5a5 all: fix staticcheck warning ST1006: don't use generic name self
The name of a method’s receiver should be a reflection of its identity;
often a one or two letter abbreviation of its type suffices (such as
“c” or “cl” for “Client”). Don’t use generic names such as “me”, “this”
or “self”, identifiers typical of object-oriented languages that place
more emphasis on methods as opposed to functions. The name need not be
as descriptive as that of a method argument, as its role is obvious and
serves no documentary purpose. It can be very short as it will appear
on almost every line of every method of the type; familiarity admits
brevity. Be consistent, too: if you call the receiver “c” in one method,
don’t call it “cl” in another.
2024-10-25 21:30:54 +08:00

805 lines
24 KiB
Go

// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package lendingstate
import (
"fmt"
"io"
"math/big"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/rlp"
)
type lendingExchangeState struct {
lendingBook common.Hash
data lendingObject
db *LendingStateDB
// DB error.
// State objects are used by the consensus core and VM which are
// unable to deal with database-level errors. Any error that occurs
// during a database read is memoized here and will eventually be returned
// by LendingStateDB.Commit.
dbErr error
investingTrie Trie
borrowingTrie Trie
lendingItemTrie Trie
lendingTradeTrie Trie
liquidationTimeTrie Trie
liquidationTimeStates map[common.Hash]*liquidationTimeState
liquidationTimestatesDirty map[common.Hash]struct{}
investingStates map[common.Hash]*itemListState
investingStatesDirty map[common.Hash]struct{}
borrowingStates map[common.Hash]*itemListState
borrowingStatesDirty map[common.Hash]struct{}
lendingItemStates map[common.Hash]*lendingItemState
lendingItemStatesDirty map[common.Hash]struct{}
lendingTradeStates map[common.Hash]*lendingTradeState
lendingTradeStatesDirty map[common.Hash]struct{}
onDirty func(hash common.Hash) // Callback method to mark a state object newly dirty
}
// empty returns whether the tradeId is considered empty.
func (s *lendingExchangeState) empty() bool {
if s.data.Nonce != 0 {
return false
}
if s.data.TradeNonce != 0 {
return false
}
if !common.EmptyHash(s.data.InvestingRoot) {
return false
}
if !common.EmptyHash(s.data.BorrowingRoot) {
return false
}
if !common.EmptyHash(s.data.LendingItemRoot) {
return false
}
if !common.EmptyHash(s.data.LendingTradeRoot) {
return false
}
if !common.EmptyHash(s.data.LiquidationTimeRoot) {
return false
}
return true
}
func newStateExchanges(db *LendingStateDB, hash common.Hash, data lendingObject, onDirty func(addr common.Hash)) *lendingExchangeState {
return &lendingExchangeState{
db: db,
lendingBook: hash,
data: data,
investingStates: make(map[common.Hash]*itemListState),
borrowingStates: make(map[common.Hash]*itemListState),
lendingItemStates: make(map[common.Hash]*lendingItemState),
lendingTradeStates: make(map[common.Hash]*lendingTradeState),
liquidationTimeStates: make(map[common.Hash]*liquidationTimeState),
investingStatesDirty: make(map[common.Hash]struct{}),
borrowingStatesDirty: make(map[common.Hash]struct{}),
lendingItemStatesDirty: make(map[common.Hash]struct{}),
lendingTradeStatesDirty: make(map[common.Hash]struct{}),
liquidationTimestatesDirty: make(map[common.Hash]struct{}),
onDirty: onDirty,
}
}
// EncodeRLP implements rlp.Encoder.
func (le *lendingExchangeState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, le.data)
}
// setError remembers the first non-nil error it is called with.
func (le *lendingExchangeState) setError(err error) {
if le.dbErr == nil {
le.dbErr = err
}
}
/**
Get Trie
*/
func (le *lendingExchangeState) getLendingItemTrie(db Database) Trie {
if le.lendingItemTrie == nil {
var err error
le.lendingItemTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LendingItemRoot)
if err != nil {
le.lendingItemTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
}
}
return le.lendingItemTrie
}
func (le *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
if le.lendingTradeTrie == nil {
var err error
le.lendingTradeTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LendingTradeRoot)
if err != nil {
le.lendingTradeTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
}
}
return le.lendingTradeTrie
}
func (le *lendingExchangeState) getInvestingTrie(db Database) Trie {
if le.investingTrie == nil {
var err error
le.investingTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.InvestingRoot)
if err != nil {
le.investingTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
}
}
return le.investingTrie
}
func (le *lendingExchangeState) getBorrowingTrie(db Database) Trie {
if le.borrowingTrie == nil {
var err error
le.borrowingTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.BorrowingRoot)
if err != nil {
le.borrowingTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create bids trie: %v", err))
}
}
return le.borrowingTrie
}
func (le *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
if le.liquidationTimeTrie == nil {
var err error
le.liquidationTimeTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LiquidationTimeRoot)
if err != nil {
le.liquidationTimeTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create bids trie: %v", err))
}
}
return le.liquidationTimeTrie
}
/*
*
Get State
*/
func (le *lendingExchangeState) getBorrowingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
// Prefer 'live' objects.
if obj := le.borrowingStates[rate]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := le.getBorrowingTrie(db).TryGet(rate[:])
if len(enc) == 0 {
le.setError(err)
return nil
}
var data itemList
if err := rlp.DecodeBytes(enc, &data); err != nil {
log.Error("Failed to decode state order list object", "rate", rate, "err", err)
return nil
}
// Insert into the live set.
obj := newItemListState(le.lendingBook, rate, data, le.MarkBorrowingDirty)
le.borrowingStates[rate] = obj
return obj
}
func (le *lendingExchangeState) getInvestingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
// Prefer 'live' objects.
if obj := le.investingStates[rate]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := le.getInvestingTrie(db).TryGet(rate[:])
if len(enc) == 0 {
le.setError(err)
return nil
}
var data itemList
if err := rlp.DecodeBytes(enc, &data); err != nil {
log.Error("Failed to decode state order list object", "rate", rate, "err", err)
return nil
}
// Insert into the live set.
obj := newItemListState(le.lendingBook, rate, data, le.MarkInvestingDirty)
le.investingStates[rate] = obj
return obj
}
func (le *lendingExchangeState) getLiquidationTimeOrderList(db Database, time common.Hash) (stateObject *liquidationTimeState) {
// Prefer 'live' objects.
if obj := le.liquidationTimeStates[time]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := le.getLiquidationTimeTrie(db).TryGet(time[:])
if len(enc) == 0 {
le.setError(err)
return nil
}
var data itemList
if err := rlp.DecodeBytes(enc, &data); err != nil {
log.Error("Failed to decode state liquidation time", "time", time, "err", err)
return nil
}
// Insert into the live set.
obj := newLiquidationTimeState(le.lendingBook, time, data, le.MarkLiquidationTimeDirty)
le.liquidationTimeStates[time] = obj
return obj
}
func (le *lendingExchangeState) getLendingItem(db Database, lendingId common.Hash) (stateObject *lendingItemState) {
// Prefer 'live' objects.
if obj := le.lendingItemStates[lendingId]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := le.getLendingItemTrie(db).TryGet(lendingId[:])
if len(enc) == 0 {
le.setError(err)
return nil
}
var data LendingItem
if err := rlp.DecodeBytes(enc, &data); err != nil {
log.Error("Failed to decode state lending item", "tradeId", lendingId, "err", err)
return nil
}
// Insert into the live set.
obj := newLendinItemState(le.lendingBook, lendingId, data, le.MarkLendingItemDirty)
le.lendingItemStates[lendingId] = obj
return obj
}
func (le *lendingExchangeState) getLendingTrade(db Database, tradeId common.Hash) (stateObject *lendingTradeState) {
// Prefer 'live' objects.
if obj := le.lendingTradeStates[tradeId]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := le.getLendingTradeTrie(db).TryGet(tradeId[:])
if len(enc) == 0 {
le.setError(err)
return nil
}
var data LendingTrade
if err := rlp.DecodeBytes(enc, &data); err != nil {
log.Error("Failed to decode state lending trade", "tradeId", tradeId, "err", err)
return nil
}
// Insert into the live set.
obj := newLendingTradeState(le.lendingBook, tradeId, data, le.MarkLendingTradeDirty)
le.lendingTradeStates[tradeId] = obj
return obj
}
/*
*
Update Trie
*/
func (le *lendingExchangeState) updateLendingTimeTrie(db Database) Trie {
tr := le.getLendingItemTrie(db)
for lendingId, lendingItem := range le.lendingItemStates {
if _, isDirty := le.lendingItemStatesDirty[lendingId]; isDirty {
delete(le.lendingItemStatesDirty, lendingId)
if lendingItem.empty() {
le.setError(tr.TryDelete(lendingId[:]))
continue
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(lendingItem)
le.setError(tr.TryUpdate(lendingId[:], v))
}
}
return tr
}
func (le *lendingExchangeState) updateLendingTradeTrie(db Database) Trie {
tr := le.getLendingTradeTrie(db)
for tradeId, lendingTradeItem := range le.lendingTradeStates {
if _, isDirty := le.lendingTradeStatesDirty[tradeId]; isDirty {
delete(le.lendingTradeStatesDirty, tradeId)
if lendingTradeItem.empty() {
le.setError(tr.TryDelete(tradeId[:]))
continue
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(lendingTradeItem)
le.setError(tr.TryUpdate(tradeId[:], v))
}
}
return tr
}
func (le *lendingExchangeState) updateBorrowingTrie(db Database) Trie {
tr := le.getBorrowingTrie(db)
for rate, orderList := range le.borrowingStates {
if _, isDirty := le.borrowingStatesDirty[rate]; isDirty {
delete(le.borrowingStatesDirty, rate)
if orderList.empty() {
le.setError(tr.TryDelete(rate[:]))
continue
}
err := orderList.updateRoot(db)
if err != nil {
log.Warn("updateBorrowingTrie updateRoot", "err", err, "rate", rate, "orderList", *orderList)
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(orderList)
le.setError(tr.TryUpdate(rate[:], v))
}
}
return tr
}
func (le *lendingExchangeState) updateInvestingTrie(db Database) Trie {
tr := le.getInvestingTrie(db)
for rate, orderList := range le.investingStates {
if _, isDirty := le.investingStatesDirty[rate]; isDirty {
delete(le.investingStatesDirty, rate)
if orderList.empty() {
le.setError(tr.TryDelete(rate[:]))
continue
}
err := orderList.updateRoot(db)
if err != nil {
log.Warn("updateInvestingTrie updateRoot", "err", err, "rate", rate, "orderList", *orderList)
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(orderList)
le.setError(tr.TryUpdate(rate[:], v))
}
}
return tr
}
func (le *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
tr := le.getLiquidationTimeTrie(db)
for time, itemList := range le.liquidationTimeStates {
if _, isDirty := le.liquidationTimestatesDirty[time]; isDirty {
delete(le.liquidationTimestatesDirty, time)
if itemList.empty() {
le.setError(tr.TryDelete(time[:]))
continue
}
err := itemList.updateRoot(db)
if err != nil {
log.Warn("updateLiquidationTimeTrie updateRoot", "err", err, "time", time, "itemList", *itemList)
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(itemList)
le.setError(tr.TryUpdate(time[:], v))
}
}
return tr
}
/**
Update Root
*/
func (le *lendingExchangeState) updateOrderRoot(db Database) {
le.updateLendingTimeTrie(db)
le.data.LendingItemRoot = le.lendingItemTrie.Hash()
}
func (le *lendingExchangeState) updateInvestingRoot(db Database) error {
le.updateInvestingTrie(db)
if le.dbErr != nil {
return le.dbErr
}
le.data.InvestingRoot = le.investingTrie.Hash()
return nil
}
func (le *lendingExchangeState) updateBorrowingRoot(db Database) {
le.updateBorrowingTrie(db)
le.data.BorrowingRoot = le.borrowingTrie.Hash()
}
func (le *lendingExchangeState) updateLiquidationTimeRoot(db Database) {
le.updateLiquidationTimeTrie(db)
le.data.LiquidationTimeRoot = le.liquidationTimeTrie.Hash()
}
func (le *lendingExchangeState) updateLendingTradeRoot(db Database) {
le.updateLendingTradeTrie(db)
le.data.LendingTradeRoot = le.lendingTradeTrie.Hash()
}
/**
Commit Trie
*/
func (le *lendingExchangeState) CommitLendingItemTrie(db Database) error {
le.updateLendingTimeTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := le.lendingItemTrie.Commit(nil)
if err == nil {
le.data.LendingItemRoot = root
}
return err
}
func (le *lendingExchangeState) CommitLendingTradeTrie(db Database) error {
le.updateLendingTradeTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := le.lendingTradeTrie.Commit(nil)
if err == nil {
le.data.LendingTradeRoot = root
}
return err
}
func (le *lendingExchangeState) CommitInvestingTrie(db Database) error {
le.updateInvestingTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := le.investingTrie.Commit(func(leaf []byte, parent common.Hash) error {
var orderList itemList
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
return nil
}
if orderList.Root != EmptyRoot {
db.TrieDB().Reference(orderList.Root, parent)
}
return nil
})
if err == nil {
le.data.InvestingRoot = root
}
return err
}
func (le *lendingExchangeState) CommitBorrowingTrie(db Database) error {
le.updateBorrowingTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := le.borrowingTrie.Commit(func(leaf []byte, parent common.Hash) error {
var orderList itemList
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
return nil
}
if orderList.Root != EmptyRoot {
db.TrieDB().Reference(orderList.Root, parent)
}
return nil
})
if err == nil {
le.data.BorrowingRoot = root
}
return err
}
func (le *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
le.updateLiquidationTimeTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := le.liquidationTimeTrie.Commit(func(leaf []byte, parent common.Hash) error {
var orderList itemList
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
return nil
}
if orderList.Root != EmptyRoot {
db.TrieDB().Reference(orderList.Root, parent)
}
return nil
})
if err == nil {
le.data.LiquidationTimeRoot = root
}
return err
}
/*
*
Get Trie Data
*/
func (le *lendingExchangeState) getBestInvestingInterest(db Database) common.Hash {
trie := le.getInvestingTrie(db)
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
if err != nil {
log.Error("Failed find best investing rate", "orderbook", le.lendingBook.Hex())
return EmptyHash
}
if len(encKey) == 0 || len(encValue) == 0 {
log.Debug("Not found get best investing rate", "encKey", encKey, "encValue", encValue)
return EmptyHash
}
// Insert into the live set.
interest := common.BytesToHash(encKey)
if _, exist := le.investingStates[interest]; !exist {
var data itemList
if err := rlp.DecodeBytes(encValue, &data); err != nil {
log.Error("Failed to decode state get best investing rate", "err", err)
return EmptyHash
}
obj := newItemListState(le.lendingBook, interest, data, le.MarkInvestingDirty)
le.investingStates[interest] = obj
}
return interest
}
func (le *lendingExchangeState) getBestBorrowingInterest(db Database) common.Hash {
trie := le.getBorrowingTrie(db)
encKey, encValue, err := trie.TryGetBestRightKeyAndValue()
if err != nil {
log.Error("Failed find best key bid trie ", "orderbook", le.lendingBook.Hex())
return EmptyHash
}
if len(encKey) == 0 || len(encValue) == 0 {
log.Debug("Not found get best bid trie", "encKey", encKey, "encValue", encValue)
return EmptyHash
}
// Insert into the live set.
interest := common.BytesToHash(encKey)
if _, exist := le.borrowingStates[interest]; !exist {
var data itemList
if err := rlp.DecodeBytes(encValue, &data); err != nil {
log.Error("Failed to decode state get best bid trie", "err", err)
return EmptyHash
}
obj := newItemListState(le.lendingBook, interest, data, le.MarkBorrowingDirty)
le.borrowingStates[interest] = obj
}
return interest
}
func (le *lendingExchangeState) getLowestLiquidationTime(db Database) (common.Hash, *liquidationTimeState) {
trie := le.getLiquidationTimeTrie(db)
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
if err != nil {
log.Error("Failed find best liquidation time trie ", "orderBook", le.lendingBook.Hex())
return EmptyHash, nil
}
if len(encKey) == 0 || len(encValue) == 0 {
log.Debug("Not found get liquidation time trie", "encKey", encKey, "encValue", encValue)
return EmptyHash, nil
}
price := common.BytesToHash(encKey)
obj, exist := le.liquidationTimeStates[price]
if !exist {
var data itemList
if err := rlp.DecodeBytes(encValue, &data); err != nil {
log.Error("Failed to decode state get liquidation time trie", "err", err)
return EmptyHash, nil
}
obj = newLiquidationTimeState(le.lendingBook, price, data, le.MarkLiquidationTimeDirty)
le.liquidationTimeStates[price] = obj
}
if obj.empty() {
return EmptyHash, nil
}
return price, obj
}
func (le *lendingExchangeState) deepCopy(db *LendingStateDB, onDirty func(hash common.Hash)) *lendingExchangeState {
stateExchanges := newStateExchanges(db, le.lendingBook, le.data, onDirty)
if le.investingTrie != nil {
stateExchanges.investingTrie = db.db.CopyTrie(le.investingTrie)
}
if le.borrowingTrie != nil {
stateExchanges.borrowingTrie = db.db.CopyTrie(le.borrowingTrie)
}
if le.lendingItemTrie != nil {
stateExchanges.lendingItemTrie = db.db.CopyTrie(le.lendingItemTrie)
}
for key, value := range le.borrowingStates {
stateExchanges.borrowingStates[key] = value.deepCopy(db, le.MarkBorrowingDirty)
}
for key := range le.borrowingStatesDirty {
stateExchanges.borrowingStatesDirty[key] = struct{}{}
}
for key, value := range le.investingStates {
stateExchanges.investingStates[key] = value.deepCopy(db, le.MarkInvestingDirty)
}
for key := range le.investingStatesDirty {
stateExchanges.investingStatesDirty[key] = struct{}{}
}
for key, value := range le.lendingItemStates {
stateExchanges.lendingItemStates[key] = value.deepCopy(le.MarkLendingItemDirty)
}
for orderId := range le.lendingItemStatesDirty {
stateExchanges.lendingItemStatesDirty[orderId] = struct{}{}
}
for key, value := range le.lendingTradeStates {
stateExchanges.lendingTradeStates[key] = value.deepCopy(le.MarkLendingTradeDirty)
}
for orderId := range le.lendingTradeStatesDirty {
stateExchanges.lendingTradeStatesDirty[orderId] = struct{}{}
}
for time, orderList := range le.liquidationTimeStates {
stateExchanges.liquidationTimeStates[time] = orderList.deepCopy(db, le.MarkLiquidationTimeDirty)
}
for time := range le.liquidationTimestatesDirty {
stateExchanges.liquidationTimestatesDirty[time] = struct{}{}
}
return stateExchanges
}
// Returns the address of the contract/tradeId
func (le *lendingExchangeState) Hash() common.Hash {
return le.lendingBook
}
func (le *lendingExchangeState) setNonce(nonce uint64) {
le.data.Nonce = nonce
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (le *lendingExchangeState) Nonce() uint64 {
return le.data.Nonce
}
func (le *lendingExchangeState) setTradeNonce(nonce uint64) {
le.data.TradeNonce = nonce
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (le *lendingExchangeState) TradeNonce() uint64 {
return le.data.TradeNonce
}
func (le *lendingExchangeState) removeInvestingOrderList(db Database, stateOrderList *itemListState) {
le.setError(le.investingTrie.TryDelete(stateOrderList.key[:]))
}
func (le *lendingExchangeState) removeBorrowingOrderList(db Database, stateOrderList *itemListState) {
le.setError(le.borrowingTrie.TryDelete(stateOrderList.key[:]))
}
func (le *lendingExchangeState) createInvestingOrderList(db Database, price common.Hash) (newobj *itemListState) {
newobj = newItemListState(le.lendingBook, price, itemList{Volume: Zero}, le.MarkInvestingDirty)
le.investingStates[price] = newobj
le.investingStatesDirty[price] = struct{}{}
data, err := rlp.EncodeToBytes(newobj)
if err != nil {
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
}
le.setError(le.getInvestingTrie(db).TryUpdate(price[:], data))
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
return newobj
}
func (le *lendingExchangeState) MarkBorrowingDirty(price common.Hash) {
le.borrowingStatesDirty[price] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (le *lendingExchangeState) MarkInvestingDirty(price common.Hash) {
le.investingStatesDirty[price] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (le *lendingExchangeState) MarkLendingItemDirty(lending common.Hash) {
le.lendingItemStatesDirty[lending] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (le *lendingExchangeState) MarkLendingTradeDirty(tradeId common.Hash) {
le.lendingTradeStatesDirty[tradeId] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (le *lendingExchangeState) MarkLiquidationTimeDirty(orderId common.Hash) {
le.liquidationTimestatesDirty[orderId] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (le *lendingExchangeState) createBorrowingOrderList(db Database, price common.Hash) (newobj *itemListState) {
newobj = newItemListState(le.lendingBook, price, itemList{Volume: Zero}, le.MarkBorrowingDirty)
le.borrowingStates[price] = newobj
le.borrowingStatesDirty[price] = struct{}{}
data, err := rlp.EncodeToBytes(newobj)
if err != nil {
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
}
le.setError(le.getBorrowingTrie(db).TryUpdate(price[:], data))
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
return newobj
}
func (le *lendingExchangeState) createLendingItem(db Database, orderId common.Hash, order LendingItem) (newobj *lendingItemState) {
newobj = newLendinItemState(le.lendingBook, orderId, order, le.MarkLendingItemDirty)
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.LendingId))
le.lendingItemStates[orderIdHash] = newobj
le.lendingItemStatesDirty[orderIdHash] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.lendingBook)
le.onDirty = nil
}
return newobj
}
func (le *lendingExchangeState) createLiquidationTime(db Database, time common.Hash) (newobj *liquidationTimeState) {
newobj = newLiquidationTimeState(time, le.lendingBook, itemList{Volume: Zero}, le.MarkLiquidationTimeDirty)
le.liquidationTimeStates[time] = newobj
le.liquidationTimestatesDirty[time] = struct{}{}
data, err := rlp.EncodeToBytes(newobj)
if err != nil {
panic(fmt.Errorf("can't encode liquidation time at %x: %v", time[:], err))
}
le.setError(le.getLiquidationTimeTrie(db).TryUpdate(time[:], data))
if le.onDirty != nil {
le.onDirty(le.lendingBook)
le.onDirty = nil
}
return newobj
}
func (le *lendingExchangeState) insertLendingTrade(tradeId common.Hash, order LendingTrade) (newobj *lendingTradeState) {
newobj = newLendingTradeState(le.lendingBook, tradeId, order, le.MarkLendingTradeDirty)
le.lendingTradeStates[tradeId] = newobj
le.lendingTradeStatesDirty[tradeId] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.lendingBook)
le.onDirty = nil
}
return newobj
}