Merge pull request #686 from gzliudan/fix-st1006

all: fix staticcheck warning ST1006
This commit is contained in:
Daniel Liu 2024-10-25 21:31:27 +08:00 committed by GitHub
commit 7b5104576e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 2792 additions and 2773 deletions

View file

@ -47,13 +47,13 @@ type DumpOrderBookInfo struct {
LowestLiquidationPrice *big.Int
}
func (self *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := t.getStateExchangeObject(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]DumpOrderList{}
it := trie.NewIterator(exhangeObject.getAsksTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getAsksTrie(t.db).NodeIterator(nil))
for it.Next() {
priceHash := common.BytesToHash(it.Key)
if common.EmptyHash(priceHash) {
@ -67,13 +67,13 @@ func (self *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]Dum
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price :%v", orderBook.Hex(), price)
}
stateOrderList := newStateOrderList(self, Ask, orderBook, priceHash, data, nil)
mapResult[price] = stateOrderList.DumpOrderList(self.db)
stateOrderList := newStateOrderList(t, Ask, orderBook, priceHash, data, nil)
mapResult[price] = stateOrderList.DumpOrderList(t.db)
}
}
for priceHash, stateOrderList := range exhangeObject.stateAskObjects {
if stateOrderList.Volume().Sign() > 0 {
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(self.db)
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(t.db)
}
}
listPrice := []*big.Int{}
@ -90,13 +90,13 @@ func (self *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]Dum
return result, nil
}
func (self *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := t.getStateExchangeObject(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]DumpOrderList{}
it := trie.NewIterator(exhangeObject.getBidsTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getBidsTrie(t.db).NodeIterator(nil))
for it.Next() {
priceHash := common.BytesToHash(it.Key)
if common.EmptyHash(priceHash) {
@ -110,13 +110,13 @@ func (self *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]Dum
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price :%v", orderBook.Hex(), price)
}
stateOrderList := newStateOrderList(self, Bid, orderBook, priceHash, data, nil)
mapResult[price] = stateOrderList.DumpOrderList(self.db)
stateOrderList := newStateOrderList(t, Bid, orderBook, priceHash, data, nil)
mapResult[price] = stateOrderList.DumpOrderList(t.db)
}
}
for priceHash, stateOrderList := range exhangeObject.stateBidObjects {
if stateOrderList.Volume().Sign() > 0 {
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(self.db)
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(t.db)
}
}
listPrice := []*big.Int{}
@ -133,13 +133,13 @@ func (self *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]Dum
return mapResult, nil
}
func (self *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := t.getStateExchangeObject(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]*big.Int{}
it := trie.NewIterator(exhangeObject.getBidsTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getBidsTrie(t.db).NodeIterator(nil))
for it.Next() {
priceHash := common.BytesToHash(it.Key)
if common.EmptyHash(priceHash) {
@ -153,7 +153,7 @@ func (self *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.In
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price :%v", orderBook.Hex(), price)
}
stateOrderList := newStateOrderList(self, Bid, orderBook, priceHash, data, nil)
stateOrderList := newStateOrderList(t, Bid, orderBook, priceHash, data, nil)
mapResult[price] = stateOrderList.data.Volume
}
}
@ -176,13 +176,13 @@ func (self *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.In
return mapResult, nil
}
func (self *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := t.getStateExchangeObject(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]*big.Int{}
it := trie.NewIterator(exhangeObject.getAsksTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getAsksTrie(t.db).NodeIterator(nil))
for it.Next() {
priceHash := common.BytesToHash(it.Key)
if common.EmptyHash(priceHash) {
@ -196,7 +196,7 @@ func (self *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.In
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price : %v", orderBook.Hex(), price)
}
stateOrderList := newStateOrderList(self, Ask, orderBook, priceHash, data, nil)
stateOrderList := newStateOrderList(t, Ask, orderBook, priceHash, data, nil)
mapResult[price] = stateOrderList.data.Volume
}
}
@ -218,22 +218,23 @@ func (self *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.In
}
return result, nil
}
func (self *stateOrderList) DumpOrderList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
func (s *stateOrderList) DumpOrderList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(s.getTrie(db).NodeIterator(nil))
for orderListIt.Next() {
keyHash := common.BytesToHash(orderListIt.Key)
if common.EmptyHash(keyHash) {
continue
}
if _, exist := self.cachedStorage[keyHash]; exist {
if _, exist := s.cachedStorage[keyHash]; exist {
continue
} else {
_, content, _, _ := rlp.Split(orderListIt.Value)
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
}
}
for key, value := range self.cachedStorage {
for key, value := range s.cachedStorage {
if !common.EmptyHash(value) {
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
}
@ -245,15 +246,15 @@ func (self *stateOrderList) DumpOrderList(db Database) DumpOrderList {
sort.Slice(listIds, func(i, j int) bool {
return listIds[i].Cmp(listIds[j]) < 0
})
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
result := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
for _, id := range listIds {
result.Orders[id] = mapResult.Orders[id]
}
return mapResult
}
func (self *TradingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
exhangeObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
exhangeObject := t.getStateExchangeObject(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
@ -264,29 +265,29 @@ func (self *TradingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrder
result.MediumPriceBeforeEpoch = exhangeObject.data.MediumPriceBeforeEpoch
result.Nonce = exhangeObject.data.Nonce
result.TotalQuantity = exhangeObject.data.TotalQuantity
result.BestAsk = new(big.Int).SetBytes(exhangeObject.getBestPriceAsksTrie(self.db).Bytes())
result.BestBid = new(big.Int).SetBytes(exhangeObject.getBestBidsTrie(self.db).Bytes())
lowestPrice, _ := exhangeObject.getLowestLiquidationPrice(self.db)
result.BestAsk = new(big.Int).SetBytes(exhangeObject.getBestPriceAsksTrie(t.db).Bytes())
result.BestBid = new(big.Int).SetBytes(exhangeObject.getBestBidsTrie(t.db).Bytes())
lowestPrice, _ := exhangeObject.getLowestLiquidationPrice(t.db)
result.LowestLiquidationPrice = new(big.Int).SetBytes(lowestPrice.Bytes())
return result, nil
}
func (self *stateLendingBook) DumpOrderList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
func (s *stateLendingBook) DumpOrderList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(s.getTrie(db).NodeIterator(nil))
for orderListIt.Next() {
keyHash := common.BytesToHash(orderListIt.Key)
if common.EmptyHash(keyHash) {
continue
}
if _, exist := self.cachedStorage[keyHash]; exist {
if _, exist := s.cachedStorage[keyHash]; exist {
continue
} else {
_, content, _, _ := rlp.Split(orderListIt.Value)
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
}
}
for key, value := range self.cachedStorage {
for key, value := range s.cachedStorage {
if !common.EmptyHash(value) {
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
}
@ -298,33 +299,33 @@ func (self *stateLendingBook) DumpOrderList(db Database) DumpOrderList {
sort.Slice(listIds, func(i, j int) bool {
return listIds[i].Cmp(listIds[j]) < 0
})
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
result := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
for _, id := range listIds {
result.Orders[id] = mapResult.Orders[id]
}
return mapResult
}
func (self *liquidationPriceState) DumpLendingBook(db Database) (DumpLendingBook, error) {
result := DumpLendingBook{Volume: self.Volume(), LendingBooks: map[common.Hash]DumpOrderList{}}
it := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
func (l *liquidationPriceState) DumpLendingBook(db Database) (DumpLendingBook, error) {
result := DumpLendingBook{Volume: l.Volume(), LendingBooks: map[common.Hash]DumpOrderList{}}
it := trie.NewIterator(l.getTrie(db).NodeIterator(nil))
for it.Next() {
lendingBook := common.BytesToHash(it.Key)
if common.EmptyHash(lendingBook) {
continue
}
if _, exist := self.stateLendingBooks[lendingBook]; exist {
if _, exist := l.stateLendingBooks[lendingBook]; exist {
continue
} else {
var data orderList
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
return result, fmt.Errorf("failed to decode state lending book orderbook: %s , liquidation price : %s , lendingBook : %s , err : %v", self.orderBook, self.liquidationPrice, lendingBook, err)
return result, fmt.Errorf("failed to decode state lending book orderbook: %s, liquidation price: %s , lendingBook: %s , err: %v", l.orderBook, l.liquidationPrice, lendingBook, err)
}
stateLendingBook := newStateLendingBook(self.orderBook, self.liquidationPrice, lendingBook, data, nil)
stateLendingBook := newStateLendingBook(l.orderBook, l.liquidationPrice, lendingBook, data, nil)
result.LendingBooks[lendingBook] = stateLendingBook.DumpOrderList(db)
}
}
for lendingBook, stateLendingBook := range self.stateLendingBooks {
for lendingBook, stateLendingBook := range l.stateLendingBooks {
if !common.EmptyHash(lendingBook) {
result.LendingBooks[lendingBook] = stateLendingBook.DumpOrderList(db)
}
@ -332,13 +333,13 @@ func (self *liquidationPriceState) DumpLendingBook(db Database) (DumpLendingBook
return result, nil
}
func (self *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map[*big.Int]DumpLendingBook, error) {
exhangeObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map[*big.Int]DumpLendingBook, error) {
exhangeObject := t.getStateExchangeObject(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]DumpLendingBook{}
it := trie.NewIterator(exhangeObject.getLiquidationPriceTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getLiquidationPriceTrie(t.db).NodeIterator(nil))
for it.Next() {
priceHash := common.BytesToHash(it.Key)
if common.EmptyHash(priceHash) {
@ -352,8 +353,8 @@ func (self *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price : %v", orderBook.Hex(), price)
}
liquidationPriceState := newLiquidationPriceState(self, orderBook, priceHash, data, nil)
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(self.db)
liquidationPriceState := newLiquidationPriceState(t, orderBook, priceHash, data, nil)
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(t.db)
if err != nil {
return nil, err
}
@ -362,7 +363,7 @@ func (self *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map
}
for priceHash, liquidationPriceState := range exhangeObject.liquidationPriceStates {
if liquidationPriceState.Volume().Sign() > 0 {
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(self.db)
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(t.db)
if err != nil {
return nil, err
}

View file

@ -65,59 +65,59 @@ func newStateLendingBook(orderBook common.Hash, price common.Hash, lendingBook c
}
}
func (self *stateLendingBook) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, self.data)
func (s *stateLendingBook) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, s.data)
}
func (self *stateLendingBook) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (s *stateLendingBook) setError(err error) {
if s.dbErr == nil {
s.dbErr = err
}
}
func (self *stateLendingBook) getTrie(db Database) Trie {
if self.trie == nil {
func (s *stateLendingBook) getTrie(db Database) Trie {
if s.trie == nil {
var err error
self.trie, err = db.OpenStorageTrie(self.lendingBook, self.data.Root)
s.trie, err = db.OpenStorageTrie(s.lendingBook, s.data.Root)
if err != nil {
self.trie, _ = db.OpenStorageTrie(self.price, EmptyHash)
self.setError(fmt.Errorf("can't create storage trie: %v", err))
s.trie, _ = db.OpenStorageTrie(s.price, EmptyHash)
s.setError(fmt.Errorf("can't create storage trie: %v", err))
}
}
return self.trie
return s.trie
}
func (self *stateLendingBook) Exist(db Database, lendingId common.Hash) bool {
amount, exists := self.cachedStorage[lendingId]
func (s *stateLendingBook) Exist(db Database, lendingId common.Hash) bool {
amount, exists := s.cachedStorage[lendingId]
if exists {
return true
}
// Load from DB in case it is missing.
enc, err := self.getTrie(db).TryGet(lendingId[:])
enc, err := s.getTrie(db).TryGet(lendingId[:])
if err != nil {
self.setError(err)
s.setError(err)
return false
}
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
self.setError(err)
s.setError(err)
}
amount.SetBytes(content)
}
if (amount != common.Hash{}) {
self.cachedStorage[lendingId] = amount
s.cachedStorage[lendingId] = amount
}
return true
}
func (self *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
func (s *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
tradeIds := []common.Hash{}
lendingBookTrie := self.getTrie(db)
lendingBookTrie := s.getTrie(db)
if lendingBookTrie == nil {
return tradeIds
}
for id, value := range self.cachedStorage {
for id, value := range s.cachedStorage {
if !common.EmptyHash(value) {
tradeIds = append(tradeIds, id)
}
@ -125,7 +125,7 @@ func (self *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
orderListIt := trie.NewIterator(lendingBookTrie.NodeIterator(nil))
for orderListIt.Next() {
id := common.BytesToHash(orderListIt.Key)
if _, exist := self.cachedStorage[id]; exist {
if _, exist := s.cachedStorage[id]; exist {
continue
}
tradeIds = append(tradeIds, id)
@ -133,83 +133,83 @@ func (self *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
return tradeIds
}
func (self *stateLendingBook) insertTradingId(db Database, tradeId common.Hash) {
self.setTradingId(tradeId, tradeId)
self.setError(self.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
func (s *stateLendingBook) insertTradingId(db Database, tradeId common.Hash) {
s.setTradingId(tradeId, tradeId)
s.setError(s.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
}
func (self *stateLendingBook) removeTradingId(db Database, tradeId common.Hash) {
tr := self.getTrie(db)
self.setError(tr.TryDelete(tradeId[:]))
self.setTradingId(tradeId, EmptyHash)
func (s *stateLendingBook) removeTradingId(db Database, tradeId common.Hash) {
tr := s.getTrie(db)
s.setError(tr.TryDelete(tradeId[:]))
s.setTradingId(tradeId, EmptyHash)
}
func (self *stateLendingBook) setTradingId(tradeId common.Hash, value common.Hash) {
self.cachedStorage[tradeId] = value
self.dirtyStorage[tradeId] = value
func (s *stateLendingBook) setTradingId(tradeId common.Hash, value common.Hash) {
s.cachedStorage[tradeId] = value
s.dirtyStorage[tradeId] = value
if self.onDirty != nil {
self.onDirty(self.lendingBook)
self.onDirty = nil
if s.onDirty != nil {
s.onDirty(s.lendingBook)
s.onDirty = nil
}
}
func (self *stateLendingBook) updateTrie(db Database) Trie {
tr := self.getTrie(db)
for key, value := range self.dirtyStorage {
delete(self.dirtyStorage, key)
func (s *stateLendingBook) updateTrie(db Database) Trie {
tr := s.getTrie(db)
for key, value := range s.dirtyStorage {
delete(s.dirtyStorage, key)
if value == EmptyHash {
self.setError(tr.TryDelete(key[:]))
s.setError(tr.TryDelete(key[:]))
continue
}
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
self.setError(tr.TryUpdate(key[:], v))
s.setError(tr.TryUpdate(key[:], v))
}
return tr
}
func (self *stateLendingBook) updateRoot(db Database) error {
self.updateTrie(db)
if self.dbErr != nil {
return self.dbErr
func (s *stateLendingBook) updateRoot(db Database) error {
s.updateTrie(db)
if s.dbErr != nil {
return s.dbErr
}
root, err := self.trie.Commit(nil)
root, err := s.trie.Commit(nil)
if err == nil {
self.data.Root = root
s.data.Root = root
}
return err
}
func (self *stateLendingBook) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateLendingBook {
stateLendingBook := newStateLendingBook(self.lendingBook, self.orderBook, self.price, self.data, onDirty)
if self.trie != nil {
stateLendingBook.trie = db.db.CopyTrie(self.trie)
func (s *stateLendingBook) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateLendingBook {
stateLendingBook := newStateLendingBook(s.lendingBook, s.orderBook, s.price, s.data, onDirty)
if s.trie != nil {
stateLendingBook.trie = db.db.CopyTrie(s.trie)
}
for key, value := range self.dirtyStorage {
for key, value := range s.dirtyStorage {
stateLendingBook.dirtyStorage[key] = value
}
for key, value := range self.cachedStorage {
for key, value := range s.cachedStorage {
stateLendingBook.cachedStorage[key] = value
}
return stateLendingBook
}
func (c *stateLendingBook) AddVolume(amount *big.Int) {
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
func (s *stateLendingBook) AddVolume(amount *big.Int) {
s.setVolume(new(big.Int).Add(s.data.Volume, amount))
}
func (c *stateLendingBook) subVolume(amount *big.Int) {
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
func (s *stateLendingBook) subVolume(amount *big.Int) {
s.setVolume(new(big.Int).Sub(s.data.Volume, amount))
}
func (self *stateLendingBook) setVolume(volume *big.Int) {
self.data.Volume = volume
if self.onDirty != nil {
self.onDirty(self.lendingBook)
self.onDirty = nil
func (s *stateLendingBook) setVolume(volume *big.Int) {
s.data.Volume = volume
if s.onDirty != nil {
s.onDirty(s.lendingBook)
s.onDirty = nil
}
}
func (self *stateLendingBook) Volume() *big.Int {
return self.data.Volume
func (s *stateLendingBook) Volume() *big.Int {
return s.data.Volume
}

View file

@ -68,54 +68,54 @@ func newLiquidationPriceState(db *TradingStateDB, orderBook common.Hash, price c
}
// EncodeRLP implements rlp.Encoder.
func (c *liquidationPriceState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, c.data)
func (l *liquidationPriceState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, l.data)
}
// setError remembers the first non-nil error it is called with.
func (self *liquidationPriceState) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (l *liquidationPriceState) setError(err error) {
if l.dbErr == nil {
l.dbErr = err
}
}
func (self *liquidationPriceState) MarkStateLendingBookDirty(price common.Hash) {
self.stateLendingBooksDirty[price] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.liquidationPrice)
self.onDirty = nil
func (l *liquidationPriceState) MarkStateLendingBookDirty(price common.Hash) {
l.stateLendingBooksDirty[price] = struct{}{}
if l.onDirty != nil {
l.onDirty(l.liquidationPrice)
l.onDirty = nil
}
}
func (self *liquidationPriceState) createLendingBook(db Database, lendingBook common.Hash) (newobj *stateLendingBook) {
newobj = newStateLendingBook(self.orderBook, self.liquidationPrice, lendingBook, orderList{Volume: Zero}, self.MarkStateLendingBookDirty)
self.stateLendingBooks[lendingBook] = newobj
self.stateLendingBooksDirty[lendingBook] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.liquidationPrice)
self.onDirty = nil
func (l *liquidationPriceState) createLendingBook(db Database, lendingBook common.Hash) (newobj *stateLendingBook) {
newobj = newStateLendingBook(l.orderBook, l.liquidationPrice, lendingBook, orderList{Volume: Zero}, l.MarkStateLendingBookDirty)
l.stateLendingBooks[lendingBook] = newobj
l.stateLendingBooksDirty[lendingBook] = struct{}{}
if l.onDirty != nil {
l.onDirty(l.liquidationPrice)
l.onDirty = nil
}
return newobj
}
func (self *liquidationPriceState) getTrie(db Database) Trie {
if self.trie == nil {
func (l *liquidationPriceState) getTrie(db Database) Trie {
if l.trie == nil {
var err error
self.trie, err = db.OpenStorageTrie(self.liquidationPrice, self.data.Root)
l.trie, err = db.OpenStorageTrie(l.liquidationPrice, l.data.Root)
if err != nil {
self.trie, _ = db.OpenStorageTrie(self.liquidationPrice, EmptyHash)
self.setError(fmt.Errorf("can't create storage trie: %v", err))
l.trie, _ = db.OpenStorageTrie(l.liquidationPrice, EmptyHash)
l.setError(fmt.Errorf("can't create storage trie: %v", err))
}
}
return self.trie
return l.trie
}
func (self *liquidationPriceState) updateTrie(db Database) Trie {
tr := self.getTrie(db)
for lendingId, stateObject := range self.stateLendingBooks {
delete(self.stateLendingBooksDirty, lendingId)
func (l *liquidationPriceState) updateTrie(db Database) Trie {
tr := l.getTrie(db)
for lendingId, stateObject := range l.stateLendingBooks {
delete(l.stateLendingBooksDirty, lendingId)
if stateObject.empty() {
self.setError(tr.TryDelete(lendingId[:]))
l.setError(tr.TryDelete(lendingId[:]))
continue
}
err := stateObject.updateRoot(db)
@ -125,17 +125,17 @@ func (self *liquidationPriceState) updateTrie(db Database) Trie {
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(stateObject)
self.setError(tr.TryUpdate(lendingId[:], v))
l.setError(tr.TryUpdate(lendingId[:], v))
}
return tr
}
func (self *liquidationPriceState) updateRoot(db Database) error {
self.updateTrie(db)
if self.dbErr != nil {
return self.dbErr
func (l *liquidationPriceState) updateRoot(db Database) error {
l.updateTrie(db)
if l.dbErr != nil {
return l.dbErr
}
root, err := self.trie.Commit(func(leaf []byte, parent common.Hash) error {
root, err := l.trie.Commit(func(leaf []byte, parent common.Hash) error {
var orderList orderList
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
return nil
@ -146,57 +146,57 @@ func (self *liquidationPriceState) updateRoot(db Database) error {
return nil
})
if err == nil {
self.data.Root = root
l.data.Root = root
}
return err
}
func (self *liquidationPriceState) deepCopy(db *TradingStateDB, onDirty func(liquidationPrice common.Hash)) *liquidationPriceState {
stateOrderList := newLiquidationPriceState(db, self.orderBook, self.liquidationPrice, self.data, onDirty)
if self.trie != nil {
stateOrderList.trie = db.db.CopyTrie(self.trie)
func (l *liquidationPriceState) deepCopy(db *TradingStateDB, onDirty func(liquidationPrice common.Hash)) *liquidationPriceState {
stateOrderList := newLiquidationPriceState(db, l.orderBook, l.liquidationPrice, l.data, onDirty)
if l.trie != nil {
stateOrderList.trie = db.db.CopyTrie(l.trie)
}
for key, value := range self.stateLendingBooks {
stateOrderList.stateLendingBooks[key] = value.deepCopy(db, self.MarkStateLendingBookDirty)
for key, value := range l.stateLendingBooks {
stateOrderList.stateLendingBooks[key] = value.deepCopy(db, l.MarkStateLendingBookDirty)
}
for key, value := range self.stateLendingBooksDirty {
for key, value := range l.stateLendingBooksDirty {
stateOrderList.stateLendingBooksDirty[key] = value
}
return stateOrderList
}
// Retrieve a state object given my the address. Returns nil if not found.
func (self *liquidationPriceState) getStateLendingBook(db Database, lendingBook common.Hash) (stateObject *stateLendingBook) {
func (l *liquidationPriceState) getStateLendingBook(db Database, lendingBook common.Hash) (stateObject *stateLendingBook) {
// Prefer 'live' objects.
if obj := self.stateLendingBooks[lendingBook]; obj != nil {
if obj := l.stateLendingBooks[lendingBook]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getTrie(db).TryGet(lendingBook[:])
enc, err := l.getTrie(db).TryGet(lendingBook[:])
if len(enc) == 0 {
self.setError(err)
l.setError(err)
return nil
}
var data orderList
if err := rlp.DecodeBytes(enc, &data); err != nil {
log.Error("Failed to decode state lending book ", "orderbook", self.orderBook, "liquidation price", self.liquidationPrice, "lendingBook", lendingBook, "err", err)
log.Error("Failed to decode state lending book ", "orderbook", l.orderBook, "liquidation price", l.liquidationPrice, "lendingBook", lendingBook, "err", err)
return nil
}
// Insert into the live set.
obj := newStateLendingBook(self.orderBook, self.liquidationPrice, lendingBook, data, self.MarkStateLendingBookDirty)
self.stateLendingBooks[lendingBook] = obj
obj := newStateLendingBook(l.orderBook, l.liquidationPrice, lendingBook, data, l.MarkStateLendingBookDirty)
l.stateLendingBooks[lendingBook] = obj
return obj
}
func (self *liquidationPriceState) getAllLiquidationData(db Database) map[common.Hash][]common.Hash {
func (l *liquidationPriceState) getAllLiquidationData(db Database) map[common.Hash][]common.Hash {
liquidationData := map[common.Hash][]common.Hash{}
lendingBookTrie := self.getTrie(db)
lendingBookTrie := l.getTrie(db)
if lendingBookTrie == nil {
return liquidationData
}
lendingBooks := []common.Hash{}
for id, stateLendingBook := range self.stateLendingBooks {
for id, stateLendingBook := range l.stateLendingBooks {
if !stateLendingBook.empty() {
lendingBooks = append(lendingBooks, id)
}
@ -204,13 +204,13 @@ func (self *liquidationPriceState) getAllLiquidationData(db Database) map[common
lendingBookListIt := trie.NewIterator(lendingBookTrie.NodeIterator(nil))
for lendingBookListIt.Next() {
id := common.BytesToHash(lendingBookListIt.Key)
if _, exist := self.stateLendingBooks[id]; exist {
if _, exist := l.stateLendingBooks[id]; exist {
continue
}
lendingBooks = append(lendingBooks, id)
}
for _, lendingBook := range lendingBooks {
stateLendingBook := self.getStateLendingBook(db, lendingBook)
stateLendingBook := l.getStateLendingBook(db, lendingBook)
if stateLendingBook != nil {
liquidationData[lendingBook] = stateLendingBook.getAllTradeIds(db)
}
@ -218,22 +218,22 @@ func (self *liquidationPriceState) getAllLiquidationData(db Database) map[common
return liquidationData
}
func (c *liquidationPriceState) AddVolume(amount *big.Int) {
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
func (l *liquidationPriceState) AddVolume(amount *big.Int) {
l.setVolume(new(big.Int).Add(l.data.Volume, amount))
}
func (c *liquidationPriceState) subVolume(amount *big.Int) {
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
}
func (self *liquidationPriceState) setVolume(volume *big.Int) {
self.data.Volume = volume
if self.onDirty != nil {
self.onDirty(self.liquidationPrice)
self.onDirty = nil
func (l *liquidationPriceState) setVolume(volume *big.Int) {
l.data.Volume = volume
if l.onDirty != nil {
l.onDirty(l.liquidationPrice)
l.onDirty = nil
}
}
func (self *liquidationPriceState) Volume() *big.Int {
return self.data.Volume
func (l *liquidationPriceState) Volume() *big.Int {
return l.data.Volume
}

View file

@ -53,23 +53,23 @@ func newStateOrderItem(orderBook common.Hash, orderId common.Hash, data OrderIte
}
// EncodeRLP implements rlp.Encoder.
func (c *stateOrderItem) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, c.data)
func (s *stateOrderItem) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, s.data)
}
func (self *stateOrderItem) deepCopy(onDirty func(orderId common.Hash)) *stateOrderItem {
stateOrderList := newStateOrderItem(self.orderBook, self.orderId, self.data, onDirty)
func (s *stateOrderItem) deepCopy(onDirty func(orderId common.Hash)) *stateOrderItem {
stateOrderList := newStateOrderItem(s.orderBook, s.orderId, s.data, onDirty)
return stateOrderList
}
func (self *stateOrderItem) setVolume(volume *big.Int) {
self.data.Quantity = volume
if self.onDirty != nil {
self.onDirty(self.orderId)
self.onDirty = nil
func (s *stateOrderItem) setVolume(volume *big.Int) {
s.data.Quantity = volume
if s.onDirty != nil {
s.onDirty(s.orderId)
s.onDirty = nil
}
}
func (self *stateOrderItem) Quantity() *big.Int {
return self.data.Quantity
func (s *stateOrderItem) Quantity() *big.Int {
return s.data.Quantity
}

View file

@ -75,14 +75,14 @@ func newStateOrderList(db *TradingStateDB, orderType string, orderBook common.Ha
}
// EncodeRLP implements rlp.Encoder.
func (c *stateOrderList) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, c.data)
func (s *stateOrderList) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, s.data)
}
// setError remembers the first non-nil error it is called with.
func (self *stateOrderList) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (s *stateOrderList) setError(err error) {
if s.dbErr == nil {
s.dbErr = err
}
}
@ -99,90 +99,90 @@ func (c *stateOrderList) getTrie(db Database) Trie {
}
// GetState returns a value in orderId storage.
func (self *stateOrderList) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
amount, exists := self.cachedStorage[orderId]
func (s *stateOrderList) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
amount, exists := s.cachedStorage[orderId]
if exists {
return amount
}
// Load from DB in case it is missing.
enc, err := self.getTrie(db).TryGet(orderId[:])
enc, err := s.getTrie(db).TryGet(orderId[:])
if err != nil {
self.setError(err)
s.setError(err)
return EmptyHash
}
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
self.setError(err)
s.setError(err)
}
amount.SetBytes(content)
}
if (amount != common.Hash{}) {
self.cachedStorage[orderId] = amount
s.cachedStorage[orderId] = amount
}
return amount
}
// SetState updates a value in orderId storage.
func (self *stateOrderList) insertOrderItem(db Database, orderId common.Hash, amount common.Hash) {
self.setOrderItem(orderId, amount)
self.setError(self.getTrie(db).TryUpdate(orderId[:], amount[:]))
func (s *stateOrderList) insertOrderItem(db Database, orderId common.Hash, amount common.Hash) {
s.setOrderItem(orderId, amount)
s.setError(s.getTrie(db).TryUpdate(orderId[:], amount[:]))
}
// SetState updates a value in orderId storage.
func (self *stateOrderList) removeOrderItem(db Database, orderId common.Hash) {
tr := self.getTrie(db)
self.setError(tr.TryDelete(orderId[:]))
self.setOrderItem(orderId, EmptyHash)
func (s *stateOrderList) removeOrderItem(db Database, orderId common.Hash) {
tr := s.getTrie(db)
s.setError(tr.TryDelete(orderId[:]))
s.setOrderItem(orderId, EmptyHash)
}
func (self *stateOrderList) setOrderItem(orderId common.Hash, amount common.Hash) {
self.cachedStorage[orderId] = amount
self.dirtyStorage[orderId] = amount
func (s *stateOrderList) setOrderItem(orderId common.Hash, amount common.Hash) {
s.cachedStorage[orderId] = amount
s.dirtyStorage[orderId] = amount
if self.onDirty != nil {
self.onDirty(self.Price())
self.onDirty = nil
if s.onDirty != nil {
s.onDirty(s.Price())
s.onDirty = nil
}
}
// updateAskTrie writes cached storage modifications into the object's storage trie.
func (self *stateOrderList) updateTrie(db Database) Trie {
tr := self.getTrie(db)
for orderId, amount := range self.dirtyStorage {
delete(self.dirtyStorage, orderId)
func (s *stateOrderList) updateTrie(db Database) Trie {
tr := s.getTrie(db)
for orderId, amount := range s.dirtyStorage {
delete(s.dirtyStorage, orderId)
if amount == EmptyHash {
self.setError(tr.TryDelete(orderId[:]))
s.setError(tr.TryDelete(orderId[:]))
continue
}
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(amount[:], "\x00"))
self.setError(tr.TryUpdate(orderId[:], v))
s.setError(tr.TryUpdate(orderId[:], v))
}
return tr
}
// UpdateRoot sets the trie root to the current root orderId of
func (self *stateOrderList) updateRoot(db Database) error {
self.updateTrie(db)
if self.dbErr != nil {
return self.dbErr
func (s *stateOrderList) updateRoot(db Database) error {
s.updateTrie(db)
if s.dbErr != nil {
return s.dbErr
}
root, err := self.trie.Commit(nil)
root, err := s.trie.Commit(nil)
if err == nil {
self.data.Root = root
s.data.Root = root
}
return err
}
func (self *stateOrderList) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateOrderList {
stateOrderList := newStateOrderList(db, self.orderType, self.orderBook, self.price, self.data, onDirty)
if self.trie != nil {
stateOrderList.trie = db.db.CopyTrie(self.trie)
func (s *stateOrderList) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateOrderList {
stateOrderList := newStateOrderList(db, s.orderType, s.orderBook, s.price, s.data, onDirty)
if s.trie != nil {
stateOrderList.trie = db.db.CopyTrie(s.trie)
}
for orderId, amount := range self.dirtyStorage {
for orderId, amount := range s.dirtyStorage {
stateOrderList.dirtyStorage[orderId] = amount
}
for orderId, amount := range self.cachedStorage {
for orderId, amount := range s.cachedStorage {
stateOrderList.cachedStorage[orderId] = amount
}
return stateOrderList
@ -190,29 +190,29 @@ func (self *stateOrderList) deepCopy(db *TradingStateDB, onDirty func(price comm
// AddVolume removes amount from c's balance.
// It is used to add funds to the destination exchanges of a transfer.
func (c *stateOrderList) AddVolume(amount *big.Int) {
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
func (s *stateOrderList) AddVolume(amount *big.Int) {
s.setVolume(new(big.Int).Add(s.data.Volume, amount))
}
// AddVolume removes amount from c's balance.
// It is used to add funds to the destination exchanges of a transfer.
func (c *stateOrderList) subVolume(amount *big.Int) {
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
func (s *stateOrderList) subVolume(amount *big.Int) {
s.setVolume(new(big.Int).Sub(s.data.Volume, amount))
}
func (self *stateOrderList) setVolume(volume *big.Int) {
self.data.Volume = volume
if self.onDirty != nil {
self.onDirty(self.price)
self.onDirty = nil
func (s *stateOrderList) setVolume(volume *big.Int) {
s.data.Volume = volume
if s.onDirty != nil {
s.onDirty(s.price)
s.onDirty = nil
}
}
// Returns the address of the contract/orderId
func (c *stateOrderList) Price() common.Hash {
return c.price
func (s *stateOrderList) Price() common.Hash {
return s.price
}
func (self *stateOrderList) Volume() *big.Int {
return self.data.Volume
func (s *stateOrderList) Volume() *big.Int {
return s.data.Volume
}

View file

@ -66,35 +66,35 @@ type tradingExchanges struct {
}
// empty returns whether the orderId is considered empty.
func (s *tradingExchanges) empty() bool {
if s.data.Nonce != 0 {
func (te *tradingExchanges) empty() bool {
if te.data.Nonce != 0 {
return false
}
if s.data.LendingCount != nil && s.data.LendingCount.Sign() > 0 {
if te.data.LendingCount != nil && te.data.LendingCount.Sign() > 0 {
return false
}
if s.data.LastPrice != nil && s.data.LastPrice.Sign() > 0 {
if te.data.LastPrice != nil && te.data.LastPrice.Sign() > 0 {
return false
}
if s.data.MediumPrice != nil && s.data.MediumPrice.Sign() > 0 {
if te.data.MediumPrice != nil && te.data.MediumPrice.Sign() > 0 {
return false
}
if s.data.MediumPriceBeforeEpoch != nil && s.data.MediumPriceBeforeEpoch.Sign() > 0 {
if te.data.MediumPriceBeforeEpoch != nil && te.data.MediumPriceBeforeEpoch.Sign() > 0 {
return false
}
if s.data.TotalQuantity != nil && s.data.TotalQuantity.Sign() > 0 {
if te.data.TotalQuantity != nil && te.data.TotalQuantity.Sign() > 0 {
return false
}
if !common.EmptyHash(s.data.AskRoot) {
if !common.EmptyHash(te.data.AskRoot) {
return false
}
if !common.EmptyHash(s.data.BidRoot) {
if !common.EmptyHash(te.data.BidRoot) {
return false
}
if !common.EmptyHash(s.data.OrderRoot) {
if !common.EmptyHash(te.data.OrderRoot) {
return false
}
if !common.EmptyHash(s.data.LiquidationPriceRoot) {
if !common.EmptyHash(te.data.LiquidationPriceRoot) {
return false
}
return true
@ -119,46 +119,46 @@ func newStateExchanges(db *TradingStateDB, hash common.Hash, data tradingExchang
}
// EncodeRLP implements rlp.Encoder.
func (c *tradingExchanges) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, c.data)
func (te *tradingExchanges) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, te.data)
}
// setError remembers the first non-nil error it is called with.
func (self *tradingExchanges) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (te *tradingExchanges) setError(err error) {
if te.dbErr == nil {
te.dbErr = err
}
}
func (c *tradingExchanges) getAsksTrie(db Database) Trie {
if c.asksTrie == nil {
func (te *tradingExchanges) getAsksTrie(db Database) Trie {
if te.asksTrie == nil {
var err error
c.asksTrie, err = db.OpenStorageTrie(c.orderBookHash, c.data.AskRoot)
te.asksTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.AskRoot)
if err != nil {
c.asksTrie, _ = db.OpenStorageTrie(c.orderBookHash, EmptyHash)
c.setError(fmt.Errorf("can't create asks trie: %v", err))
te.asksTrie, _ = db.OpenStorageTrie(te.orderBookHash, EmptyHash)
te.setError(fmt.Errorf("can't create asks trie: %v", err))
}
}
return c.asksTrie
return te.asksTrie
}
func (c *tradingExchanges) getOrdersTrie(db Database) Trie {
if c.ordersTrie == nil {
func (te *tradingExchanges) getOrdersTrie(db Database) Trie {
if te.ordersTrie == nil {
var err error
c.ordersTrie, err = db.OpenStorageTrie(c.orderBookHash, c.data.OrderRoot)
te.ordersTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.OrderRoot)
if err != nil {
c.ordersTrie, _ = db.OpenStorageTrie(c.orderBookHash, EmptyHash)
c.setError(fmt.Errorf("can't create asks trie: %v", err))
te.ordersTrie, _ = db.OpenStorageTrie(te.orderBookHash, EmptyHash)
te.setError(fmt.Errorf("can't create asks trie: %v", err))
}
}
return c.ordersTrie
return te.ordersTrie
}
func (c *tradingExchanges) getBestPriceAsksTrie(db Database) common.Hash {
trie := c.getAsksTrie(db)
func (te *tradingExchanges) getBestPriceAsksTrie(db Database) common.Hash {
trie := te.getAsksTrie(db)
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
if err != nil {
log.Error("Failed find best price ask trie ", "orderbook", c.orderBookHash.Hex())
log.Error("Failed find best price ask trie ", "orderbook", te.orderBookHash.Hex())
return EmptyHash
}
if len(encKey) == 0 || len(encValue) == 0 {
@ -166,23 +166,23 @@ func (c *tradingExchanges) getBestPriceAsksTrie(db Database) common.Hash {
return EmptyHash
}
price := common.BytesToHash(encKey)
if _, exit := c.stateAskObjects[price]; !exit {
if _, exit := te.stateAskObjects[price]; !exit {
var data orderList
if err := rlp.DecodeBytes(encValue, &data); err != nil {
log.Error("Failed to decode state get best ask trie", "err", err)
return EmptyHash
}
obj := newStateOrderList(c.db, Bid, c.orderBookHash, price, data, c.MarkStateAskObjectDirty)
c.stateAskObjects[price] = obj
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateAskObjectDirty)
te.stateAskObjects[price] = obj
}
return common.BytesToHash(encKey)
}
func (c *tradingExchanges) getBestBidsTrie(db Database) common.Hash {
trie := c.getBidsTrie(db)
func (te *tradingExchanges) getBestBidsTrie(db Database) common.Hash {
trie := te.getBidsTrie(db)
encKey, encValue, err := trie.TryGetBestRightKeyAndValue()
if err != nil {
log.Error("Failed find best price bid trie ", "orderbook", c.orderBookHash.Hex())
log.Error("Failed find best price bid trie ", "orderbook", te.orderBookHash.Hex())
return EmptyHash
}
if len(encKey) == 0 || len(encValue) == 0 {
@ -190,27 +190,27 @@ func (c *tradingExchanges) getBestBidsTrie(db Database) common.Hash {
return EmptyHash
}
price := common.BytesToHash(encKey)
if _, exit := c.stateBidObjects[price]; !exit {
if _, exit := te.stateBidObjects[price]; !exit {
var data orderList
if err := rlp.DecodeBytes(encValue, &data); err != nil {
log.Error("Failed to decode state get best bid trie", "err", err)
return EmptyHash
}
// Insert into the live set.
obj := newStateOrderList(c.db, Bid, c.orderBookHash, price, data, c.MarkStateBidObjectDirty)
c.stateBidObjects[price] = obj
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateBidObjectDirty)
te.stateBidObjects[price] = obj
}
return common.BytesToHash(encKey)
}
// updateAskTrie writes cached storage modifications into the object's storage trie.
func (self *tradingExchanges) updateAsksTrie(db Database) Trie {
tr := self.getAsksTrie(db)
for price, orderList := range self.stateAskObjects {
if _, isDirty := self.stateAskObjectsDirty[price]; isDirty {
delete(self.stateAskObjectsDirty, price)
func (te *tradingExchanges) updateAsksTrie(db Database) Trie {
tr := te.getAsksTrie(db)
for price, orderList := range te.stateAskObjects {
if _, isDirty := te.stateAskObjectsDirty[price]; isDirty {
delete(te.stateAskObjectsDirty, price)
if orderList.empty() {
self.setError(tr.TryDelete(price[:]))
te.setError(tr.TryDelete(price[:]))
continue
}
err := orderList.updateRoot(db)
@ -219,7 +219,7 @@ func (self *tradingExchanges) updateAsksTrie(db Database) Trie {
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(orderList)
self.setError(tr.TryUpdate(price[:], v))
te.setError(tr.TryUpdate(price[:], v))
}
}
@ -228,23 +228,23 @@ func (self *tradingExchanges) updateAsksTrie(db Database) Trie {
// CommitAskTrie the storage trie of the object to dwb.
// This updates the trie root.
func (self *tradingExchanges) updateAsksRoot(db Database) error {
self.updateAsksTrie(db)
if self.dbErr != nil {
return self.dbErr
func (te *tradingExchanges) updateAsksRoot(db Database) error {
te.updateAsksTrie(db)
if te.dbErr != nil {
return te.dbErr
}
self.data.AskRoot = self.asksTrie.Hash()
te.data.AskRoot = te.asksTrie.Hash()
return nil
}
// CommitAskTrie the storage trie of the object to dwb.
// This updates the trie root.
func (self *tradingExchanges) CommitAsksTrie(db Database) error {
self.updateAsksTrie(db)
if self.dbErr != nil {
return self.dbErr
func (te *tradingExchanges) CommitAsksTrie(db Database) error {
te.updateAsksTrie(db)
if te.dbErr != nil {
return te.dbErr
}
root, err := self.asksTrie.Commit(func(leaf []byte, parent common.Hash) error {
root, err := te.asksTrie.Commit(func(leaf []byte, parent common.Hash) error {
var orderList orderList
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
return nil
@ -255,31 +255,31 @@ func (self *tradingExchanges) CommitAsksTrie(db Database) error {
return nil
})
if err == nil {
self.data.AskRoot = root
te.data.AskRoot = root
}
return err
}
func (c *tradingExchanges) getBidsTrie(db Database) Trie {
if c.bidsTrie == nil {
func (te *tradingExchanges) getBidsTrie(db Database) Trie {
if te.bidsTrie == nil {
var err error
c.bidsTrie, err = db.OpenStorageTrie(c.orderBookHash, c.data.BidRoot)
te.bidsTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.BidRoot)
if err != nil {
c.bidsTrie, _ = db.OpenStorageTrie(c.orderBookHash, EmptyHash)
c.setError(fmt.Errorf("can't create bids trie: %v", err))
te.bidsTrie, _ = db.OpenStorageTrie(te.orderBookHash, EmptyHash)
te.setError(fmt.Errorf("can't create bids trie: %v", err))
}
}
return c.bidsTrie
return te.bidsTrie
}
// updateAskTrie writes cached storage modifications into the object's storage trie.
func (self *tradingExchanges) updateBidsTrie(db Database) Trie {
tr := self.getBidsTrie(db)
for price, orderList := range self.stateBidObjects {
if _, isDirty := self.stateBidObjectsDirty[price]; isDirty {
delete(self.stateBidObjectsDirty, price)
func (te *tradingExchanges) updateBidsTrie(db Database) Trie {
tr := te.getBidsTrie(db)
for price, orderList := range te.stateBidObjects {
if _, isDirty := te.stateBidObjectsDirty[price]; isDirty {
delete(te.stateBidObjectsDirty, price)
if orderList.empty() {
self.setError(tr.TryDelete(price[:]))
te.setError(tr.TryDelete(price[:]))
continue
}
err := orderList.updateRoot(db)
@ -288,25 +288,25 @@ func (self *tradingExchanges) updateBidsTrie(db Database) Trie {
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(orderList)
self.setError(tr.TryUpdate(price[:], v))
te.setError(tr.TryUpdate(price[:], v))
}
}
return tr
}
func (self *tradingExchanges) updateBidsRoot(db Database) {
self.updateBidsTrie(db)
self.data.BidRoot = self.bidsTrie.Hash()
func (te *tradingExchanges) updateBidsRoot(db Database) {
te.updateBidsTrie(db)
te.data.BidRoot = te.bidsTrie.Hash()
}
// CommitAskTrie the storage trie of the object to dwb.
// This updates the trie root.
func (self *tradingExchanges) CommitBidsTrie(db Database) error {
self.updateBidsTrie(db)
if self.dbErr != nil {
return self.dbErr
func (te *tradingExchanges) CommitBidsTrie(db Database) error {
te.updateBidsTrie(db)
if te.dbErr != nil {
return te.dbErr
}
root, err := self.bidsTrie.Commit(func(leaf []byte, parent common.Hash) error {
root, err := te.bidsTrie.Commit(func(leaf []byte, parent common.Hash) error {
var orderList orderList
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
return nil
@ -317,116 +317,116 @@ func (self *tradingExchanges) CommitBidsTrie(db Database) error {
return nil
})
if err == nil {
self.data.BidRoot = root
te.data.BidRoot = root
}
return err
}
func (self *tradingExchanges) deepCopy(db *TradingStateDB, onDirty func(hash common.Hash)) *tradingExchanges {
stateExchanges := newStateExchanges(db, self.orderBookHash, self.data, onDirty)
if self.asksTrie != nil {
stateExchanges.asksTrie = db.db.CopyTrie(self.asksTrie)
func (te *tradingExchanges) deepCopy(db *TradingStateDB, onDirty func(hash common.Hash)) *tradingExchanges {
stateExchanges := newStateExchanges(db, te.orderBookHash, te.data, onDirty)
if te.asksTrie != nil {
stateExchanges.asksTrie = db.db.CopyTrie(te.asksTrie)
}
if self.bidsTrie != nil {
stateExchanges.bidsTrie = db.db.CopyTrie(self.bidsTrie)
if te.bidsTrie != nil {
stateExchanges.bidsTrie = db.db.CopyTrie(te.bidsTrie)
}
if self.ordersTrie != nil {
stateExchanges.ordersTrie = db.db.CopyTrie(self.ordersTrie)
if te.ordersTrie != nil {
stateExchanges.ordersTrie = db.db.CopyTrie(te.ordersTrie)
}
for price, bidObject := range self.stateBidObjects {
stateExchanges.stateBidObjects[price] = bidObject.deepCopy(db, self.MarkStateBidObjectDirty)
for price, bidObject := range te.stateBidObjects {
stateExchanges.stateBidObjects[price] = bidObject.deepCopy(db, te.MarkStateBidObjectDirty)
}
for price := range self.stateBidObjectsDirty {
for price := range te.stateBidObjectsDirty {
stateExchanges.stateBidObjectsDirty[price] = struct{}{}
}
for price, askObject := range self.stateAskObjects {
stateExchanges.stateAskObjects[price] = askObject.deepCopy(db, self.MarkStateAskObjectDirty)
for price, askObject := range te.stateAskObjects {
stateExchanges.stateAskObjects[price] = askObject.deepCopy(db, te.MarkStateAskObjectDirty)
}
for price := range self.stateAskObjectsDirty {
for price := range te.stateAskObjectsDirty {
stateExchanges.stateAskObjectsDirty[price] = struct{}{}
}
for orderId, orderItem := range self.stateOrderObjects {
stateExchanges.stateOrderObjects[orderId] = orderItem.deepCopy(self.MarkStateOrderObjectDirty)
for orderId, orderItem := range te.stateOrderObjects {
stateExchanges.stateOrderObjects[orderId] = orderItem.deepCopy(te.MarkStateOrderObjectDirty)
}
for orderId := range self.stateOrderObjectsDirty {
for orderId := range te.stateOrderObjectsDirty {
stateExchanges.stateOrderObjectsDirty[orderId] = struct{}{}
}
for price, liquidationPrice := range self.liquidationPriceStates {
stateExchanges.liquidationPriceStates[price] = liquidationPrice.deepCopy(db, self.MarkStateLiquidationPriceDirty)
for price, liquidationPrice := range te.liquidationPriceStates {
stateExchanges.liquidationPriceStates[price] = liquidationPrice.deepCopy(db, te.MarkStateLiquidationPriceDirty)
}
for price := range self.liquidationPriceStatesDirty {
for price := range te.liquidationPriceStatesDirty {
stateExchanges.liquidationPriceStatesDirty[price] = struct{}{}
}
return stateExchanges
}
// Returns the address of the contract/orderId
func (c *tradingExchanges) Hash() common.Hash {
return c.orderBookHash
func (te *tradingExchanges) Hash() common.Hash {
return te.orderBookHash
}
func (self *tradingExchanges) SetNonce(nonce uint64) {
self.setNonce(nonce)
func (te *tradingExchanges) SetNonce(nonce uint64) {
te.setNonce(nonce)
}
func (self *tradingExchanges) setNonce(nonce uint64) {
self.data.Nonce = nonce
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (te *tradingExchanges) setNonce(nonce uint64) {
te.data.Nonce = nonce
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
}
func (self *tradingExchanges) Nonce() uint64 {
return self.data.Nonce
func (te *tradingExchanges) Nonce() uint64 {
return te.data.Nonce
}
func (self *tradingExchanges) setLastPrice(price *big.Int) {
self.data.LastPrice = price
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (te *tradingExchanges) setLastPrice(price *big.Int) {
te.data.LastPrice = price
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
}
func (self *tradingExchanges) setMediumPriceBeforeEpoch(price *big.Int) {
self.data.MediumPriceBeforeEpoch = price
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (te *tradingExchanges) setMediumPriceBeforeEpoch(price *big.Int) {
te.data.MediumPriceBeforeEpoch = price
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
}
func (self *tradingExchanges) setMediumPrice(price *big.Int, quantity *big.Int) {
self.data.MediumPrice = price
self.data.TotalQuantity = quantity
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (te *tradingExchanges) setMediumPrice(price *big.Int, quantity *big.Int) {
te.data.MediumPrice = price
te.data.TotalQuantity = quantity
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
}
// updateStateExchangeObject writes the given object to the trie.
func (self *tradingExchanges) removeStateOrderListAskObject(db Database, stateOrderList *stateOrderList) {
self.setError(self.asksTrie.TryDelete(stateOrderList.price[:]))
func (te *tradingExchanges) removeStateOrderListAskObject(db Database, stateOrderList *stateOrderList) {
te.setError(te.asksTrie.TryDelete(stateOrderList.price[:]))
}
// updateStateExchangeObject writes the given object to the trie.
func (self *tradingExchanges) removeStateOrderListBidObject(db Database, stateOrderList *stateOrderList) {
self.setError(self.bidsTrie.TryDelete(stateOrderList.price[:]))
func (te *tradingExchanges) removeStateOrderListBidObject(db Database, stateOrderList *stateOrderList) {
te.setError(te.bidsTrie.TryDelete(stateOrderList.price[:]))
}
// Retrieve a state object given my the address. Returns nil if not found.
func (self *tradingExchanges) getStateOrderListAskObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
func (te *tradingExchanges) getStateOrderListAskObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
// Prefer 'live' objects.
if obj := self.stateAskObjects[price]; obj != nil {
if obj := te.stateAskObjects[price]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getAsksTrie(db).TryGet(price[:])
enc, err := te.getAsksTrie(db).TryGet(price[:])
if len(enc) == 0 {
self.setError(err)
te.setError(err)
return nil
}
var data orderList
@ -435,50 +435,50 @@ func (self *tradingExchanges) getStateOrderListAskObject(db Database, price comm
return nil
}
// Insert into the live set.
obj := newStateOrderList(self.db, Bid, self.orderBookHash, price, data, self.MarkStateAskObjectDirty)
self.stateAskObjects[price] = obj
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateAskObjectDirty)
te.stateAskObjects[price] = obj
return obj
}
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *tradingExchanges) MarkStateAskObjectDirty(price common.Hash) {
self.stateAskObjectsDirty[price] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (te *tradingExchanges) MarkStateAskObjectDirty(price common.Hash) {
te.stateAskObjectsDirty[price] = struct{}{}
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
}
// createStateOrderListObject creates a new state object. If there is an existing orderId with
// the given address, it is overwritten and returned as the second return value.
func (self *tradingExchanges) createStateOrderListAskObject(db Database, price common.Hash) (newobj *stateOrderList) {
newobj = newStateOrderList(self.db, Ask, self.orderBookHash, price, orderList{Volume: Zero}, self.MarkStateAskObjectDirty)
self.stateAskObjects[price] = newobj
self.stateAskObjectsDirty[price] = struct{}{}
func (te *tradingExchanges) createStateOrderListAskObject(db Database, price common.Hash) (newobj *stateOrderList) {
newobj = newStateOrderList(te.db, Ask, te.orderBookHash, price, orderList{Volume: Zero}, te.MarkStateAskObjectDirty)
te.stateAskObjects[price] = newobj
te.stateAskObjectsDirty[price] = struct{}{}
data, err := rlp.EncodeToBytes(newobj)
if err != nil {
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
}
self.setError(self.asksTrie.TryUpdate(price[:], data))
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
te.setError(te.asksTrie.TryUpdate(price[:], data))
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
return newobj
}
// Retrieve a state object given my the address. Returns nil if not found.
func (self *tradingExchanges) getStateBidOrderListObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
func (te *tradingExchanges) getStateBidOrderListObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
// Prefer 'live' objects.
if obj := self.stateBidObjects[price]; obj != nil {
if obj := te.stateBidObjects[price]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getBidsTrie(db).TryGet(price[:])
enc, err := te.getBidsTrie(db).TryGet(price[:])
if len(enc) == 0 {
self.setError(err)
te.setError(err)
return nil
}
var data orderList
@ -487,50 +487,50 @@ func (self *tradingExchanges) getStateBidOrderListObject(db Database, price comm
return nil
}
// Insert into the live set.
obj := newStateOrderList(self.db, Bid, self.orderBookHash, price, data, self.MarkStateBidObjectDirty)
self.stateBidObjects[price] = obj
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateBidObjectDirty)
te.stateBidObjects[price] = obj
return obj
}
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *tradingExchanges) MarkStateBidObjectDirty(price common.Hash) {
self.stateBidObjectsDirty[price] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (te *tradingExchanges) MarkStateBidObjectDirty(price common.Hash) {
te.stateBidObjectsDirty[price] = struct{}{}
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
}
// createStateOrderListObject creates a new state object. If there is an existing orderId with
// the given address, it is overwritten and returned as the second return value.
func (self *tradingExchanges) createStateBidOrderListObject(db Database, price common.Hash) (newobj *stateOrderList) {
newobj = newStateOrderList(self.db, Bid, self.orderBookHash, price, orderList{Volume: Zero}, self.MarkStateBidObjectDirty)
self.stateBidObjects[price] = newobj
self.stateBidObjectsDirty[price] = struct{}{}
func (te *tradingExchanges) createStateBidOrderListObject(db Database, price common.Hash) (newobj *stateOrderList) {
newobj = newStateOrderList(te.db, Bid, te.orderBookHash, price, orderList{Volume: Zero}, te.MarkStateBidObjectDirty)
te.stateBidObjects[price] = newobj
te.stateBidObjectsDirty[price] = struct{}{}
data, err := rlp.EncodeToBytes(newobj)
if err != nil {
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
}
self.setError(self.bidsTrie.TryUpdate(price[:], data))
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
te.setError(te.bidsTrie.TryUpdate(price[:], data))
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
return newobj
}
// Retrieve a state object given my the address. Returns nil if not found.
func (self *tradingExchanges) getStateOrderObject(db Database, orderId common.Hash) (stateOrderItem *stateOrderItem) {
func (te *tradingExchanges) getStateOrderObject(db Database, orderId common.Hash) (stateOrderItem *stateOrderItem) {
// Prefer 'live' objects.
if obj := self.stateOrderObjects[orderId]; obj != nil {
if obj := te.stateOrderObjects[orderId]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getOrdersTrie(db).TryGet(orderId[:])
enc, err := te.getOrdersTrie(db).TryGet(orderId[:])
if len(enc) == 0 {
self.setError(err)
te.setError(err)
return nil
}
var data OrderItem
@ -539,48 +539,48 @@ func (self *tradingExchanges) getStateOrderObject(db Database, orderId common.Ha
return nil
}
// Insert into the live set.
obj := newStateOrderItem(self.orderBookHash, orderId, data, self.MarkStateOrderObjectDirty)
self.stateOrderObjects[orderId] = obj
obj := newStateOrderItem(te.orderBookHash, orderId, data, te.MarkStateOrderObjectDirty)
te.stateOrderObjects[orderId] = obj
return obj
}
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *tradingExchanges) MarkStateOrderObjectDirty(orderId common.Hash) {
self.stateOrderObjectsDirty[orderId] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (te *tradingExchanges) MarkStateOrderObjectDirty(orderId common.Hash) {
te.stateOrderObjectsDirty[orderId] = struct{}{}
if te.onDirty != nil {
te.onDirty(te.Hash())
te.onDirty = nil
}
}
// createStateOrderListObject creates a new state object. If there is an existing orderId with
// the given address, it is overwritten and returned as the second return value.
func (self *tradingExchanges) createStateOrderObject(db Database, orderId common.Hash, order OrderItem) (newobj *stateOrderItem) {
newobj = newStateOrderItem(self.orderBookHash, orderId, order, self.MarkStateOrderObjectDirty)
func (t *tradingExchanges) createStateOrderObject(db Database, orderId common.Hash, order OrderItem) (newobj *stateOrderItem) {
newobj = newStateOrderItem(t.orderBookHash, orderId, order, t.MarkStateOrderObjectDirty)
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.OrderID))
self.stateOrderObjects[orderIdHash] = newobj
self.stateOrderObjectsDirty[orderIdHash] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.orderBookHash)
self.onDirty = nil
t.stateOrderObjects[orderIdHash] = newobj
t.stateOrderObjectsDirty[orderIdHash] = struct{}{}
if t.onDirty != nil {
t.onDirty(t.orderBookHash)
t.onDirty = nil
}
return newobj
}
// updateAskTrie writes cached storage modifications into the object's storage trie.
func (self *tradingExchanges) updateOrdersTrie(db Database) Trie {
tr := self.getOrdersTrie(db)
for orderId, orderItem := range self.stateOrderObjects {
if _, isDirty := self.stateOrderObjectsDirty[orderId]; isDirty {
delete(self.stateOrderObjectsDirty, orderId)
func (t *tradingExchanges) updateOrdersTrie(db Database) Trie {
tr := t.getOrdersTrie(db)
for orderId, orderItem := range t.stateOrderObjects {
if _, isDirty := t.stateOrderObjectsDirty[orderId]; isDirty {
delete(t.stateOrderObjectsDirty, orderId)
if orderItem.empty() {
self.setError(tr.TryDelete(orderId[:]))
t.setError(tr.TryDelete(orderId[:]))
continue
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(orderItem)
self.setError(tr.TryUpdate(orderId[:], v))
t.setError(tr.TryUpdate(orderId[:], v))
}
}
return tr
@ -588,71 +588,71 @@ func (self *tradingExchanges) updateOrdersTrie(db Database) Trie {
// CommitAskTrie the storage trie of the object to dwb.
// This updates the trie root.
func (self *tradingExchanges) updateOrdersRoot(db Database) {
self.updateOrdersTrie(db)
self.data.OrderRoot = self.ordersTrie.Hash()
func (t *tradingExchanges) updateOrdersRoot(db Database) {
t.updateOrdersTrie(db)
t.data.OrderRoot = t.ordersTrie.Hash()
}
// CommitAskTrie the storage trie of the object to dwb.
// This updates the trie root.
func (self *tradingExchanges) CommitOrdersTrie(db Database) error {
self.updateOrdersTrie(db)
if self.dbErr != nil {
return self.dbErr
func (t *tradingExchanges) CommitOrdersTrie(db Database) error {
t.updateOrdersTrie(db)
if t.dbErr != nil {
return t.dbErr
}
root, err := self.ordersTrie.Commit(nil)
root, err := t.ordersTrie.Commit(nil)
if err == nil {
self.data.OrderRoot = root
t.data.OrderRoot = root
}
return err
}
func (self *tradingExchanges) MarkStateLiquidationPriceDirty(price common.Hash) {
self.liquidationPriceStatesDirty[price] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (t *tradingExchanges) MarkStateLiquidationPriceDirty(price common.Hash) {
t.liquidationPriceStatesDirty[price] = struct{}{}
if t.onDirty != nil {
t.onDirty(t.Hash())
t.onDirty = nil
}
}
func (self *tradingExchanges) createStateLiquidationPrice(db Database, liquidationPrice common.Hash) (newobj *liquidationPriceState) {
newobj = newLiquidationPriceState(self.db, self.orderBookHash, liquidationPrice, orderList{Volume: Zero}, self.MarkStateLiquidationPriceDirty)
self.liquidationPriceStates[liquidationPrice] = newobj
self.liquidationPriceStatesDirty[liquidationPrice] = struct{}{}
func (t *tradingExchanges) createStateLiquidationPrice(db Database, liquidationPrice common.Hash) (newobj *liquidationPriceState) {
newobj = newLiquidationPriceState(t.db, t.orderBookHash, liquidationPrice, orderList{Volume: Zero}, t.MarkStateLiquidationPriceDirty)
t.liquidationPriceStates[liquidationPrice] = newobj
t.liquidationPriceStatesDirty[liquidationPrice] = struct{}{}
data, err := rlp.EncodeToBytes(newobj)
if err != nil {
panic(fmt.Errorf("can't encode liquidation price object at %x: %v", liquidationPrice[:], err))
}
self.setError(self.getLiquidationPriceTrie(db).TryUpdate(liquidationPrice[:], data))
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
t.setError(t.getLiquidationPriceTrie(db).TryUpdate(liquidationPrice[:], data))
if t.onDirty != nil {
t.onDirty(t.Hash())
t.onDirty = nil
}
return newobj
}
func (self *tradingExchanges) getLiquidationPriceTrie(db Database) Trie {
if self.liquidationPriceTrie == nil {
func (t *tradingExchanges) getLiquidationPriceTrie(db Database) Trie {
if t.liquidationPriceTrie == nil {
var err error
self.liquidationPriceTrie, err = db.OpenStorageTrie(self.orderBookHash, self.data.LiquidationPriceRoot)
t.liquidationPriceTrie, err = db.OpenStorageTrie(t.orderBookHash, t.data.LiquidationPriceRoot)
if err != nil {
self.liquidationPriceTrie, _ = db.OpenStorageTrie(self.orderBookHash, EmptyHash)
self.setError(fmt.Errorf("can't create liquidation liquidationPrice trie: %v", err))
t.liquidationPriceTrie, _ = db.OpenStorageTrie(t.orderBookHash, EmptyHash)
t.setError(fmt.Errorf("can't create liquidation liquidationPrice trie: %v", err))
}
}
return self.liquidationPriceTrie
return t.liquidationPriceTrie
}
func (self *tradingExchanges) getStateLiquidationPrice(db Database, price common.Hash) (stateObject *liquidationPriceState) {
func (t *tradingExchanges) getStateLiquidationPrice(db Database, price common.Hash) (stateObject *liquidationPriceState) {
// Prefer 'live' objects.
if obj := self.liquidationPriceStates[price]; obj != nil {
if obj := t.liquidationPriceStates[price]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getLiquidationPriceTrie(db).TryGet(price[:])
enc, err := t.getLiquidationPriceTrie(db).TryGet(price[:])
if len(enc) == 0 {
self.setError(err)
t.setError(err)
return nil
}
var data orderList
@ -661,16 +661,16 @@ func (self *tradingExchanges) getStateLiquidationPrice(db Database, price common
return nil
}
// Insert into the live set.
obj := newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
self.liquidationPriceStates[price] = obj
obj := newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
t.liquidationPriceStates[price] = obj
return obj
}
func (self *tradingExchanges) getLowestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
trie := self.getLiquidationPriceTrie(db)
func (t *tradingExchanges) getLowestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
trie := t.getLiquidationPriceTrie(db)
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
if err != nil {
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", self.orderBookHash.Hex())
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", t.orderBookHash.Hex())
return EmptyHash, nil
}
if len(encKey) == 0 || len(encValue) == 0 {
@ -678,25 +678,25 @@ func (self *tradingExchanges) getLowestLiquidationPrice(db Database) (common.Has
return EmptyHash, nil
}
price := common.BytesToHash(encKey)
obj := self.liquidationPriceStates[price]
obj := t.liquidationPriceStates[price]
if obj == nil {
var data orderList
if err := rlp.DecodeBytes(encValue, &data); err != nil {
log.Error("Failed to decode state get best ask trie", "err", err)
return EmptyHash, nil
}
obj = newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
self.liquidationPriceStates[price] = obj
obj = newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
t.liquidationPriceStates[price] = obj
}
return price, obj
}
func (self *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit common.Hash) map[common.Hash]*liquidationPriceState {
trie := self.getLiquidationPriceTrie(db)
func (t *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit common.Hash) map[common.Hash]*liquidationPriceState {
trie := t.getLiquidationPriceTrie(db)
encKeys, encValues, err := trie.TryGetAllLeftKeyAndValue(limit.Bytes())
result := map[common.Hash]*liquidationPriceState{}
if err != nil || len(encKeys) != len(encValues) {
log.Error("Failed get lower liquidation price trie ", "orderbook", self.orderBookHash.Hex(), "encKeys", len(encKeys), "encValues", len(encValues))
log.Error("Failed get lower liquidation price trie ", "orderbook", t.orderBookHash.Hex(), "encKeys", len(encKeys), "encValues", len(encValues))
return result
}
if len(encKeys) == 0 || len(encValues) == 0 {
@ -705,15 +705,15 @@ func (self *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit com
}
for i := range encKeys {
price := common.BytesToHash(encKeys[i])
obj := self.liquidationPriceStates[price]
obj := t.liquidationPriceStates[price]
if obj == nil {
var data orderList
if err := rlp.DecodeBytes(encValues[i], &data); err != nil {
log.Error("Failed to decode state get all lower liquidation price trie", "price", price, "encValues", encValues[i], "err", err)
return result
}
obj = newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
self.liquidationPriceStates[price] = obj
obj = newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
t.liquidationPriceStates[price] = obj
}
if obj.empty() {
continue
@ -723,11 +723,11 @@ func (self *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit com
return result
}
func (self *tradingExchanges) getHighestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
trie := self.getLiquidationPriceTrie(db)
func (t *tradingExchanges) getHighestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
trie := t.getLiquidationPriceTrie(db)
encKey, encValue, err := trie.TryGetBestRightKeyAndValue()
if err != nil {
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", self.orderBookHash.Hex())
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", t.orderBookHash.Hex())
return EmptyHash, nil
}
if len(encKey) == 0 || len(encValue) == 0 {
@ -735,28 +735,29 @@ func (self *tradingExchanges) getHighestLiquidationPrice(db Database) (common.Ha
return EmptyHash, nil
}
price := common.BytesToHash(encKey)
obj := self.liquidationPriceStates[price]
obj := t.liquidationPriceStates[price]
if obj == nil {
var data orderList
if err := rlp.DecodeBytes(encValue, &data); err != nil {
log.Error("Failed to decode state get best ask trie", "err", err)
return EmptyHash, nil
}
obj = newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
self.liquidationPriceStates[price] = obj
obj = newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
t.liquidationPriceStates[price] = obj
}
if obj.empty() {
return EmptyHash, nil
}
return price, obj
}
func (self *tradingExchanges) updateLiquidationPriceTrie(db Database) Trie {
tr := self.getLiquidationPriceTrie(db)
for price, stateObject := range self.liquidationPriceStates {
if _, isDirty := self.liquidationPriceStatesDirty[price]; isDirty {
delete(self.liquidationPriceStatesDirty, price)
func (t *tradingExchanges) updateLiquidationPriceTrie(db Database) Trie {
tr := t.getLiquidationPriceTrie(db)
for price, stateObject := range t.liquidationPriceStates {
if _, isDirty := t.liquidationPriceStatesDirty[price]; isDirty {
delete(t.liquidationPriceStatesDirty, price)
if stateObject.empty() {
self.setError(tr.TryDelete(price[:]))
t.setError(tr.TryDelete(price[:]))
continue
}
err := stateObject.updateRoot(db)
@ -765,23 +766,23 @@ func (self *tradingExchanges) updateLiquidationPriceTrie(db Database) Trie {
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(stateObject)
self.setError(tr.TryUpdate(price[:], v))
t.setError(tr.TryUpdate(price[:], v))
}
}
return tr
}
func (self *tradingExchanges) updateLiquidationPriceRoot(db Database) {
self.updateLiquidationPriceTrie(db)
self.data.LiquidationPriceRoot = self.liquidationPriceTrie.Hash()
func (t *tradingExchanges) updateLiquidationPriceRoot(db Database) {
t.updateLiquidationPriceTrie(db)
t.data.LiquidationPriceRoot = t.liquidationPriceTrie.Hash()
}
func (self *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
self.updateLiquidationPriceTrie(db)
if self.dbErr != nil {
return self.dbErr
func (t *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
t.updateLiquidationPriceTrie(db)
if t.dbErr != nil {
return t.dbErr
}
root, err := self.liquidationPriceTrie.Commit(func(leaf []byte, parent common.Hash) error {
root, err := t.liquidationPriceTrie.Commit(func(leaf []byte, parent common.Hash) error {
var orderList orderList
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
return nil
@ -792,23 +793,23 @@ func (self *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
return nil
})
if err == nil {
self.data.LiquidationPriceRoot = root
t.data.LiquidationPriceRoot = root
}
return err
}
func (c *tradingExchanges) addLendingCount(amount *big.Int) {
c.setLendingCount(new(big.Int).Add(c.data.LendingCount, amount))
func (t *tradingExchanges) addLendingCount(amount *big.Int) {
t.setLendingCount(new(big.Int).Add(t.data.LendingCount, amount))
}
func (c *tradingExchanges) subLendingCount(amount *big.Int) {
c.setLendingCount(new(big.Int).Sub(c.data.LendingCount, amount))
func (t *tradingExchanges) subLendingCount(amount *big.Int) {
t.setLendingCount(new(big.Int).Sub(t.data.LendingCount, amount))
}
func (self *tradingExchanges) setLendingCount(volume *big.Int) {
self.data.LendingCount = volume
if self.onDirty != nil {
self.onDirty(self.orderBookHash)
self.onDirty = nil
func (t *tradingExchanges) setLendingCount(volume *big.Int) {
t.data.LendingCount = volume
if t.onDirty != nil {
t.onDirty(t.orderBookHash)
t.onDirty = nil
}
}

View file

@ -78,55 +78,55 @@ func New(root common.Hash, db Database) (*TradingStateDB, error) {
}
// setError remembers the first non-nil error it is called with.
func (self *TradingStateDB) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (t *TradingStateDB) setError(err error) {
if t.dbErr == nil {
t.dbErr = err
}
}
func (self *TradingStateDB) Error() error {
return self.dbErr
func (t *TradingStateDB) Error() error {
return t.dbErr
}
// Exist reports whether the given orderId address exists in the state.
// Notably this also returns true for suicided exchanges.
func (self *TradingStateDB) Exist(addr common.Hash) bool {
return self.getStateExchangeObject(addr) != nil
func (t *TradingStateDB) Exist(addr common.Hash) bool {
return t.getStateExchangeObject(addr) != nil
}
// Empty returns whether the state object is either non-existent
// or empty according to the EIP161 specification (balance = nonce = code = 0)
func (self *TradingStateDB) Empty(addr common.Hash) bool {
so := self.getStateExchangeObject(addr)
func (t *TradingStateDB) Empty(addr common.Hash) bool {
so := t.getStateExchangeObject(addr)
return so == nil || so.empty()
}
func (self *TradingStateDB) GetNonce(addr common.Hash) uint64 {
stateObject := self.getStateExchangeObject(addr)
func (t *TradingStateDB) GetNonce(addr common.Hash) uint64 {
stateObject := t.getStateExchangeObject(addr)
if stateObject != nil {
return stateObject.Nonce()
}
return 0
}
func (self *TradingStateDB) GetLastPrice(addr common.Hash) *big.Int {
stateObject := self.getStateExchangeObject(addr)
func (t *TradingStateDB) GetLastPrice(addr common.Hash) *big.Int {
stateObject := t.getStateExchangeObject(addr)
if stateObject != nil {
return stateObject.data.LastPrice
}
return nil
}
func (self *TradingStateDB) GetMediumPriceBeforeEpoch(addr common.Hash) *big.Int {
stateObject := self.getStateExchangeObject(addr)
func (t *TradingStateDB) GetMediumPriceBeforeEpoch(addr common.Hash) *big.Int {
stateObject := t.getStateExchangeObject(addr)
if stateObject != nil {
return stateObject.data.MediumPriceBeforeEpoch
}
return Zero
}
func (self *TradingStateDB) GetMediumPriceAndTotalAmount(addr common.Hash) (*big.Int, *big.Int) {
stateObject := self.getStateExchangeObject(addr)
func (t *TradingStateDB) GetMediumPriceAndTotalAmount(addr common.Hash) (*big.Int, *big.Int) {
stateObject := t.getStateExchangeObject(addr)
if stateObject != nil {
return stateObject.data.MediumPrice, stateObject.data.TotalQuantity
}
@ -134,25 +134,25 @@ func (self *TradingStateDB) GetMediumPriceAndTotalAmount(addr common.Hash) (*big
}
// Database retrieves the low level database supporting the lower level trie ops.
func (self *TradingStateDB) Database() Database {
return self.db
func (t *TradingStateDB) Database() Database {
return t.db
}
func (self *TradingStateDB) SetNonce(addr common.Hash, nonce uint64) {
stateObject := self.GetOrNewStateExchangeObject(addr)
func (t *TradingStateDB) SetNonce(addr common.Hash, nonce uint64) {
stateObject := t.GetOrNewStateExchangeObject(addr)
if stateObject != nil {
self.journal = append(self.journal, nonceChange{
t.journal = append(t.journal, nonceChange{
hash: addr,
prev: self.GetNonce(addr),
prev: t.GetNonce(addr),
})
stateObject.SetNonce(nonce)
}
}
func (self *TradingStateDB) SetLastPrice(addr common.Hash, price *big.Int) {
stateObject := self.GetOrNewStateExchangeObject(addr)
func (t *TradingStateDB) SetLastPrice(addr common.Hash, price *big.Int) {
stateObject := t.GetOrNewStateExchangeObject(addr)
if stateObject != nil {
self.journal = append(self.journal, lastPriceChange{
t.journal = append(t.journal, lastPriceChange{
hash: addr,
prev: stateObject.data.LastPrice,
})
@ -160,10 +160,10 @@ func (self *TradingStateDB) SetLastPrice(addr common.Hash, price *big.Int) {
}
}
func (self *TradingStateDB) SetMediumPrice(addr common.Hash, price *big.Int, quantity *big.Int) {
stateObject := self.GetOrNewStateExchangeObject(addr)
func (t *TradingStateDB) SetMediumPrice(addr common.Hash, price *big.Int, quantity *big.Int) {
stateObject := t.GetOrNewStateExchangeObject(addr)
if stateObject != nil {
self.journal = append(self.journal, mediumPriceChange{
t.journal = append(t.journal, mediumPriceChange{
hash: addr,
prevPrice: stateObject.data.MediumPrice,
prevQuantity: stateObject.data.TotalQuantity,
@ -172,10 +172,10 @@ func (self *TradingStateDB) SetMediumPrice(addr common.Hash, price *big.Int, qua
}
}
func (self *TradingStateDB) SetMediumPriceBeforeEpoch(addr common.Hash, price *big.Int) {
stateObject := self.GetOrNewStateExchangeObject(addr)
func (t *TradingStateDB) SetMediumPriceBeforeEpoch(addr common.Hash, price *big.Int) {
stateObject := t.GetOrNewStateExchangeObject(addr)
if stateObject != nil {
self.journal = append(self.journal, mediumPriceBeforeEpochChange{
t.journal = append(t.journal, mediumPriceBeforeEpochChange{
hash: addr,
prevPrice: stateObject.data.MediumPriceBeforeEpoch,
})
@ -183,78 +183,79 @@ func (self *TradingStateDB) SetMediumPriceBeforeEpoch(addr common.Hash, price *b
}
}
func (self *TradingStateDB) InsertOrderItem(orderBook common.Hash, orderId common.Hash, order OrderItem) {
func (t *TradingStateDB) InsertOrderItem(orderBook common.Hash, orderId common.Hash, order OrderItem) {
priceHash := common.BigToHash(order.Price)
stateExchange := self.getStateExchangeObject(orderBook)
stateExchange := t.getStateExchangeObject(orderBook)
if stateExchange == nil {
stateExchange = self.createExchangeObject(orderBook)
stateExchange = t.createExchangeObject(orderBook)
}
var stateOrderList *stateOrderList
switch order.Side {
case Ask:
stateOrderList = stateExchange.getStateOrderListAskObject(self.db, priceHash)
stateOrderList = stateExchange.getStateOrderListAskObject(t.db, priceHash)
if stateOrderList == nil {
stateOrderList = stateExchange.createStateOrderListAskObject(self.db, priceHash)
stateOrderList = stateExchange.createStateOrderListAskObject(t.db, priceHash)
}
case Bid:
stateOrderList = stateExchange.getStateBidOrderListObject(self.db, priceHash)
stateOrderList = stateExchange.getStateBidOrderListObject(t.db, priceHash)
if stateOrderList == nil {
stateOrderList = stateExchange.createStateBidOrderListObject(self.db, priceHash)
stateOrderList = stateExchange.createStateBidOrderListObject(t.db, priceHash)
}
default:
return
}
self.journal = append(self.journal, insertOrder{
t.journal = append(t.journal, insertOrder{
orderBook: orderBook,
orderId: orderId,
order: &order,
})
stateExchange.createStateOrderObject(self.db, orderId, order)
stateOrderList.insertOrderItem(self.db, orderId, common.BigToHash(order.Quantity))
stateExchange.createStateOrderObject(t.db, orderId, order)
stateOrderList.insertOrderItem(t.db, orderId, common.BigToHash(order.Quantity))
stateOrderList.AddVolume(order.Quantity)
}
func (self *TradingStateDB) GetOrder(orderBook common.Hash, orderId common.Hash) OrderItem {
stateObject := self.GetOrNewStateExchangeObject(orderBook)
func (t *TradingStateDB) GetOrder(orderBook common.Hash, orderId common.Hash) OrderItem {
stateObject := t.GetOrNewStateExchangeObject(orderBook)
if stateObject == nil {
return EmptyOrder
}
stateOrderItem := stateObject.getStateOrderObject(self.db, orderId)
stateOrderItem := stateObject.getStateOrderObject(t.db, orderId)
if stateOrderItem == nil {
return EmptyOrder
}
return stateOrderItem.data
}
func (self *TradingStateDB) SubAmountOrderItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
func (t *TradingStateDB) SubAmountOrderItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
priceHash := common.BigToHash(price)
stateObject := self.GetOrNewStateExchangeObject(orderBook)
stateObject := t.GetOrNewStateExchangeObject(orderBook)
if stateObject == nil {
return fmt.Errorf("not found orderBook: %s", orderBook.Hex())
}
var stateOrderList *stateOrderList
switch side {
case Ask:
stateOrderList = stateObject.getStateOrderListAskObject(self.db, priceHash)
stateOrderList = stateObject.getStateOrderListAskObject(t.db, priceHash)
case Bid:
stateOrderList = stateObject.getStateBidOrderListObject(self.db, priceHash)
stateOrderList = stateObject.getStateBidOrderListObject(t.db, priceHash)
default:
return fmt.Errorf("not found order type: %s", side)
}
if stateOrderList == nil || stateOrderList.empty() {
return fmt.Errorf("empty Orderlist: order book: %s , order id : %s , price : %s", orderBook, orderId.Hex(), priceHash.Hex())
}
stateOrderItem := stateObject.getStateOrderObject(self.db, orderId)
stateOrderItem := stateObject.getStateOrderObject(t.db, orderId)
if stateOrderItem == nil || stateOrderItem.empty() {
return fmt.Errorf("empty OrderItem: order book: %s , order id : %s , price : %s", orderBook, orderId.Hex(), priceHash.Hex())
}
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(self.db, orderId).Bytes()[:])
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(t.db, orderId).Bytes()[:])
if currentAmount.Cmp(amount) < 0 {
return fmt.Errorf("not enough order amount: %s , have : %d , want : %d ", orderId.Hex(), currentAmount, amount)
}
self.journal = append(self.journal, subAmountOrder{
t.journal = append(t.journal, subAmountOrder{
orderBook: orderBook,
orderId: orderId,
order: self.GetOrder(orderBook, orderId),
order: t.GetOrder(orderBook, orderId),
amount: amount,
})
newAmount := new(big.Int).Sub(currentAmount, amount)
@ -262,29 +263,29 @@ func (self *TradingStateDB) SubAmountOrderItem(orderBook common.Hash, orderId co
stateOrderList.subVolume(amount)
stateOrderItem.setVolume(newAmount)
if newAmount.Sign() == 0 {
stateOrderList.removeOrderItem(self.db, orderId)
stateOrderList.removeOrderItem(t.db, orderId)
} else {
stateOrderList.setOrderItem(orderId, common.BigToHash(newAmount))
}
if stateOrderList.empty() {
switch side {
case Ask:
stateObject.removeStateOrderListAskObject(self.db, stateOrderList)
stateObject.removeStateOrderListAskObject(t.db, stateOrderList)
case Bid:
stateObject.removeStateOrderListBidObject(self.db, stateOrderList)
stateObject.removeStateOrderListBidObject(t.db, stateOrderList)
default:
}
}
return nil
}
func (self *TradingStateDB) CancelOrder(orderBook common.Hash, order *OrderItem) error {
func (t *TradingStateDB) CancelOrder(orderBook common.Hash, order *OrderItem) error {
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.OrderID))
stateObject := self.GetOrNewStateExchangeObject(orderBook)
stateObject := t.GetOrNewStateExchangeObject(orderBook)
if stateObject == nil {
return fmt.Errorf("not found orderBook: %s", orderBook.Hex())
}
stateOrderItem := stateObject.getStateOrderObject(self.db, orderIdHash)
stateOrderItem := stateObject.getStateOrderObject(t.db, orderIdHash)
if stateOrderItem == nil || stateOrderItem.empty() {
return fmt.Errorf("empty OrderItem: order book: %s , order id : %s", orderBook, orderIdHash.Hex())
}
@ -292,9 +293,9 @@ func (self *TradingStateDB) CancelOrder(orderBook common.Hash, order *OrderItem)
var stateOrderList *stateOrderList
switch stateOrderItem.data.Side {
case Ask:
stateOrderList = stateObject.getStateOrderListAskObject(self.db, priceHash)
stateOrderList = stateObject.getStateOrderListAskObject(t.db, priceHash)
case Bid:
stateOrderList = stateObject.getStateBidOrderListObject(self.db, priceHash)
stateOrderList = stateObject.getStateBidOrderListObject(t.db, priceHash)
default:
return fmt.Errorf("not found order.Side: %s", order.Side)
}
@ -311,37 +312,37 @@ func (self *TradingStateDB) CancelOrder(orderBook common.Hash, order *OrderItem)
if stateOrderItem.data.ExchangeAddress != order.ExchangeAddress {
return fmt.Errorf("mismatch ExchangeAddress when cancel: order book : %s , order id : %s , got : %s , expect : %s", orderBook, orderIdHash.Hex(), order.ExchangeAddress.Hex(), stateOrderItem.data.ExchangeAddress.Hex())
}
self.journal = append(self.journal, cancelOrder{
t.journal = append(t.journal, cancelOrder{
orderBook: orderBook,
orderId: orderIdHash,
order: stateOrderItem.data,
})
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(self.db, orderIdHash).Bytes()[:])
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(t.db, orderIdHash).Bytes()[:])
stateOrderItem.setVolume(big.NewInt(0))
stateOrderList.subVolume(currentAmount)
stateOrderList.removeOrderItem(self.db, orderIdHash)
stateOrderList.removeOrderItem(t.db, orderIdHash)
if stateOrderList.empty() {
switch stateOrderItem.data.Side {
case Ask:
stateObject.removeStateOrderListAskObject(self.db, stateOrderList)
stateObject.removeStateOrderListAskObject(t.db, stateOrderList)
case Bid:
stateObject.removeStateOrderListBidObject(self.db, stateOrderList)
stateObject.removeStateOrderListBidObject(t.db, stateOrderList)
default:
}
}
return nil
}
func (self *TradingStateDB) GetVolume(orderBook common.Hash, price *big.Int, orderType string) *big.Int {
stateObject := self.GetOrNewStateExchangeObject(orderBook)
func (t *TradingStateDB) GetVolume(orderBook common.Hash, price *big.Int, orderType string) *big.Int {
stateObject := t.GetOrNewStateExchangeObject(orderBook)
var volume *big.Int = nil
if stateObject != nil {
var stateOrderList *stateOrderList
switch orderType {
case Ask:
stateOrderList = stateObject.getStateOrderListAskObject(self.db, common.BigToHash(price))
stateOrderList = stateObject.getStateOrderListAskObject(t.db, common.BigToHash(price))
case Bid:
stateOrderList = stateObject.getStateBidOrderListObject(self.db, common.BigToHash(price))
stateOrderList = stateObject.getStateBidOrderListObject(t.db, common.BigToHash(price))
default:
return Zero
}
@ -352,14 +353,15 @@ func (self *TradingStateDB) GetVolume(orderBook common.Hash, price *big.Int, ord
}
return volume
}
func (self *TradingStateDB) GetBestAskPrice(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) GetBestAskPrice(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := t.getStateExchangeObject(orderBook)
if stateObject != nil {
priceHash := stateObject.getBestPriceAsksTrie(self.db)
priceHash := stateObject.getBestPriceAsksTrie(t.db)
if common.EmptyHash(priceHash) {
return Zero, Zero
}
orderList := stateObject.getStateOrderListAskObject(self.db, priceHash)
orderList := stateObject.getStateOrderListAskObject(t.db, priceHash)
if orderList == nil {
log.Error("order list ask not found", "price", priceHash.Hex())
return Zero, Zero
@ -369,14 +371,14 @@ func (self *TradingStateDB) GetBestAskPrice(orderBook common.Hash) (*big.Int, *b
return Zero, Zero
}
func (self *TradingStateDB) GetBestBidPrice(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := self.getStateExchangeObject(orderBook)
func (t *TradingStateDB) GetBestBidPrice(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := t.getStateExchangeObject(orderBook)
if stateObject != nil {
priceHash := stateObject.getBestBidsTrie(self.db)
priceHash := stateObject.getBestBidsTrie(t.db)
if common.EmptyHash(priceHash) {
return Zero, Zero
}
orderList := stateObject.getStateBidOrderListObject(self.db, priceHash)
orderList := stateObject.getStateBidOrderListObject(t.db, priceHash)
if orderList == nil {
log.Error("order list bid not found", "price", priceHash.Hex())
return Zero, Zero
@ -386,25 +388,25 @@ func (self *TradingStateDB) GetBestBidPrice(orderBook common.Hash) (*big.Int, *b
return Zero, Zero
}
func (self *TradingStateDB) GetBestOrderIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
stateObject := self.GetOrNewStateExchangeObject(orderBook)
func (t *TradingStateDB) GetBestOrderIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
stateObject := t.GetOrNewStateExchangeObject(orderBook)
if stateObject != nil {
var stateOrderList *stateOrderList
switch side {
case Ask:
stateOrderList = stateObject.getStateOrderListAskObject(self.db, common.BigToHash(price))
stateOrderList = stateObject.getStateOrderListAskObject(t.db, common.BigToHash(price))
case Bid:
stateOrderList = stateObject.getStateBidOrderListObject(self.db, common.BigToHash(price))
stateOrderList = stateObject.getStateBidOrderListObject(t.db, common.BigToHash(price))
default:
return EmptyHash, Zero, fmt.Errorf("not found side: %s", side)
}
if stateOrderList != nil {
key, _, err := stateOrderList.getTrie(self.db).TryGetBestLeftKeyAndValue()
key, _, err := stateOrderList.getTrie(t.db).TryGetBestLeftKeyAndValue()
if err != nil {
return EmptyHash, Zero, err
}
orderId := common.BytesToHash(key)
amount := stateOrderList.GetOrderAmount(self.db, orderId)
amount := stateOrderList.GetOrderAmount(t.db, orderId)
return orderId, new(big.Int).SetBytes(amount.Bytes()), nil
}
return EmptyHash, Zero, fmt.Errorf("not found order list with orderBook: %s , price : %d , side : %s", orderBook.Hex(), price, side)
@ -413,25 +415,25 @@ func (self *TradingStateDB) GetBestOrderIdAndAmount(orderBook common.Hash, price
}
// updateStateExchangeObject writes the given object to the trie.
func (self *TradingStateDB) updateStateExchangeObject(stateObject *tradingExchanges) {
func (t *TradingStateDB) updateStateExchangeObject(stateObject *tradingExchanges) {
addr := stateObject.Hash()
data, err := rlp.EncodeToBytes(stateObject)
if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
}
self.setError(self.trie.TryUpdate(addr[:], data))
t.setError(t.trie.TryUpdate(addr[:], data))
}
// Retrieve a state object given my the address. Returns nil if not found.
func (self *TradingStateDB) getStateExchangeObject(addr common.Hash) (stateObject *tradingExchanges) {
func (t *TradingStateDB) getStateExchangeObject(addr common.Hash) (stateObject *tradingExchanges) {
// Prefer 'live' objects.
if obj := self.stateExhangeObjects[addr]; obj != nil {
if obj := t.stateExhangeObjects[addr]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.trie.TryGet(addr[:])
enc, err := t.trie.TryGet(addr[:])
if len(enc) == 0 {
self.setError(err)
t.setError(err)
return nil
}
var data tradingExchangeObject
@ -440,169 +442,169 @@ func (self *TradingStateDB) getStateExchangeObject(addr common.Hash) (stateObjec
return nil
}
// Insert into the live set.
obj := newStateExchanges(self, addr, data, self.MarkStateExchangeObjectDirty)
self.stateExhangeObjects[addr] = obj
obj := newStateExchanges(t, addr, data, t.MarkStateExchangeObjectDirty)
t.stateExhangeObjects[addr] = obj
return obj
}
func (self *TradingStateDB) setStateExchangeObject(object *tradingExchanges) {
self.stateExhangeObjects[object.Hash()] = object
self.stateExhangeObjectsDirty[object.Hash()] = struct{}{}
func (t *TradingStateDB) setStateExchangeObject(object *tradingExchanges) {
t.stateExhangeObjects[object.Hash()] = object
t.stateExhangeObjectsDirty[object.Hash()] = struct{}{}
}
// Retrieve a state object or create a new state object if nil.
func (self *TradingStateDB) GetOrNewStateExchangeObject(addr common.Hash) *tradingExchanges {
stateExchangeObject := self.getStateExchangeObject(addr)
func (t *TradingStateDB) GetOrNewStateExchangeObject(addr common.Hash) *tradingExchanges {
stateExchangeObject := t.getStateExchangeObject(addr)
if stateExchangeObject == nil {
stateExchangeObject = self.createExchangeObject(addr)
stateExchangeObject = t.createExchangeObject(addr)
}
return stateExchangeObject
}
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *TradingStateDB) MarkStateExchangeObjectDirty(addr common.Hash) {
self.stateExhangeObjectsDirty[addr] = struct{}{}
func (t *TradingStateDB) MarkStateExchangeObjectDirty(addr common.Hash) {
t.stateExhangeObjectsDirty[addr] = struct{}{}
}
// createStateOrderListObject creates a new state object. If there is an existing orderId with
// the given address, it is overwritten and returned as the second return value.
func (self *TradingStateDB) createExchangeObject(hash common.Hash) (newobj *tradingExchanges) {
newobj = newStateExchanges(self, hash, tradingExchangeObject{LendingCount: Zero, MediumPrice: Zero, MediumPriceBeforeEpoch: Zero, TotalQuantity: Zero}, self.MarkStateExchangeObjectDirty)
func (t *TradingStateDB) createExchangeObject(hash common.Hash) (newobj *tradingExchanges) {
newobj = newStateExchanges(t, hash, tradingExchangeObject{LendingCount: Zero, MediumPrice: Zero, MediumPriceBeforeEpoch: Zero, TotalQuantity: Zero}, t.MarkStateExchangeObjectDirty)
newobj.setNonce(0) // sets the object to dirty
self.setStateExchangeObject(newobj)
t.setStateExchangeObject(newobj)
return newobj
}
// Copy creates a deep, independent copy of the state.
// Snapshots of the copied state cannot be applied to the copy.
func (self *TradingStateDB) Copy() *TradingStateDB {
self.lock.Lock()
defer self.lock.Unlock()
func (t *TradingStateDB) Copy() *TradingStateDB {
t.lock.Lock()
defer t.lock.Unlock()
// Copy all the basic fields, initialize the memory ones
state := &TradingStateDB{
db: self.db,
trie: self.db.CopyTrie(self.trie),
stateExhangeObjects: make(map[common.Hash]*tradingExchanges, len(self.stateExhangeObjectsDirty)),
stateExhangeObjectsDirty: make(map[common.Hash]struct{}, len(self.stateExhangeObjectsDirty)),
db: t.db,
trie: t.db.CopyTrie(t.trie),
stateExhangeObjects: make(map[common.Hash]*tradingExchanges, len(t.stateExhangeObjectsDirty)),
stateExhangeObjectsDirty: make(map[common.Hash]struct{}, len(t.stateExhangeObjectsDirty)),
}
// Copy the dirty states, logs, and preimages
for addr := range self.stateExhangeObjectsDirty {
for addr := range t.stateExhangeObjectsDirty {
state.stateExhangeObjectsDirty[addr] = struct{}{}
}
for addr, exchangeObject := range self.stateExhangeObjects {
for addr, exchangeObject := range t.stateExhangeObjects {
state.stateExhangeObjects[addr] = exchangeObject.deepCopy(state, state.MarkStateExchangeObjectDirty)
}
return state
}
func (s *TradingStateDB) clearJournalAndRefund() {
s.journal = nil
s.validRevisions = s.validRevisions[:0]
func (t *TradingStateDB) clearJournalAndRefund() {
t.journal = nil
t.validRevisions = t.validRevisions[:0]
}
// Snapshot returns an identifier for the current revision of the state.
func (self *TradingStateDB) Snapshot() int {
id := self.nextRevisionId
self.nextRevisionId++
self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)})
func (t *TradingStateDB) Snapshot() int {
id := t.nextRevisionId
t.nextRevisionId++
t.validRevisions = append(t.validRevisions, revision{id, len(t.journal)})
return id
}
// RevertToSnapshot reverts all state changes made since the given revision.
func (self *TradingStateDB) RevertToSnapshot(revid int) {
func (t *TradingStateDB) RevertToSnapshot(revid int) {
// Find the snapshot in the stack of valid snapshots.
idx := sort.Search(len(self.validRevisions), func(i int) bool {
return self.validRevisions[i].id >= revid
idx := sort.Search(len(t.validRevisions), func(i int) bool {
return t.validRevisions[i].id >= revid
})
if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid {
if idx == len(t.validRevisions) || t.validRevisions[idx].id != revid {
panic(fmt.Errorf("revision id %v cannot be reverted", revid))
}
snapshot := self.validRevisions[idx].journalIndex
snapshot := t.validRevisions[idx].journalIndex
// Replay the journal to undo changes.
for i := len(self.journal) - 1; i >= snapshot; i-- {
self.journal[i].undo(self)
for i := len(t.journal) - 1; i >= snapshot; i-- {
t.journal[i].undo(t)
}
self.journal = self.journal[:snapshot]
t.journal = t.journal[:snapshot]
// Remove invalidated snapshots from the stack.
self.validRevisions = self.validRevisions[:idx]
t.validRevisions = t.validRevisions[:idx]
}
// Finalise finalises the state by removing the self destructed objects
// and clears the journal as well as the refunds.
func (s *TradingStateDB) Finalise() {
func (t *TradingStateDB) Finalise() {
// Commit objects to the trie.
for addr, stateObject := range s.stateExhangeObjects {
if _, isDirty := s.stateExhangeObjectsDirty[addr]; isDirty {
for addr, stateObject := range t.stateExhangeObjects {
if _, isDirty := t.stateExhangeObjectsDirty[addr]; isDirty {
// Write any storage changes in the state object to its storage trie.
err := stateObject.updateAsksRoot(s.db)
err := stateObject.updateAsksRoot(t.db)
if err != nil {
log.Warn("Finalise updateAsksRoot", "err", err, "addr", addr, "stateObject", *stateObject)
}
stateObject.updateBidsRoot(s.db)
stateObject.updateOrdersRoot(s.db)
stateObject.updateLiquidationPriceRoot(s.db)
stateObject.updateBidsRoot(t.db)
stateObject.updateOrdersRoot(t.db)
stateObject.updateLiquidationPriceRoot(t.db)
// Update the object in the main orderId trie.
s.updateStateExchangeObject(stateObject)
t.updateStateExchangeObject(stateObject)
//delete(s.stateExhangeObjectsDirty, addr)
}
}
s.clearJournalAndRefund()
t.clearJournalAndRefund()
}
// IntermediateRoot computes the current root orderBookHash of the state trie.
// It is called in between transactions to get the root orderBookHash that
// goes into transaction receipts.
func (s *TradingStateDB) IntermediateRoot() common.Hash {
s.Finalise()
return s.trie.Hash()
func (t *TradingStateDB) IntermediateRoot() common.Hash {
t.Finalise()
return t.trie.Hash()
}
// Commit writes the state to the underlying in-memory trie database.
func (s *TradingStateDB) Commit() (root common.Hash, err error) {
defer s.clearJournalAndRefund()
func (t *TradingStateDB) Commit() (root common.Hash, err error) {
defer t.clearJournalAndRefund()
// Commit objects to the trie.
for addr, stateObject := range s.stateExhangeObjects {
if _, isDirty := s.stateExhangeObjectsDirty[addr]; isDirty {
for addr, stateObject := range t.stateExhangeObjects {
if _, isDirty := t.stateExhangeObjectsDirty[addr]; isDirty {
// Write any storage changes in the state object to its storage trie.
if err := stateObject.CommitAsksTrie(s.db); err != nil {
if err := stateObject.CommitAsksTrie(t.db); err != nil {
return EmptyHash, err
}
if err := stateObject.CommitBidsTrie(s.db); err != nil {
if err := stateObject.CommitBidsTrie(t.db); err != nil {
return EmptyHash, err
}
if err := stateObject.CommitOrdersTrie(s.db); err != nil {
if err := stateObject.CommitOrdersTrie(t.db); err != nil {
return EmptyHash, err
}
if err := stateObject.CommitLiquidationPriceTrie(s.db); err != nil {
if err := stateObject.CommitLiquidationPriceTrie(t.db); err != nil {
return EmptyHash, err
}
// Update the object in the main orderId trie.
s.updateStateExchangeObject(stateObject)
delete(s.stateExhangeObjectsDirty, addr)
t.updateStateExchangeObject(stateObject)
delete(t.stateExhangeObjectsDirty, addr)
}
}
// Write trie changes.
root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {
root, err = t.trie.Commit(func(leaf []byte, parent common.Hash) error {
var exchange tradingExchangeObject
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
return nil
}
if exchange.AskRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.AskRoot, parent)
t.db.TrieDB().Reference(exchange.AskRoot, parent)
}
if exchange.BidRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.BidRoot, parent)
t.db.TrieDB().Reference(exchange.BidRoot, parent)
}
if exchange.OrderRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.OrderRoot, parent)
t.db.TrieDB().Reference(exchange.OrderRoot, parent)
}
if exchange.LiquidationPriceRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.LiquidationPriceRoot, parent)
t.db.TrieDB().Reference(exchange.LiquidationPriceRoot, parent)
}
return nil
})
@ -610,19 +612,19 @@ func (s *TradingStateDB) Commit() (root common.Hash, err error) {
return root, err
}
func (self *TradingStateDB) GetAllLowerLiquidationPriceData(orderBook common.Hash, limit *big.Int) map[*big.Int]map[common.Hash][]common.Hash {
func (t *TradingStateDB) GetAllLowerLiquidationPriceData(orderBook common.Hash, limit *big.Int) map[*big.Int]map[common.Hash][]common.Hash {
result := map[*big.Int]map[common.Hash][]common.Hash{}
orderbookState := self.getStateExchangeObject(orderBook)
orderbookState := t.getStateExchangeObject(orderBook)
if orderbookState == nil {
return result
}
mapPrices := orderbookState.getAllLowerLiquidationPrice(self.db, common.BigToHash(limit))
mapPrices := orderbookState.getAllLowerLiquidationPrice(t.db, common.BigToHash(limit))
for priceHash, liquidationState := range mapPrices {
price := new(big.Int).SetBytes(priceHash[:])
log.Debug("GetAllLowerLiquidationPriceData", "price", price, "limit", limit)
if liquidationState != nil && price.Sign() > 0 && price.Cmp(limit) < 0 {
liquidationData := map[common.Hash][]common.Hash{}
priceLiquidationData := liquidationState.getAllLiquidationData(self.db)
priceLiquidationData := liquidationState.getAllLiquidationData(t.db)
for lendingBook, data := range priceLiquidationData {
if len(data) == 0 {
continue
@ -641,16 +643,16 @@ func (self *TradingStateDB) GetAllLowerLiquidationPriceData(orderBook common.Has
return result
}
func (self *TradingStateDB) GetHighestLiquidationPriceData(orderBook common.Hash, price *big.Int) (*big.Int, map[common.Hash][]common.Hash) {
func (t *TradingStateDB) GetHighestLiquidationPriceData(orderBook common.Hash, price *big.Int) (*big.Int, map[common.Hash][]common.Hash) {
liquidationData := map[common.Hash][]common.Hash{}
orderbookState := self.getStateExchangeObject(orderBook)
orderbookState := t.getStateExchangeObject(orderBook)
if orderbookState == nil {
return common.Big0, liquidationData
}
highestPriceHash, liquidationState := orderbookState.getHighestLiquidationPrice(self.db)
highestPriceHash, liquidationState := orderbookState.getHighestLiquidationPrice(t.db)
highestPrice := new(big.Int).SetBytes(highestPriceHash[:])
if liquidationState != nil && highestPrice.Sign() > 0 && price.Cmp(highestPrice) < 0 {
priceLiquidationData := liquidationState.getAllLiquidationData(self.db)
priceLiquidationData := liquidationState.getAllLiquidationData(t.db)
for lendingBook, data := range priceLiquidationData {
if len(data) == 0 {
continue
@ -667,26 +669,26 @@ func (self *TradingStateDB) GetHighestLiquidationPriceData(orderBook common.Hash
return highestPrice, liquidationData
}
func (self *TradingStateDB) InsertLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) {
func (t *TradingStateDB) InsertLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) {
tradIdHash := common.Uint64ToHash(tradeId)
priceHash := common.BigToHash(price)
orderBookState := self.getStateExchangeObject(orderBook)
orderBookState := t.getStateExchangeObject(orderBook)
if orderBookState == nil {
orderBookState = self.createExchangeObject(orderBook)
orderBookState = t.createExchangeObject(orderBook)
}
liquidationPriceState := orderBookState.getStateLiquidationPrice(self.db, priceHash)
liquidationPriceState := orderBookState.getStateLiquidationPrice(t.db, priceHash)
if liquidationPriceState == nil {
liquidationPriceState = orderBookState.createStateLiquidationPrice(self.db, priceHash)
liquidationPriceState = orderBookState.createStateLiquidationPrice(t.db, priceHash)
}
lendingBookState := liquidationPriceState.getStateLendingBook(self.db, lendingBook)
lendingBookState := liquidationPriceState.getStateLendingBook(t.db, lendingBook)
if lendingBookState == nil {
lendingBookState = liquidationPriceState.createLendingBook(self.db, lendingBook)
lendingBookState = liquidationPriceState.createLendingBook(t.db, lendingBook)
}
lendingBookState.insertTradingId(self.db, tradIdHash)
lendingBookState.insertTradingId(t.db, tradIdHash)
lendingBookState.AddVolume(One)
liquidationPriceState.AddVolume(One)
orderBookState.addLendingCount(One)
self.journal = append(self.journal, insertLiquidationPrice{
t.journal = append(t.journal, insertLiquidationPrice{
orderBook: orderBook,
price: price,
lendingBook: lendingBook,
@ -694,35 +696,35 @@ func (self *TradingStateDB) InsertLiquidationPrice(orderBook common.Hash, price
})
}
func (self *TradingStateDB) RemoveLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) error {
func (t *TradingStateDB) RemoveLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) error {
tradeIdHash := common.Uint64ToHash(tradeId)
priceHash := common.BigToHash(price)
orderbookState := self.getStateExchangeObject(orderBook)
orderbookState := t.getStateExchangeObject(orderBook)
if orderbookState == nil {
return fmt.Errorf("not found order book: %s", orderBook.Hex())
}
liquidationPriceState := orderbookState.getStateLiquidationPrice(self.db, priceHash)
liquidationPriceState := orderbookState.getStateLiquidationPrice(t.db, priceHash)
if liquidationPriceState == nil {
return fmt.Errorf("not found liquidation price: %s , %s", orderBook.Hex(), priceHash.Hex())
}
lendingBookState := liquidationPriceState.getStateLendingBook(self.db, lendingBook)
lendingBookState := liquidationPriceState.getStateLendingBook(t.db, lendingBook)
if lendingBookState == nil {
return fmt.Errorf("not found lending book: %s , %s ,%s", orderBook.Hex(), priceHash.Hex(), lendingBook.Hex())
}
if !lendingBookState.Exist(self.db, tradeIdHash) {
return fmt.Errorf("not found trade id: %s , %s ,%s , %d ", orderBook.Hex(), priceHash.Hex(), lendingBook.Hex(), tradeId)
if !lendingBookState.Exist(t.db, tradeIdHash) {
return fmt.Errorf("not found trade id: %s, %s ,%s , %d", orderBook.Hex(), priceHash.Hex(), lendingBook.Hex(), tradeId)
}
lendingBookState.removeTradingId(self.db, tradeIdHash)
lendingBookState.removeTradingId(t.db, tradeIdHash)
lendingBookState.subVolume(One)
liquidationPriceState.subVolume(One)
if liquidationPriceState.Volume().Sign() == 0 {
err := orderbookState.getLiquidationPriceTrie(self.db).TryDelete(priceHash[:])
err := orderbookState.getLiquidationPriceTrie(t.db).TryDelete(priceHash[:])
if err != nil {
log.Warn("RemoveLiquidationPrice getLiquidationPriceTrie.TryDelete", "err", err, "priceHash", priceHash[:])
}
}
orderbookState.subLendingCount(One)
self.journal = append(self.journal, removeLiquidationPrice{
t.journal = append(t.journal, removeLiquidationPrice{
orderBook: orderBook,
price: price,
lendingBook: lendingBook,

View file

@ -39,13 +39,13 @@ type DumpOrderBookInfo struct {
LowestLiquidationTime *big.Int
}
func (self *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]DumpOrderList{}
it := trie.NewIterator(exhangeObject.getInvestingTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getInvestingTrie(ls.db).NodeIterator(nil))
for it.Next() {
interestHash := common.BytesToHash(it.Key)
if common.EmptyHash(interestHash) {
@ -60,12 +60,12 @@ func (self *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.I
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , interest : %v", orderBook.Hex(), interest)
}
stateOrderList := newItemListState(orderBook, interestHash, data, nil)
mapResult[interest] = stateOrderList.DumpItemList(self.db)
mapResult[interest] = stateOrderList.DumpItemList(ls.db)
}
}
for interestHash, itemList := range exhangeObject.investingStates {
if itemList.Volume().Sign() > 0 {
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(self.db)
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(ls.db)
}
}
listInterest := []*big.Int{}
@ -82,13 +82,13 @@ func (self *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.I
return result, nil
}
func (self *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]DumpOrderList{}
it := trie.NewIterator(exhangeObject.getBorrowingTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getBorrowingTrie(ls.db).NodeIterator(nil))
for it.Next() {
interestHash := common.BytesToHash(it.Key)
if common.EmptyHash(interestHash) {
@ -103,12 +103,12 @@ func (self *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.I
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , interest : %v", orderBook.Hex(), interest)
}
stateOrderList := newItemListState(orderBook, interestHash, data, nil)
mapResult[interest] = stateOrderList.DumpItemList(self.db)
mapResult[interest] = stateOrderList.DumpItemList(ls.db)
}
}
for interestHash, itemList := range exhangeObject.borrowingStates {
if itemList.Volume().Sign() > 0 {
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(self.db)
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(ls.db)
}
}
listInterest := []*big.Int{}
@ -125,13 +125,13 @@ func (self *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.I
return result, nil
}
func (self *LendingStateDB) GetInvestings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) GetInvestings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]*big.Int{}
it := trie.NewIterator(exhangeObject.getInvestingTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getInvestingTrie(ls.db).NodeIterator(nil))
for it.Next() {
interestHash := common.BytesToHash(it.Key)
if common.EmptyHash(interestHash) {
@ -168,13 +168,13 @@ func (self *LendingStateDB) GetInvestings(orderBook common.Hash) (map[*big.Int]*
return result, nil
}
func (self *LendingStateDB) GetBorrowings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) GetBorrowings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]*big.Int{}
it := trie.NewIterator(exhangeObject.getBorrowingTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getBorrowingTrie(ls.db).NodeIterator(nil))
for it.Next() {
interestHash := common.BytesToHash(it.Key)
if common.EmptyHash(interestHash) {
@ -211,22 +211,22 @@ func (self *LendingStateDB) GetBorrowings(orderBook common.Hash) (map[*big.Int]*
return result, nil
}
func (self *itemListState) DumpItemList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
func (il *itemListState) DumpItemList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: il.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(il.getTrie(db).NodeIterator(nil))
for orderListIt.Next() {
keyHash := common.BytesToHash(orderListIt.Key)
if common.EmptyHash(keyHash) {
continue
}
if _, exist := self.cachedStorage[keyHash]; exist {
if _, exist := il.cachedStorage[keyHash]; exist {
continue
} else {
_, content, _, _ := rlp.Split(orderListIt.Value)
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
}
}
for key, value := range self.cachedStorage {
for key, value := range il.cachedStorage {
if !common.EmptyHash(value) {
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
}
@ -238,44 +238,44 @@ func (self *itemListState) DumpItemList(db Database) DumpOrderList {
sort.Slice(listIds, func(i, j int) bool {
return listIds[i].Cmp(listIds[j]) < 0
})
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
result := DumpOrderList{Volume: il.Volume(), Orders: map[*big.Int]*big.Int{}}
for _, id := range listIds {
result.Orders[id] = mapResult.Orders[id]
}
return result
}
func (self *LendingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
result := &DumpOrderBookInfo{}
result.Nonce = exhangeObject.data.Nonce
result.TradeNonce = exhangeObject.data.TradeNonce
result.BestInvesting = new(big.Int).SetBytes(exhangeObject.getBestInvestingInterest(self.db).Bytes())
result.BestBorrowing = new(big.Int).SetBytes(exhangeObject.getBestBorrowingInterest(self.db).Bytes())
lowestLiquidationTime, _ := exhangeObject.getLowestLiquidationTime(self.db)
result.BestInvesting = new(big.Int).SetBytes(exhangeObject.getBestInvestingInterest(ls.db).Bytes())
result.BestBorrowing = new(big.Int).SetBytes(exhangeObject.getBestBorrowingInterest(ls.db).Bytes())
lowestLiquidationTime, _ := exhangeObject.getLowestLiquidationTime(ls.db)
result.LowestLiquidationTime = new(big.Int).SetBytes(lowestLiquidationTime.Bytes())
return result, nil
}
func (self *liquidationTimeState) DumpItemList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
func (lts *liquidationTimeState) DumpItemList(db Database) DumpOrderList {
mapResult := DumpOrderList{Volume: lts.Volume(), Orders: map[*big.Int]*big.Int{}}
orderListIt := trie.NewIterator(lts.getTrie(db).NodeIterator(nil))
for orderListIt.Next() {
keyHash := common.BytesToHash(orderListIt.Key)
if common.EmptyHash(keyHash) {
continue
}
if _, exist := self.cachedStorage[keyHash]; exist {
if _, exist := lts.cachedStorage[keyHash]; exist {
continue
} else {
_, content, _, _ := rlp.Split(orderListIt.Value)
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
}
}
for key, value := range self.cachedStorage {
for key, value := range lts.cachedStorage {
if !common.EmptyHash(value) {
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
}
@ -287,19 +287,20 @@ func (self *liquidationTimeState) DumpItemList(db Database) DumpOrderList {
sort.Slice(listIds, func(i, j int) bool {
return listIds[i].Cmp(listIds[j]) < 0
})
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
result := DumpOrderList{Volume: lts.Volume(), Orders: map[*big.Int]*big.Int{}}
for _, id := range listIds {
result.Orders[id] = mapResult.Orders[id]
}
return mapResult
}
func (self *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]DumpOrderList{}
it := trie.NewIterator(exhangeObject.getLiquidationTimeTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getLiquidationTimeTrie(ls.db).NodeIterator(nil))
for it.Next() {
unixTimeHash := common.BytesToHash(it.Key)
if common.EmptyHash(unixTimeHash) {
@ -314,12 +315,12 @@ func (self *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , unixTime : %v", orderBook.Hex(), unixTime)
}
stateOrderList := newLiquidationTimeState(orderBook, unixTimeHash, data, nil)
mapResult[unixTime] = stateOrderList.DumpItemList(self.db)
mapResult[unixTime] = stateOrderList.DumpItemList(ls.db)
}
}
for unixTimeHash, itemList := range exhangeObject.liquidationTimeStates {
if itemList.Volume().Sign() > 0 {
mapResult[new(big.Int).SetBytes(unixTimeHash.Bytes())] = itemList.DumpItemList(self.db)
mapResult[new(big.Int).SetBytes(unixTimeHash.Bytes())] = itemList.DumpItemList(ls.db)
}
}
listUnixTime := []*big.Int{}
@ -336,13 +337,13 @@ func (self *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[
return result, nil
}
func (self *LendingStateDB) DumpLendingOrderTrie(orderBook common.Hash) (map[*big.Int]LendingItem, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) DumpLendingOrderTrie(orderBook common.Hash) (map[*big.Int]LendingItem, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]LendingItem{}
it := trie.NewIterator(exhangeObject.getLendingItemTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getLendingItemTrie(ls.db).NodeIterator(nil))
for it.Next() {
orderIdHash := common.BytesToHash(it.Key)
if common.EmptyHash(orderIdHash) {
@ -376,13 +377,13 @@ func (self *LendingStateDB) DumpLendingOrderTrie(orderBook common.Hash) (map[*bi
return result, nil
}
func (self *LendingStateDB) DumpLendingTradeTrie(orderBook common.Hash) (map[*big.Int]LendingTrade, error) {
exhangeObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) DumpLendingTradeTrie(orderBook common.Hash) (map[*big.Int]LendingTrade, error) {
exhangeObject := ls.getLendingExchange(orderBook)
if exhangeObject == nil {
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
}
mapResult := map[*big.Int]LendingTrade{}
it := trie.NewIterator(exhangeObject.getLendingTradeTrie(self.db).NodeIterator(nil))
it := trie.NewIterator(exhangeObject.getLendingTradeTrie(ls.db).NodeIterator(nil))
for it.Next() {
tradeIdHash := common.BytesToHash(it.Key)
if common.EmptyHash(tradeIdHash) {

View file

@ -19,10 +19,11 @@ package lendingstate
import (
"bytes"
"fmt"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/rlp"
"io"
"math/big"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/rlp"
)
type itemListState struct {
@ -46,8 +47,8 @@ type itemListState struct {
onDirty func(price common.Hash) // Callback method to mark a state object newly dirty
}
func (s *itemListState) empty() bool {
return s.data.Volume == nil || s.data.Volume.Sign() == 0
func (il *itemListState) empty() bool {
return il.data.Volume == nil || il.data.Volume.Sign() == 0
}
func newItemListState(lendingBook common.Hash, key common.Hash, data itemList, onDirty func(price common.Hash)) *itemListState {
@ -62,132 +63,132 @@ func newItemListState(lendingBook common.Hash, key common.Hash, data itemList, o
}
// EncodeRLP implements rlp.Encoder.
func (c *itemListState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, c.data)
func (il *itemListState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, il.data)
}
// setError remembers the first non-nil error it is called with.
func (self *itemListState) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (il *itemListState) setError(err error) {
if il.dbErr == nil {
il.dbErr = err
}
}
func (c *itemListState) getTrie(db Database) Trie {
if c.trie == nil {
func (il *itemListState) getTrie(db Database) Trie {
if il.trie == nil {
var err error
c.trie, err = db.OpenStorageTrie(c.key, c.data.Root)
il.trie, err = db.OpenStorageTrie(il.key, il.data.Root)
if err != nil {
c.trie, _ = db.OpenStorageTrie(c.key, EmptyHash)
c.setError(fmt.Errorf("can't create storage trie: %v", err))
il.trie, _ = db.OpenStorageTrie(il.key, EmptyHash)
il.setError(fmt.Errorf("can't create storage trie: %v", err))
}
}
return c.trie
return il.trie
}
func (self *itemListState) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
amount, exists := self.cachedStorage[orderId]
func (il *itemListState) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
amount, exists := il.cachedStorage[orderId]
if exists {
return amount
}
// Load from DB in case it is missing.
enc, err := self.getTrie(db).TryGet(orderId[:])
enc, err := il.getTrie(db).TryGet(orderId[:])
if err != nil {
self.setError(err)
il.setError(err)
return EmptyHash
}
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
self.setError(err)
il.setError(err)
}
amount.SetBytes(content)
}
if (amount != common.Hash{}) {
self.cachedStorage[orderId] = amount
il.cachedStorage[orderId] = amount
}
return amount
}
func (self *itemListState) insertLendingItem(db Database, orderId common.Hash, amount common.Hash) {
self.setOrderItem(orderId, amount)
self.setError(self.getTrie(db).TryUpdate(orderId[:], amount[:]))
func (il *itemListState) insertLendingItem(db Database, orderId common.Hash, amount common.Hash) {
il.setOrderItem(orderId, amount)
il.setError(il.getTrie(db).TryUpdate(orderId[:], amount[:]))
}
func (self *itemListState) removeOrderItem(db Database, orderId common.Hash) {
tr := self.getTrie(db)
self.setError(tr.TryDelete(orderId[:]))
self.setOrderItem(orderId, EmptyHash)
func (il *itemListState) removeOrderItem(db Database, orderId common.Hash) {
tr := il.getTrie(db)
il.setError(tr.TryDelete(orderId[:]))
il.setOrderItem(orderId, EmptyHash)
}
func (self *itemListState) setOrderItem(orderId common.Hash, amount common.Hash) {
self.cachedStorage[orderId] = amount
self.dirtyStorage[orderId] = amount
func (il *itemListState) setOrderItem(orderId common.Hash, amount common.Hash) {
il.cachedStorage[orderId] = amount
il.dirtyStorage[orderId] = amount
if self.onDirty != nil {
self.onDirty(self.key)
self.onDirty = nil
if il.onDirty != nil {
il.onDirty(il.key)
il.onDirty = nil
}
}
// updateAskTrie writes cached storage modifications into the object's storage trie.
func (self *itemListState) updateTrie(db Database) Trie {
tr := self.getTrie(db)
for orderId, amount := range self.dirtyStorage {
delete(self.dirtyStorage, orderId)
func (il *itemListState) updateTrie(db Database) Trie {
tr := il.getTrie(db)
for orderId, amount := range il.dirtyStorage {
delete(il.dirtyStorage, orderId)
if amount == EmptyHash {
self.setError(tr.TryDelete(orderId[:]))
il.setError(tr.TryDelete(orderId[:]))
continue
}
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(amount[:], "\x00"))
self.setError(tr.TryUpdate(orderId[:], v))
il.setError(tr.TryUpdate(orderId[:], v))
}
return tr
}
// UpdateRoot sets the trie root to the current root tradeId of
func (self *itemListState) updateRoot(db Database) error {
self.updateTrie(db)
if self.dbErr != nil {
return self.dbErr
func (il *itemListState) updateRoot(db Database) error {
il.updateTrie(db)
if il.dbErr != nil {
return il.dbErr
}
root, err := self.trie.Commit(nil)
root, err := il.trie.Commit(nil)
if err == nil {
self.data.Root = root
il.data.Root = root
}
return err
}
func (self *itemListState) deepCopy(db *LendingStateDB, onDirty func(price common.Hash)) *itemListState {
stateOrderList := newItemListState(self.lendingBook, self.key, self.data, onDirty)
if self.trie != nil {
stateOrderList.trie = db.db.CopyTrie(self.trie)
func (il *itemListState) deepCopy(db *LendingStateDB, onDirty func(price common.Hash)) *itemListState {
stateOrderList := newItemListState(il.lendingBook, il.key, il.data, onDirty)
if il.trie != nil {
stateOrderList.trie = db.db.CopyTrie(il.trie)
}
for orderId, amount := range self.dirtyStorage {
for orderId, amount := range il.dirtyStorage {
stateOrderList.dirtyStorage[orderId] = amount
}
for orderId, amount := range self.cachedStorage {
for orderId, amount := range il.cachedStorage {
stateOrderList.cachedStorage[orderId] = amount
}
return stateOrderList
}
func (c *itemListState) AddVolume(amount *big.Int) {
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
func (il *itemListState) AddVolume(amount *big.Int) {
il.setVolume(new(big.Int).Add(il.data.Volume, amount))
}
func (c *itemListState) subVolume(amount *big.Int) {
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
func (il *itemListState) subVolume(amount *big.Int) {
il.setVolume(new(big.Int).Sub(il.data.Volume, amount))
}
func (self *itemListState) setVolume(volume *big.Int) {
self.data.Volume = volume
if self.onDirty != nil {
self.onDirty(self.key)
self.onDirty = nil
func (il *itemListState) setVolume(volume *big.Int) {
il.data.Volume = volume
if il.onDirty != nil {
il.onDirty(il.key)
il.onDirty = nil
}
}
func (self *itemListState) Volume() *big.Int {
return self.data.Volume
func (il *itemListState) Volume() *big.Int {
return il.data.Volume
}

View file

@ -108,14 +108,14 @@ func newStateExchanges(db *LendingStateDB, hash common.Hash, data lendingObject,
}
// EncodeRLP implements rlp.Encoder.
func (self *lendingExchangeState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, self.data)
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 (self *lendingExchangeState) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (le *lendingExchangeState) setError(err error) {
if le.dbErr == nil {
le.dbErr = err
}
}
@ -123,63 +123,64 @@ func (self *lendingExchangeState) setError(err error) {
Get Trie
*/
func (self *lendingExchangeState) getLendingItemTrie(db Database) Trie {
if self.lendingItemTrie == nil {
func (le *lendingExchangeState) getLendingItemTrie(db Database) Trie {
if le.lendingItemTrie == nil {
var err error
self.lendingItemTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.LendingItemRoot)
le.lendingItemTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LendingItemRoot)
if err != nil {
self.lendingItemTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
self.setError(fmt.Errorf("can't create Lendings trie: %v", err))
le.lendingItemTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
}
}
return self.lendingItemTrie
return le.lendingItemTrie
}
func (self *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
if self.lendingTradeTrie == nil {
func (le *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
if le.lendingTradeTrie == nil {
var err error
self.lendingTradeTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.LendingTradeRoot)
le.lendingTradeTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LendingTradeRoot)
if err != nil {
self.lendingTradeTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
self.setError(fmt.Errorf("can't create Lendings trie: %v", err))
le.lendingTradeTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
}
}
return self.lendingTradeTrie
}
func (self *lendingExchangeState) getInvestingTrie(db Database) Trie {
if self.investingTrie == nil {
var err error
self.investingTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.InvestingRoot)
if err != nil {
self.investingTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
self.setError(fmt.Errorf("can't create Lendings trie: %v", err))
}
}
return self.investingTrie
return le.lendingTradeTrie
}
func (self *lendingExchangeState) getBorrowingTrie(db Database) Trie {
if self.borrowingTrie == nil {
func (le *lendingExchangeState) getInvestingTrie(db Database) Trie {
if le.investingTrie == nil {
var err error
self.borrowingTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.BorrowingRoot)
le.investingTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.InvestingRoot)
if err != nil {
self.borrowingTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
self.setError(fmt.Errorf("can't create bids trie: %v", err))
le.investingTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
}
}
return self.borrowingTrie
return le.investingTrie
}
func (self *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
if self.liquidationTimeTrie == nil {
func (le *lendingExchangeState) getBorrowingTrie(db Database) Trie {
if le.borrowingTrie == nil {
var err error
self.liquidationTimeTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.LiquidationTimeRoot)
le.borrowingTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.BorrowingRoot)
if err != nil {
self.liquidationTimeTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
self.setError(fmt.Errorf("can't create bids trie: %v", err))
le.borrowingTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
le.setError(fmt.Errorf("can't create bids trie: %v", err))
}
}
return self.liquidationTimeTrie
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
}
/*
@ -187,16 +188,16 @@ func (self *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
Get State
*/
func (self *lendingExchangeState) getBorrowingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
func (le *lendingExchangeState) getBorrowingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
// Prefer 'live' objects.
if obj := self.borrowingStates[rate]; obj != nil {
if obj := le.borrowingStates[rate]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getBorrowingTrie(db).TryGet(rate[:])
enc, err := le.getBorrowingTrie(db).TryGet(rate[:])
if len(enc) == 0 {
self.setError(err)
le.setError(err)
return nil
}
var data itemList
@ -205,21 +206,21 @@ func (self *lendingExchangeState) getBorrowingOrderList(db Database, rate common
return nil
}
// Insert into the live set.
obj := newItemListState(self.lendingBook, rate, data, self.MarkBorrowingDirty)
self.borrowingStates[rate] = obj
obj := newItemListState(le.lendingBook, rate, data, le.MarkBorrowingDirty)
le.borrowingStates[rate] = obj
return obj
}
func (self *lendingExchangeState) getInvestingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
func (le *lendingExchangeState) getInvestingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
// Prefer 'live' objects.
if obj := self.investingStates[rate]; obj != nil {
if obj := le.investingStates[rate]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getInvestingTrie(db).TryGet(rate[:])
enc, err := le.getInvestingTrie(db).TryGet(rate[:])
if len(enc) == 0 {
self.setError(err)
le.setError(err)
return nil
}
var data itemList
@ -228,21 +229,21 @@ func (self *lendingExchangeState) getInvestingOrderList(db Database, rate common
return nil
}
// Insert into the live set.
obj := newItemListState(self.lendingBook, rate, data, self.MarkInvestingDirty)
self.investingStates[rate] = obj
obj := newItemListState(le.lendingBook, rate, data, le.MarkInvestingDirty)
le.investingStates[rate] = obj
return obj
}
func (self *lendingExchangeState) getLiquidationTimeOrderList(db Database, time common.Hash) (stateObject *liquidationTimeState) {
func (le *lendingExchangeState) getLiquidationTimeOrderList(db Database, time common.Hash) (stateObject *liquidationTimeState) {
// Prefer 'live' objects.
if obj := self.liquidationTimeStates[time]; obj != nil {
if obj := le.liquidationTimeStates[time]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getLiquidationTimeTrie(db).TryGet(time[:])
enc, err := le.getLiquidationTimeTrie(db).TryGet(time[:])
if len(enc) == 0 {
self.setError(err)
le.setError(err)
return nil
}
var data itemList
@ -251,21 +252,21 @@ func (self *lendingExchangeState) getLiquidationTimeOrderList(db Database, time
return nil
}
// Insert into the live set.
obj := newLiquidationTimeState(self.lendingBook, time, data, self.MarkLiquidationTimeDirty)
self.liquidationTimeStates[time] = obj
obj := newLiquidationTimeState(le.lendingBook, time, data, le.MarkLiquidationTimeDirty)
le.liquidationTimeStates[time] = obj
return obj
}
func (self *lendingExchangeState) getLendingItem(db Database, lendingId common.Hash) (stateObject *lendingItemState) {
func (le *lendingExchangeState) getLendingItem(db Database, lendingId common.Hash) (stateObject *lendingItemState) {
// Prefer 'live' objects.
if obj := self.lendingItemStates[lendingId]; obj != nil {
if obj := le.lendingItemStates[lendingId]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getLendingItemTrie(db).TryGet(lendingId[:])
enc, err := le.getLendingItemTrie(db).TryGet(lendingId[:])
if len(enc) == 0 {
self.setError(err)
le.setError(err)
return nil
}
var data LendingItem
@ -274,21 +275,21 @@ func (self *lendingExchangeState) getLendingItem(db Database, lendingId common.H
return nil
}
// Insert into the live set.
obj := newLendinItemState(self.lendingBook, lendingId, data, self.MarkLendingItemDirty)
self.lendingItemStates[lendingId] = obj
obj := newLendinItemState(le.lendingBook, lendingId, data, le.MarkLendingItemDirty)
le.lendingItemStates[lendingId] = obj
return obj
}
func (self *lendingExchangeState) getLendingTrade(db Database, tradeId common.Hash) (stateObject *lendingTradeState) {
func (le *lendingExchangeState) getLendingTrade(db Database, tradeId common.Hash) (stateObject *lendingTradeState) {
// Prefer 'live' objects.
if obj := self.lendingTradeStates[tradeId]; obj != nil {
if obj := le.lendingTradeStates[tradeId]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.getLendingTradeTrie(db).TryGet(tradeId[:])
enc, err := le.getLendingTradeTrie(db).TryGet(tradeId[:])
if len(enc) == 0 {
self.setError(err)
le.setError(err)
return nil
}
var data LendingTrade
@ -297,8 +298,8 @@ func (self *lendingExchangeState) getLendingTrade(db Database, tradeId common.Ha
return nil
}
// Insert into the live set.
obj := newLendingTradeState(self.lendingBook, tradeId, data, self.MarkLendingTradeDirty)
self.lendingTradeStates[tradeId] = obj
obj := newLendingTradeState(le.lendingBook, tradeId, data, le.MarkLendingTradeDirty)
le.lendingTradeStates[tradeId] = obj
return obj
}
@ -307,46 +308,47 @@ func (self *lendingExchangeState) getLendingTrade(db Database, tradeId common.Ha
Update Trie
*/
func (self *lendingExchangeState) updateLendingTimeTrie(db Database) Trie {
tr := self.getLendingItemTrie(db)
for lendingId, lendingItem := range self.lendingItemStates {
if _, isDirty := self.lendingItemStatesDirty[lendingId]; isDirty {
delete(self.lendingItemStatesDirty, lendingId)
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() {
self.setError(tr.TryDelete(lendingId[:]))
le.setError(tr.TryDelete(lendingId[:]))
continue
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(lendingItem)
self.setError(tr.TryUpdate(lendingId[:], v))
le.setError(tr.TryUpdate(lendingId[:], v))
}
}
return tr
}
func (self *lendingExchangeState) updateLendingTradeTrie(db Database) Trie {
tr := self.getLendingTradeTrie(db)
for tradeId, lendingTradeItem := range self.lendingTradeStates {
if _, isDirty := self.lendingTradeStatesDirty[tradeId]; isDirty {
delete(self.lendingTradeStatesDirty, tradeId)
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() {
self.setError(tr.TryDelete(tradeId[:]))
le.setError(tr.TryDelete(tradeId[:]))
continue
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(lendingTradeItem)
self.setError(tr.TryUpdate(tradeId[:], v))
le.setError(tr.TryUpdate(tradeId[:], v))
}
}
return tr
}
func (self *lendingExchangeState) updateBorrowingTrie(db Database) Trie {
tr := self.getBorrowingTrie(db)
for rate, orderList := range self.borrowingStates {
if _, isDirty := self.borrowingStatesDirty[rate]; isDirty {
delete(self.borrowingStatesDirty, rate)
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() {
self.setError(tr.TryDelete(rate[:]))
le.setError(tr.TryDelete(rate[:]))
continue
}
err := orderList.updateRoot(db)
@ -355,19 +357,19 @@ func (self *lendingExchangeState) updateBorrowingTrie(db Database) Trie {
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(orderList)
self.setError(tr.TryUpdate(rate[:], v))
le.setError(tr.TryUpdate(rate[:], v))
}
}
return tr
}
func (self *lendingExchangeState) updateInvestingTrie(db Database) Trie {
tr := self.getInvestingTrie(db)
for rate, orderList := range self.investingStates {
if _, isDirty := self.investingStatesDirty[rate]; isDirty {
delete(self.investingStatesDirty, rate)
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() {
self.setError(tr.TryDelete(rate[:]))
le.setError(tr.TryDelete(rate[:]))
continue
}
err := orderList.updateRoot(db)
@ -376,19 +378,19 @@ func (self *lendingExchangeState) updateInvestingTrie(db Database) Trie {
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(orderList)
self.setError(tr.TryUpdate(rate[:], v))
le.setError(tr.TryUpdate(rate[:], v))
}
}
return tr
}
func (self *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
tr := self.getLiquidationTimeTrie(db)
for time, itemList := range self.liquidationTimeStates {
if _, isDirty := self.liquidationTimestatesDirty[time]; isDirty {
delete(self.liquidationTimestatesDirty, time)
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() {
self.setError(tr.TryDelete(time[:]))
le.setError(tr.TryDelete(time[:]))
continue
}
err := itemList.updateRoot(db)
@ -397,7 +399,7 @@ func (self *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
}
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(itemList)
self.setError(tr.TryUpdate(time[:], v))
le.setError(tr.TryUpdate(time[:], v))
}
}
return tr
@ -407,69 +409,69 @@ func (self *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
Update Root
*/
func (self *lendingExchangeState) updateOrderRoot(db Database) {
self.updateLendingTimeTrie(db)
self.data.LendingItemRoot = self.lendingItemTrie.Hash()
func (le *lendingExchangeState) updateOrderRoot(db Database) {
le.updateLendingTimeTrie(db)
le.data.LendingItemRoot = le.lendingItemTrie.Hash()
}
func (self *lendingExchangeState) updateInvestingRoot(db Database) error {
self.updateInvestingTrie(db)
if self.dbErr != nil {
return self.dbErr
func (le *lendingExchangeState) updateInvestingRoot(db Database) error {
le.updateInvestingTrie(db)
if le.dbErr != nil {
return le.dbErr
}
self.data.InvestingRoot = self.investingTrie.Hash()
le.data.InvestingRoot = le.investingTrie.Hash()
return nil
}
func (self *lendingExchangeState) updateBorrowingRoot(db Database) {
self.updateBorrowingTrie(db)
self.data.BorrowingRoot = self.borrowingTrie.Hash()
func (le *lendingExchangeState) updateBorrowingRoot(db Database) {
le.updateBorrowingTrie(db)
le.data.BorrowingRoot = le.borrowingTrie.Hash()
}
func (self *lendingExchangeState) updateLiquidationTimeRoot(db Database) {
self.updateLiquidationTimeTrie(db)
self.data.LiquidationTimeRoot = self.liquidationTimeTrie.Hash()
func (le *lendingExchangeState) updateLiquidationTimeRoot(db Database) {
le.updateLiquidationTimeTrie(db)
le.data.LiquidationTimeRoot = le.liquidationTimeTrie.Hash()
}
func (self *lendingExchangeState) updateLendingTradeRoot(db Database) {
self.updateLendingTradeTrie(db)
self.data.LendingTradeRoot = self.lendingTradeTrie.Hash()
func (le *lendingExchangeState) updateLendingTradeRoot(db Database) {
le.updateLendingTradeTrie(db)
le.data.LendingTradeRoot = le.lendingTradeTrie.Hash()
}
/**
Commit Trie
*/
func (self *lendingExchangeState) CommitLendingItemTrie(db Database) error {
self.updateLendingTimeTrie(db)
if self.dbErr != nil {
return self.dbErr
func (le *lendingExchangeState) CommitLendingItemTrie(db Database) error {
le.updateLendingTimeTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := self.lendingItemTrie.Commit(nil)
root, err := le.lendingItemTrie.Commit(nil)
if err == nil {
self.data.LendingItemRoot = root
le.data.LendingItemRoot = root
}
return err
}
func (self *lendingExchangeState) CommitLendingTradeTrie(db Database) error {
self.updateLendingTradeTrie(db)
if self.dbErr != nil {
return self.dbErr
func (le *lendingExchangeState) CommitLendingTradeTrie(db Database) error {
le.updateLendingTradeTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := self.lendingTradeTrie.Commit(nil)
root, err := le.lendingTradeTrie.Commit(nil)
if err == nil {
self.data.LendingTradeRoot = root
le.data.LendingTradeRoot = root
}
return err
}
func (self *lendingExchangeState) CommitInvestingTrie(db Database) error {
self.updateInvestingTrie(db)
if self.dbErr != nil {
return self.dbErr
func (le *lendingExchangeState) CommitInvestingTrie(db Database) error {
le.updateInvestingTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := self.investingTrie.Commit(func(leaf []byte, parent common.Hash) error {
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
@ -480,17 +482,17 @@ func (self *lendingExchangeState) CommitInvestingTrie(db Database) error {
return nil
})
if err == nil {
self.data.InvestingRoot = root
le.data.InvestingRoot = root
}
return err
}
func (self *lendingExchangeState) CommitBorrowingTrie(db Database) error {
self.updateBorrowingTrie(db)
if self.dbErr != nil {
return self.dbErr
func (le *lendingExchangeState) CommitBorrowingTrie(db Database) error {
le.updateBorrowingTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := self.borrowingTrie.Commit(func(leaf []byte, parent common.Hash) error {
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
@ -501,17 +503,17 @@ func (self *lendingExchangeState) CommitBorrowingTrie(db Database) error {
return nil
})
if err == nil {
self.data.BorrowingRoot = root
le.data.BorrowingRoot = root
}
return err
}
func (self *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
self.updateLiquidationTimeTrie(db)
if self.dbErr != nil {
return self.dbErr
func (le *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
le.updateLiquidationTimeTrie(db)
if le.dbErr != nil {
return le.dbErr
}
root, err := self.liquidationTimeTrie.Commit(func(leaf []byte, parent common.Hash) error {
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
@ -522,7 +524,7 @@ func (self *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
return nil
})
if err == nil {
self.data.LiquidationTimeRoot = root
le.data.LiquidationTimeRoot = root
}
return err
}
@ -532,11 +534,11 @@ func (self *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
Get Trie Data
*/
func (self *lendingExchangeState) getBestInvestingInterest(db Database) common.Hash {
trie := self.getInvestingTrie(db)
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", self.lendingBook.Hex())
log.Error("Failed find best investing rate", "orderbook", le.lendingBook.Hex())
return EmptyHash
}
if len(encKey) == 0 || len(encValue) == 0 {
@ -545,23 +547,23 @@ func (self *lendingExchangeState) getBestInvestingInterest(db Database) common.H
}
// Insert into the live set.
interest := common.BytesToHash(encKey)
if _, exist := self.investingStates[interest]; !exist {
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(self.lendingBook, interest, data, self.MarkInvestingDirty)
self.investingStates[interest] = obj
obj := newItemListState(le.lendingBook, interest, data, le.MarkInvestingDirty)
le.investingStates[interest] = obj
}
return interest
}
func (self *lendingExchangeState) getBestBorrowingInterest(db Database) common.Hash {
trie := self.getBorrowingTrie(db)
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", self.lendingBook.Hex())
log.Error("Failed find best key bid trie ", "orderbook", le.lendingBook.Hex())
return EmptyHash
}
if len(encKey) == 0 || len(encValue) == 0 {
@ -570,23 +572,23 @@ func (self *lendingExchangeState) getBestBorrowingInterest(db Database) common.H
}
// Insert into the live set.
interest := common.BytesToHash(encKey)
if _, exist := self.borrowingStates[interest]; !exist {
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(self.lendingBook, interest, data, self.MarkBorrowingDirty)
self.borrowingStates[interest] = obj
obj := newItemListState(le.lendingBook, interest, data, le.MarkBorrowingDirty)
le.borrowingStates[interest] = obj
}
return interest
}
func (self *lendingExchangeState) getLowestLiquidationTime(db Database) (common.Hash, *liquidationTimeState) {
trie := self.getLiquidationTimeTrie(db)
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", self.lendingBook.Hex())
log.Error("Failed find best liquidation time trie ", "orderBook", le.lendingBook.Hex())
return EmptyHash, nil
}
if len(encKey) == 0 || len(encValue) == 0 {
@ -594,15 +596,15 @@ func (self *lendingExchangeState) getLowestLiquidationTime(db Database) (common.
return EmptyHash, nil
}
price := common.BytesToHash(encKey)
obj, exist := self.liquidationTimeStates[price]
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(self.lendingBook, price, data, self.MarkLiquidationTimeDirty)
self.liquidationTimeStates[price] = obj
obj = newLiquidationTimeState(le.lendingBook, price, data, le.MarkLiquidationTimeDirty)
le.liquidationTimeStates[price] = obj
}
if obj.empty() {
return EmptyHash, nil
@ -610,193 +612,194 @@ func (self *lendingExchangeState) getLowestLiquidationTime(db Database) (common.
return price, obj
}
func (self *lendingExchangeState) deepCopy(db *LendingStateDB, onDirty func(hash common.Hash)) *lendingExchangeState {
stateExchanges := newStateExchanges(db, self.lendingBook, self.data, onDirty)
if self.investingTrie != nil {
stateExchanges.investingTrie = db.db.CopyTrie(self.investingTrie)
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 self.borrowingTrie != nil {
stateExchanges.borrowingTrie = db.db.CopyTrie(self.borrowingTrie)
if le.borrowingTrie != nil {
stateExchanges.borrowingTrie = db.db.CopyTrie(le.borrowingTrie)
}
if self.lendingItemTrie != nil {
stateExchanges.lendingItemTrie = db.db.CopyTrie(self.lendingItemTrie)
if le.lendingItemTrie != nil {
stateExchanges.lendingItemTrie = db.db.CopyTrie(le.lendingItemTrie)
}
for key, value := range self.borrowingStates {
stateExchanges.borrowingStates[key] = value.deepCopy(db, self.MarkBorrowingDirty)
for key, value := range le.borrowingStates {
stateExchanges.borrowingStates[key] = value.deepCopy(db, le.MarkBorrowingDirty)
}
for key := range self.borrowingStatesDirty {
for key := range le.borrowingStatesDirty {
stateExchanges.borrowingStatesDirty[key] = struct{}{}
}
for key, value := range self.investingStates {
stateExchanges.investingStates[key] = value.deepCopy(db, self.MarkInvestingDirty)
for key, value := range le.investingStates {
stateExchanges.investingStates[key] = value.deepCopy(db, le.MarkInvestingDirty)
}
for key := range self.investingStatesDirty {
for key := range le.investingStatesDirty {
stateExchanges.investingStatesDirty[key] = struct{}{}
}
for key, value := range self.lendingItemStates {
stateExchanges.lendingItemStates[key] = value.deepCopy(self.MarkLendingItemDirty)
for key, value := range le.lendingItemStates {
stateExchanges.lendingItemStates[key] = value.deepCopy(le.MarkLendingItemDirty)
}
for orderId := range self.lendingItemStatesDirty {
for orderId := range le.lendingItemStatesDirty {
stateExchanges.lendingItemStatesDirty[orderId] = struct{}{}
}
for key, value := range self.lendingTradeStates {
stateExchanges.lendingTradeStates[key] = value.deepCopy(self.MarkLendingTradeDirty)
for key, value := range le.lendingTradeStates {
stateExchanges.lendingTradeStates[key] = value.deepCopy(le.MarkLendingTradeDirty)
}
for orderId := range self.lendingTradeStatesDirty {
for orderId := range le.lendingTradeStatesDirty {
stateExchanges.lendingTradeStatesDirty[orderId] = struct{}{}
}
for time, orderList := range self.liquidationTimeStates {
stateExchanges.liquidationTimeStates[time] = orderList.deepCopy(db, self.MarkLiquidationTimeDirty)
for time, orderList := range le.liquidationTimeStates {
stateExchanges.liquidationTimeStates[time] = orderList.deepCopy(db, le.MarkLiquidationTimeDirty)
}
for time := range self.liquidationTimestatesDirty {
for time := range le.liquidationTimestatesDirty {
stateExchanges.liquidationTimestatesDirty[time] = struct{}{}
}
return stateExchanges
}
// Returns the address of the contract/tradeId
func (self *lendingExchangeState) Hash() common.Hash {
return self.lendingBook
func (le *lendingExchangeState) Hash() common.Hash {
return le.lendingBook
}
func (self *lendingExchangeState) setNonce(nonce uint64) {
self.data.Nonce = nonce
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (le *lendingExchangeState) setNonce(nonce uint64) {
le.data.Nonce = nonce
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (self *lendingExchangeState) Nonce() uint64 {
return self.data.Nonce
func (le *lendingExchangeState) Nonce() uint64 {
return le.data.Nonce
}
func (self *lendingExchangeState) setTradeNonce(nonce uint64) {
self.data.TradeNonce = nonce
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (le *lendingExchangeState) setTradeNonce(nonce uint64) {
le.data.TradeNonce = nonce
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (self *lendingExchangeState) TradeNonce() uint64 {
return self.data.TradeNonce
func (le *lendingExchangeState) TradeNonce() uint64 {
return le.data.TradeNonce
}
func (self *lendingExchangeState) removeInvestingOrderList(db Database, stateOrderList *itemListState) {
self.setError(self.investingTrie.TryDelete(stateOrderList.key[:]))
func (le *lendingExchangeState) removeInvestingOrderList(db Database, stateOrderList *itemListState) {
le.setError(le.investingTrie.TryDelete(stateOrderList.key[:]))
}
func (self *lendingExchangeState) removeBorrowingOrderList(db Database, stateOrderList *itemListState) {
self.setError(self.borrowingTrie.TryDelete(stateOrderList.key[:]))
func (le *lendingExchangeState) removeBorrowingOrderList(db Database, stateOrderList *itemListState) {
le.setError(le.borrowingTrie.TryDelete(stateOrderList.key[:]))
}
func (self *lendingExchangeState) createInvestingOrderList(db Database, price common.Hash) (newobj *itemListState) {
newobj = newItemListState(self.lendingBook, price, itemList{Volume: Zero}, self.MarkInvestingDirty)
self.investingStates[price] = newobj
self.investingStatesDirty[price] = struct{}{}
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))
}
self.setError(self.getInvestingTrie(db).TryUpdate(price[:], data))
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
le.setError(le.getInvestingTrie(db).TryUpdate(price[:], data))
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
return newobj
}
func (self *lendingExchangeState) MarkBorrowingDirty(price common.Hash) {
self.borrowingStatesDirty[price] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
func (le *lendingExchangeState) MarkBorrowingDirty(price common.Hash) {
le.borrowingStatesDirty[price] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
}
func (self *lendingExchangeState) MarkInvestingDirty(price common.Hash) {
self.investingStatesDirty[price] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.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 (self *lendingExchangeState) MarkLendingItemDirty(lending common.Hash) {
self.lendingItemStatesDirty[lending] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.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 (self *lendingExchangeState) MarkLendingTradeDirty(tradeId common.Hash) {
self.lendingTradeStatesDirty[tradeId] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.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 (self *lendingExchangeState) MarkLiquidationTimeDirty(orderId common.Hash) {
self.liquidationTimestatesDirty[orderId] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.Hash())
self.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 (self *lendingExchangeState) createBorrowingOrderList(db Database, price common.Hash) (newobj *itemListState) {
newobj = newItemListState(self.lendingBook, price, itemList{Volume: Zero}, self.MarkBorrowingDirty)
self.borrowingStates[price] = newobj
self.borrowingStatesDirty[price] = struct{}{}
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))
}
self.setError(self.getBorrowingTrie(db).TryUpdate(price[:], data))
if self.onDirty != nil {
self.onDirty(self.Hash())
self.onDirty = nil
le.setError(le.getBorrowingTrie(db).TryUpdate(price[:], data))
if le.onDirty != nil {
le.onDirty(le.Hash())
le.onDirty = nil
}
return newobj
}
func (self *lendingExchangeState) createLendingItem(db Database, orderId common.Hash, order LendingItem) (newobj *lendingItemState) {
newobj = newLendinItemState(self.lendingBook, orderId, order, self.MarkLendingItemDirty)
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))
self.lendingItemStates[orderIdHash] = newobj
self.lendingItemStatesDirty[orderIdHash] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.lendingBook)
self.onDirty = nil
le.lendingItemStates[orderIdHash] = newobj
le.lendingItemStatesDirty[orderIdHash] = struct{}{}
if le.onDirty != nil {
le.onDirty(le.lendingBook)
le.onDirty = nil
}
return newobj
}
func (self *lendingExchangeState) createLiquidationTime(db Database, time common.Hash) (newobj *liquidationTimeState) {
newobj = newLiquidationTimeState(time, self.lendingBook, itemList{Volume: Zero}, self.MarkLiquidationTimeDirty)
self.liquidationTimeStates[time] = newobj
self.liquidationTimestatesDirty[time] = struct{}{}
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))
}
self.setError(self.getLiquidationTimeTrie(db).TryUpdate(time[:], data))
if self.onDirty != nil {
self.onDirty(self.lendingBook)
self.onDirty = nil
le.setError(le.getLiquidationTimeTrie(db).TryUpdate(time[:], data))
if le.onDirty != nil {
le.onDirty(le.lendingBook)
le.onDirty = nil
}
return newobj
}
func (self *lendingExchangeState) insertLendingTrade(tradeId common.Hash, order LendingTrade) (newobj *lendingTradeState) {
newobj = newLendingTradeState(self.lendingBook, tradeId, order, self.MarkLendingTradeDirty)
self.lendingTradeStates[tradeId] = newobj
self.lendingTradeStatesDirty[tradeId] = struct{}{}
if self.onDirty != nil {
self.onDirty(self.lendingBook)
self.onDirty = nil
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
}

View file

@ -31,8 +31,8 @@ type lendingItemState struct {
onDirty func(orderId common.Hash) // Callback method to mark a state object newly dirty
}
func (s *lendingItemState) empty() bool {
return s.data.Quantity == nil || s.data.Quantity.Cmp(Zero) == 0
func (li *lendingItemState) empty() bool {
return li.data.Quantity == nil || li.data.Quantity.Cmp(Zero) == 0
}
func newLendinItemState(orderBook common.Hash, orderId common.Hash, data LendingItem, onDirty func(orderId common.Hash)) *lendingItemState {
@ -45,23 +45,23 @@ func newLendinItemState(orderBook common.Hash, orderId common.Hash, data Lending
}
// EncodeRLP implements rlp.Encoder.
func (c *lendingItemState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, c.data)
func (li *lendingItemState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, li.data)
}
func (self *lendingItemState) deepCopy(onDirty func(orderId common.Hash)) *lendingItemState {
stateOrderList := newLendinItemState(self.orderBook, self.orderId, self.data, onDirty)
func (li *lendingItemState) deepCopy(onDirty func(orderId common.Hash)) *lendingItemState {
stateOrderList := newLendinItemState(li.orderBook, li.orderId, li.data, onDirty)
return stateOrderList
}
func (self *lendingItemState) setVolume(volume *big.Int) {
self.data.Quantity = volume
if self.onDirty != nil {
self.onDirty(self.orderId)
self.onDirty = nil
func (li *lendingItemState) setVolume(volume *big.Int) {
li.data.Quantity = volume
if li.onDirty != nil {
li.onDirty(li.orderId)
li.onDirty = nil
}
}
func (self *lendingItemState) Quantity() *big.Int {
return self.data.Quantity
func (li *lendingItemState) Quantity() *big.Int {
return li.data.Quantity
}

View file

@ -17,10 +17,11 @@
package lendingstate
import (
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/rlp"
"io"
"math/big"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/rlp"
)
type lendingTradeState struct {
@ -30,8 +31,8 @@ type lendingTradeState struct {
onDirty func(orderId common.Hash) // Callback method to mark a state object newly dirty
}
func (s *lendingTradeState) empty() bool {
return s.data.Amount.Sign() == 0
func (lt *lendingTradeState) empty() bool {
return lt.data.Amount.Sign() == 0
}
func newLendingTradeState(orderBook common.Hash, tradeId common.Hash, data LendingTrade, onDirty func(orderId common.Hash)) *lendingTradeState {
@ -44,35 +45,35 @@ func newLendingTradeState(orderBook common.Hash, tradeId common.Hash, data Lendi
}
// EncodeRLP implements rlp.Encoder.
func (c *lendingTradeState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, c.data)
func (lt *lendingTradeState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, lt.data)
}
func (self *lendingTradeState) deepCopy(onDirty func(orderId common.Hash)) *lendingTradeState {
stateOrderList := newLendingTradeState(self.orderBook, self.tradeId, self.data, onDirty)
func (lt *lendingTradeState) deepCopy(onDirty func(orderId common.Hash)) *lendingTradeState {
stateOrderList := newLendingTradeState(lt.orderBook, lt.tradeId, lt.data, onDirty)
return stateOrderList
}
func (self *lendingTradeState) SetCollateralLockedAmount(amount *big.Int) {
self.data.CollateralLockedAmount = amount
if self.onDirty != nil {
self.onDirty(self.tradeId)
self.onDirty = nil
func (lt *lendingTradeState) SetCollateralLockedAmount(amount *big.Int) {
lt.data.CollateralLockedAmount = amount
if lt.onDirty != nil {
lt.onDirty(lt.tradeId)
lt.onDirty = nil
}
}
func (self *lendingTradeState) SetLiquidationPrice(price *big.Int) {
self.data.LiquidationPrice = price
if self.onDirty != nil {
self.onDirty(self.tradeId)
self.onDirty = nil
func (lt *lendingTradeState) SetLiquidationPrice(price *big.Int) {
lt.data.LiquidationPrice = price
if lt.onDirty != nil {
lt.onDirty(lt.tradeId)
lt.onDirty = nil
}
}
func (self *lendingTradeState) SetAmount(amount *big.Int) {
self.data.Amount = amount
if self.onDirty != nil {
self.onDirty(self.tradeId)
self.onDirty = nil
func (lt *lendingTradeState) SetAmount(amount *big.Int) {
lt.data.Amount = amount
if lt.onDirty != nil {
lt.onDirty(lt.tradeId)
lt.onDirty = nil
}
}

View file

@ -19,11 +19,12 @@ package lendingstate
import (
"bytes"
"fmt"
"io"
"math/big"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/trie"
"io"
"math/big"
)
type liquidationTimeState struct {
@ -47,8 +48,8 @@ type liquidationTimeState struct {
onDirty func(time common.Hash) // Callback method to mark a state object newly dirty
}
func (s *liquidationTimeState) empty() bool {
return s.data.Volume == nil || s.data.Volume.Sign() == 0
func (lt *liquidationTimeState) empty() bool {
return lt.data.Volume == nil || lt.data.Volume.Sign() == 0
}
func newLiquidationTimeState(time common.Hash, lendingBook common.Hash, data itemList, onDirty func(time common.Hash)) *liquidationTimeState {
@ -62,59 +63,59 @@ func newLiquidationTimeState(time common.Hash, lendingBook common.Hash, data ite
}
}
func (self *liquidationTimeState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, self.data)
func (lt *liquidationTimeState) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, lt.data)
}
func (self *liquidationTimeState) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (lt *liquidationTimeState) setError(err error) {
if lt.dbErr == nil {
lt.dbErr = err
}
}
func (self *liquidationTimeState) getTrie(db Database) Trie {
if self.trie == nil {
func (lt *liquidationTimeState) getTrie(db Database) Trie {
if lt.trie == nil {
var err error
self.trie, err = db.OpenStorageTrie(self.lendingBook, self.data.Root)
lt.trie, err = db.OpenStorageTrie(lt.lendingBook, lt.data.Root)
if err != nil {
self.trie, _ = db.OpenStorageTrie(self.time, EmptyHash)
self.setError(fmt.Errorf("can't create storage trie: %v", err))
lt.trie, _ = db.OpenStorageTrie(lt.time, EmptyHash)
lt.setError(fmt.Errorf("can't create storage trie: %v", err))
}
}
return self.trie
return lt.trie
}
func (self *liquidationTimeState) Exist(db Database, tradeId common.Hash) bool {
amount, exists := self.cachedStorage[tradeId]
func (lt *liquidationTimeState) Exist(db Database, tradeId common.Hash) bool {
amount, exists := lt.cachedStorage[tradeId]
if exists {
return true
}
// Load from DB in case it is missing.
enc, err := self.getTrie(db).TryGet(tradeId[:])
enc, err := lt.getTrie(db).TryGet(tradeId[:])
if err != nil {
self.setError(err)
lt.setError(err)
return false
}
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
self.setError(err)
lt.setError(err)
}
amount.SetBytes(content)
}
if (amount != common.Hash{}) {
self.cachedStorage[tradeId] = amount
lt.cachedStorage[tradeId] = amount
}
return true
}
func (self *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
func (lt *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
tradeIds := []common.Hash{}
lendingBookTrie := self.getTrie(db)
lendingBookTrie := lt.getTrie(db)
if lendingBookTrie == nil {
return tradeIds
}
for id, value := range self.cachedStorage {
for id, value := range lt.cachedStorage {
if !common.EmptyHash(value) {
tradeIds = append(tradeIds, id)
}
@ -122,7 +123,7 @@ func (self *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
orderListIt := trie.NewIterator(lendingBookTrie.NodeIterator(nil))
for orderListIt.Next() {
id := common.BytesToHash(orderListIt.Key)
if _, exist := self.cachedStorage[id]; exist {
if _, exist := lt.cachedStorage[id]; exist {
continue
}
tradeIds = append(tradeIds, id)
@ -130,83 +131,83 @@ func (self *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
return tradeIds
}
func (self *liquidationTimeState) insertTradeId(db Database, tradeId common.Hash) {
self.setTradeId(tradeId, tradeId)
self.setError(self.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
func (lt *liquidationTimeState) insertTradeId(db Database, tradeId common.Hash) {
lt.setTradeId(tradeId, tradeId)
lt.setError(lt.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
}
func (self *liquidationTimeState) removeTradeId(db Database, tradeId common.Hash) {
tr := self.getTrie(db)
self.setError(tr.TryDelete(tradeId[:]))
self.setTradeId(tradeId, EmptyHash)
func (lt *liquidationTimeState) removeTradeId(db Database, tradeId common.Hash) {
tr := lt.getTrie(db)
lt.setError(tr.TryDelete(tradeId[:]))
lt.setTradeId(tradeId, EmptyHash)
}
func (self *liquidationTimeState) setTradeId(tradeId common.Hash, value common.Hash) {
self.cachedStorage[tradeId] = value
self.dirtyStorage[tradeId] = value
func (lt *liquidationTimeState) setTradeId(tradeId common.Hash, value common.Hash) {
lt.cachedStorage[tradeId] = value
lt.dirtyStorage[tradeId] = value
if self.onDirty != nil {
self.onDirty(self.lendingBook)
self.onDirty = nil
if lt.onDirty != nil {
lt.onDirty(lt.lendingBook)
lt.onDirty = nil
}
}
func (self *liquidationTimeState) updateTrie(db Database) Trie {
tr := self.getTrie(db)
for key, value := range self.dirtyStorage {
delete(self.dirtyStorage, key)
func (lt *liquidationTimeState) updateTrie(db Database) Trie {
tr := lt.getTrie(db)
for key, value := range lt.dirtyStorage {
delete(lt.dirtyStorage, key)
if value == EmptyHash {
self.setError(tr.TryDelete(key[:]))
lt.setError(tr.TryDelete(key[:]))
continue
}
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
self.setError(tr.TryUpdate(key[:], v))
lt.setError(tr.TryUpdate(key[:], v))
}
return tr
}
func (self *liquidationTimeState) updateRoot(db Database) error {
self.updateTrie(db)
if self.dbErr != nil {
return self.dbErr
func (lt *liquidationTimeState) updateRoot(db Database) error {
lt.updateTrie(db)
if lt.dbErr != nil {
return lt.dbErr
}
root, err := self.trie.Commit(nil)
root, err := lt.trie.Commit(nil)
if err == nil {
self.data.Root = root
lt.data.Root = root
}
return err
}
func (self *liquidationTimeState) deepCopy(db *LendingStateDB, onDirty func(time common.Hash)) *liquidationTimeState {
stateLendingBook := newLiquidationTimeState(self.lendingBook, self.time, self.data, onDirty)
if self.trie != nil {
stateLendingBook.trie = db.db.CopyTrie(self.trie)
func (lt *liquidationTimeState) deepCopy(db *LendingStateDB, onDirty func(time common.Hash)) *liquidationTimeState {
stateLendingBook := newLiquidationTimeState(lt.lendingBook, lt.time, lt.data, onDirty)
if lt.trie != nil {
stateLendingBook.trie = db.db.CopyTrie(lt.trie)
}
for key, value := range self.dirtyStorage {
for key, value := range lt.dirtyStorage {
stateLendingBook.dirtyStorage[key] = value
}
for key, value := range self.cachedStorage {
for key, value := range lt.cachedStorage {
stateLendingBook.cachedStorage[key] = value
}
return stateLendingBook
}
func (c *liquidationTimeState) AddVolume(amount *big.Int) {
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
func (lt *liquidationTimeState) AddVolume(amount *big.Int) {
lt.setVolume(new(big.Int).Add(lt.data.Volume, amount))
}
func (c *liquidationTimeState) subVolume(amount *big.Int) {
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
func (lt *liquidationTimeState) subVolume(amount *big.Int) {
lt.setVolume(new(big.Int).Sub(lt.data.Volume, amount))
}
func (self *liquidationTimeState) setVolume(volume *big.Int) {
self.data.Volume = volume
if self.onDirty != nil {
self.onDirty(self.lendingBook)
self.onDirty = nil
func (lt *liquidationTimeState) setVolume(volume *big.Int) {
lt.data.Volume = volume
if lt.onDirty != nil {
lt.onDirty(lt.lendingBook)
lt.onDirty = nil
}
}
func (self *liquidationTimeState) Volume() *big.Int {
return self.data.Volume
func (lt *liquidationTimeState) Volume() *big.Int {
return lt.data.Volume
}

View file

@ -73,39 +73,39 @@ func New(root common.Hash, db Database) (*LendingStateDB, error) {
}
// setError remembers the first non-nil error it is called with.
func (self *LendingStateDB) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (ls *LendingStateDB) setError(err error) {
if ls.dbErr == nil {
ls.dbErr = err
}
}
func (self *LendingStateDB) Error() error {
return self.dbErr
func (ls *LendingStateDB) Error() error {
return ls.dbErr
}
// Exist reports whether the given tradeId address exists in the state.
// Notably this also returns true for suicided lenddinges.
func (self *LendingStateDB) Exist(addr common.Hash) bool {
return self.getLendingExchange(addr) != nil
func (ls *LendingStateDB) Exist(addr common.Hash) bool {
return ls.getLendingExchange(addr) != nil
}
// Empty returns whether the state object is either non-existent
// or empty according to the EIP161 specification (balance = nonce = code = 0)
func (self *LendingStateDB) Empty(addr common.Hash) bool {
so := self.getLendingExchange(addr)
func (ls *LendingStateDB) Empty(addr common.Hash) bool {
so := ls.getLendingExchange(addr)
return so == nil || so.empty()
}
func (self *LendingStateDB) GetNonce(addr common.Hash) uint64 {
stateObject := self.getLendingExchange(addr)
func (ls *LendingStateDB) GetNonce(addr common.Hash) uint64 {
stateObject := ls.getLendingExchange(addr)
if stateObject != nil {
return stateObject.Nonce()
}
return 0
}
func (self *LendingStateDB) GetTradeNonce(addr common.Hash) uint64 {
stateObject := self.getLendingExchange(addr)
func (ls *LendingStateDB) GetTradeNonce(addr common.Hash) uint64 {
stateObject := ls.getLendingExchange(addr)
if stateObject != nil {
return stateObject.TradeNonce()
}
@ -113,14 +113,14 @@ func (self *LendingStateDB) GetTradeNonce(addr common.Hash) uint64 {
}
// Database retrieves the low level database supporting the lower level trie ops.
func (self *LendingStateDB) Database() Database {
return self.db
func (ls *LendingStateDB) Database() Database {
return ls.db
}
func (self *LendingStateDB) SetNonce(addr common.Hash, nonce uint64) {
stateObject := self.GetOrNewLendingExchangeObject(addr)
func (ls *LendingStateDB) SetNonce(addr common.Hash, nonce uint64) {
stateObject := ls.GetOrNewLendingExchangeObject(addr)
if stateObject != nil {
self.journal = append(self.journal, nonceChange{
ls.journal = append(ls.journal, nonceChange{
hash: addr,
prev: stateObject.Nonce(),
})
@ -128,10 +128,10 @@ func (self *LendingStateDB) SetNonce(addr common.Hash, nonce uint64) {
}
}
func (self *LendingStateDB) SetTradeNonce(addr common.Hash, nonce uint64) {
stateObject := self.GetOrNewLendingExchangeObject(addr)
func (ls *LendingStateDB) SetTradeNonce(addr common.Hash, nonce uint64) {
stateObject := ls.GetOrNewLendingExchangeObject(addr)
if stateObject != nil {
self.journal = append(self.journal, tradeNonceChange{
ls.journal = append(ls.journal, tradeNonceChange{
hash: addr,
prev: stateObject.TradeNonce(),
})
@ -139,45 +139,45 @@ func (self *LendingStateDB) SetTradeNonce(addr common.Hash, nonce uint64) {
}
}
func (self *LendingStateDB) InsertLendingItem(orderBook common.Hash, orderId common.Hash, order LendingItem) {
func (ls *LendingStateDB) InsertLendingItem(orderBook common.Hash, orderId common.Hash, order LendingItem) {
interestHash := common.BigToHash(order.Interest)
stateExchange := self.getLendingExchange(orderBook)
stateExchange := ls.getLendingExchange(orderBook)
if stateExchange == nil {
stateExchange = self.createLendingExchangeObject(orderBook)
stateExchange = ls.createLendingExchangeObject(orderBook)
}
var stateOrderList *itemListState
switch order.Side {
case Investing:
stateOrderList = stateExchange.getInvestingOrderList(self.db, interestHash)
stateOrderList = stateExchange.getInvestingOrderList(ls.db, interestHash)
if stateOrderList == nil {
stateOrderList = stateExchange.createInvestingOrderList(self.db, interestHash)
stateOrderList = stateExchange.createInvestingOrderList(ls.db, interestHash)
}
case Borrowing:
stateOrderList = stateExchange.getBorrowingOrderList(self.db, interestHash)
stateOrderList = stateExchange.getBorrowingOrderList(ls.db, interestHash)
if stateOrderList == nil {
stateOrderList = stateExchange.createBorrowingOrderList(self.db, interestHash)
stateOrderList = stateExchange.createBorrowingOrderList(ls.db, interestHash)
}
default:
return
}
self.journal = append(self.journal, insertOrder{
ls.journal = append(ls.journal, insertOrder{
orderBook: orderBook,
orderId: orderId,
order: &order,
})
stateExchange.createLendingItem(self.db, orderId, order)
stateOrderList.insertLendingItem(self.db, orderId, common.BigToHash(order.Quantity))
stateExchange.createLendingItem(ls.db, orderId, order)
stateOrderList.insertLendingItem(ls.db, orderId, common.BigToHash(order.Quantity))
stateOrderList.AddVolume(order.Quantity)
}
func (self *LendingStateDB) InsertTradingItem(orderBook common.Hash, tradeId uint64, order LendingTrade) {
func (ls *LendingStateDB) InsertTradingItem(orderBook common.Hash, tradeId uint64, order LendingTrade) {
tradeIdHash := common.Uint64ToHash(tradeId)
stateExchange := self.getLendingExchange(orderBook)
stateExchange := ls.getLendingExchange(orderBook)
if stateExchange == nil {
stateExchange = self.createLendingExchangeObject(orderBook)
stateExchange = ls.createLendingExchangeObject(orderBook)
}
prvTrade := self.GetLendingTrade(orderBook, tradeIdHash)
self.journal = append(self.journal, insertTrading{
prvTrade := ls.GetLendingTrade(orderBook, tradeIdHash)
ls.journal = append(ls.journal, insertTrading{
orderBook: orderBook,
tradeId: tradeId,
prvTrade: &prvTrade,
@ -185,88 +185,90 @@ func (self *LendingStateDB) InsertTradingItem(orderBook common.Hash, tradeId uin
stateExchange.insertLendingTrade(tradeIdHash, order)
}
func (self *LendingStateDB) UpdateLiquidationPrice(orderBook common.Hash, tradeId uint64, price *big.Int) {
func (ls *LendingStateDB) UpdateLiquidationPrice(orderBook common.Hash, tradeId uint64, price *big.Int) {
tradeIdHash := common.Uint64ToHash(tradeId)
stateExchange := self.getLendingExchange(orderBook)
stateExchange := ls.getLendingExchange(orderBook)
if stateExchange == nil {
stateExchange = self.createLendingExchangeObject(orderBook)
stateExchange = ls.createLendingExchangeObject(orderBook)
}
stateLendingTrade := stateExchange.getLendingTrade(self.db, tradeIdHash)
self.journal = append(self.journal, liquidationPriceChange{
stateLendingTrade := stateExchange.getLendingTrade(ls.db, tradeIdHash)
ls.journal = append(ls.journal, liquidationPriceChange{
orderBook: orderBook,
tradeId: tradeIdHash,
prev: stateLendingTrade.data.LiquidationPrice,
})
stateLendingTrade.SetLiquidationPrice(price)
}
func (self *LendingStateDB) UpdateCollateralLockedAmount(orderBook common.Hash, tradeId uint64, amount *big.Int) {
func (ls *LendingStateDB) UpdateCollateralLockedAmount(orderBook common.Hash, tradeId uint64, amount *big.Int) {
tradeIdHash := common.Uint64ToHash(tradeId)
stateExchange := self.getLendingExchange(orderBook)
stateExchange := ls.getLendingExchange(orderBook)
if stateExchange == nil {
stateExchange = self.createLendingExchangeObject(orderBook)
stateExchange = ls.createLendingExchangeObject(orderBook)
}
stateLendingTrade := stateExchange.getLendingTrade(self.db, tradeIdHash)
self.journal = append(self.journal, collateralLockedAmount{
stateLendingTrade := stateExchange.getLendingTrade(ls.db, tradeIdHash)
ls.journal = append(ls.journal, collateralLockedAmount{
orderBook: orderBook,
tradeId: tradeIdHash,
prev: stateLendingTrade.data.CollateralLockedAmount,
})
stateLendingTrade.SetCollateralLockedAmount(amount)
}
func (self *LendingStateDB) GetLendingOrder(orderBook common.Hash, orderId common.Hash) LendingItem {
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
func (ls *LendingStateDB) GetLendingOrder(orderBook common.Hash, orderId common.Hash) LendingItem {
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
if stateObject == nil {
return EmptyLendingOrder
}
stateOrderItem := stateObject.getLendingItem(self.db, orderId)
stateOrderItem := stateObject.getLendingItem(ls.db, orderId)
if stateOrderItem == nil {
return EmptyLendingOrder
}
return stateOrderItem.data
}
func (self *LendingStateDB) GetLendingTrade(orderBook common.Hash, tradeId common.Hash) LendingTrade {
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
func (ls *LendingStateDB) GetLendingTrade(orderBook common.Hash, tradeId common.Hash) LendingTrade {
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
if stateObject == nil {
return EmptyLendingTrade
}
stateOrderItem := stateObject.getLendingTrade(self.db, tradeId)
stateOrderItem := stateObject.getLendingTrade(ls.db, tradeId)
if stateOrderItem == nil || stateOrderItem.empty() {
return EmptyLendingTrade
}
return stateOrderItem.data
}
func (self *LendingStateDB) SubAmountLendingItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
func (ls *LendingStateDB) SubAmountLendingItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
priceHash := common.BigToHash(price)
lendingExchange := self.GetOrNewLendingExchangeObject(orderBook)
lendingExchange := ls.GetOrNewLendingExchangeObject(orderBook)
if lendingExchange == nil {
return fmt.Errorf("not found order book: %s", orderBook.Hex())
}
var orderList *itemListState
switch side {
case Investing:
orderList = lendingExchange.getInvestingOrderList(self.db, priceHash)
orderList = lendingExchange.getInvestingOrderList(ls.db, priceHash)
case Borrowing:
orderList = lendingExchange.getBorrowingOrderList(self.db, priceHash)
orderList = lendingExchange.getBorrowingOrderList(ls.db, priceHash)
default:
return fmt.Errorf("not found order type: %s", side)
}
if orderList == nil || orderList.empty() {
return fmt.Errorf("empty orderList: order book : %s , order id : %s , key : %s", orderBook, orderId.Hex(), priceHash.Hex())
}
lendingItem := lendingExchange.getLendingItem(self.db, orderId)
lendingItem := lendingExchange.getLendingItem(ls.db, orderId)
if lendingItem == nil || lendingItem.empty() {
return fmt.Errorf("empty order item: order book : %s , order id : %s , key : %s", orderBook, orderId.Hex(), priceHash.Hex())
}
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(self.db, orderId).Bytes()[:])
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(ls.db, orderId).Bytes()[:])
if currentAmount.Cmp(amount) < 0 {
return fmt.Errorf("not enough order amount %s: have : %d , want : %d", orderId.Hex(), currentAmount, amount)
}
self.journal = append(self.journal, subAmountOrder{
ls.journal = append(ls.journal, subAmountOrder{
orderBook: orderBook,
orderId: orderId,
order: self.GetLendingOrder(orderBook, orderId),
order: ls.GetLendingOrder(orderBook, orderId),
amount: amount,
})
newAmount := new(big.Int).Sub(currentAmount, amount)
@ -274,36 +276,36 @@ func (self *LendingStateDB) SubAmountLendingItem(orderBook common.Hash, orderId
log.Debug("SubAmountOrderItem", "tradeId", orderId.Hex(), "side", side, "key", price.Uint64(), "amount", amount.Uint64(), "new amount", newAmount.Uint64())
orderList.subVolume(amount)
if newAmount.Sign() == 0 {
orderList.removeOrderItem(self.db, orderId)
orderList.removeOrderItem(ls.db, orderId)
} else {
orderList.setOrderItem(orderId, common.BigToHash(newAmount))
}
if orderList.empty() {
switch side {
case Investing:
lendingExchange.removeInvestingOrderList(self.db, orderList)
lendingExchange.removeInvestingOrderList(ls.db, orderList)
case Borrowing:
lendingExchange.removeBorrowingOrderList(self.db, orderList)
lendingExchange.removeBorrowingOrderList(ls.db, orderList)
default:
}
}
return nil
}
func (self *LendingStateDB) CancelLendingOrder(orderBook common.Hash, order *LendingItem) error {
func (ls *LendingStateDB) CancelLendingOrder(orderBook common.Hash, order *LendingItem) error {
interestHash := common.BigToHash(order.Interest)
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.LendingId))
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
if stateObject == nil {
return fmt.Errorf("not found order book: %s", orderBook.Hex())
}
lendingItem := stateObject.getLendingItem(self.db, orderIdHash)
lendingItem := stateObject.getLendingItem(ls.db, orderIdHash)
var orderList *itemListState
switch lendingItem.data.Side {
case Investing:
orderList = stateObject.getInvestingOrderList(self.db, interestHash)
orderList = stateObject.getInvestingOrderList(ls.db, interestHash)
case Borrowing:
orderList = stateObject.getBorrowingOrderList(self.db, interestHash)
orderList = stateObject.getBorrowingOrderList(ls.db, interestHash)
default:
return fmt.Errorf("not found order side: %s", order.Side)
}
@ -316,35 +318,35 @@ func (self *LendingStateDB) CancelLendingOrder(orderBook common.Hash, order *Len
if lendingItem.data.UserAddress != order.UserAddress {
return fmt.Errorf("error Order UserAddress mismatch when cancel order book: %s , order id : %s , got : %s , expect : %s", orderBook, orderIdHash.Hex(), lendingItem.data.UserAddress.Hex(), order.UserAddress.Hex())
}
self.journal = append(self.journal, cancelOrder{
ls.journal = append(ls.journal, cancelOrder{
orderBook: orderBook,
orderId: orderIdHash,
order: self.GetLendingOrder(orderBook, orderIdHash),
order: ls.GetLendingOrder(orderBook, orderIdHash),
})
lendingItem.setVolume(big.NewInt(0))
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(self.db, orderIdHash).Bytes()[:])
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(ls.db, orderIdHash).Bytes()[:])
orderList.subVolume(currentAmount)
orderList.removeOrderItem(self.db, orderIdHash)
orderList.removeOrderItem(ls.db, orderIdHash)
if orderList.empty() {
switch order.Side {
case Investing:
stateObject.removeInvestingOrderList(self.db, orderList)
stateObject.removeInvestingOrderList(ls.db, orderList)
case Borrowing:
stateObject.removeBorrowingOrderList(self.db, orderList)
stateObject.removeBorrowingOrderList(ls.db, orderList)
default:
}
}
return nil
}
func (self *LendingStateDB) GetBestInvestingRate(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) GetBestInvestingRate(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := ls.getLendingExchange(orderBook)
if stateObject != nil {
investingHash := stateObject.getBestInvestingInterest(self.db)
investingHash := stateObject.getBestInvestingInterest(ls.db)
if common.EmptyHash(investingHash) {
return Zero, Zero
}
orderList := stateObject.getInvestingOrderList(self.db, investingHash)
orderList := stateObject.getInvestingOrderList(ls.db, investingHash)
if orderList == nil {
log.Error("order list investing not found", "key", investingHash.Hex())
return Zero, Zero
@ -354,14 +356,14 @@ func (self *LendingStateDB) GetBestInvestingRate(orderBook common.Hash) (*big.In
return Zero, Zero
}
func (self *LendingStateDB) GetBestBorrowRate(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := self.getLendingExchange(orderBook)
func (ls *LendingStateDB) GetBestBorrowRate(orderBook common.Hash) (*big.Int, *big.Int) {
stateObject := ls.getLendingExchange(orderBook)
if stateObject != nil {
priceHash := stateObject.getBestBorrowingInterest(self.db)
priceHash := stateObject.getBestBorrowingInterest(ls.db)
if common.EmptyHash(priceHash) {
return Zero, Zero
}
orderList := stateObject.getBorrowingOrderList(self.db, priceHash)
orderList := stateObject.getBorrowingOrderList(ls.db, priceHash)
if orderList == nil {
log.Error("order list ask not found", "key", priceHash.Hex())
return Zero, Zero
@ -371,25 +373,25 @@ func (self *LendingStateDB) GetBestBorrowRate(orderBook common.Hash) (*big.Int,
return Zero, Zero
}
func (self *LendingStateDB) GetBestLendingIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
func (ls *LendingStateDB) GetBestLendingIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
if stateObject != nil {
var stateOrderList *itemListState
switch side {
case Investing:
stateOrderList = stateObject.getInvestingOrderList(self.db, common.BigToHash(price))
stateOrderList = stateObject.getInvestingOrderList(ls.db, common.BigToHash(price))
case Borrowing:
stateOrderList = stateObject.getBorrowingOrderList(self.db, common.BigToHash(price))
stateOrderList = stateObject.getBorrowingOrderList(ls.db, common.BigToHash(price))
default:
return EmptyHash, Zero, fmt.Errorf("not found side: %s", side)
}
if stateOrderList != nil {
key, _, err := stateOrderList.getTrie(self.db).TryGetBestLeftKeyAndValue()
key, _, err := stateOrderList.getTrie(ls.db).TryGetBestLeftKeyAndValue()
if err != nil {
return EmptyHash, Zero, err
}
orderId := common.BytesToHash(key)
amount := stateOrderList.GetOrderAmount(self.db, orderId)
amount := stateOrderList.GetOrderAmount(ls.db, orderId)
return orderId, new(big.Int).SetBytes(amount.Bytes()), nil
}
return EmptyHash, Zero, fmt.Errorf("not found order list with orderBook: %s , key : %d , side : %s", orderBook.Hex(), price, side)
@ -398,25 +400,25 @@ func (self *LendingStateDB) GetBestLendingIdAndAmount(orderBook common.Hash, pri
}
// updateLendingExchange writes the given object to the trie.
func (self *LendingStateDB) updateLendingExchange(stateObject *lendingExchangeState) {
func (ls *LendingStateDB) updateLendingExchange(stateObject *lendingExchangeState) {
addr := stateObject.Hash()
data, err := rlp.EncodeToBytes(stateObject)
if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
}
self.setError(self.trie.TryUpdate(addr[:], data))
ls.setError(ls.trie.TryUpdate(addr[:], data))
}
// Retrieve a state object given my the address. Returns nil if not found.
func (self *LendingStateDB) getLendingExchange(addr common.Hash) (stateObject *lendingExchangeState) {
func (ls *LendingStateDB) getLendingExchange(addr common.Hash) (stateObject *lendingExchangeState) {
// Prefer 'live' objects.
if obj := self.lendingExchangeStates[addr]; obj != nil {
if obj := ls.lendingExchangeStates[addr]; obj != nil {
return obj
}
// Load the object from the database.
enc, err := self.trie.TryGet(addr[:])
enc, err := ls.trie.TryGet(addr[:])
if len(enc) == 0 {
self.setError(err)
ls.setError(err)
return nil
}
var data lendingObject
@ -425,176 +427,176 @@ func (self *LendingStateDB) getLendingExchange(addr common.Hash) (stateObject *l
return nil
}
// Insert into the live set.
obj := newStateExchanges(self, addr, data, self.MarkLendingExchangeObjectDirty)
self.lendingExchangeStates[addr] = obj
obj := newStateExchanges(ls, addr, data, ls.MarkLendingExchangeObjectDirty)
ls.lendingExchangeStates[addr] = obj
return obj
}
func (self *LendingStateDB) setLendingExchangeObject(object *lendingExchangeState) {
self.lendingExchangeStates[object.Hash()] = object
self.lendingExchangeStatesDirty[object.Hash()] = struct{}{}
func (ls *LendingStateDB) setLendingExchangeObject(object *lendingExchangeState) {
ls.lendingExchangeStates[object.Hash()] = object
ls.lendingExchangeStatesDirty[object.Hash()] = struct{}{}
}
// Retrieve a state object or create a new state object if nil.
func (self *LendingStateDB) GetOrNewLendingExchangeObject(addr common.Hash) *lendingExchangeState {
stateExchangeObject := self.getLendingExchange(addr)
func (ls *LendingStateDB) GetOrNewLendingExchangeObject(addr common.Hash) *lendingExchangeState {
stateExchangeObject := ls.getLendingExchange(addr)
if stateExchangeObject == nil {
stateExchangeObject = self.createLendingExchangeObject(addr)
stateExchangeObject = ls.createLendingExchangeObject(addr)
}
return stateExchangeObject
}
// MarkStateLendObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *LendingStateDB) MarkLendingExchangeObjectDirty(addr common.Hash) {
self.lendingExchangeStatesDirty[addr] = struct{}{}
func (ls *LendingStateDB) MarkLendingExchangeObjectDirty(addr common.Hash) {
ls.lendingExchangeStatesDirty[addr] = struct{}{}
}
// createStateOrderListObject creates a new state object. If there is an existing tradeId with
// the given address, it is overwritten and returned as the second return value.
func (self *LendingStateDB) createLendingExchangeObject(hash common.Hash) (newobj *lendingExchangeState) {
newobj = newStateExchanges(self, hash, lendingObject{}, self.MarkLendingExchangeObjectDirty)
func (ls *LendingStateDB) createLendingExchangeObject(hash common.Hash) (newobj *lendingExchangeState) {
newobj = newStateExchanges(ls, hash, lendingObject{}, ls.MarkLendingExchangeObjectDirty)
newobj.setNonce(0) // sets the object to dirty
self.setLendingExchangeObject(newobj)
ls.setLendingExchangeObject(newobj)
return newobj
}
// Copy creates a deep, independent copy of the state.
// Snapshots of the copied state cannot be applied to the copy.
func (self *LendingStateDB) Copy() *LendingStateDB {
self.lock.Lock()
defer self.lock.Unlock()
func (ls *LendingStateDB) Copy() *LendingStateDB {
ls.lock.Lock()
defer ls.lock.Unlock()
// Copy all the basic fields, initialize the memory ones
state := &LendingStateDB{
db: self.db,
trie: self.db.CopyTrie(self.trie),
lendingExchangeStates: make(map[common.Hash]*lendingExchangeState, len(self.lendingExchangeStatesDirty)),
lendingExchangeStatesDirty: make(map[common.Hash]struct{}, len(self.lendingExchangeStatesDirty)),
db: ls.db,
trie: ls.db.CopyTrie(ls.trie),
lendingExchangeStates: make(map[common.Hash]*lendingExchangeState, len(ls.lendingExchangeStatesDirty)),
lendingExchangeStatesDirty: make(map[common.Hash]struct{}, len(ls.lendingExchangeStatesDirty)),
}
// Copy the dirty states, logs, and preimages
for addr := range self.lendingExchangeStatesDirty {
for addr := range ls.lendingExchangeStatesDirty {
state.lendingExchangeStatesDirty[addr] = struct{}{}
}
for addr, exchangeObject := range self.lendingExchangeStates {
for addr, exchangeObject := range ls.lendingExchangeStates {
state.lendingExchangeStates[addr] = exchangeObject.deepCopy(state, state.MarkLendingExchangeObjectDirty)
}
return state
}
func (s *LendingStateDB) clearJournalAndRefund() {
s.journal = nil
s.validRevisions = s.validRevisions[:0]
func (ls *LendingStateDB) clearJournalAndRefund() {
ls.journal = nil
ls.validRevisions = ls.validRevisions[:0]
}
// Snapshot returns an identifier for the current revision of the state.
func (self *LendingStateDB) Snapshot() int {
id := self.nextRevisionId
self.nextRevisionId++
self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)})
func (ls *LendingStateDB) Snapshot() int {
id := ls.nextRevisionId
ls.nextRevisionId++
ls.validRevisions = append(ls.validRevisions, revision{id, len(ls.journal)})
return id
}
// RevertToSnapshot reverts all state changes made since the given revision.
func (self *LendingStateDB) RevertToSnapshot(revid int) {
func (ls *LendingStateDB) RevertToSnapshot(revid int) {
// Find the snapshot in the stack of valid snapshots.
idx := sort.Search(len(self.validRevisions), func(i int) bool {
return self.validRevisions[i].id >= revid
idx := sort.Search(len(ls.validRevisions), func(i int) bool {
return ls.validRevisions[i].id >= revid
})
if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid {
if idx == len(ls.validRevisions) || ls.validRevisions[idx].id != revid {
panic(fmt.Errorf("revision id %v cannot be reverted", revid))
}
snapshot := self.validRevisions[idx].journalIndex
snapshot := ls.validRevisions[idx].journalIndex
// Replay the journal to undo changes.
for i := len(self.journal) - 1; i >= snapshot; i-- {
self.journal[i].undo(self)
for i := len(ls.journal) - 1; i >= snapshot; i-- {
ls.journal[i].undo(ls)
}
self.journal = self.journal[:snapshot]
ls.journal = ls.journal[:snapshot]
// Remove invalidated snapshots from the stack.
self.validRevisions = self.validRevisions[:idx]
ls.validRevisions = ls.validRevisions[:idx]
}
// Finalise finalises the state by removing the self destructed objects
// and clears the journal as well as the refunds.
func (s *LendingStateDB) Finalise() {
func (ls *LendingStateDB) Finalise() {
// Commit objects to the trie.
for addr, stateObject := range s.lendingExchangeStates {
if _, isDirty := s.lendingExchangeStatesDirty[addr]; isDirty {
for addr, stateObject := range ls.lendingExchangeStates {
if _, isDirty := ls.lendingExchangeStatesDirty[addr]; isDirty {
// Write any storage changes in the state object to its storage trie.
err := stateObject.updateInvestingRoot(s.db)
err := stateObject.updateInvestingRoot(ls.db)
if err != nil {
log.Warn("Finalise updateInvestingRoot", "err", err, "addr", addr, "stateObject", *stateObject)
}
stateObject.updateBorrowingRoot(s.db)
stateObject.updateOrderRoot(s.db)
stateObject.updateLendingTradeRoot(s.db)
stateObject.updateLiquidationTimeRoot(s.db)
stateObject.updateBorrowingRoot(ls.db)
stateObject.updateOrderRoot(ls.db)
stateObject.updateLendingTradeRoot(ls.db)
stateObject.updateLiquidationTimeRoot(ls.db)
// Update the object in the main tradeId trie.
s.updateLendingExchange(stateObject)
ls.updateLendingExchange(stateObject)
//delete(s.investingStatesDirty, addr)
}
}
s.clearJournalAndRefund()
ls.clearJournalAndRefund()
}
// IntermediateRoot computes the current root orderBook of the state trie.
// It is called in between transactions to get the root orderBook that
// goes into transaction receipts.
func (s *LendingStateDB) IntermediateRoot() common.Hash {
s.Finalise()
return s.trie.Hash()
func (ls *LendingStateDB) IntermediateRoot() common.Hash {
ls.Finalise()
return ls.trie.Hash()
}
// Commit writes the state to the underlying in-memory trie database.
func (s *LendingStateDB) Commit() (root common.Hash, err error) {
defer s.clearJournalAndRefund()
func (ls *LendingStateDB) Commit() (root common.Hash, err error) {
defer ls.clearJournalAndRefund()
// Commit objects to the trie.
for addr, stateObject := range s.lendingExchangeStates {
if _, isDirty := s.lendingExchangeStatesDirty[addr]; isDirty {
for addr, stateObject := range ls.lendingExchangeStates {
if _, isDirty := ls.lendingExchangeStatesDirty[addr]; isDirty {
// Write any storage changes in the state object to its storage trie.
if err := stateObject.CommitInvestingTrie(s.db); err != nil {
if err := stateObject.CommitInvestingTrie(ls.db); err != nil {
return EmptyHash, err
}
if err := stateObject.CommitBorrowingTrie(s.db); err != nil {
if err := stateObject.CommitBorrowingTrie(ls.db); err != nil {
return EmptyHash, err
}
if err := stateObject.CommitLendingItemTrie(s.db); err != nil {
if err := stateObject.CommitLendingItemTrie(ls.db); err != nil {
return EmptyHash, err
}
if err := stateObject.CommitLendingTradeTrie(s.db); err != nil {
if err := stateObject.CommitLendingTradeTrie(ls.db); err != nil {
return EmptyHash, err
}
if err := stateObject.CommitLiquidationTimeTrie(s.db); err != nil {
if err := stateObject.CommitLiquidationTimeTrie(ls.db); err != nil {
return EmptyHash, err
}
// Update the object in the main tradeId trie.
s.updateLendingExchange(stateObject)
delete(s.lendingExchangeStatesDirty, addr)
ls.updateLendingExchange(stateObject)
delete(ls.lendingExchangeStatesDirty, addr)
}
}
// Write trie changes.
root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {
root, err = ls.trie.Commit(func(leaf []byte, parent common.Hash) error {
var exchange lendingObject
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
return nil
}
if exchange.InvestingRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.InvestingRoot, parent)
ls.db.TrieDB().Reference(exchange.InvestingRoot, parent)
}
if exchange.BorrowingRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.BorrowingRoot, parent)
ls.db.TrieDB().Reference(exchange.BorrowingRoot, parent)
}
if exchange.LendingItemRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.LendingItemRoot, parent)
ls.db.TrieDB().Reference(exchange.LendingItemRoot, parent)
}
if exchange.LendingTradeRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.LendingTradeRoot, parent)
ls.db.TrieDB().Reference(exchange.LendingTradeRoot, parent)
}
if exchange.LiquidationTimeRoot != EmptyRoot {
s.db.TrieDB().Reference(exchange.LiquidationTimeRoot, parent)
ls.db.TrieDB().Reference(exchange.LiquidationTimeRoot, parent)
}
return nil
})
@ -602,38 +604,38 @@ func (s *LendingStateDB) Commit() (root common.Hash, err error) {
return root, err
}
func (self *LendingStateDB) InsertLiquidationTime(lendingBook common.Hash, time *big.Int, tradeId uint64) {
func (ls *LendingStateDB) InsertLiquidationTime(lendingBook common.Hash, time *big.Int, tradeId uint64) {
timeHash := common.BigToHash(time)
lendingExchangeState := self.getLendingExchange(lendingBook)
lendingExchangeState := ls.getLendingExchange(lendingBook)
if lendingExchangeState == nil {
lendingExchangeState = self.createLendingExchangeObject(lendingBook)
lendingExchangeState = ls.createLendingExchangeObject(lendingBook)
}
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(self.db, timeHash)
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(ls.db, timeHash)
if liquidationTime == nil {
liquidationTime = lendingExchangeState.createLiquidationTime(self.db, timeHash)
liquidationTime = lendingExchangeState.createLiquidationTime(ls.db, timeHash)
}
liquidationTime.insertTradeId(self.db, common.Uint64ToHash(tradeId))
liquidationTime.insertTradeId(ls.db, common.Uint64ToHash(tradeId))
liquidationTime.AddVolume(One)
}
func (self *LendingStateDB) RemoveLiquidationTime(lendingBook common.Hash, tradeId uint64, time uint64) error {
func (ls *LendingStateDB) RemoveLiquidationTime(lendingBook common.Hash, tradeId uint64, time uint64) error {
timeHash := common.Uint64ToHash(time)
tradeIdHash := common.Uint64ToHash(tradeId)
lendingExchangeState := self.getLendingExchange(lendingBook)
lendingExchangeState := ls.getLendingExchange(lendingBook)
if lendingExchangeState == nil {
return fmt.Errorf("lending book not found: %s", lendingBook.Hex())
}
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(self.db, timeHash)
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(ls.db, timeHash)
if liquidationTime == nil {
return fmt.Errorf("not found liquidation time: %s , %d", lendingBook.Hex(), time)
}
if !liquidationTime.Exist(self.db, tradeIdHash) {
return fmt.Errorf("not exist tradeId: %s , %d , %d", lendingBook.Hex(), time, tradeId)
if !liquidationTime.Exist(ls.db, tradeIdHash) {
return fmt.Errorf("not exist tradeId: %s, %d, %d", lendingBook.Hex(), time, tradeId)
}
liquidationTime.removeTradeId(self.db, tradeIdHash)
liquidationTime.removeTradeId(ls.db, tradeIdHash)
liquidationTime.subVolume(One)
if liquidationTime.Volume().Sign() == 0 {
err := lendingExchangeState.getLiquidationTimeTrie(self.db).TryDelete(timeHash[:])
err := lendingExchangeState.getLiquidationTimeTrie(ls.db).TryDelete(timeHash[:])
if err != nil {
log.Warn("RemoveLiquidationTime getLiquidationTimeTrie.TryDelete", "err", err, "timeHash[:]", timeHash[:])
}
@ -641,33 +643,33 @@ func (self *LendingStateDB) RemoveLiquidationTime(lendingBook common.Hash, trade
return nil
}
func (self *LendingStateDB) GetLowestLiquidationTime(lendingBook common.Hash, time *big.Int) (*big.Int, []common.Hash) {
func (ls *LendingStateDB) GetLowestLiquidationTime(lendingBook common.Hash, time *big.Int) (*big.Int, []common.Hash) {
liquidationData := []common.Hash{}
lendingExchangeState := self.getLendingExchange(lendingBook)
lendingExchangeState := ls.getLendingExchange(lendingBook)
if lendingExchangeState == nil {
return common.Big0, liquidationData
}
lowestPriceHash, liquidationState := lendingExchangeState.getLowestLiquidationTime(self.db)
lowestPriceHash, liquidationState := lendingExchangeState.getLowestLiquidationTime(ls.db)
lowestTime := new(big.Int).SetBytes(lowestPriceHash[:])
if liquidationState != nil && lowestTime.Sign() > 0 && lowestTime.Cmp(time) <= 0 {
liquidationData = liquidationState.getAllTradeIds(self.db)
liquidationData = liquidationState.getAllTradeIds(ls.db)
}
return lowestTime, liquidationData
}
func (self *LendingStateDB) CancelLendingTrade(orderBook common.Hash, tradeId uint64) error {
func (ls *LendingStateDB) CancelLendingTrade(orderBook common.Hash, tradeId uint64) error {
tradeIdHash := common.Uint64ToHash(tradeId)
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
if stateObject == nil {
return fmt.Errorf("not found order book: %s", orderBook.Hex())
}
lendingTrade := stateObject.getLendingTrade(self.db, tradeIdHash)
lendingTrade := stateObject.getLendingTrade(ls.db, tradeIdHash)
if lendingTrade == nil || lendingTrade.empty() {
return fmt.Errorf("lending trade empty order book: %s , trade id : %s , trade id hash : %s", orderBook, tradeIdHash.Hex(), tradeIdHash.Hex())
}
self.journal = append(self.journal, cancelTrading{
ls.journal = append(ls.journal, cancelTrading{
orderBook: orderBook,
order: self.GetLendingTrade(orderBook, tradeIdHash),
order: ls.GetLendingTrade(orderBook, tradeIdHash),
})
lendingTrade.SetAmount(Zero)
return nil

View file

@ -150,29 +150,29 @@ func NewTreePool(hasher BaseHasher, segmentCount, capacity int) *TreePool {
}
// Drain drains the pool uptil it has no more than n resources
func (self *TreePool) Drain(n int) {
self.lock.Lock()
defer self.lock.Unlock()
for len(self.c) > n {
<-self.c
self.count--
func (tp *TreePool) Drain(n int) {
tp.lock.Lock()
defer tp.lock.Unlock()
for len(tp.c) > n {
<-tp.c
tp.count--
}
}
// Reserve is blocking until it returns an available Tree
// it reuses free Trees or creates a new one if size is not reached
func (self *TreePool) Reserve() *Tree {
self.lock.Lock()
defer self.lock.Unlock()
func (tp *TreePool) Reserve() *Tree {
tp.lock.Lock()
defer tp.lock.Unlock()
var t *Tree
if self.count == self.Capacity {
return <-self.c
if tp.count == tp.Capacity {
return <-tp.c
}
select {
case t = <-self.c:
case t = <-tp.c:
default:
t = NewTree(self.hasher, self.SegmentSize, self.SegmentCount)
self.count++
t = NewTree(tp.hasher, tp.SegmentSize, tp.SegmentCount)
tp.count++
}
return t
}
@ -180,8 +180,8 @@ func (self *TreePool) Reserve() *Tree {
// Release gives back a Tree to the pool.
// This Tree is guaranteed to be in reusable state
// does not need locking
func (self *TreePool) Release(t *Tree) {
self.c <- t // can never fail but...
func (tp *TreePool) Release(t *Tree) {
tp.c <- t // can never fail but...
}
// Tree is a reusable control structure representing a BMT
@ -193,17 +193,17 @@ type Tree struct {
}
// Draw draws the BMT (badly)
func (self *Tree) Draw(hash []byte, d int) string {
func (t *Tree) Draw(hash []byte, d int) string {
var left, right []string
var anc []*Node
for i, n := range self.leaves {
for i, n := range t.leaves {
left = append(left, fmt.Sprintf("%v", hashstr(n.left)))
if i%2 == 0 {
anc = append(anc, n.parent)
}
right = append(right, fmt.Sprintf("%v", hashstr(n.right)))
}
anc = self.leaves
anc = t.leaves
var hashes [][]string
for l := 0; len(anc) > 0; l++ {
var nodes []*Node
@ -277,42 +277,42 @@ func NewTree(hasher BaseHasher, segmentSize, segmentCount int) *Tree {
// methods needed by hash.Hash
// Size returns the size
func (self *Hasher) Size() int {
return self.size
func (ha *Hasher) Size() int {
return ha.size
}
// BlockSize returns the block size
func (self *Hasher) BlockSize() int {
return self.blocksize
func (ha *Hasher) BlockSize() int {
return ha.blocksize
}
// Sum returns the hash of the buffer
// hash.Hash interface Sum method appends the byte slice to the underlying
// data before it calculates and returns the hash of the chunk
func (self *Hasher) Sum(b []byte) (r []byte) {
t := self.bmt
i := self.cur
func (ha *Hasher) Sum(b []byte) (r []byte) {
t := ha.bmt
i := ha.cur
n := t.leaves[i]
j := i
// must run strictly before all nodes calculate
// datanodes are guaranteed to have a parent
if len(self.segment) > self.size && i > 0 && n.parent != nil {
if len(ha.segment) > ha.size && i > 0 && n.parent != nil {
n = n.parent
} else {
i *= 2
}
d := self.finalise(n, i)
self.writeSegment(j, self.segment, d)
c := <-self.result
self.releaseTree()
d := ha.finalise(n, i)
ha.writeSegment(j, ha.segment, d)
c := <-ha.result
ha.releaseTree()
// sha3(length + BMT(pure_chunk))
if self.blockLength == nil {
if ha.blockLength == nil {
return c
}
res := self.pool.hasher()
res := ha.pool.hasher()
res.Reset()
res.Write(self.blockLength)
res.Write(ha.blockLength)
res.Write(c)
return res.Sum(nil)
}
@ -321,8 +321,8 @@ func (self *Hasher) Sum(b []byte) (r []byte) {
// Hash waits for the hasher result and returns it
// caller must call this on a BMT Hasher being written to
func (self *Hasher) Hash() []byte {
return <-self.result
func (ha *Hasher) Hash() []byte {
return <-ha.result
}
// Hasher implements the io.Writer interface
@ -330,16 +330,16 @@ func (self *Hasher) Hash() []byte {
// Write fills the buffer to hash
// with every full segment complete launches a hasher go routine
// that shoots up the BMT
func (self *Hasher) Write(b []byte) (int, error) {
func (ha *Hasher) Write(b []byte) (int, error) {
l := len(b)
if l <= 0 {
return 0, nil
}
s := self.segment
i := self.cur
count := (self.count + 1) / 2
need := self.count*self.size - self.cur*2*self.size
size := self.size
s := ha.segment
i := ha.cur
count := (ha.count + 1) / 2
need := ha.count*ha.size - ha.cur*2*ha.size
size := ha.size
if need > size {
size *= 2
}
@ -356,7 +356,7 @@ func (self *Hasher) Write(b []byte) (int, error) {
// read full segments and the last possibly partial segment
for need > 0 && i < count-1 {
// push all finished chunks we read
self.writeSegment(i, s, self.depth)
ha.writeSegment(i, s, ha.depth)
need -= size
if need < 0 {
size += need
@ -365,8 +365,8 @@ func (self *Hasher) Write(b []byte) (int, error) {
rest += size
i++
}
self.segment = s
self.cur = i
ha.segment = s
ha.cur = i
// otherwise, we can assume len(s) == 0, so all buffer is read and chunk is not yet full
return l, nil
}
@ -376,8 +376,8 @@ func (self *Hasher) Write(b []byte) (int, error) {
// ReadFrom reads from io.Reader and appends to the data to hash using Write
// it reads so that chunk to hash is maximum length or reader reaches EOF
// caller must Reset the hasher prior to call
func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
bufsize := self.size*self.count - self.size*self.cur - len(self.segment)
func (ha *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
bufsize := ha.size*ha.count - ha.size*ha.cur - len(ha.segment)
buf := make([]byte, bufsize)
var read int
for {
@ -385,7 +385,7 @@ func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
n, err = r.Read(buf)
read += n
if err == io.EOF || read == len(buf) {
hash := self.Sum(buf[:n])
hash := ha.Sum(buf[:n])
if read == len(buf) {
err = NewEOC(hash)
}
@ -394,7 +394,7 @@ func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
if err != nil {
break
}
_, err = self.Write(buf[:n])
_, err = ha.Write(buf[:n])
if err != nil {
break
}
@ -403,9 +403,9 @@ func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
}
// Reset needs to be called before writing to the hasher
func (self *Hasher) Reset() {
self.getTree()
self.blockLength = nil
func (ha *Hasher) Reset() {
ha.getTree()
ha.blockLength = nil
}
// Hasher implements the SwarmHash interface
@ -413,53 +413,53 @@ func (self *Hasher) Reset() {
// ResetWithLength needs to be called before writing to the hasher
// the argument is supposed to be the byte slice binary representation of
// the legth of the data subsumed under the hash
func (self *Hasher) ResetWithLength(l []byte) {
self.Reset()
self.blockLength = l
func (ha *Hasher) ResetWithLength(l []byte) {
ha.Reset()
ha.blockLength = l
}
// Release gives back the Tree to the pool whereby it unlocks
// it resets tree, segment and index
func (self *Hasher) releaseTree() {
if self.bmt != nil {
n := self.bmt.leaves[self.cur]
func (ha *Hasher) releaseTree() {
if ha.bmt != nil {
n := ha.bmt.leaves[ha.cur]
for ; n != nil; n = n.parent {
n.unbalanced = false
if n.parent != nil {
n.root = false
}
}
self.pool.Release(self.bmt)
self.bmt = nil
ha.pool.Release(ha.bmt)
ha.bmt = nil
}
self.cur = 0
self.segment = nil
ha.cur = 0
ha.segment = nil
}
func (self *Hasher) writeSegment(i int, s []byte, d int) {
h := self.pool.hasher()
n := self.bmt.leaves[i]
func (ha *Hasher) writeSegment(i int, s []byte, d int) {
h := ha.pool.hasher()
n := ha.bmt.leaves[i]
if len(s) > self.size && n.parent != nil {
if len(s) > ha.size && n.parent != nil {
go func() {
h.Reset()
h.Write(s)
s = h.Sum(nil)
if n.root {
self.result <- s
ha.result <- s
return
}
self.run(n.parent, h, d, n.index, s)
ha.run(n.parent, h, d, n.index, s)
}()
return
}
go self.run(n, h, d, i*2, s)
go ha.run(n, h, d, i*2, s)
}
func (self *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
func (ha *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
isLeft := i%2 == 0
for {
if isLeft {
@ -480,9 +480,9 @@ func (self *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
s = append(n.left, n.right...)
}
self.hash = s
ha.hash = s
if n.root {
self.result <- s
ha.result <- s
return
}
@ -493,20 +493,20 @@ func (self *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
}
// getTree obtains a BMT resource by reserving one from the pool
func (self *Hasher) getTree() *Tree {
if self.bmt != nil {
return self.bmt
func (ha *Hasher) getTree() *Tree {
if ha.bmt != nil {
return ha.bmt
}
t := self.pool.Reserve()
self.bmt = t
t := ha.pool.Reserve()
ha.bmt = t
return t
}
// atomic bool toggle implementing a concurrent reusable 2-state object
// atomic addint with %2 implements atomic bool toggle
// it returns true if the toggler just put it in the active/waiting state
func (self *Node) toggle() bool {
return atomic.AddInt32(&self.state, 1)%2 == 1
func (n *Node) toggle() bool {
return atomic.AddInt32(&n.state, 1)%2 == 1
}
func hashstr(b []byte) string {
@ -526,7 +526,7 @@ func depth(n int) (d int) {
// finalise is following the zigzags on the tree belonging
// to the final datasegment
func (self *Hasher) finalise(n *Node, i int) (d int) {
func (ha *Hasher) finalise(n *Node, i int) (d int) {
isLeft := i%2 == 0
for {
// when the final segment's path is going via left segments
@ -551,8 +551,8 @@ type EOC struct {
}
// Error returns the error string
func (self *EOC) Error() string {
return fmt.Sprintf("hasher limit reached, chunk hash: %x", self.Hash)
func (e *EOC) Error() string {
return fmt.Sprintf("hasher limit reached, chunk hash: %x", e.Hash)
}
// NewEOC creates new end of chunk error with the hash

View file

@ -38,12 +38,12 @@ type DirectoryString struct {
Value string
}
func (self *DirectoryString) String() string {
return self.Value
func (ds *DirectoryString) String() string {
return ds.Value
}
func (self *DirectoryString) Set(value string) error {
self.Value = expandPath(value)
func (ds *DirectoryString) Set(value string) error {
ds.Value = expandPath(value)
return nil
}
@ -55,12 +55,12 @@ type DirectoryFlag struct {
Usage string
}
func (self DirectoryFlag) String() string {
func (df DirectoryFlag) String() string {
fmtString := "%s %v\t%v"
if len(self.Value.Value) > 0 {
if len(df.Value.Value) > 0 {
fmtString = "%s \"%v\"\t%v"
}
return fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage)
return fmt.Sprintf(fmtString, prefixedNames(df.Name), df.Value.Value, df.Usage)
}
func eachName(longName string, fn func(string)) {
@ -73,9 +73,9 @@ func eachName(longName string, fn func(string)) {
// called by cli library, grabs variable from environment (if in env)
// and adds variable to flag set for parsing.
func (self DirectoryFlag) Apply(set *flag.FlagSet) {
eachName(self.Name, func(name string) {
set.Var(&self.Value, self.Name, self.Usage)
func (df DirectoryFlag) Apply(set *flag.FlagSet) {
eachName(df.Name, func(name string) {
set.Var(&df.Value, df.Name, df.Usage)
})
}
@ -89,16 +89,16 @@ type textMarshalerVal struct {
v TextMarshaler
}
func (v textMarshalerVal) String() string {
if v.v == nil {
func (t textMarshalerVal) String() string {
if t.v == nil {
return ""
}
text, _ := v.v.MarshalText()
text, _ := t.v.MarshalText()
return string(text)
}
func (v textMarshalerVal) Set(s string) error {
return v.v.UnmarshalText([]byte(s))
func (t textMarshalerVal) Set(s string) error {
return t.v.UnmarshalText([]byte(s))
}
// TextMarshalerFlag wraps a TextMarshaler value.
@ -108,17 +108,17 @@ type TextMarshalerFlag struct {
Usage string
}
func (f TextMarshalerFlag) GetName() string {
return f.Name
func (t TextMarshalerFlag) GetName() string {
return t.Name
}
func (f TextMarshalerFlag) String() string {
return fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)
func (t TextMarshalerFlag) String() string {
return fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(t.Name), t.Value, t.Usage)
}
func (f TextMarshalerFlag) Apply(set *flag.FlagSet) {
eachName(f.Name, func(name string) {
set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage)
func (t TextMarshalerFlag) Apply(set *flag.FlagSet) {
eachName(t.Name, func(name string) {
set.Var(textMarshalerVal{t.Value}, t.Name, t.Usage)
})
}
@ -142,37 +142,37 @@ type BigFlag struct {
// bigValue turns *big.Int into a flag.Value
type bigValue big.Int
func (b *bigValue) String() string {
if b == nil {
func (bv *bigValue) String() string {
if bv == nil {
return ""
}
return (*big.Int)(b).String()
return (*big.Int)(bv).String()
}
func (b *bigValue) Set(s string) error {
func (bv *bigValue) Set(s string) error {
int, ok := math.ParseBig256(s)
if !ok {
return errors.New("invalid integer syntax")
}
*b = (bigValue)(*int)
*bv = (bigValue)(*int)
return nil
}
func (f BigFlag) GetName() string {
return f.Name
func (bf BigFlag) GetName() string {
return bf.Name
}
func (f BigFlag) String() string {
func (bf BigFlag) String() string {
fmtString := "%s %v\t%v"
if f.Value != nil {
if bf.Value != nil {
fmtString = "%s \"%v\"\t%v"
}
return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage)
return fmt.Sprintf(fmtString, prefixedNames(bf.Name), bf.Value, bf.Usage)
}
func (f BigFlag) Apply(set *flag.FlagSet) {
eachName(f.Name, func(name string) {
set.Var((*bigValue)(f.Value), f.Name, f.Usage)
func (bf BigFlag) Apply(set *flag.FlagSet) {
eachName(bf.Name, func(name string) {
set.Var((*bigValue)(bf.Value), bf.Name, bf.Usage)
})
}
@ -207,12 +207,12 @@ func prefixedNames(fullName string) (prefixed string) {
return
}
func (self DirectoryFlag) GetName() string {
return self.Name
func (df DirectoryFlag) GetName() string {
return df.Name
}
func (self *DirectoryFlag) Set(value string) {
self.Value.Value = value
func (df *DirectoryFlag) Set(value string) {
df.Value.Value = value
}
// Expands a file path

View file

@ -100,45 +100,45 @@ func ensNode(name string) common.Hash {
return crypto.Keccak256Hash(parentNode[:], parentLabel[:])
}
func (self *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) {
resolverAddr, err := self.Resolver(node)
func (e *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) {
resolverAddr, err := e.Resolver(node)
if err != nil {
return nil, err
}
resolver, err := contract.NewPublicResolver(resolverAddr, self.contractBackend)
resolver, err := contract.NewPublicResolver(resolverAddr, e.contractBackend)
if err != nil {
return nil, err
}
return &contract.PublicResolverSession{
Contract: resolver,
TransactOpts: self.TransactOpts,
TransactOpts: e.TransactOpts,
}, nil
}
func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) {
registrarAddr, err := self.Owner(node)
func (e *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) {
registrarAddr, err := e.Owner(node)
if err != nil {
return nil, err
}
registrar, err := contract.NewFIFSRegistrar(registrarAddr, self.contractBackend)
registrar, err := contract.NewFIFSRegistrar(registrarAddr, e.contractBackend)
if err != nil {
return nil, err
}
return &contract.FIFSRegistrarSession{
Contract: registrar,
TransactOpts: self.TransactOpts,
TransactOpts: e.TransactOpts,
}, nil
}
// Resolve is a non-transactional call that returns the content hash associated with a name.
func (self *ENS) Resolve(name string) (common.Hash, error) {
func (e *ENS) Resolve(name string) (common.Hash, error) {
node := ensNode(name)
resolver, err := self.getResolver(node)
resolver, err := e.getResolver(node)
if err != nil {
return common.Hash{}, err
}
@ -153,26 +153,26 @@ func (self *ENS) Resolve(name string) (common.Hash, error) {
// Register registers a new domain name for the caller, making them the owner of the new name.
// Only works if the registrar for the parent domain implements the FIFS registrar protocol.
func (self *ENS) Register(name string) (*types.Transaction, error) {
func (e *ENS) Register(name string) (*types.Transaction, error) {
parentNode, label := ensParentNode(name)
registrar, err := self.getRegistrar(parentNode)
registrar, err := e.getRegistrar(parentNode)
if err != nil {
return nil, err
}
return registrar.Contract.Register(&self.TransactOpts, label, self.TransactOpts.From)
return registrar.Contract.Register(&e.TransactOpts, label, e.TransactOpts.From)
}
// SetContentHash sets the content hash associated with a name. Only works if the caller
// owns the name, and the associated resolver implements a `setContent` function.
func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
func (e *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
node := ensNode(name)
resolver, err := self.getResolver(node)
resolver, err := e.getResolver(node)
if err != nil {
return nil, err
}
opts := self.TransactOpts
opts := e.TransactOpts
opts.GasLimit = 200000
return resolver.Contract.SetContent(&opts, node, hash)
}

View file

@ -39,15 +39,15 @@ type Dump struct {
Accounts map[string]DumpAccount `json:"accounts"`
}
func (self *StateDB) RawDump() Dump {
func (s *StateDB) RawDump() Dump {
dump := Dump{
Root: fmt.Sprintf("%x", self.trie.Hash()),
Root: fmt.Sprintf("%x", s.trie.Hash()),
Accounts: make(map[string]DumpAccount),
}
it := trie.NewIterator(self.trie.NodeIterator(nil))
it := trie.NewIterator(s.trie.NodeIterator(nil))
for it.Next() {
addr := self.trie.GetKey(it.Key)
addr := s.trie.GetKey(it.Key)
var data Account
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
panic(err)
@ -59,20 +59,20 @@ func (self *StateDB) RawDump() Dump {
Nonce: data.Nonce,
Root: common.Bytes2Hex(data.Root[:]),
CodeHash: common.Bytes2Hex(data.CodeHash),
Code: common.Bytes2Hex(obj.Code(self.db)),
Code: common.Bytes2Hex(obj.Code(s.db)),
Storage: make(map[string]string),
}
storageIt := trie.NewIterator(obj.getTrie(self.db).NodeIterator(nil))
storageIt := trie.NewIterator(obj.getTrie(s.db).NodeIterator(nil))
for storageIt.Next() {
account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value)
account.Storage[common.Bytes2Hex(s.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value)
}
dump.Accounts[common.Bytes2Hex(addr)] = account
}
return dump
}
func (self *StateDB) Dump() []byte {
json, err := json.MarshalIndent(self.RawDump(), "", " ")
func (s *StateDB) Dump() []byte {
json, err := json.MarshalIndent(s.RawDump(), "", " ")
if err != nil {
fmt.Println("dump err", err)
}

View file

@ -86,19 +86,19 @@ type AccountInfo struct {
StorageHash common.Hash
}
func (self *StateDB) SubRefund(gas uint64) {
self.journal = append(self.journal, refundChange{
prev: self.refund})
if gas > self.refund {
panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, self.refund))
func (s *StateDB) SubRefund(gas uint64) {
s.journal = append(s.journal, refundChange{
prev: s.refund})
if gas > s.refund {
panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund))
}
self.refund -= gas
s.refund -= gas
}
func (self *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.GetCommittedState(self.db, hash)
return stateObject.GetCommittedState(s.db, hash)
}
return common.Hash{}
}
@ -121,44 +121,44 @@ func New(root common.Hash, db Database) (*StateDB, error) {
}
// setError remembers the first non-nil error it is called with.
func (self *StateDB) setError(err error) {
if self.dbErr == nil {
self.dbErr = err
func (s *StateDB) setError(err error) {
if s.dbErr == nil {
s.dbErr = err
}
}
func (self *StateDB) Error() error {
return self.dbErr
func (s *StateDB) Error() error {
return s.dbErr
}
// Reset clears out all ephemeral state objects from the state db, but keeps
// the underlying state trie to avoid reloading data for the next operations.
func (self *StateDB) Reset(root common.Hash) error {
tr, err := self.db.OpenTrie(root)
func (s *StateDB) Reset(root common.Hash) error {
tr, err := s.db.OpenTrie(root)
if err != nil {
return err
}
self.trie = tr
self.stateObjects = make(map[common.Address]*stateObject)
self.stateObjectsDirty = make(map[common.Address]struct{})
self.thash = common.Hash{}
self.txIndex = 0
self.logs = make(map[common.Hash][]*types.Log)
self.logSize = 0
self.preimages = make(map[common.Hash][]byte)
self.clearJournalAndRefund()
self.accessList = newAccessList()
s.trie = tr
s.stateObjects = make(map[common.Address]*stateObject)
s.stateObjectsDirty = make(map[common.Address]struct{})
s.thash = common.Hash{}
s.txIndex = 0
s.logs = make(map[common.Hash][]*types.Log)
s.logSize = 0
s.preimages = make(map[common.Hash][]byte)
s.clearJournalAndRefund()
s.accessList = newAccessList()
return nil
}
func (self *StateDB) AddLog(log *types.Log) {
self.journal = append(self.journal, addLogChange{txhash: self.thash})
func (s *StateDB) AddLog(log *types.Log) {
s.journal = append(s.journal, addLogChange{txhash: s.thash})
log.TxHash = self.thash
log.TxIndex = uint(self.txIndex)
log.Index = self.logSize
self.logs[self.thash] = append(self.logs[self.thash], log)
self.logSize++
log.TxHash = s.thash
log.TxIndex = uint(s.txIndex)
log.Index = s.logSize
s.logs[s.thash] = append(s.logs[s.thash], log)
s.logSize++
}
func (s *StateDB) GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log {
@ -169,58 +169,58 @@ func (s *StateDB) GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log
return logs
}
func (self *StateDB) Logs() []*types.Log {
func (s *StateDB) Logs() []*types.Log {
var logs []*types.Log
for _, lgs := range self.logs {
for _, lgs := range s.logs {
logs = append(logs, lgs...)
}
return logs
}
// AddPreimage records a SHA3 preimage seen by the VM.
func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) {
if _, ok := self.preimages[hash]; !ok {
self.journal = append(self.journal, addPreimageChange{hash: hash})
func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) {
if _, ok := s.preimages[hash]; !ok {
s.journal = append(s.journal, addPreimageChange{hash: hash})
pi := make([]byte, len(preimage))
copy(pi, preimage)
self.preimages[hash] = pi
s.preimages[hash] = pi
}
}
// Preimages returns a list of SHA3 preimages that have been submitted.
func (self *StateDB) Preimages() map[common.Hash][]byte {
return self.preimages
func (s *StateDB) Preimages() map[common.Hash][]byte {
return s.preimages
}
func (self *StateDB) AddRefund(gas uint64) {
self.journal = append(self.journal, refundChange{prev: self.refund})
self.refund += gas
func (s *StateDB) AddRefund(gas uint64) {
s.journal = append(s.journal, refundChange{prev: s.refund})
s.refund += gas
}
// Exist reports whether the given account address exists in the state.
// Notably this also returns true for suicided accounts.
func (self *StateDB) Exist(addr common.Address) bool {
return self.getStateObject(addr) != nil
func (s *StateDB) Exist(addr common.Address) bool {
return s.getStateObject(addr) != nil
}
// Empty returns whether the state object is either non-existent
// or empty according to the EIP161 specification (balance = nonce = code = 0)
func (self *StateDB) Empty(addr common.Address) bool {
so := self.getStateObject(addr)
func (s *StateDB) Empty(addr common.Address) bool {
so := s.getStateObject(addr)
return so == nil || so.empty()
}
// Retrieve the balance from the given address or 0 if object not found
func (self *StateDB) GetBalance(addr common.Address) *big.Int {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetBalance(addr common.Address) *big.Int {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.Balance()
}
return common.Big0
}
func (self *StateDB) GetNonce(addr common.Address) uint64 {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetNonce(addr common.Address) uint64 {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.Nonce()
}
@ -230,8 +230,8 @@ func (self *StateDB) GetNonce(addr common.Address) uint64 {
// GetStorageRoot retrieves the storage root from the given address or empty
// if object not found.
func (self *StateDB) GetStorageRoot(addr common.Address) common.Hash {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.Root()
}
@ -239,45 +239,45 @@ func (self *StateDB) GetStorageRoot(addr common.Address) common.Hash {
}
// TxIndex returns the current transaction index set by Prepare.
func (self *StateDB) TxIndex() int {
return self.txIndex
func (s *StateDB) TxIndex() int {
return s.txIndex
}
func (self *StateDB) GetCode(addr common.Address) []byte {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetCode(addr common.Address) []byte {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.Code(self.db)
return stateObject.Code(s.db)
}
return nil
}
func (self *StateDB) GetCodeSize(addr common.Address) int {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetCodeSize(addr common.Address) int {
stateObject := s.getStateObject(addr)
if stateObject == nil {
return 0
}
if stateObject.code != nil {
return len(stateObject.code)
}
size, err := self.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash()))
size, err := s.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash()))
if err != nil {
self.setError(err)
s.setError(err)
}
return size
}
func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
stateObject := s.getStateObject(addr)
if stateObject == nil {
return common.Hash{}
}
return common.BytesToHash(stateObject.CodeHash())
}
func (self *StateDB) GetAccountInfo(addr common.Address) *AccountInfo {
func (s *StateDB) GetAccountInfo(addr common.Address) *AccountInfo {
result := AccountInfo{}
stateObject := self.getStateObject(addr)
stateObject := s.getStateObject(addr)
if stateObject == nil {
result.Balance = common.Big0
return &result
@ -286,7 +286,7 @@ func (self *StateDB) GetAccountInfo(addr common.Address) *AccountInfo {
if stateObject.code != nil {
result.CodeSize = len(stateObject.code)
} else {
result.CodeSize, _ = self.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash()))
result.CodeSize, _ = s.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash()))
}
result.Nonce = stateObject.Nonce()
result.Balance = stateObject.Balance()
@ -296,32 +296,32 @@ func (self *StateDB) GetAccountInfo(addr common.Address) *AccountInfo {
return &result
}
func (self *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.GetState(self.db, bhash)
return stateObject.GetState(s.db, bhash)
}
return common.Hash{}
}
// Database retrieves the low level database supporting the lower level trie ops.
func (self *StateDB) Database() Database {
return self.db
func (s *StateDB) Database() Database {
return s.db
}
// StorageTrie returns the storage trie of an account.
// The return value is a copy and is nil for non-existent accounts.
func (self *StateDB) StorageTrie(addr common.Address) Trie {
stateObject := self.getStateObject(addr)
func (s *StateDB) StorageTrie(addr common.Address) Trie {
stateObject := s.getStateObject(addr)
if stateObject == nil {
return nil
}
cpy := stateObject.deepCopy(self, nil)
return cpy.updateTrie(self.db)
cpy := stateObject.deepCopy(s, nil)
return cpy.updateTrie(s.db)
}
func (self *StateDB) HasSuicided(addr common.Address) bool {
stateObject := self.getStateObject(addr)
func (s *StateDB) HasSuicided(addr common.Address) bool {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.suicided
}
@ -333,46 +333,46 @@ func (self *StateDB) HasSuicided(addr common.Address) bool {
*/
// AddBalance adds amount to the account associated with addr.
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr)
func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.AddBalance(amount)
}
}
// SubBalance subtracts amount from the account associated with addr.
func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr)
func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SubBalance(amount)
}
}
func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr)
func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) {
stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetBalance(amount)
}
}
func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := self.GetOrNewStateObject(addr)
func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetNonce(nonce)
}
}
func (self *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := self.GetOrNewStateObject(addr)
func (s *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetCode(crypto.Keccak256Hash(code), code)
}
}
func (self *StateDB) SetState(addr common.Address, key, value common.Hash) {
stateObject := self.GetOrNewStateObject(addr)
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetState(self.db, key, value)
stateObject.SetState(s.db, key, value)
}
}
@ -390,12 +390,12 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
//
// The account's state object is still available until the state is committed,
// getStateObject will return a non-nil account after Suicide.
func (self *StateDB) Suicide(addr common.Address) bool {
stateObject := self.getStateObject(addr)
func (s *StateDB) Suicide(addr common.Address) bool {
stateObject := s.getStateObject(addr)
if stateObject == nil {
return false
}
self.journal = append(self.journal, suicideChange{
s.journal = append(s.journal, suicideChange{
account: &addr,
prev: stateObject.suicided,
prevbalance: new(big.Int).Set(stateObject.Balance()),
@ -411,34 +411,34 @@ func (self *StateDB) Suicide(addr common.Address) bool {
//
// updateStateObject writes the given object to the trie.
func (self *StateDB) updateStateObject(stateObject *stateObject) {
func (s *StateDB) updateStateObject(stateObject *stateObject) {
addr := stateObject.Address()
data, err := rlp.EncodeToBytes(stateObject)
if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
}
self.setError(self.trie.TryUpdate(addr[:], data))
s.setError(s.trie.TryUpdate(addr[:], data))
}
// deleteStateObject removes the given object from the state trie.
func (self *StateDB) deleteStateObject(stateObject *stateObject) {
func (s *StateDB) deleteStateObject(stateObject *stateObject) {
stateObject.deleted = true
addr := stateObject.Address()
self.setError(self.trie.TryDelete(addr[:]))
s.setError(s.trie.TryDelete(addr[:]))
}
// DeleteAddress removes the address from the state trie.
func (self *StateDB) DeleteAddress(addr common.Address) {
stateObject := self.getStateObject(addr)
func (s *StateDB) DeleteAddress(addr common.Address) {
stateObject := s.getStateObject(addr)
if stateObject != nil && !stateObject.deleted {
self.deleteStateObject(stateObject)
s.deleteStateObject(stateObject)
}
}
// Retrieve a state object given my the address. Returns nil if not found.
func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
func (s *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer 'live' objects.
if obj := self.stateObjects[addr]; obj != nil {
if obj := s.stateObjects[addr]; obj != nil {
if obj.deleted {
return nil
}
@ -446,9 +446,9 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje
}
// Load the object from the database.
enc, err := self.trie.TryGet(addr[:])
enc, err := s.trie.TryGet(addr[:])
if len(enc) == 0 {
self.setError(err)
s.setError(err)
return nil
}
var data Account
@ -457,42 +457,42 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje
return nil
}
// Insert into the live set.
obj := newObject(self, addr, data, self.MarkStateObjectDirty)
self.setStateObject(obj)
obj := newObject(s, addr, data, s.MarkStateObjectDirty)
s.setStateObject(obj)
return obj
}
func (self *StateDB) setStateObject(object *stateObject) {
self.stateObjects[object.Address()] = object
func (s *StateDB) setStateObject(object *stateObject) {
s.stateObjects[object.Address()] = object
}
// Retrieve a state object or create a new state object if nil.
func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
stateObject := self.getStateObject(addr)
func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
stateObject := s.getStateObject(addr)
if stateObject == nil || stateObject.deleted {
stateObject, _ = self.createObject(addr)
stateObject, _ = s.createObject(addr)
}
return stateObject
}
// MarkStateObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *StateDB) MarkStateObjectDirty(addr common.Address) {
self.stateObjectsDirty[addr] = struct{}{}
func (s *StateDB) MarkStateObjectDirty(addr common.Address) {
s.stateObjectsDirty[addr] = struct{}{}
}
// createObject creates a new state object. If there is an existing account with
// the given address, it is overwritten and returned as the second return value.
func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
prev = self.getStateObject(addr)
newobj = newObject(self, addr, Account{}, self.MarkStateObjectDirty)
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
prev = s.getStateObject(addr)
newobj = newObject(s, addr, Account{}, s.MarkStateObjectDirty)
newobj.setNonce(0) // sets the object to dirty
if prev == nil {
self.journal = append(self.journal, createObjectChange{account: &addr})
s.journal = append(s.journal, createObjectChange{account: &addr})
} else {
self.journal = append(self.journal, resetObjectChange{prev: prev})
s.journal = append(s.journal, resetObjectChange{prev: prev})
}
self.setStateObject(newobj)
s.setStateObject(newobj)
return newobj, prev
}
@ -506,8 +506,8 @@ func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObjec
// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
//
// Carrying over the balance ensures that Ether doesn't disappear.
func (self *StateDB) CreateAccount(addr common.Address) {
new, prev := self.createObject(addr)
func (s *StateDB) CreateAccount(addr common.Address) {
new, prev := s.createObject(addr)
if prev != nil {
new.setBalance(prev.data.Balance)
}
@ -537,29 +537,29 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common
// Copy creates a deep, independent copy of the state.
// Snapshots of the copied state cannot be applied to the copy.
func (self *StateDB) Copy() *StateDB {
self.lock.Lock()
defer self.lock.Unlock()
func (s *StateDB) Copy() *StateDB {
s.lock.Lock()
defer s.lock.Unlock()
// Copy all the basic fields, initialize the memory ones
state := &StateDB{
db: self.db,
trie: self.db.CopyTrie(self.trie),
stateObjects: make(map[common.Address]*stateObject, len(self.stateObjectsDirty)),
stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
refund: self.refund,
logs: make(map[common.Hash][]*types.Log, len(self.logs)),
logSize: self.logSize,
db: s.db,
trie: s.db.CopyTrie(s.trie),
stateObjects: make(map[common.Address]*stateObject, len(s.stateObjectsDirty)),
stateObjectsDirty: make(map[common.Address]struct{}, len(s.stateObjectsDirty)),
refund: s.refund,
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
logSize: s.logSize,
preimages: make(map[common.Hash][]byte),
}
// Copy the dirty states, logs, and preimages
for addr := range self.stateObjectsDirty {
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
for addr := range s.stateObjectsDirty {
state.stateObjects[addr] = s.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
state.stateObjectsDirty[addr] = struct{}{}
}
// Deep copy the logs occurred in the scope of block
for hash, logs := range self.logs {
for hash, logs := range s.logs {
cpy := make([]*types.Log, len(logs))
for i, l := range logs {
cpy[i] = new(types.Log)
@ -568,7 +568,7 @@ func (self *StateDB) Copy() *StateDB {
state.logs[hash] = cpy
}
for hash, preimage := range self.preimages {
for hash, preimage := range s.preimages {
state.preimages[hash] = preimage
}
// Do we need to copy the access list? In practice: No. At the start of a
@ -576,42 +576,42 @@ func (self *StateDB) Copy() *StateDB {
// _between_ transactions/blocks, never in the middle of a transaction.
// However, it doesn't cost us much to copy an empty list, so we do it anyway
// to not blow up if we ever decide copy it in the middle of a transaction
state.accessList = self.accessList.Copy()
state.accessList = s.accessList.Copy()
return state
}
// Snapshot returns an identifier for the current revision of the state.
func (self *StateDB) Snapshot() int {
id := self.nextRevisionId
self.nextRevisionId++
self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)})
func (s *StateDB) Snapshot() int {
id := s.nextRevisionId
s.nextRevisionId++
s.validRevisions = append(s.validRevisions, revision{id, len(s.journal)})
return id
}
// RevertToSnapshot reverts all state changes made since the given revision.
func (self *StateDB) RevertToSnapshot(revid int) {
func (s *StateDB) RevertToSnapshot(revid int) {
// Find the snapshot in the stack of valid snapshots.
idx := sort.Search(len(self.validRevisions), func(i int) bool {
return self.validRevisions[i].id >= revid
idx := sort.Search(len(s.validRevisions), func(i int) bool {
return s.validRevisions[i].id >= revid
})
if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid {
if idx == len(s.validRevisions) || s.validRevisions[idx].id != revid {
panic(fmt.Errorf("revision id %v cannot be reverted", revid))
}
snapshot := self.validRevisions[idx].journalIndex
snapshot := s.validRevisions[idx].journalIndex
// Replay the journal to undo changes.
for i := len(self.journal) - 1; i >= snapshot; i-- {
self.journal[i].undo(self)
for i := len(s.journal) - 1; i >= snapshot; i-- {
s.journal[i].undo(s)
}
self.journal = self.journal[:snapshot]
s.journal = s.journal[:snapshot]
// Remove invalidated snapshots from the stack.
self.validRevisions = self.validRevisions[:idx]
s.validRevisions = s.validRevisions[:idx]
}
// GetRefund returns the current value of the refund counter.
func (self *StateDB) GetRefund() uint64 {
return self.refund
func (s *StateDB) GetRefund() uint64 {
return s.refund
}
// Finalise finalises the state by removing the self destructed objects

View file

@ -450,10 +450,10 @@ type Blocks []*Block
type BlockBy func(b1, b2 *Block) bool
func (self BlockBy) Sort(blocks Blocks) {
func (bb BlockBy) Sort(blocks Blocks) {
bs := blockSorter{
blocks: blocks,
by: self,
by: bb,
}
sort.Sort(bs)
}
@ -463,10 +463,12 @@ type blockSorter struct {
by func(b1, b2 *Block) bool
}
func (self blockSorter) Len() int { return len(self.blocks) }
func (self blockSorter) Swap(i, j int) {
self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i]
func (bs blockSorter) Len() int { return len(bs.blocks) }
func (bs blockSorter) Swap(i, j int) {
bs.blocks[i], bs.blocks[j] = bs.blocks[j], bs.blocks[i]
}
func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) }
func (bs blockSorter) Less(i, j int) bool { return bs.by(bs.blocks[i], bs.blocks[j]) }
func Number(b1, b2 *Block) bool { return b1.header.Number.Cmp(b2.header.Number) < 0 }

View file

@ -103,9 +103,9 @@ type Ethereum struct {
Lending *XDCxlending.Lending
}
func (s *Ethereum) AddLesServer(ls LesServer) {
s.lesServer = ls
ls.SetBloomBitsIndexer(s.bloomIndexer)
func (e *Ethereum) AddLesServer(ls LesServer) {
e.lesServer = ls
ls.SetBloomBitsIndexer(e.bloomIndexer)
}
// New creates a new Ethereum object (including the
@ -371,80 +371,80 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chai
// APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func (s *Ethereum) APIs() []rpc.API {
apis := ethapi.GetAPIs(s.ApiBackend, s.BlockChain())
func (e *Ethereum) APIs() []rpc.API {
apis := ethapi.GetAPIs(e.ApiBackend, e.BlockChain())
// Append any APIs exposed explicitly by the consensus engine
apis = append(apis, s.engine.APIs(s.BlockChain())...)
apis = append(apis, e.engine.APIs(e.BlockChain())...)
// Append all the local APIs and return
return append(apis, []rpc.API{
{
Namespace: "eth",
Version: "1.0",
Service: NewPublicEthereumAPI(s),
Service: NewPublicEthereumAPI(e),
Public: true,
}, {
Namespace: "eth",
Version: "1.0",
Service: NewPublicMinerAPI(s),
Service: NewPublicMinerAPI(e),
Public: true,
}, {
Namespace: "eth",
Version: "1.0",
Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux),
Service: downloader.NewPublicDownloaderAPI(e.protocolManager.downloader, e.eventMux),
Public: true,
}, {
Namespace: "miner",
Version: "1.0",
Service: NewPrivateMinerAPI(s),
Service: NewPrivateMinerAPI(e),
Public: false,
}, {
Namespace: "eth",
Version: "1.0",
Service: filters.NewFilterAPI(filters.NewFilterSystem(s.ApiBackend, filters.Config{LogCacheSize: s.config.FilterLogCacheSize}), false),
Service: filters.NewFilterAPI(filters.NewFilterSystem(e.ApiBackend, filters.Config{LogCacheSize: e.config.FilterLogCacheSize}), false),
Public: true,
}, {
Namespace: "admin",
Version: "1.0",
Service: NewPrivateAdminAPI(s),
Service: NewPrivateAdminAPI(e),
}, {
Namespace: "debug",
Version: "1.0",
Service: NewPublicDebugAPI(s),
Service: NewPublicDebugAPI(e),
Public: true,
}, {
Namespace: "debug",
Version: "1.0",
Service: NewPrivateDebugAPI(s.chainConfig, s),
Service: NewPrivateDebugAPI(e.chainConfig, e),
}, {
Namespace: "net",
Version: "1.0",
Service: s.netRPCService,
Service: e.netRPCService,
Public: true,
},
}...)
}
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
s.blockchain.ResetWithGenesisBlock(gb)
func (e *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
e.blockchain.ResetWithGenesisBlock(gb)
}
func (s *Ethereum) Etherbase() (eb common.Address, err error) {
s.lock.RLock()
etherbase := s.etherbase
s.lock.RUnlock()
func (e *Ethereum) Etherbase() (eb common.Address, err error) {
e.lock.RLock()
etherbase := e.etherbase
e.lock.RUnlock()
if etherbase != (common.Address{}) {
return etherbase, nil
}
if wallets := s.AccountManager().Wallets(); len(wallets) > 0 {
if wallets := e.AccountManager().Wallets(); len(wallets) > 0 {
if accounts := wallets[0].Accounts(); len(accounts) > 0 {
etherbase := accounts[0].Address
s.lock.Lock()
s.etherbase = etherbase
s.lock.Unlock()
e.lock.Lock()
e.etherbase = etherbase
e.lock.Unlock()
log.Info("Etherbase automatically configured", "address", etherbase)
return etherbase, nil
@ -454,25 +454,25 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
}
// set in js console via admin interface or wrapper from cli flags
func (self *Ethereum) SetEtherbase(etherbase common.Address) {
self.lock.Lock()
self.etherbase = etherbase
self.lock.Unlock()
func (e *Ethereum) SetEtherbase(etherbase common.Address) {
e.lock.Lock()
e.etherbase = etherbase
e.lock.Unlock()
self.miner.SetEtherbase(etherbase)
e.miner.SetEtherbase(etherbase)
}
// ValidateMasternode checks if node's address is in set of masternodes
func (s *Ethereum) ValidateMasternode() (bool, error) {
eb, err := s.Etherbase()
func (e *Ethereum) ValidateMasternode() (bool, error) {
eb, err := e.Etherbase()
if err != nil {
return false, err
}
if s.chainConfig.XDPoS != nil {
if e.chainConfig.XDPoS != nil {
//check if miner's wallet is in set of validators
c := s.engine.(*XDPoS.XDPoS)
c := e.engine.(*XDPoS.XDPoS)
authorized := c.IsAuthorisedAddress(s.blockchain, s.blockchain.CurrentHeader(), eb)
authorized := c.IsAuthorisedAddress(e.blockchain, e.blockchain.CurrentHeader(), eb)
if !authorized {
//This miner doesn't belong to set of validators
return false, nil
@ -483,14 +483,14 @@ func (s *Ethereum) ValidateMasternode() (bool, error) {
return true, nil
}
func (s *Ethereum) StartStaking(local bool) error {
eb, err := s.Etherbase()
func (e *Ethereum) StartStaking(local bool) error {
eb, err := e.Etherbase()
if err != nil {
log.Error("Cannot start mining without etherbase", "err", err)
return fmt.Errorf("etherbase missing: %v", err)
}
if XDPoS, ok := s.engine.(*XDPoS.XDPoS); ok {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
if XDPoS, ok := e.engine.(*XDPoS.XDPoS); ok {
wallet, err := e.accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "address", eb, "err", err)
return fmt.Errorf("signer missing: %v", err)
@ -502,102 +502,104 @@ func (s *Ethereum) StartStaking(local bool) error {
// mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous
// so noone will ever hit this path, whereas marking sync done on CPU mining
// will ensure that private networks work in single miner mode too.
atomic.StoreUint32(&s.protocolManager.acceptTxs, 1)
atomic.StoreUint32(&e.protocolManager.acceptTxs, 1)
}
go s.miner.Start(eb)
go e.miner.Start(eb)
return nil
}
func (s *Ethereum) StopStaking() {
s.miner.Stop()
func (e *Ethereum) StopStaking() {
e.miner.Stop()
}
func (s *Ethereum) IsStaking() bool { return s.miner.Mining() }
func (s *Ethereum) Miner() *miner.Miner { return s.miner }
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
func (s *Ethereum) Engine() consensus.Engine { return s.engine }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
func (s *Ethereum) IsListening() bool { return true } // Always listening
func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
func (s *Ethereum) NetVersion() uint64 { return s.networkId }
func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
func (e *Ethereum) IsStaking() bool { return e.miner.Mining() }
func (e *Ethereum) Miner() *miner.Miner { return e.miner }
func (e *Ethereum) AccountManager() *accounts.Manager { return e.accountManager }
func (e *Ethereum) BlockChain() *core.BlockChain { return e.blockchain }
func (e *Ethereum) TxPool() *core.TxPool { return e.txPool }
func (e *Ethereum) EventMux() *event.TypeMux { return e.eventMux }
func (e *Ethereum) Engine() consensus.Engine { return e.engine }
func (e *Ethereum) ChainDb() ethdb.Database { return e.chainDb }
func (e *Ethereum) IsListening() bool { return true } // Always listening
func (e *Ethereum) EthVersion() int { return int(e.protocolManager.SubProtocols[0].Version) }
func (e *Ethereum) NetVersion() uint64 { return e.networkId }
func (e *Ethereum) Downloader() *downloader.Downloader { return e.protocolManager.downloader }
// Protocols implements node.Service, returning all the currently configured
// network protocols to start.
func (s *Ethereum) Protocols() []p2p.Protocol {
if s.lesServer == nil {
return s.protocolManager.SubProtocols
func (e *Ethereum) Protocols() []p2p.Protocol {
if e.lesServer == nil {
return e.protocolManager.SubProtocols
}
return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...)
return append(e.protocolManager.SubProtocols, e.lesServer.Protocols()...)
}
// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
func (s *Ethereum) Start(srvr *p2p.Server) error {
func (e *Ethereum) Start(srvr *p2p.Server) error {
// Start the bloom bits servicing goroutines
s.startBloomHandlers()
e.startBloomHandlers()
// Start the RPC service
s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion())
e.netRPCService = ethapi.NewPublicNetAPI(srvr, e.NetVersion())
// Figure out a max peers count based on the server limits
maxPeers := srvr.MaxPeers
if s.config.LightServ > 0 {
if s.config.LightPeers >= srvr.MaxPeers {
return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, srvr.MaxPeers)
if e.config.LightServ > 0 {
if e.config.LightPeers >= srvr.MaxPeers {
return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", e.config.LightPeers, srvr.MaxPeers)
}
maxPeers -= s.config.LightPeers
maxPeers -= e.config.LightPeers
}
// Start the networking layer and the light server if requested
s.protocolManager.Start(maxPeers)
if s.lesServer != nil {
s.lesServer.Start(srvr)
e.protocolManager.Start(maxPeers)
if e.lesServer != nil {
e.lesServer.Start(srvr)
}
return nil
}
func (s *Ethereum) SaveData() {
s.blockchain.SaveData()
func (e *Ethereum) SaveData() {
e.blockchain.SaveData()
}
// Stop implements node.Service, terminating all internal goroutines used by the
// Ethereum protocol.
func (s *Ethereum) Stop() error {
s.bloomIndexer.Close()
s.blockchain.Stop()
s.protocolManager.Stop()
if s.lesServer != nil {
s.lesServer.Stop()
func (e *Ethereum) Stop() error {
e.bloomIndexer.Close()
e.blockchain.Stop()
e.protocolManager.Stop()
if e.lesServer != nil {
e.lesServer.Stop()
}
s.txPool.Stop()
s.miner.Stop()
s.eventMux.Stop()
e.txPool.Stop()
e.miner.Stop()
e.eventMux.Stop()
s.chainDb.Close()
close(s.shutdownChan)
e.chainDb.Close()
close(e.shutdownChan)
return nil
}
func (s *Ethereum) GetPeer() int {
return len(s.protocolManager.peers.peers)
func (e *Ethereum) GetPeer() int {
return len(e.protocolManager.peers.peers)
}
func (s *Ethereum) GetXDCX() *XDCx.XDCX {
return s.XDCX
func (e *Ethereum) GetXDCX() *XDCx.XDCX {
return e.XDCX
}
func (s *Ethereum) OrderPool() *core.OrderPool {
return s.orderPool
func (e *Ethereum) OrderPool() *core.OrderPool {
return e.orderPool
}
func (s *Ethereum) GetXDCXLending() *XDCxlending.Lending {
return s.Lending
func (e *Ethereum) GetXDCXLending() *XDCxlending.Lending {
return e.Lending
}
// LendingPool geth eth lending pool
func (s *Ethereum) LendingPool() *core.LendingPool {
return s.lendingPool
func (e *Ethereum) LendingPool() *core.LendingPool {
return e.lendingPool
}

View file

@ -266,9 +266,11 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
func (pm *ProtocolManager) addOrderPoolProtocol(orderpool orderPool) {
pm.orderpool = orderpool
}
func (pm *ProtocolManager) addLendingPoolProtocol(lendingpool lendingPool) {
pm.lendingpool = lendingpool
}
func (pm *ProtocolManager) removePeer(id string) {
// Short circuit if the peer was already removed
peer := pm.peers.Peer(id)
@ -1037,12 +1039,12 @@ func (pm *ProtocolManager) LendingBroadcastTx(hash common.Hash, tx *types.Lendin
}
// minedBroadcastLoop broadcast loop
func (self *ProtocolManager) minedBroadcastLoop() {
func (pm *ProtocolManager) minedBroadcastLoop() {
// automatically stops if unsubscribe
for obj := range self.minedBlockSub.Chan() {
for obj := range pm.minedBlockSub.Chan() {
switch ev := obj.Data.(type) {
case core.NewMinedBlockEvent:
self.BroadcastBlock(ev.Block, true) // First propagate block to peers
pm.BroadcastBlock(ev.Block, true) // First propagate block to peers
//self.BroadcastBlock(ev.Block, false) // Only then announce to the rest
}
}
@ -1062,34 +1064,34 @@ func (pm *ProtocolManager) txBroadcastLoop() {
}
// orderTxBroadcastLoop broadcast order
func (self *ProtocolManager) orderTxBroadcastLoop() {
if self.orderTxSub == nil {
func (pm *ProtocolManager) orderTxBroadcastLoop() {
if pm.orderTxSub == nil {
return
}
for {
select {
case event := <-self.orderTxCh:
self.OrderBroadcastTx(event.Tx.Hash(), event.Tx)
case event := <-pm.orderTxCh:
pm.OrderBroadcastTx(event.Tx.Hash(), event.Tx)
// Err() channel will be closed when unsubscribing.
case <-self.orderTxSub.Err():
case <-pm.orderTxSub.Err():
return
}
}
}
// lendingTxBroadcastLoop broadcast order
func (self *ProtocolManager) lendingTxBroadcastLoop() {
if self.lendingTxSub == nil {
func (pm *ProtocolManager) lendingTxBroadcastLoop() {
if pm.lendingTxSub == nil {
return
}
for {
select {
case event := <-self.lendingTxCh:
self.LendingBroadcastTx(event.Tx.Hash(), event.Tx)
case event := <-pm.lendingTxCh:
pm.LendingBroadcastTx(event.Tx.Hash(), event.Tx)
// Err() channel will be closed when unsubscribing.
case <-self.lendingTxSub.Err():
case <-pm.lendingTxSub.Err():
return
}
}
@ -1106,13 +1108,13 @@ type NodeInfo struct {
}
// NodeInfo retrieves some protocol metadata about the running host node.
func (self *ProtocolManager) NodeInfo() *NodeInfo {
currentBlock := self.blockchain.CurrentBlock()
func (pm *ProtocolManager) NodeInfo() *NodeInfo {
currentBlock := pm.blockchain.CurrentBlock()
return &NodeInfo{
Network: self.networkId,
Difficulty: self.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()),
Genesis: self.blockchain.Genesis().Hash(),
Config: self.blockchain.Config(),
Network: pm.networkId,
Difficulty: pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()),
Genesis: pm.blockchain.Genesis().Hash(),
Config: pm.blockchain.Config(),
Head: currentBlock.Hash(),
}
}

View file

@ -45,37 +45,37 @@ func New() *Filters {
}
}
func (self *Filters) Start() {
go self.loop()
func (f *Filters) Start() {
go f.loop()
}
func (self *Filters) Stop() {
close(self.quit)
func (f *Filters) Stop() {
close(f.quit)
}
func (self *Filters) Notify(filter Filter, data interface{}) {
self.ch <- FilterEvent{filter, data}
func (f *Filters) Notify(filter Filter, data interface{}) {
f.ch <- FilterEvent{filter, data}
}
func (self *Filters) Install(watcher Filter) int {
self.watchers[self.id] = watcher
self.id++
func (f *Filters) Install(watcher Filter) int {
f.watchers[f.id] = watcher
f.id++
return self.id - 1
return f.id - 1
}
func (self *Filters) Uninstall(id int) {
delete(self.watchers, id)
func (f *Filters) Uninstall(id int) {
delete(f.watchers, id)
}
func (self *Filters) loop() {
func (f *Filters) loop() {
out:
for {
select {
case <-self.quit:
case <-f.quit:
break out
case event := <-self.ch:
for _, watcher := range self.watchers {
case event := <-f.ch:
for _, watcher := range f.watchers {
if reflect.TypeOf(watcher) == reflect.TypeOf(event.filter) {
if watcher.Compare(event.filter) {
watcher.Trigger(event.data)
@ -86,10 +86,10 @@ out:
}
}
func (self *Filters) Match(a, b Filter) bool {
func (f *Filters) Match(a, b Filter) bool {
return reflect.TypeOf(a) == reflect.TypeOf(b) && a.Compare(b)
}
func (self *Filters) Get(i int) Filter {
return self.watchers[i]
func (f *Filters) Get(i int) Filter {
return f.watchers[i]
}

View file

@ -23,18 +23,18 @@ type Generic struct {
Fn func(data interface{})
}
// self = registered, f = incoming
func (self Generic) Compare(f Filter) bool {
// g = registered, f = incoming
func (g Generic) Compare(f Filter) bool {
var strMatch, dataMatch = true, true
filter := f.(Generic)
if (len(self.Str1) > 0 && filter.Str1 != self.Str1) ||
(len(self.Str2) > 0 && filter.Str2 != self.Str2) ||
(len(self.Str3) > 0 && filter.Str3 != self.Str3) {
if (len(g.Str1) > 0 && filter.Str1 != g.Str1) ||
(len(g.Str2) > 0 && filter.Str2 != g.Str2) ||
(len(g.Str3) > 0 && filter.Str3 != g.Str3) {
strMatch = false
}
for k := range self.Data {
for k := range g.Data {
if _, ok := filter.Data[k]; !ok {
return false
}
@ -43,6 +43,6 @@ func (self Generic) Compare(f Filter) bool {
return strMatch && dataMatch
}
func (self Generic) Trigger(data interface{}) {
self.Fn(data)
func (g Generic) Trigger(data interface{}) {
g.Fn(data)
}

View file

@ -35,35 +35,35 @@ type cmNode struct {
finishRecharge mclock.AbsTime
}
func (node *cmNode) update(time mclock.AbsTime) {
dt := int64(time - node.lastUpdate)
node.rcValue += node.rcDelta * dt / rcConst
node.lastUpdate = time
if node.recharging && time >= node.finishRecharge {
node.recharging = false
node.rcDelta = 0
node.rcValue = 0
func (n *cmNode) update(time mclock.AbsTime) {
dt := int64(time - n.lastUpdate)
n.rcValue += n.rcDelta * dt / rcConst
n.lastUpdate = time
if n.recharging && time >= n.finishRecharge {
n.recharging = false
n.rcDelta = 0
n.rcValue = 0
}
}
func (node *cmNode) set(serving bool, simReqCnt, sumWeight uint64) {
if node.serving && !serving {
node.recharging = true
sumWeight += node.rcWeight
func (n *cmNode) set(serving bool, simReqCnt, sumWeight uint64) {
if n.serving && !serving {
n.recharging = true
sumWeight += n.rcWeight
}
node.serving = serving
if node.recharging && serving {
node.recharging = false
sumWeight -= node.rcWeight
n.serving = serving
if n.recharging && serving {
n.recharging = false
sumWeight -= n.rcWeight
}
node.rcDelta = 0
n.rcDelta = 0
if serving {
node.rcDelta = int64(rcConst / simReqCnt)
n.rcDelta = int64(rcConst / simReqCnt)
}
if node.recharging {
node.rcDelta = -int64(node.node.cm.rcRecharge * node.rcWeight / sumWeight)
node.finishRecharge = node.lastUpdate + mclock.AbsTime(node.rcValue*rcConst/(-node.rcDelta))
if n.recharging {
n.rcDelta = -int64(n.node.cm.rcRecharge * n.rcWeight / sumWeight)
n.finishRecharge = n.lastUpdate + mclock.AbsTime(n.rcValue*rcConst/(-n.rcDelta))
}
}
@ -89,16 +89,16 @@ func NewClientManager(rcTarget, maxSimReq, maxRcSum uint64) *ClientManager {
return cm
}
func (self *ClientManager) Stop() {
self.lock.Lock()
defer self.lock.Unlock()
func (cm *ClientManager) Stop() {
cm.lock.Lock()
defer cm.lock.Unlock()
// signal any waiting accept routines to return false
self.nodes = make(map[*cmNode]struct{})
close(self.resumeQueue)
cm.nodes = make(map[*cmNode]struct{})
close(cm.resumeQueue)
}
func (self *ClientManager) addNode(cnode *ClientNode) *cmNode {
func (cm *ClientManager) addNode(cnode *ClientNode) *cmNode {
time := mclock.Now()
node := &cmNode{
node: cnode,
@ -106,28 +106,28 @@ func (self *ClientManager) addNode(cnode *ClientNode) *cmNode {
finishRecharge: time,
rcWeight: 1,
}
self.lock.Lock()
defer self.lock.Unlock()
cm.lock.Lock()
defer cm.lock.Unlock()
self.nodes[node] = struct{}{}
self.update(mclock.Now())
cm.nodes[node] = struct{}{}
cm.update(mclock.Now())
return node
}
func (self *ClientManager) removeNode(node *cmNode) {
self.lock.Lock()
defer self.lock.Unlock()
func (cm *ClientManager) removeNode(node *cmNode) {
cm.lock.Lock()
defer cm.lock.Unlock()
time := mclock.Now()
self.stop(node, time)
delete(self.nodes, node)
self.update(time)
cm.stop(node, time)
delete(cm.nodes, node)
cm.update(time)
}
// recalc sumWeight
func (self *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) {
func (cm *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) {
var sumWeight, rcSum uint64
for node := range self.nodes {
for node := range cm.nodes {
rc := node.recharging
node.update(time)
if rc && !node.recharging {
@ -138,44 +138,44 @@ func (self *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) {
}
rcSum += uint64(node.rcValue)
}
self.sumWeight = sumWeight
self.rcSumValue = rcSum
cm.sumWeight = sumWeight
cm.rcSumValue = rcSum
return
}
func (self *ClientManager) update(time mclock.AbsTime) {
func (cm *ClientManager) update(time mclock.AbsTime) {
for {
firstTime := time
for node := range self.nodes {
for node := range cm.nodes {
if node.recharging && node.finishRecharge < firstTime {
firstTime = node.finishRecharge
}
}
if self.updateNodes(firstTime) {
for node := range self.nodes {
if cm.updateNodes(firstTime) {
for node := range cm.nodes {
if node.recharging {
node.set(node.serving, self.simReqCnt, self.sumWeight)
node.set(node.serving, cm.simReqCnt, cm.sumWeight)
}
}
} else {
self.time = time
cm.time = time
return
}
}
}
func (self *ClientManager) canStartReq() bool {
return self.simReqCnt < self.maxSimReq && self.rcSumValue < self.maxRcSum
func (cm *ClientManager) canStartReq() bool {
return cm.simReqCnt < cm.maxSimReq && cm.rcSumValue < cm.maxRcSum
}
func (self *ClientManager) queueProc() {
for rc := range self.resumeQueue {
func (cm *ClientManager) queueProc() {
for rc := range cm.resumeQueue {
for {
time.Sleep(time.Millisecond * 10)
self.lock.Lock()
self.update(mclock.Now())
cs := self.canStartReq()
self.lock.Unlock()
cm.lock.Lock()
cm.update(mclock.Now())
cs := cm.canStartReq()
cm.lock.Unlock()
if cs {
break
}
@ -184,41 +184,41 @@ func (self *ClientManager) queueProc() {
}
}
func (self *ClientManager) accept(node *cmNode, time mclock.AbsTime) bool {
self.lock.Lock()
defer self.lock.Unlock()
func (cm *ClientManager) accept(node *cmNode, time mclock.AbsTime) bool {
cm.lock.Lock()
defer cm.lock.Unlock()
self.update(time)
if !self.canStartReq() {
cm.update(time)
if !cm.canStartReq() {
resume := make(chan bool)
self.lock.Unlock()
self.resumeQueue <- resume
cm.lock.Unlock()
cm.resumeQueue <- resume
<-resume
self.lock.Lock()
if _, ok := self.nodes[node]; !ok {
cm.lock.Lock()
if _, ok := cm.nodes[node]; !ok {
return false // reject if node has been removed or manager has been stopped
}
}
self.simReqCnt++
node.set(true, self.simReqCnt, self.sumWeight)
cm.simReqCnt++
node.set(true, cm.simReqCnt, cm.sumWeight)
node.startValue = node.rcValue
self.update(self.time)
cm.update(cm.time)
return true
}
func (self *ClientManager) stop(node *cmNode, time mclock.AbsTime) {
func (cm *ClientManager) stop(node *cmNode, time mclock.AbsTime) {
if node.serving {
self.update(time)
self.simReqCnt--
node.set(false, self.simReqCnt, self.sumWeight)
self.update(time)
cm.update(time)
cm.simReqCnt--
node.set(false, cm.simReqCnt, cm.sumWeight)
cm.update(time)
}
}
func (self *ClientManager) processed(node *cmNode, time mclock.AbsTime) (rcValue, rcCost uint64) {
self.lock.Lock()
defer self.lock.Unlock()
func (cm *ClientManager) processed(node *cmNode, time mclock.AbsTime) (rcValue, rcCost uint64) {
cm.lock.Lock()
defer cm.lock.Unlock()
self.stop(node, time)
cm.stop(node, time)
return uint64(node.rcValue), uint64(node.rcValue - node.startValue)
}

View file

@ -1181,15 +1181,15 @@ type NodeInfo struct {
}
// NodeInfo retrieves some protocol metadata about the running host node.
func (self *ProtocolManager) NodeInfo() *NodeInfo {
head := self.blockchain.CurrentHeader()
func (pm *ProtocolManager) NodeInfo() *NodeInfo {
head := pm.blockchain.CurrentHeader()
hash := head.Hash()
return &NodeInfo{
Network: self.networkId,
Difficulty: self.blockchain.GetTd(hash, head.Number.Uint64()),
Genesis: self.blockchain.Genesis().Hash(),
Config: self.blockchain.Config(),
Network: pm.networkId,
Difficulty: pm.blockchain.GetTd(hash, head.Number.Uint64()),
Genesis: pm.blockchain.Genesis().Hash(),
Config: pm.blockchain.Config(),
Head: hash,
}
}

View file

@ -50,47 +50,47 @@ func NewLesTxRelay(ps *peerSet, reqDist *requestDistributor) *LesTxRelay {
return r
}
func (self *LesTxRelay) registerPeer(p *peer) {
self.lock.Lock()
defer self.lock.Unlock()
func (l *LesTxRelay) registerPeer(p *peer) {
l.lock.Lock()
defer l.lock.Unlock()
self.peerList = self.ps.AllPeers()
l.peerList = l.ps.AllPeers()
}
func (self *LesTxRelay) unregisterPeer(p *peer) {
self.lock.Lock()
defer self.lock.Unlock()
func (l *LesTxRelay) unregisterPeer(p *peer) {
l.lock.Lock()
defer l.lock.Unlock()
self.peerList = self.ps.AllPeers()
l.peerList = l.ps.AllPeers()
}
// send sends a list of transactions to at most a given number of peers at
// once, never resending any particular transaction to the same peer twice
func (self *LesTxRelay) send(txs types.Transactions, count int) {
func (l *LesTxRelay) send(txs types.Transactions, count int) {
sendTo := make(map[*peer]types.Transactions)
self.peerStartPos++ // rotate the starting position of the peer list
if self.peerStartPos >= len(self.peerList) {
self.peerStartPos = 0
l.peerStartPos++ // rotate the starting position of the peer list
if l.peerStartPos >= len(l.peerList) {
l.peerStartPos = 0
}
for _, tx := range txs {
hash := tx.Hash()
ltr, ok := self.txSent[hash]
ltr, ok := l.txSent[hash]
if !ok {
ltr = &ltrInfo{
tx: tx,
sentTo: make(map[*peer]struct{}),
}
self.txSent[hash] = ltr
self.txPending[hash] = struct{}{}
l.txSent[hash] = ltr
l.txPending[hash] = struct{}{}
}
if len(self.peerList) > 0 {
if len(l.peerList) > 0 {
cnt := count
pos := self.peerStartPos
pos := l.peerStartPos
for {
peer := self.peerList[pos]
peer := l.peerList[pos]
if _, ok := ltr.sentTo[peer]; !ok {
sendTo[peer] = append(sendTo[peer], tx)
ltr.sentTo[peer] = struct{}{}
@ -100,10 +100,10 @@ func (self *LesTxRelay) send(txs types.Transactions, count int) {
break // sent it to the desired number of peers
}
pos++
if pos == len(self.peerList) {
if pos == len(l.peerList) {
pos = 0
}
if pos == self.peerStartPos {
if pos == l.peerStartPos {
break // tried all available peers
}
}
@ -130,46 +130,46 @@ func (self *LesTxRelay) send(txs types.Transactions, count int) {
return func() { peer.SendTxs(reqID, cost, ll) }
},
}
self.reqDist.queue(rq)
l.reqDist.queue(rq)
}
}
func (self *LesTxRelay) Send(txs types.Transactions) {
self.lock.Lock()
defer self.lock.Unlock()
func (l *LesTxRelay) Send(txs types.Transactions) {
l.lock.Lock()
defer l.lock.Unlock()
self.send(txs, 3)
l.send(txs, 3)
}
func (self *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) {
self.lock.Lock()
defer self.lock.Unlock()
func (l *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) {
l.lock.Lock()
defer l.lock.Unlock()
for _, hash := range mined {
delete(self.txPending, hash)
delete(l.txPending, hash)
}
for _, hash := range rollback {
self.txPending[hash] = struct{}{}
l.txPending[hash] = struct{}{}
}
if len(self.txPending) > 0 {
txs := make(types.Transactions, len(self.txPending))
if len(l.txPending) > 0 {
txs := make(types.Transactions, len(l.txPending))
i := 0
for hash := range self.txPending {
txs[i] = self.txSent[hash].tx
for hash := range l.txPending {
txs[i] = l.txSent[hash].tx
i++
}
self.send(txs, 1)
l.send(txs, 1)
}
}
func (self *LesTxRelay) Discard(hashes []common.Hash) {
self.lock.Lock()
defer self.lock.Unlock()
func (l *LesTxRelay) Discard(hashes []common.Hash) {
l.lock.Lock()
defer l.lock.Unlock()
for _, hash := range hashes {
delete(self.txSent, hash)
delete(self.txPending, hash)
delete(l.txSent, hash)
delete(l.txPending, hash)
}
}

View file

@ -116,45 +116,45 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
}
// addTrustedCheckpoint adds a trusted checkpoint to the blockchain
func (self *LightChain) addTrustedCheckpoint(cp trustedCheckpoint) {
if self.odr.ChtIndexer() != nil {
StoreChtRoot(self.chainDb, cp.sectionIdx, cp.sectionHead, cp.chtRoot)
self.odr.ChtIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
func (lc *LightChain) addTrustedCheckpoint(cp trustedCheckpoint) {
if lc.odr.ChtIndexer() != nil {
StoreChtRoot(lc.chainDb, cp.sectionIdx, cp.sectionHead, cp.chtRoot)
lc.odr.ChtIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
}
if self.odr.BloomTrieIndexer() != nil {
StoreBloomTrieRoot(self.chainDb, cp.sectionIdx, cp.sectionHead, cp.bloomTrieRoot)
self.odr.BloomTrieIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
if lc.odr.BloomTrieIndexer() != nil {
StoreBloomTrieRoot(lc.chainDb, cp.sectionIdx, cp.sectionHead, cp.bloomTrieRoot)
lc.odr.BloomTrieIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
}
if self.odr.BloomIndexer() != nil {
self.odr.BloomIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
if lc.odr.BloomIndexer() != nil {
lc.odr.BloomIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
}
log.Info("Added trusted checkpoint", "chain", cp.name, "block", (cp.sectionIdx+1)*CHTFrequencyClient-1, "hash", cp.sectionHead)
}
func (self *LightChain) getProcInterrupt() bool {
return atomic.LoadInt32(&self.procInterrupt) == 1
func (lc *LightChain) getProcInterrupt() bool {
return atomic.LoadInt32(&lc.procInterrupt) == 1
}
// Odr returns the ODR backend of the chain
func (self *LightChain) Odr() OdrBackend {
return self.odr
func (lc *LightChain) Odr() OdrBackend {
return lc.odr
}
// loadLastState loads the last known chain state from the database. This method
// assumes that the chain manager mutex is held.
func (self *LightChain) loadLastState() error {
if head := core.GetHeadHeaderHash(self.chainDb); head == (common.Hash{}) {
func (lc *LightChain) loadLastState() error {
if head := core.GetHeadHeaderHash(lc.chainDb); head == (common.Hash{}) {
// Corrupt or empty database, init from scratch
self.Reset()
lc.Reset()
} else {
if header := self.GetHeaderByHash(head); header != nil {
self.hc.SetCurrentHeader(header)
if header := lc.GetHeaderByHash(head); header != nil {
lc.hc.SetCurrentHeader(header)
}
}
// Issue a status log and return
header := self.hc.CurrentHeader()
headerTd := self.GetTd(header.Hash(), header.Number.Uint64())
header := lc.hc.CurrentHeader()
headerTd := lc.GetTd(header.Hash(), header.Number.Uint64())
log.Info("Loaded most recent local header", "number", header.Number, "hash", header.Hash(), "td", headerTd)
return nil
@ -162,128 +162,128 @@ func (self *LightChain) loadLastState() error {
// SetHead rewinds the local chain to a new head. Everything above the new
// head will be deleted and the new one set.
func (bc *LightChain) SetHead(head uint64) {
bc.mu.Lock()
defer bc.mu.Unlock()
func (lc *LightChain) SetHead(head uint64) {
lc.mu.Lock()
defer lc.mu.Unlock()
bc.hc.SetHead(head, nil)
bc.loadLastState()
lc.hc.SetHead(head, nil)
lc.loadLastState()
}
// GasLimit returns the gas limit of the current HEAD block.
func (self *LightChain) GasLimit() uint64 {
return self.hc.CurrentHeader().GasLimit
func (lc *LightChain) GasLimit() uint64 {
return lc.hc.CurrentHeader().GasLimit
}
// Reset purges the entire blockchain, restoring it to its genesis state.
func (bc *LightChain) Reset() {
bc.ResetWithGenesisBlock(bc.genesisBlock)
func (lc *LightChain) Reset() {
lc.ResetWithGenesisBlock(lc.genesisBlock)
}
// ResetWithGenesisBlock purges the entire blockchain, restoring it to the
// specified genesis state.
func (bc *LightChain) ResetWithGenesisBlock(genesis *types.Block) {
func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) {
// Dump the entire block chain and purge the caches
bc.SetHead(0)
lc.SetHead(0)
bc.mu.Lock()
defer bc.mu.Unlock()
lc.mu.Lock()
defer lc.mu.Unlock()
// Prepare the genesis block and reinitialise the chain
if err := core.WriteTd(bc.chainDb, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()); err != nil {
if err := core.WriteTd(lc.chainDb, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()); err != nil {
log.Crit("Failed to write genesis block TD", "err", err)
}
rawdb.WriteBlock(bc.chainDb, genesis)
bc.genesisBlock = genesis
bc.hc.SetGenesis(bc.genesisBlock.Header())
bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
rawdb.WriteBlock(lc.chainDb, genesis)
lc.genesisBlock = genesis
lc.hc.SetGenesis(lc.genesisBlock.Header())
lc.hc.SetCurrentHeader(lc.genesisBlock.Header())
}
// Accessors
// Engine retrieves the light chain's consensus engine.
func (bc *LightChain) Engine() consensus.Engine { return bc.engine }
func (lc *LightChain) Engine() consensus.Engine { return lc.engine }
// Genesis returns the genesis block
func (bc *LightChain) Genesis() *types.Block {
return bc.genesisBlock
func (lc *LightChain) Genesis() *types.Block {
return lc.genesisBlock
}
// State returns a new mutable state based on the current HEAD block.
func (bc *LightChain) State() (*state.StateDB, error) {
func (lc *LightChain) State() (*state.StateDB, error) {
return nil, errors.New("not implemented, needs client/server interface split")
}
// GetBody retrieves a block body (transactions and uncles) from the database
// or ODR service by hash, caching it if found.
func (self *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) {
func (lc *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) {
// Short circuit if the body's already in the cache, retrieve otherwise
if cached, ok := self.bodyCache.Get(hash); ok {
if cached, ok := lc.bodyCache.Get(hash); ok {
body := cached.(*types.Body)
return body, nil
}
body, err := GetBody(ctx, self.odr, hash, self.hc.GetBlockNumber(hash))
body, err := GetBody(ctx, lc.odr, hash, lc.hc.GetBlockNumber(hash))
if err != nil {
return nil, err
}
// Cache the found body for next time and return
self.bodyCache.Add(hash, body)
lc.bodyCache.Add(hash, body)
return body, nil
}
// GetBodyRLP retrieves a block body in RLP encoding from the database or
// ODR service by hash, caching it if found.
func (self *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) {
func (lc *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) {
// Short circuit if the body's already in the cache, retrieve otherwise
if cached, ok := self.bodyRLPCache.Get(hash); ok {
if cached, ok := lc.bodyRLPCache.Get(hash); ok {
return cached.(rlp.RawValue), nil
}
body, err := GetBodyRLP(ctx, self.odr, hash, self.hc.GetBlockNumber(hash))
body, err := GetBodyRLP(ctx, lc.odr, hash, lc.hc.GetBlockNumber(hash))
if err != nil {
return nil, err
}
// Cache the found body for next time and return
self.bodyRLPCache.Add(hash, body)
lc.bodyRLPCache.Add(hash, body)
return body, nil
}
// HasBlock checks if a block is fully present in the database or not, caching
// it if present.
func (bc *LightChain) HasBlock(hash common.Hash, number uint64) bool {
blk, _ := bc.GetBlock(NoOdr, hash, number)
func (lc *LightChain) HasBlock(hash common.Hash, number uint64) bool {
blk, _ := lc.GetBlock(NoOdr, hash, number)
return blk != nil
}
// GetBlock retrieves a block from the database or ODR service by hash and number,
// caching it if found.
func (self *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) {
func (lc *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) {
// Short circuit if the block's already in the cache, retrieve otherwise
if block, ok := self.blockCache.Get(hash); ok {
if block, ok := lc.blockCache.Get(hash); ok {
return block.(*types.Block), nil
}
block, err := GetBlock(ctx, self.odr, hash, number)
block, err := GetBlock(ctx, lc.odr, hash, number)
if err != nil {
return nil, err
}
// Cache the found block for next time and return
self.blockCache.Add(block.Hash(), block)
lc.blockCache.Add(block.Hash(), block)
return block, nil
}
// GetBlockByHash retrieves a block from the database or ODR service by hash,
// caching it if found.
func (self *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
return self.GetBlock(ctx, hash, self.hc.GetBlockNumber(hash))
func (lc *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
return lc.GetBlock(ctx, hash, lc.hc.GetBlockNumber(hash))
}
// GetBlockByNumber retrieves a block from the database or ODR service by
// number, caching it (associated with its hash) if found.
func (self *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) {
hash, err := GetCanonicalHash(ctx, self.odr, number)
func (lc *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) {
hash, err := GetCanonicalHash(ctx, lc.odr, number)
if hash == (common.Hash{}) || err != nil {
return nil, err
}
return self.GetBlock(ctx, hash, number)
return lc.GetBlock(ctx, hash, number)
}
func (bc *LightChain) SaveData() {
@ -291,44 +291,44 @@ func (bc *LightChain) SaveData() {
// Stop stops the blockchain service. If any imports are currently in progress
// it will abort them using the procInterrupt.
func (bc *LightChain) Stop() {
if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) {
func (lc *LightChain) Stop() {
if !atomic.CompareAndSwapInt32(&lc.running, 0, 1) {
return
}
close(bc.quit)
atomic.StoreInt32(&bc.procInterrupt, 1)
close(lc.quit)
atomic.StoreInt32(&lc.procInterrupt, 1)
bc.wg.Wait()
lc.wg.Wait()
log.Info("Blockchain manager stopped")
}
// Rollback is designed to remove a chain of links from the database that aren't
// certain enough to be valid.
func (self *LightChain) Rollback(chain []common.Hash) {
self.mu.Lock()
defer self.mu.Unlock()
func (lc *LightChain) Rollback(chain []common.Hash) {
lc.mu.Lock()
defer lc.mu.Unlock()
for i := len(chain) - 1; i >= 0; i-- {
hash := chain[i]
if head := self.hc.CurrentHeader(); head.Hash() == hash {
self.hc.SetCurrentHeader(self.GetHeader(head.ParentHash, head.Number.Uint64()-1))
if head := lc.hc.CurrentHeader(); head.Hash() == hash {
lc.hc.SetCurrentHeader(lc.GetHeader(head.ParentHash, head.Number.Uint64()-1))
}
}
}
// postChainEvents iterates over the events generated by a chain insertion and
// posts them into the event feed.
func (self *LightChain) postChainEvents(events []interface{}) {
func (lc *LightChain) postChainEvents(events []interface{}) {
for _, event := range events {
switch ev := event.(type) {
case core.ChainEvent:
if self.CurrentHeader().Hash() == ev.Hash {
self.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block})
if lc.CurrentHeader().Hash() == ev.Hash {
lc.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block})
}
self.chainFeed.Send(ev)
lc.chainFeed.Send(ev)
case core.ChainSideEvent:
self.chainSideFeed.Send(ev)
lc.chainSideFeed.Send(ev)
}
}
}
@ -344,28 +344,28 @@ func (self *LightChain) postChainEvents(events []interface{}) {
//
// In the case of a light chain, InsertHeaderChain also creates and posts light
// chain events when necessary.
func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
func (lc *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
start := time.Now()
if i, err := self.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
if i, err := lc.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
return i, err
}
// Make sure only one thread manipulates the chain at once
self.chainmu.Lock()
lc.chainmu.Lock()
defer func() {
self.chainmu.Unlock()
lc.chainmu.Unlock()
time.Sleep(time.Millisecond * 10) // ugly hack; do not hog chain lock in case syncing is CPU-limited by validation
}()
self.wg.Add(1)
defer self.wg.Done()
lc.wg.Add(1)
defer lc.wg.Done()
var events []interface{}
whFunc := func(header *types.Header) error {
self.mu.Lock()
defer self.mu.Unlock()
lc.mu.Lock()
defer lc.mu.Unlock()
status, err := self.hc.WriteHeader(header)
status, err := lc.hc.WriteHeader(header)
switch status {
case core.CanonStatTy:
@ -378,91 +378,91 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
}
return err
}
i, err := self.hc.InsertHeaderChain(chain, whFunc, start)
self.postChainEvents(events)
i, err := lc.hc.InsertHeaderChain(chain, whFunc, start)
lc.postChainEvents(events)
return i, err
}
// CurrentHeader retrieves the current head header of the canonical chain. The
// header is retrieved from the HeaderChain's internal cache.
func (self *LightChain) CurrentHeader() *types.Header {
return self.hc.CurrentHeader()
func (lc *LightChain) CurrentHeader() *types.Header {
return lc.hc.CurrentHeader()
}
// GetTd retrieves a block's total difficulty in the canonical chain from the
// database by hash and number, caching it if found.
func (self *LightChain) GetTd(hash common.Hash, number uint64) *big.Int {
return self.hc.GetTd(hash, number)
func (lc *LightChain) GetTd(hash common.Hash, number uint64) *big.Int {
return lc.hc.GetTd(hash, number)
}
// GetTdByHash retrieves a block's total difficulty in the canonical chain from the
// database by hash, caching it if found.
func (self *LightChain) GetTdByHash(hash common.Hash) *big.Int {
return self.hc.GetTdByHash(hash)
func (lc *LightChain) GetTdByHash(hash common.Hash) *big.Int {
return lc.hc.GetTdByHash(hash)
}
// GetHeader retrieves a block header from the database by hash and number,
// caching it if found.
func (self *LightChain) GetHeader(hash common.Hash, number uint64) *types.Header {
return self.hc.GetHeader(hash, number)
func (lc *LightChain) GetHeader(hash common.Hash, number uint64) *types.Header {
return lc.hc.GetHeader(hash, number)
}
// GetHeaderByHash retrieves a block header from the database by hash, caching it if
// found.
func (self *LightChain) GetHeaderByHash(hash common.Hash) *types.Header {
return self.hc.GetHeaderByHash(hash)
func (lc *LightChain) GetHeaderByHash(hash common.Hash) *types.Header {
return lc.hc.GetHeaderByHash(hash)
}
// HasHeader checks if a block header is present in the database or not, caching
// it if present.
func (bc *LightChain) HasHeader(hash common.Hash, number uint64) bool {
return bc.hc.HasHeader(hash, number)
func (lc *LightChain) HasHeader(hash common.Hash, number uint64) bool {
return lc.hc.HasHeader(hash, number)
}
// GetCanonicalHash returns the canonical hash for a given block number
func (bc *LightChain) GetCanonicalHash(number uint64) common.Hash {
return bc.hc.GetCanonicalHash(number)
func (lc *LightChain) GetCanonicalHash(number uint64) common.Hash {
return lc.hc.GetCanonicalHash(number)
}
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
// hash, fetching towards the genesis block.
func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
return self.hc.GetBlockHashesFromHash(hash, max)
func (lc *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
return lc.hc.GetBlockHashesFromHash(hash, max)
}
// GetHeaderByNumber retrieves a block header from the database by number,
// caching it (associated with its hash) if found.
func (self *LightChain) GetHeaderByNumber(number uint64) *types.Header {
return self.hc.GetHeaderByNumber(number)
func (lc *LightChain) GetHeaderByNumber(number uint64) *types.Header {
return lc.hc.GetHeaderByNumber(number)
}
// GetHeaderByNumberOdr retrieves a block header from the database or network
// by number, caching it (associated with its hash) if found.
func (self *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) (*types.Header, error) {
if header := self.hc.GetHeaderByNumber(number); header != nil {
func (lc *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) (*types.Header, error) {
if header := lc.hc.GetHeaderByNumber(number); header != nil {
return header, nil
}
return GetHeaderByNumber(ctx, self.odr, number)
return GetHeaderByNumber(ctx, lc.odr, number)
}
// Config retrieves the header chain's chain configuration.
func (self *LightChain) Config() *params.ChainConfig { return self.hc.Config() }
func (lc *LightChain) Config() *params.ChainConfig { return lc.hc.Config() }
func (self *LightChain) SyncCht(ctx context.Context) bool {
if self.odr.ChtIndexer() == nil {
func (lc *LightChain) SyncCht(ctx context.Context) bool {
if lc.odr.ChtIndexer() == nil {
return false
}
headNum := self.CurrentHeader().Number.Uint64()
chtCount, _, _ := self.odr.ChtIndexer().Sections()
headNum := lc.CurrentHeader().Number.Uint64()
chtCount, _, _ := lc.odr.ChtIndexer().Sections()
if headNum+1 < chtCount*CHTFrequencyClient {
num := chtCount*CHTFrequencyClient - 1
header, err := GetHeaderByNumber(ctx, self.odr, num)
header, err := GetHeaderByNumber(ctx, lc.odr, num)
if header != nil && err == nil {
self.mu.Lock()
if self.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() {
self.hc.SetCurrentHeader(header)
lc.mu.Lock()
if lc.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() {
lc.hc.SetCurrentHeader(header)
}
self.mu.Unlock()
lc.mu.Unlock()
return true
}
}
@ -471,38 +471,38 @@ func (self *LightChain) SyncCht(ctx context.Context) bool {
// LockChain locks the chain mutex for reading so that multiple canonical hashes can be
// retrieved while it is guaranteed that they belong to the same version of the chain
func (self *LightChain) LockChain() {
self.chainmu.RLock()
func (lc *LightChain) LockChain() {
lc.chainmu.RLock()
}
// UnlockChain unlocks the chain mutex
func (self *LightChain) UnlockChain() {
self.chainmu.RUnlock()
func (lc *LightChain) UnlockChain() {
lc.chainmu.RUnlock()
}
// SubscribeChainEvent registers a subscription of ChainEvent.
func (self *LightChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
return self.scope.Track(self.chainFeed.Subscribe(ch))
func (lc *LightChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
return lc.scope.Track(lc.chainFeed.Subscribe(ch))
}
// SubscribeChainHeadEvent registers a subscription of ChainHeadEvent.
func (self *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return self.scope.Track(self.chainHeadFeed.Subscribe(ch))
func (lc *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return lc.scope.Track(lc.chainHeadFeed.Subscribe(ch))
}
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
func (self *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
return self.scope.Track(self.chainSideFeed.Subscribe(ch))
func (lc *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
return lc.scope.Track(lc.chainSideFeed.Subscribe(ch))
}
// SubscribeLogsEvent implements the interface of filters.Backend
// LightChain does not send logs events, so return an empty subscription.
func (self *LightChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
return self.scope.Track(new(event.Feed).Subscribe(ch))
func (lc *LightChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
return lc.scope.Track(new(event.Feed).Subscribe(ch))
}
// SubscribeRemovedLogsEvent implements the interface of filters.Backend
// LightChain does not send core.RemovedLogsEvent, so return an empty subscription.
func (self *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
return self.scope.Track(new(event.Feed).Subscribe(ch))
func (lc *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
return lc.scope.Track(new(event.Feed).Subscribe(ch))
}

View file

@ -113,25 +113,25 @@ func NewTxPool(config *params.ChainConfig, chain *LightChain, relay TxRelayBacke
}
// currentState returns the light state of the current head header
func (pool *TxPool) currentState(ctx context.Context) *state.StateDB {
return NewState(ctx, pool.chain.CurrentHeader(), pool.odr)
func (p *TxPool) currentState(ctx context.Context) *state.StateDB {
return NewState(ctx, p.chain.CurrentHeader(), p.odr)
}
// GetNonce returns the "pending" nonce of a given address. It always queries
// the nonce belonging to the latest header too in order to detect if another
// client using the same key sent a transaction.
func (pool *TxPool) GetNonce(ctx context.Context, addr common.Address) (uint64, error) {
state := pool.currentState(ctx)
func (p *TxPool) GetNonce(ctx context.Context, addr common.Address) (uint64, error) {
state := p.currentState(ctx)
nonce := state.GetNonce(addr)
if state.Error() != nil {
return 0, state.Error()
}
sn, ok := pool.nonce[addr]
sn, ok := p.nonce[addr]
if ok && sn > nonce {
nonce = sn
}
if !ok || sn < nonce {
pool.nonce[addr] = nonce
p.nonce[addr] = nonce
}
return nonce, nil
}
@ -165,52 +165,52 @@ func (txc txStateChanges) getLists() (mined []common.Hash, rollback []common.Has
// checkMinedTxs checks newly added blocks for the currently pending transactions
// and marks them as mined if necessary. It also stores block position in the db
// and adds them to the received txStateChanges map.
func (pool *TxPool) checkMinedTxs(ctx context.Context, hash common.Hash, number uint64, txc txStateChanges) error {
func (p *TxPool) checkMinedTxs(ctx context.Context, hash common.Hash, number uint64, txc txStateChanges) error {
// If no transactions are pending, we don't care about anything
if len(pool.pending) == 0 {
if len(p.pending) == 0 {
return nil
}
block, err := GetBlock(ctx, pool.odr, hash, number)
block, err := GetBlock(ctx, p.odr, hash, number)
if err != nil {
return err
}
// Gather all the local transaction mined in this block
list := pool.mined[hash]
list := p.mined[hash]
for _, tx := range block.Transactions() {
if _, ok := pool.pending[tx.Hash()]; ok {
if _, ok := p.pending[tx.Hash()]; ok {
list = append(list, tx)
}
}
// If some transactions have been mined, write the needed data to disk and update
if list != nil {
// Retrieve all the receipts belonging to this block and write the lookup table
if _, err := GetBlockReceipts(ctx, pool.odr, hash, number); err != nil { // ODR caches, ignore results
if _, err := GetBlockReceipts(ctx, p.odr, hash, number); err != nil { // ODR caches, ignore results
return err
}
if err := core.WriteTxLookupEntries(pool.chainDb, block); err != nil {
if err := core.WriteTxLookupEntries(p.chainDb, block); err != nil {
return err
}
// Update the transaction pool's state
for _, tx := range list {
delete(pool.pending, tx.Hash())
delete(p.pending, tx.Hash())
txc.setState(tx.Hash(), true)
}
pool.mined[hash] = list
p.mined[hash] = list
}
return nil
}
// rollbackTxs marks the transactions contained in recently rolled back blocks
// as rolled back. It also removes any positional lookup entries.
func (pool *TxPool) rollbackTxs(hash common.Hash, txc txStateChanges) {
if list, ok := pool.mined[hash]; ok {
func (p *TxPool) rollbackTxs(hash common.Hash, txc txStateChanges) {
if list, ok := p.mined[hash]; ok {
for _, tx := range list {
txHash := tx.Hash()
core.DeleteTxLookupEntry(pool.chainDb, txHash)
pool.pending[txHash] = tx
core.DeleteTxLookupEntry(p.chainDb, txHash)
p.pending[txHash] = tx
txc.setState(txHash, false)
}
delete(pool.mined, hash)
delete(p.mined, hash)
}
}
@ -220,60 +220,60 @@ func (pool *TxPool) rollbackTxs(hash common.Hash, txc txStateChanges) {
// timeout) occurs during checking new blocks, it leaves the locally known head
// at the latest checked block and still returns a valid txStateChanges, making it
// possible to continue checking the missing blocks at the next chain head event
func (pool *TxPool) reorgOnNewHead(ctx context.Context, newHeader *types.Header) (txStateChanges, error) {
func (p *TxPool) reorgOnNewHead(ctx context.Context, newHeader *types.Header) (txStateChanges, error) {
txc := make(txStateChanges)
oldh := pool.chain.GetHeaderByHash(pool.head)
oldh := p.chain.GetHeaderByHash(p.head)
newh := newHeader
// find common ancestor, create list of rolled back and new block hashes
var oldHashes, newHashes []common.Hash
for oldh.Hash() != newh.Hash() {
if oldh.Number.Uint64() >= newh.Number.Uint64() {
oldHashes = append(oldHashes, oldh.Hash())
oldh = pool.chain.GetHeader(oldh.ParentHash, oldh.Number.Uint64()-1)
oldh = p.chain.GetHeader(oldh.ParentHash, oldh.Number.Uint64()-1)
}
if oldh.Number.Uint64() < newh.Number.Uint64() {
newHashes = append(newHashes, newh.Hash())
newh = pool.chain.GetHeader(newh.ParentHash, newh.Number.Uint64()-1)
newh = p.chain.GetHeader(newh.ParentHash, newh.Number.Uint64()-1)
if newh == nil {
// happens when CHT syncing, nothing to do
newh = oldh
}
}
}
if oldh.Number.Uint64() < pool.clearIdx {
pool.clearIdx = oldh.Number.Uint64()
if oldh.Number.Uint64() < p.clearIdx {
p.clearIdx = oldh.Number.Uint64()
}
// roll back old blocks
for _, hash := range oldHashes {
pool.rollbackTxs(hash, txc)
p.rollbackTxs(hash, txc)
}
pool.head = oldh.Hash()
p.head = oldh.Hash()
// check mined txs of new blocks (array is in reversed order)
for i := len(newHashes) - 1; i >= 0; i-- {
hash := newHashes[i]
if err := pool.checkMinedTxs(ctx, hash, newHeader.Number.Uint64()-uint64(i), txc); err != nil {
if err := p.checkMinedTxs(ctx, hash, newHeader.Number.Uint64()-uint64(i), txc); err != nil {
return txc, err
}
pool.head = hash
p.head = hash
}
// clear old mined tx entries of old blocks
if idx := newHeader.Number.Uint64(); idx > pool.clearIdx+txPermanent {
if idx := newHeader.Number.Uint64(); idx > p.clearIdx+txPermanent {
idx2 := idx - txPermanent
if len(pool.mined) > 0 {
for i := pool.clearIdx; i < idx2; i++ {
hash := core.GetCanonicalHash(pool.chainDb, i)
if list, ok := pool.mined[hash]; ok {
if len(p.mined) > 0 {
for i := p.clearIdx; i < idx2; i++ {
hash := core.GetCanonicalHash(p.chainDb, i)
if list, ok := p.mined[hash]; ok {
hashes := make([]common.Hash, len(list))
for i, tx := range list {
hashes[i] = tx.Hash()
}
pool.relay.Discard(hashes)
delete(pool.mined, hash)
p.relay.Discard(hashes)
delete(p.mined, hash)
}
}
}
pool.clearIdx = idx2
p.clearIdx = idx2
}
return txc, nil
@ -285,66 +285,66 @@ const blockCheckTimeout = time.Second * 3
// eventLoop processes chain head events and also notifies the tx relay backend
// about the new head hash and tx state changes
func (pool *TxPool) eventLoop() {
func (p *TxPool) eventLoop() {
for {
select {
case ev := <-pool.chainHeadCh:
pool.setNewHead(ev.Block.Header())
case ev := <-p.chainHeadCh:
p.setNewHead(ev.Block.Header())
// hack in order to avoid hogging the lock; this part will
// be replaced by a subsequent PR.
time.Sleep(time.Millisecond)
// System stopped
case <-pool.chainHeadSub.Err():
case <-p.chainHeadSub.Err():
return
}
}
}
func (pool *TxPool) setNewHead(head *types.Header) {
pool.mu.Lock()
defer pool.mu.Unlock()
func (p *TxPool) setNewHead(head *types.Header) {
p.mu.Lock()
defer p.mu.Unlock()
ctx, cancel := context.WithTimeout(context.Background(), blockCheckTimeout)
defer cancel()
txc, _ := pool.reorgOnNewHead(ctx, head)
txc, _ := p.reorgOnNewHead(ctx, head)
m, r := txc.getLists()
pool.relay.NewHead(pool.head, m, r)
p.relay.NewHead(p.head, m, r)
// Update fork indicator by next pending block number
next := new(big.Int).Add(head.Number, big.NewInt(1))
pool.homestead = pool.config.IsHomestead(head.Number)
pool.eip2718 = pool.config.IsEIP1559(next)
p.homestead = p.config.IsHomestead(head.Number)
p.eip2718 = p.config.IsEIP1559(next)
}
// Stop stops the light transaction pool
func (pool *TxPool) Stop() {
func (p *TxPool) Stop() {
// Unsubscribe all subscriptions registered from txpool
pool.scope.Close()
p.scope.Close()
// Unsubscribe subscriptions registered from blockchain
pool.chainHeadSub.Unsubscribe()
close(pool.quit)
p.chainHeadSub.Unsubscribe()
close(p.quit)
log.Info("Transaction pool stopped")
}
// SubscribeNewTxsEvent registers a subscription of core.NewTxsEvent and
// starts sending event to the given channel.
func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
return pool.scope.Track(pool.txFeed.Subscribe(ch))
func (p *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
return p.scope.Track(p.txFeed.Subscribe(ch))
}
// Stats returns the number of currently pending (locally created) transactions
func (pool *TxPool) Stats() (pending int) {
pool.mu.RLock()
defer pool.mu.RUnlock()
func (p *TxPool) Stats() (pending int) {
p.mu.RLock()
defer p.mu.RUnlock()
pending = len(pool.pending)
pending = len(p.pending)
return
}
// validateTx checks whether a transaction is valid according to the consensus rules.
func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error {
func (p *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error {
// Validate sender
var (
from common.Address
@ -362,33 +362,33 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// validate minFee slot for XDCZ
if tx.IsXDCZApplyTransaction() {
copyState := pool.currentState(ctx).Copy()
if err := core.ValidateXDCZApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
copyState := p.currentState(ctx).Copy()
if err := core.ValidateXDCZApplyTransaction(p.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
return err
}
}
// validate balance slot, token decimal for XDCX
if tx.IsXDCXApplyTransaction() {
copyState := pool.currentState(ctx).Copy()
if err := core.ValidateXDCXApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
copyState := p.currentState(ctx).Copy()
if err := core.ValidateXDCXApplyTransaction(p.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
return err
}
}
// Validate the transaction sender and it's sig. Throw
// if the from fields is invalid.
if from, err = types.Sender(pool.signer, tx); err != nil {
if from, err = types.Sender(p.signer, tx); err != nil {
return core.ErrInvalidSender
}
// Last but not least check for nonce errors
currentState := pool.currentState(ctx)
currentState := p.currentState(ctx)
if n := currentState.GetNonce(from); n > tx.Nonce() {
return core.ErrNonceTooLow
}
// Check the transaction doesn't exceed the current
// block limit gas.
header := pool.chain.GetHeaderByHash(pool.head)
header := p.chain.GetHeaderByHash(p.head)
if header.GasLimit < tx.Gas() {
return core.ErrGasLimit
}
@ -407,7 +407,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
}
// Should supply enough intrinsic gas
gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, pool.homestead)
gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, p.homestead)
if err != nil {
return err
}
@ -419,80 +419,80 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// add validates a new transaction and sets its state pending if processable.
// It also updates the locally stored nonce if necessary.
func (self *TxPool) add(ctx context.Context, tx *types.Transaction) error {
func (p *TxPool) add(ctx context.Context, tx *types.Transaction) error {
hash := tx.Hash()
if self.pending[hash] != nil {
if p.pending[hash] != nil {
return fmt.Errorf("known transaction (%x)", hash[:4])
}
err := self.validateTx(ctx, tx)
err := p.validateTx(ctx, tx)
if err != nil {
return err
}
if _, ok := self.pending[hash]; !ok {
self.pending[hash] = tx
if _, ok := p.pending[hash]; !ok {
p.pending[hash] = tx
nonce := tx.Nonce() + 1
addr, _ := types.Sender(self.signer, tx)
if nonce > self.nonce[addr] {
self.nonce[addr] = nonce
addr, _ := types.Sender(p.signer, tx)
if nonce > p.nonce[addr] {
p.nonce[addr] = nonce
}
// Notify the subscribers. This event is posted in a goroutine
// because it's possible that somewhere during the post "Remove transaction"
// gets called which will then wait for the global tx pool lock and deadlock.
go self.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
go p.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
}
// Print a log message if low enough level is set
log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(self.signer, tx); return from }}, "to", tx.To())
log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(p.signer, tx); return from }}, "to", tx.To())
return nil
}
// Add adds a transaction to the pool if valid and passes it to the tx relay
// backend
func (self *TxPool) Add(ctx context.Context, tx *types.Transaction) error {
self.mu.Lock()
defer self.mu.Unlock()
func (p *TxPool) Add(ctx context.Context, tx *types.Transaction) error {
p.mu.Lock()
defer p.mu.Unlock()
data, err := tx.MarshalBinary()
if err != nil {
return err
}
if err := self.add(ctx, tx); err != nil {
if err := p.add(ctx, tx); err != nil {
return err
}
//fmt.Println("Send", tx.Hash())
self.relay.Send(types.Transactions{tx})
p.relay.Send(types.Transactions{tx})
self.chainDb.Put(tx.Hash().Bytes(), data)
p.chainDb.Put(tx.Hash().Bytes(), data)
return nil
}
// AddTransactions adds all valid transactions to the pool and passes them to
// the tx relay backend
func (self *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) {
self.mu.Lock()
defer self.mu.Unlock()
func (p *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) {
p.mu.Lock()
defer p.mu.Unlock()
var sendTx types.Transactions
for _, tx := range txs {
if err := self.add(ctx, tx); err == nil {
if err := p.add(ctx, tx); err == nil {
sendTx = append(sendTx, tx)
}
}
if len(sendTx) > 0 {
self.relay.Send(sendTx)
p.relay.Send(sendTx)
}
}
// GetTransaction returns a transaction if it is contained in the pool
// and nil otherwise.
func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction {
func (p *TxPool) GetTransaction(hash common.Hash) *types.Transaction {
// check the txs first
if tx, ok := tp.pending[hash]; ok {
if tx, ok := p.pending[hash]; ok {
return tx
}
return nil
@ -500,13 +500,13 @@ func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction {
// GetTransactions returns all currently processable transactions.
// The returned slice may be modified by the caller.
func (self *TxPool) GetTransactions() (txs types.Transactions, err error) {
self.mu.RLock()
defer self.mu.RUnlock()
func (p *TxPool) GetTransactions() (txs types.Transactions, err error) {
p.mu.RLock()
defer p.mu.RUnlock()
txs = make(types.Transactions, len(self.pending))
txs = make(types.Transactions, len(p.pending))
i := 0
for _, tx := range self.pending {
for _, tx := range p.pending {
txs[i] = tx
i++
}
@ -515,14 +515,14 @@ func (self *TxPool) GetTransactions() (txs types.Transactions, err error) {
// Content retrieves the data content of the transaction pool, returning all the
// pending as well as queued transactions, grouped by account and nonce.
func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
self.mu.RLock()
defer self.mu.RUnlock()
func (p *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
p.mu.RLock()
defer p.mu.RUnlock()
// Retrieve all the pending transactions and sort by account and by nonce
pending := make(map[common.Address]types.Transactions)
for _, tx := range self.pending {
account, _ := types.Sender(self.signer, tx)
for _, tx := range p.pending {
account, _ := types.Sender(p.signer, tx)
pending[account] = append(pending[account], tx)
}
// There are no queued transactions in a light pool, just return an empty map
@ -531,26 +531,26 @@ func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common
}
// RemoveTransactions removes all given transactions from the pool.
func (self *TxPool) RemoveTransactions(txs types.Transactions) {
self.mu.Lock()
defer self.mu.Unlock()
func (p *TxPool) RemoveTransactions(txs types.Transactions) {
p.mu.Lock()
defer p.mu.Unlock()
var hashes []common.Hash
for _, tx := range txs {
//self.RemoveTx(tx.Hash())
hash := tx.Hash()
delete(self.pending, hash)
self.chainDb.Delete(hash[:])
delete(p.pending, hash)
p.chainDb.Delete(hash[:])
hashes = append(hashes, hash)
}
self.relay.Discard(hashes)
p.relay.Discard(hashes)
}
// RemoveTx removes the transaction with the given hash from the pool.
func (pool *TxPool) RemoveTx(hash common.Hash) {
pool.mu.Lock()
defer pool.mu.Unlock()
func (p *TxPool) RemoveTx(hash common.Hash) {
p.mu.Lock()
defer p.mu.Unlock()
// delete from pending pool
delete(pool.pending, hash)
pool.chainDb.Delete(hash[:])
pool.relay.Discard([]common.Hash{hash})
delete(p.pending, hash)
p.chainDb.Delete(hash[:])
p.relay.Discard([]common.Hash{hash})
}

View file

@ -36,19 +36,19 @@ type testTxRelay struct {
send, discard, mined chan int
}
func (self *testTxRelay) Send(txs types.Transactions) {
self.send <- len(txs)
func (r *testTxRelay) Send(txs types.Transactions) {
r.send <- len(txs)
}
func (self *testTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) {
func (r *testTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) {
m := len(mined)
if m != 0 {
self.mined <- m
r.mined <- m
}
}
func (self *testTxRelay) Discard(hashes []common.Hash) {
self.discard <- len(hashes)
func (r *testTxRelay) Discard(hashes []common.Hash) {
r.discard <- len(hashes)
}
const poolTestTxs = 1000

View file

@ -65,7 +65,7 @@ type Batch struct {
Source string `json:"source"`
}
func (self *LibratoClient) PostMetrics(batch Batch) (err error) {
func (lc *LibratoClient) PostMetrics(batch Batch) (err error) {
var (
js []byte
req *http.Request
@ -85,7 +85,7 @@ func (self *LibratoClient) PostMetrics(batch Batch) (err error) {
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(self.Email, self.Token)
req.SetBasicAuth(lc.Email, lc.Token)
if resp, err = http.DefaultClient.Do(req); err != nil {
return

View file

@ -40,14 +40,14 @@ func Librato(r metrics.Registry, d time.Duration, e string, t string, s string,
NewReporter(r, d, e, t, s, p, u).Run()
}
func (self *Reporter) Run() {
func (re *Reporter) Run() {
log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-librato and will be removed from rcrowley/go-metrics on August 5th 2015")
ticker := time.Tick(self.Interval)
metricsApi := &LibratoClient{self.Email, self.Token}
ticker := time.Tick(re.Interval)
metricsApi := &LibratoClient{re.Email, re.Token}
for now := range ticker {
var metrics Batch
var err error
if metrics, err = self.BuildRequest(now, self.Registry); err != nil {
if metrics, err = re.BuildRequest(now, re.Registry); err != nil {
log.Printf("ERROR constructing librato request body %s", err)
continue
}
@ -79,21 +79,21 @@ func sumSquaresTimer(t metrics.Timer) float64 {
return sumSquares
}
func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
func (re *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
snapshot = Batch{
// coerce timestamps to a stepping fn so that they line up in Librato graphs
MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec,
Source: self.Source,
MeasureTime: (now.Unix() / re.intervalSec) * re.intervalSec,
Source: re.Source,
}
snapshot.Gauges = make([]Measurement, 0)
snapshot.Counters = make([]Measurement, 0)
histogramGaugeCount := 1 + len(self.Percentiles)
histogramGaugeCount := 1 + len(re.Percentiles)
r.Each(func(name string, metric interface{}) {
if self.Namespace != "" {
name = fmt.Sprintf("%s.%s", self.Namespace, name)
if re.Namespace != "" {
name = fmt.Sprintf("%s.%s", re.Namespace, name)
}
measurement := Measurement{}
measurement[Period] = self.Interval.Seconds()
measurement[Period] = re.Interval.Seconds()
switch m := metric.(type) {
case metrics.Counter:
if m.Count() > 0 {
@ -125,7 +125,7 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
measurement[Sum] = float64(s.Sum())
measurement[SumSquares] = sumSquares(s)
gauges[0] = measurement
for i, p := range self.Percentiles {
for i, p := range re.Percentiles {
gauges[i+1] = Measurement{
Name: fmt.Sprintf("%s.%.2f", measurement[Name], p),
Value: s.Percentile(p),
@ -142,7 +142,7 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
Measurement{
Name: fmt.Sprintf("%s.%s", name, "1min"),
Value: m.Rate1(),
Period: int64(self.Interval.Seconds()),
Period: int64(re.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
@ -152,7 +152,7 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
Measurement{
Name: fmt.Sprintf("%s.%s", name, "5min"),
Value: m.Rate5(),
Period: int64(self.Interval.Seconds()),
Period: int64(re.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
@ -162,7 +162,7 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
Measurement{
Name: fmt.Sprintf("%s.%s", name, "15min"),
Value: m.Rate15(),
Period: int64(self.Interval.Seconds()),
Period: int64(re.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
@ -184,15 +184,15 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
Max: float64(m.Max()),
Min: float64(m.Min()),
SumSquares: sumSquaresTimer(m),
Period: int64(self.Interval.Seconds()),
Attributes: self.TimerAttributes,
Period: int64(re.Interval.Seconds()),
Attributes: re.TimerAttributes,
}
for i, p := range self.Percentiles {
for i, p := range re.Percentiles {
gauges[i+1] = Measurement{
Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100),
Value: m.Percentile(p),
Period: int64(self.Interval.Seconds()),
Attributes: self.TimerAttributes,
Period: int64(re.Interval.Seconds()),
Attributes: re.TimerAttributes,
}
}
snapshot.Gauges = append(snapshot.Gauges, gauges...)
@ -200,7 +200,7 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.1min"),
Value: m.Rate1(),
Period: int64(self.Interval.Seconds()),
Period: int64(re.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
@ -210,7 +210,7 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.5min"),
Value: m.Rate5(),
Period: int64(self.Interval.Seconds()),
Period: int64(re.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
@ -220,7 +220,7 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.15min"),
Value: m.Rate15(),
Period: int64(self.Interval.Seconds()),
Period: int64(re.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,

View file

@ -49,70 +49,70 @@ func NewCpuAgent(chain consensus.ChainReader, engine consensus.Engine) *CpuAgent
return miner
}
func (self *CpuAgent) Work() chan<- *Work { return self.workCh }
func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch }
func (ca *CpuAgent) Work() chan<- *Work { return ca.workCh }
func (ca *CpuAgent) SetReturnCh(ch chan<- *Result) { ca.returnCh = ch }
func (self *CpuAgent) Stop() {
if !atomic.CompareAndSwapInt32(&self.isMining, 1, 0) {
func (ca *CpuAgent) Stop() {
if !atomic.CompareAndSwapInt32(&ca.isMining, 1, 0) {
return // agent already stopped
}
self.stop <- struct{}{}
ca.stop <- struct{}{}
done:
// Empty work channel
for {
select {
case <-self.workCh:
case <-ca.workCh:
default:
break done
}
}
}
func (self *CpuAgent) Start() {
if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) {
func (ca *CpuAgent) Start() {
if !atomic.CompareAndSwapInt32(&ca.isMining, 0, 1) {
return // agent already started
}
go self.update()
go ca.update()
}
func (self *CpuAgent) update() {
func (ca *CpuAgent) update() {
out:
for {
select {
case work := <-self.workCh:
self.mu.Lock()
if self.quitCurrentOp != nil {
close(self.quitCurrentOp)
case work := <-ca.workCh:
ca.mu.Lock()
if ca.quitCurrentOp != nil {
close(ca.quitCurrentOp)
}
self.quitCurrentOp = make(chan struct{})
go self.mine(work, self.quitCurrentOp)
self.mu.Unlock()
case <-self.stop:
self.mu.Lock()
if self.quitCurrentOp != nil {
close(self.quitCurrentOp)
self.quitCurrentOp = nil
ca.quitCurrentOp = make(chan struct{})
go ca.mine(work, ca.quitCurrentOp)
ca.mu.Unlock()
case <-ca.stop:
ca.mu.Lock()
if ca.quitCurrentOp != nil {
close(ca.quitCurrentOp)
ca.quitCurrentOp = nil
}
self.mu.Unlock()
ca.mu.Unlock()
break out
}
}
}
func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) {
if result, err := self.engine.Seal(self.chain, work.Block, stop); result != nil {
func (ca *CpuAgent) mine(work *Work, stop <-chan struct{}) {
if result, err := ca.engine.Seal(ca.chain, work.Block, stop); result != nil {
log.Info("Successfully sealed new block", "number", result.Number(), "hash", result.Hash())
self.returnCh <- &Result{work, result}
ca.returnCh <- &Result{work, result}
} else {
if err != nil {
log.Warn("Block sealing failed", "err", err)
}
self.returnCh <- nil
ca.returnCh <- nil
}
}
func (self *CpuAgent) GetHashRate() int64 {
if pow, ok := self.engine.(consensus.PoW); ok {
func (ca *CpuAgent) GetHashRate() int64 {
if pow, ok := ca.engine.(consensus.PoW); ok {
return int64(pow.Hashrate())
}
return 0

View file

@ -82,73 +82,73 @@ func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine con
// It's entered once and as soon as `Done` or `Failed` has been broadcasted the events are unregistered and
// the loop is exited. This to prevent a major security vuln where external parties can DOS you with blocks
// and halt your mining operation for as long as the DOS continues.
func (self *Miner) update() {
events := self.mux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{})
func (m *Miner) update() {
events := m.mux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{})
for ev := range events.Chan() {
switch ev.Data.(type) {
case downloader.StartEvent:
atomic.StoreInt32(&self.canStart, 0)
if self.Mining() {
self.Stop()
atomic.StoreInt32(&self.shouldStart, 1)
atomic.StoreInt32(&m.canStart, 0)
if m.Mining() {
m.Stop()
atomic.StoreInt32(&m.shouldStart, 1)
log.Info("Mining aborted due to sync")
}
case downloader.DoneEvent, downloader.FailedEvent:
shouldStart := atomic.LoadInt32(&self.shouldStart) == 1
shouldStart := atomic.LoadInt32(&m.shouldStart) == 1
atomic.StoreInt32(&self.canStart, 1)
atomic.StoreInt32(&self.shouldStart, 0)
atomic.StoreInt32(&m.canStart, 1)
atomic.StoreInt32(&m.shouldStart, 0)
if shouldStart {
self.Start(self.coinbase)
m.Start(m.coinbase)
}
}
}
}
func (self *Miner) Start(coinbase common.Address) {
atomic.StoreInt32(&self.shouldStart, 1)
self.SetEtherbase(coinbase)
func (m *Miner) Start(coinbase common.Address) {
atomic.StoreInt32(&m.shouldStart, 1)
m.SetEtherbase(coinbase)
if atomic.LoadInt32(&self.canStart) == 0 {
if atomic.LoadInt32(&m.canStart) == 0 {
log.Info("Network syncing, will start miner afterwards")
return
}
atomic.StoreInt32(&self.mining, 1)
atomic.StoreInt32(&m.mining, 1)
log.Info("Starting mining operation")
self.worker.start()
self.worker.commitNewWork()
m.worker.start()
m.worker.commitNewWork()
}
func (self *Miner) Stop() {
self.worker.stop()
atomic.StoreInt32(&self.mining, 0)
atomic.StoreInt32(&self.shouldStart, 0)
func (m *Miner) Stop() {
m.worker.stop()
atomic.StoreInt32(&m.mining, 0)
atomic.StoreInt32(&m.shouldStart, 0)
}
func (self *Miner) Register(agent Agent) {
if self.Mining() {
func (m *Miner) Register(agent Agent) {
if m.Mining() {
agent.Start()
}
self.worker.register(agent)
m.worker.register(agent)
}
func (self *Miner) Unregister(agent Agent) {
self.worker.unregister(agent)
func (m *Miner) Unregister(agent Agent) {
m.worker.unregister(agent)
}
func (self *Miner) Mining() bool {
return atomic.LoadInt32(&self.mining) > 0
func (m *Miner) Mining() bool {
return atomic.LoadInt32(&m.mining) > 0
}
func (self *Miner) HashRate() (tot int64) {
if pow, ok := self.engine.(consensus.PoW); ok {
func (m *Miner) HashRate() (tot int64) {
if pow, ok := m.engine.(consensus.PoW); ok {
tot += int64(pow.Hashrate())
}
// do we care this might race? is it worth we're rewriting some
// aspects of the worker/locking up agents so we can get an accurate
// hashrate?
for agent := range self.worker.agents {
for agent := range m.worker.agents {
if _, ok := agent.(*CpuAgent); !ok {
tot += agent.GetHashRate()
}
@ -156,17 +156,17 @@ func (self *Miner) HashRate() (tot int64) {
return
}
func (self *Miner) SetExtra(extra []byte) error {
func (m *Miner) SetExtra(extra []byte) error {
if uint64(len(extra)) > params.MaximumExtraDataSize {
return fmt.Errorf("extra exceeds max length: %d > %v", len(extra), params.MaximumExtraDataSize)
}
self.worker.setExtra(extra)
m.worker.setExtra(extra)
return nil
}
// Pending returns the currently pending block and associated state.
func (self *Miner) Pending() (*types.Block, *state.StateDB) {
return self.worker.pending()
func (m *Miner) Pending() (*types.Block, *state.StateDB) {
return m.worker.pending()
}
// PendingBlock returns the currently pending block.
@ -174,22 +174,22 @@ func (self *Miner) Pending() (*types.Block, *state.StateDB) {
// Note, to access both the pending block and the pending state
// simultaneously, please use Pending(), as the pending state can
// change between multiple method calls
func (self *Miner) PendingBlock() *types.Block {
return self.worker.pendingBlock()
func (m *Miner) PendingBlock() *types.Block {
return m.worker.pendingBlock()
}
// PendingBlockAndReceipts returns the currently pending block and corresponding receipts.
func (miner *Miner) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
return miner.worker.pendingBlockAndReceipts()
func (m *Miner) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
return m.worker.pendingBlockAndReceipts()
}
func (self *Miner) SetEtherbase(addr common.Address) {
self.coinbase = addr
self.worker.setEtherbase(addr)
func (m *Miner) SetEtherbase(addr common.Address) {
m.coinbase = addr
m.worker.setEtherbase(addr)
}
// SubscribePendingLogs starts delivering logs from pending transactions
// to the given channel.
func (self *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscription {
return self.worker.pendingLogsFeed.Subscribe(ch)
func (m *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscription {
return m.worker.pendingLogsFeed.Subscribe(ch)
}

View file

@ -182,16 +182,16 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, coinbase com
return worker
}
func (self *worker) setEtherbase(addr common.Address) {
self.mu.Lock()
defer self.mu.Unlock()
self.coinbase = addr
func (w *worker) setEtherbase(addr common.Address) {
w.mu.Lock()
defer w.mu.Unlock()
w.coinbase = addr
}
func (self *worker) setExtra(extra []byte) {
self.mu.Lock()
defer self.mu.Unlock()
self.extra = extra
func (w *worker) setExtra(extra []byte) {
w.mu.Lock()
defer w.mu.Unlock()
w.extra = extra
}
// pending returns the pending state and corresponding block. The returned
@ -221,56 +221,56 @@ func (w *worker) pendingBlockAndReceipts() (*types.Block, types.Receipts) {
return w.snapshotBlock, w.snapshotReceipts
}
func (self *worker) start() {
self.mu.Lock()
defer self.mu.Unlock()
func (w *worker) start() {
w.mu.Lock()
defer w.mu.Unlock()
atomic.StoreInt32(&self.mining, 1)
atomic.StoreInt32(&w.mining, 1)
// spin up agents
for agent := range self.agents {
for agent := range w.agents {
agent.Start()
}
}
func (self *worker) stop() {
self.wg.Wait()
func (w *worker) stop() {
w.wg.Wait()
self.mu.Lock()
defer self.mu.Unlock()
if atomic.LoadInt32(&self.mining) == 1 {
for agent := range self.agents {
w.mu.Lock()
defer w.mu.Unlock()
if atomic.LoadInt32(&w.mining) == 1 {
for agent := range w.agents {
agent.Stop()
}
}
atomic.StoreInt32(&self.mining, 0)
atomic.StoreInt32(&self.atWork, 0)
atomic.StoreInt32(&w.mining, 0)
atomic.StoreInt32(&w.atWork, 0)
}
func (self *worker) register(agent Agent) {
self.mu.Lock()
defer self.mu.Unlock()
self.agents[agent] = struct{}{}
agent.SetReturnCh(self.recv)
func (w *worker) register(agent Agent) {
w.mu.Lock()
defer w.mu.Unlock()
w.agents[agent] = struct{}{}
agent.SetReturnCh(w.recv)
}
func (self *worker) unregister(agent Agent) {
self.mu.Lock()
defer self.mu.Unlock()
delete(self.agents, agent)
func (w *worker) unregister(agent Agent) {
w.mu.Lock()
defer w.mu.Unlock()
delete(w.agents, agent)
agent.Stop()
}
func (self *worker) update() {
if self.announceTxs {
defer self.txsSub.Unsubscribe()
func (w *worker) update() {
if w.announceTxs {
defer w.txsSub.Unsubscribe()
}
defer self.chainHeadSub.Unsubscribe()
defer self.chainSideSub.Unsubscribe()
defer w.chainHeadSub.Unsubscribe()
defer w.chainSideSub.Unsubscribe()
// timeout waiting for v1 inital value
minePeriod := 2
MinePeriodCh := self.engine.(*XDPoS.XDPoS).MinePeriodCh
MinePeriodCh := w.engine.(*XDPoS.XDPoS).MinePeriodCh
defer close(MinePeriodCh)
timeout := time.NewTimer(time.Duration(minePeriod) * time.Second)
@ -298,73 +298,73 @@ func (self *worker) update() {
timeout.Reset(time.Duration(minePeriod) * time.Second)
case <-c:
if atomic.LoadInt32(&self.mining) == 1 {
self.commitNewWork()
if atomic.LoadInt32(&w.mining) == 1 {
w.commitNewWork()
}
timeout.Reset(time.Duration(minePeriod) * time.Second)
// Handle ChainHeadEvent
case <-self.chainHeadCh:
self.commitNewWork()
case <-w.chainHeadCh:
w.commitNewWork()
timeout.Reset(time.Duration(minePeriod) * time.Second)
// Handle ChainSideEvent
case <-self.chainSideCh:
case <-w.chainSideCh:
// Handle NewTxsEvent
case ev := <-self.txsCh:
case ev := <-w.txsCh:
// Apply transactions to the pending state if we're not mining.
//
// Note all transactions received may not be continuous with transactions
// already included in the current mining block. These transactions will
// be automatically eliminated.
if atomic.LoadInt32(&self.mining) == 0 {
self.currentMu.Lock()
if atomic.LoadInt32(&w.mining) == 0 {
w.currentMu.Lock()
txs := make(map[common.Address]types.Transactions)
for _, tx := range ev.Txs {
acc, _ := types.Sender(self.current.signer, tx)
acc, _ := types.Sender(w.current.signer, tx)
txs[acc] = append(txs[acc], tx)
}
feeCapacity := state.GetTRC21FeeCapacityFromState(self.current.state)
txset, specialTxs := types.NewTransactionsByPriceAndNonce(self.current.signer, txs, nil, feeCapacity)
feeCapacity := state.GetTRC21FeeCapacityFromState(w.current.state)
txset, specialTxs := types.NewTransactionsByPriceAndNonce(w.current.signer, txs, nil, feeCapacity)
tcount := self.current.tcount
self.current.commitTransactions(self.mux, feeCapacity, txset, specialTxs, self.chain, self.coinbase, &self.pendingLogsFeed)
tcount := w.current.tcount
w.current.commitTransactions(w.mux, feeCapacity, txset, specialTxs, w.chain, w.coinbase, &w.pendingLogsFeed)
// Only update the snapshot if any new transactions were added
// to the pending block
if tcount != self.current.tcount {
self.updateSnapshot()
if tcount != w.current.tcount {
w.updateSnapshot()
}
self.currentMu.Unlock()
w.currentMu.Unlock()
} else {
// If we're mining, but nothing is being processed, wake on new transactions
if self.config.XDPoS != nil && self.config.XDPoS.Period == 0 {
self.commitNewWork()
if w.config.XDPoS != nil && w.config.XDPoS.Period == 0 {
w.commitNewWork()
}
}
case <-self.chainHeadSub.Err():
case <-w.chainHeadSub.Err():
return
case <-self.chainSideSub.Err():
case <-w.chainSideSub.Err():
return
}
}
}
func (self *worker) wait() {
func (w *worker) wait() {
for {
mustCommitNewWork := true
for result := range self.recv {
atomic.AddInt32(&self.atWork, -1)
for result := range w.recv {
atomic.AddInt32(&w.atWork, -1)
if result == nil {
continue
}
block := result.Block
if self.config.XDPoS != nil && block.NumberU64() >= self.config.XDPoS.Epoch && len(block.Validator()) == 0 {
self.mux.Post(core.NewMinedBlockEvent{Block: block})
if w.config.XDPoS != nil && block.NumberU64() >= w.config.XDPoS.Epoch && len(block.Validator()) == 0 {
w.mux.Post(core.NewMinedBlockEvent{Block: block})
continue
}
work := result.Work
@ -387,9 +387,9 @@ func (self *worker) wait() {
log.BlockHash = hash
}
// Commit block and state to database.
self.currentMu.Lock()
stat, err := self.chain.WriteBlockWithState(block, receipts, work.state, work.tradingState, work.lendingState)
self.currentMu.Unlock()
w.currentMu.Lock()
stat, err := w.chain.WriteBlockWithState(block, receipts, work.state, work.tradingState, work.lendingState)
w.currentMu.Unlock()
if err != nil {
log.Error("Failed writing block to chain", "err", err)
continue
@ -400,7 +400,7 @@ func (self *worker) wait() {
mustCommitNewWork = false
}
// Broadcast the block and announce chain insertion event
self.mux.Post(core.NewMinedBlockEvent{Block: block})
w.mux.Post(core.NewMinedBlockEvent{Block: block})
var (
events []interface{}
logs = work.state.Logs()
@ -411,7 +411,7 @@ func (self *worker) wait() {
}
if work.config.XDPoS != nil {
// epoch block
isEpochSwitchBlock, _, err := self.engine.(*XDPoS.XDPoS).IsEpochSwitch(block.Header())
isEpochSwitchBlock, _, err := w.engine.(*XDPoS.XDPoS).IsEpochSwitch(block.Header())
if err != nil {
log.Error("[wait] fail to check if block is epoch switch block when worker waiting", "BlockNum", block.Number(), "Hash", block.Hash())
}
@ -419,29 +419,29 @@ func (self *worker) wait() {
core.CheckpointCh <- 1
}
}
self.chain.UpdateBlocksHashCache(block)
self.chain.PostChainEvents(events, logs)
w.chain.UpdateBlocksHashCache(block)
w.chain.PostChainEvents(events, logs)
// Insert the block into the set of pending ones to wait for confirmations
self.unconfirmed.Insert(block.NumberU64(), block.Hash())
w.unconfirmed.Insert(block.NumberU64(), block.Hash())
if mustCommitNewWork {
self.commitNewWork()
w.commitNewWork()
}
if self.config.XDPoS != nil {
c := self.engine.(*XDPoS.XDPoS)
err = c.HandleProposedBlock(self.chain, block.Header())
if w.config.XDPoS != nil {
c := w.engine.(*XDPoS.XDPoS)
err = c.HandleProposedBlock(w.chain, block.Header())
if err != nil {
log.Warn("[wait] Unable to handle new proposed block", "err", err, "number", block.Number(), "hash", block.Hash())
}
authorized := c.IsAuthorisedAddress(self.chain, block.Header(), self.coinbase)
authorized := c.IsAuthorisedAddress(w.chain, block.Header(), w.coinbase)
if !authorized {
valid := false
masternodes := c.GetMasternodes(self.chain, block.Header())
masternodes := c.GetMasternodes(w.chain, block.Header())
for _, m := range masternodes {
if m == self.coinbase {
if m == w.coinbase {
valid = true
break
}
@ -452,8 +452,8 @@ func (self *worker) wait() {
}
}
// Send tx sign to smart contract blockSigners.
if block.NumberU64()%common.MergeSignRange == 0 || !self.config.IsTIP2019(block.Number()) {
if err := contracts.CreateTransactionSign(self.config, self.eth.TxPool(), self.eth.AccountManager(), block, self.chainDb, self.coinbase); err != nil {
if block.NumberU64()%common.MergeSignRange == 0 || !w.config.IsTIP2019(block.Number()) {
if err := contracts.CreateTransactionSign(w.config, w.eth.TxPool(), w.eth.AccountManager(), block, w.chainDb, w.coinbase); err != nil {
log.Error("Fail to create tx sign for signer", "error", err)
}
}
@ -463,12 +463,12 @@ func (self *worker) wait() {
}
// push sends a new work task to currently live miner agents.
func (self *worker) push(work *Work) {
if atomic.LoadInt32(&self.mining) != 1 {
func (w *worker) push(work *Work) {
if atomic.LoadInt32(&w.mining) != 1 {
return
}
for agent := range self.agents {
atomic.AddInt32(&self.atWork, 1)
for agent := range w.agents {
atomic.AddInt32(&w.atWork, 1)
if ch := agent.Work(); ch != nil {
ch <- work
}
@ -502,25 +502,25 @@ func (w *worker) updateSnapshot() {
}
// makeCurrent creates a new environment for the current cycle.
func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error {
func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
// Retrieve the parent state to execute on top and start a prefetcher for
// the miner to speed block sealing up a bit
state, err := self.chain.StateAt(parent.Root())
state, err := w.chain.StateAt(parent.Root())
if err != nil {
return err
}
author, _ := self.chain.Engine().Author(parent.Header())
author, _ := w.chain.Engine().Author(parent.Header())
var XDCxState *tradingstate.TradingStateDB
var lendingState *lendingstate.LendingStateDB
if self.config.XDPoS != nil {
XDCX := self.eth.GetXDCX()
if w.config.XDPoS != nil {
XDCX := w.eth.GetXDCX()
XDCxState, err = XDCX.GetTradingState(parent, author)
if err != nil {
log.Error("Failed to get XDCx state ", "number", parent.Number(), "err", err)
return err
}
lending := self.eth.GetXDCXLending()
lending := w.eth.GetXDCXLending()
lendingState, err = lending.GetLendingState(parent, author)
if err != nil {
log.Error("Failed to get lending state ", "number", parent.Number(), "err", err)
@ -529,8 +529,8 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
}
work := &Work{
config: self.config,
signer: types.MakeSigner(self.config, header.Number),
config: w.config,
signer: types.MakeSigner(w.config, header.Number),
state: state,
parentState: state.Copy(),
tradingState: XDCxState,
@ -544,7 +544,7 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
// Keep track of transactions which return errors so they can be removed
work.tcount = 0
self.current = work
w.current = work
return nil
}
@ -555,37 +555,37 @@ func abs(x int64) int64 {
return x
}
func (self *worker) commitNewWork() {
self.mu.Lock()
defer self.mu.Unlock()
self.uncleMu.Lock()
defer self.uncleMu.Unlock()
self.currentMu.Lock()
defer self.currentMu.Unlock()
func (w *worker) commitNewWork() {
w.mu.Lock()
defer w.mu.Unlock()
w.uncleMu.Lock()
defer w.uncleMu.Unlock()
w.currentMu.Lock()
defer w.currentMu.Unlock()
tstart := time.Now()
c := self.engine.(*XDPoS.XDPoS)
c := w.engine.(*XDPoS.XDPoS)
var parent *types.Block
if c != nil {
parent = c.FindParentBlockToAssign(self.chain, self.chain.CurrentBlock())
parent = c.FindParentBlockToAssign(w.chain, w.chain.CurrentBlock())
} else {
parent = self.chain.CurrentBlock()
parent = w.chain.CurrentBlock()
}
var signers map[common.Address]struct{}
if parent.Hash().Hex() == self.lastParentBlockCommit {
if parent.Hash().Hex() == w.lastParentBlockCommit {
return
}
if !self.announceTxs && atomic.LoadInt32(&self.mining) == 0 {
if !w.announceTxs && atomic.LoadInt32(&w.mining) == 0 {
return
}
// Only try to commit new work if we are mining
if atomic.LoadInt32(&self.mining) == 1 {
if atomic.LoadInt32(&w.mining) == 1 {
// check if we are right after parent's coinbase in the list
if self.config.XDPoS != nil {
ok, err := c.YourTurn(self.chain, parent.Header(), self.coinbase)
if w.config.XDPoS != nil {
ok, err := c.YourTurn(w.chain, parent.Header(), w.coinbase)
if err != nil {
log.Warn("Failed when trying to commit new work", "err", err)
return
@ -612,15 +612,15 @@ func (self *worker) commitNewWork() {
ParentHash: parent.Hash(),
Number: num.Add(num, common.Big1),
GasLimit: params.TargetGasLimit,
Extra: self.extra,
Extra: w.extra,
Time: big.NewInt(tstamp),
}
// Only set the coinbase if we are mining (avoid spurious block rewards)
if atomic.LoadInt32(&self.mining) == 1 {
header.Coinbase = self.coinbase
if atomic.LoadInt32(&w.mining) == 1 {
header.Coinbase = w.coinbase
}
if err := self.engine.Prepare(self.chain, header); err != nil {
if err := w.engine.Prepare(w.chain, header); err != nil {
if err == consensus.ErrNotReadyToPropose {
log.Info("Waiting...", "err", err)
return
@ -629,12 +629,12 @@ func (self *worker) commitNewWork() {
return
}
// If we are care about TheDAO hard-fork check whether to override the extra-data or not
if daoBlock := self.config.DAOForkBlock; daoBlock != nil {
if daoBlock := w.config.DAOForkBlock; daoBlock != nil {
// Check whether the block is among the fork extra-override range
limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 {
// Depending whether we support or oppose the fork, override differently
if self.config.DAOForkSupport {
if w.config.DAOForkSupport {
header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
} else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data
@ -642,14 +642,14 @@ func (self *worker) commitNewWork() {
}
}
// Could potentially happen if starting to mine in an odd state.
err := self.makeCurrent(parent, header)
err := w.makeCurrent(parent, header)
if err != nil {
log.Error("Failed to create mining context", "err", err)
return
}
// Create the current work task and check any fork transitions needed
work := self.current
if self.config.DAOForkSupport && self.config.DAOForkBlock != nil && self.config.DAOForkBlock.Cmp(header.Number) == 0 {
work := w.current
if w.config.DAOForkSupport && w.config.DAOForkBlock != nil && w.config.DAOForkBlock.Cmp(header.Number) == 0 {
misc.ApplyDAOHardFork(work.state)
}
if common.TIPSigning.Cmp(header.Number) == 0 {
@ -670,31 +670,31 @@ func (self *worker) commitNewWork() {
lendingFinalizedTradeTransaction *types.Transaction
)
feeCapacity := state.GetTRC21FeeCapacityFromStateWithCache(parent.Root(), work.state)
if self.config.XDPoS != nil {
isEpochSwitchBlock, _, err := self.engine.(*XDPoS.XDPoS).IsEpochSwitch(header)
if w.config.XDPoS != nil {
isEpochSwitchBlock, _, err := w.engine.(*XDPoS.XDPoS).IsEpochSwitch(header)
if err != nil {
log.Error("[commitNewWork] fail to check if block is epoch switch block when fetching pending transactions", "BlockNum", header.Number, "Hash", header.Hash())
}
if !isEpochSwitchBlock {
pending, err := self.eth.TxPool().Pending()
pending, err := w.eth.TxPool().Pending()
if err != nil {
log.Error("Failed to fetch pending transactions", "err", err)
return
}
txs, specialTxs = types.NewTransactionsByPriceAndNonce(self.current.signer, pending, signers, feeCapacity)
txs, specialTxs = types.NewTransactionsByPriceAndNonce(w.current.signer, pending, signers, feeCapacity)
}
}
if atomic.LoadInt32(&self.mining) == 1 {
wallet, err := self.eth.AccountManager().Find(accounts.Account{Address: self.coinbase})
if atomic.LoadInt32(&w.mining) == 1 {
wallet, err := w.eth.AccountManager().Find(accounts.Account{Address: w.coinbase})
if err != nil {
log.Warn("Can't find coinbase account wallet", "coinbase", self.coinbase, "err", err)
log.Warn("Can't find coinbase account wallet", "coinbase", w.coinbase, "err", err)
return
}
if self.config.XDPoS != nil && self.chain.Config().IsTIPXDCXMiner(header.Number) {
XDCX := self.eth.GetXDCX()
XDCXLending := self.eth.GetXDCXLending()
if XDCX != nil && header.Number.Uint64() > self.config.XDPoS.Epoch {
isEpochSwitchBlock, epochNumber, err := self.engine.(*XDPoS.XDPoS).IsEpochSwitch(header)
if w.config.XDPoS != nil && w.chain.Config().IsTIPXDCXMiner(header.Number) {
XDCX := w.eth.GetXDCX()
XDCXLending := w.eth.GetXDCXLending()
if XDCX != nil && header.Number.Uint64() > w.config.XDPoS.Epoch {
isEpochSwitchBlock, epochNumber, err := w.engine.(*XDPoS.XDPoS).IsEpochSwitch(header)
if err != nil {
log.Error("[commitNewWork] fail to check if block is epoch switch block when performing XDCX and XDCXLending operations", "BlockNum", header.Number, "Hash", header.Hash())
}
@ -709,16 +709,16 @@ func (self *worker) commitNewWork() {
// won't grasp tx at checkpoint
//https://github.com/XinFinOrg/XDPoSChain-v1/pull/416
log.Debug("Start processing order pending")
tradingOrderPending, _ := self.eth.OrderPool().Pending()
tradingOrderPending, _ := w.eth.OrderPool().Pending()
log.Debug("Start processing order pending", "len", len(tradingOrderPending))
tradingTxMatches, tradingMatchingResults = XDCX.ProcessOrderPending(header, self.coinbase, self.chain, tradingOrderPending, work.state, work.tradingState)
tradingTxMatches, tradingMatchingResults = XDCX.ProcessOrderPending(header, w.coinbase, w.chain, tradingOrderPending, work.state, work.tradingState)
log.Debug("trading transaction matches found", "tradingTxMatches", len(tradingTxMatches))
lendingOrderPending, _ := self.eth.LendingPool().Pending()
lendingInput, lendingMatchingResults = XDCXLending.ProcessOrderPending(header, self.coinbase, self.chain, lendingOrderPending, work.state, work.lendingState, work.tradingState)
lendingOrderPending, _ := w.eth.LendingPool().Pending()
lendingInput, lendingMatchingResults = XDCXLending.ProcessOrderPending(header, w.coinbase, w.chain, lendingOrderPending, work.state, work.lendingState, work.tradingState)
log.Debug("lending transaction matches found", "lendingInput", len(lendingInput), "lendingMatchingResults", len(lendingMatchingResults))
if header.Number.Uint64()%self.config.XDPoS.Epoch == common.LiquidateLendingTradeBlock {
updatedTrades, liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades, err = XDCXLending.ProcessLiquidationData(header, self.chain, work.state, work.tradingState, work.lendingState)
if header.Number.Uint64()%w.config.XDPoS.Epoch == common.LiquidateLendingTradeBlock {
updatedTrades, liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades, err = XDCXLending.ProcessLiquidationData(header, w.chain, work.state, work.tradingState, work.lendingState)
if err != nil {
log.Error("Fail when process lending liquidation data ", "error", err)
return
@ -737,16 +737,16 @@ func (self *worker) commitNewWork() {
log.Error("Fail to marshal txMatch", "error", err)
return
}
nonce := work.state.GetNonce(self.coinbase)
nonce := work.state.GetNonce(w.coinbase)
tx := types.NewTransaction(nonce, common.XDCXAddrBinary, big.NewInt(0), txMatchGasLimit, big.NewInt(0), txMatchBytes)
txM, err := wallet.SignTx(accounts.Account{Address: self.coinbase}, tx, self.config.ChainId)
txM, err := wallet.SignTx(accounts.Account{Address: w.coinbase}, tx, w.config.ChainId)
if err != nil {
log.Error("Fail to create tx matches", "error", err)
return
} else {
tradingTransaction = txM
if XDCX.IsSDKNode() {
self.chain.AddMatchingResult(tradingTransaction.Hash(), tradingMatchingResults)
w.chain.AddMatchingResult(tradingTransaction.Hash(), tradingMatchingResults)
}
// force adding trading, lending transaction to this block
if tradingTransaction != nil {
@ -767,16 +767,16 @@ func (self *worker) commitNewWork() {
log.Error("Fail to marshal lendingData", "error", err)
return
}
nonce := work.state.GetNonce(self.coinbase)
nonce := work.state.GetNonce(w.coinbase)
lendingTx := types.NewTransaction(nonce, common.XDCXLendingAddressBinary, big.NewInt(0), txMatchGasLimit, big.NewInt(0), lendingDataBytes)
signedLendingTx, err := wallet.SignTx(accounts.Account{Address: self.coinbase}, lendingTx, self.config.ChainId)
signedLendingTx, err := wallet.SignTx(accounts.Account{Address: w.coinbase}, lendingTx, w.config.ChainId)
if err != nil {
log.Error("Fail to create lending tx", "error", err)
return
} else {
lendingTransaction = signedLendingTx
if XDCX.IsSDKNode() {
self.chain.AddLendingResult(lendingTransaction.Hash(), lendingMatchingResults)
w.chain.AddLendingResult(lendingTransaction.Hash(), lendingMatchingResults)
}
if lendingTransaction != nil {
specialTxs = append(specialTxs, lendingTransaction)
@ -791,16 +791,16 @@ func (self *worker) commitNewWork() {
log.Error("Fail to marshal lendingData", "error", err)
return
}
nonce := work.state.GetNonce(self.coinbase)
nonce := work.state.GetNonce(w.coinbase)
finalizedTx := types.NewTransaction(nonce, common.XDCXLendingFinalizedTradeAddressBinary, big.NewInt(0), txMatchGasLimit, big.NewInt(0), finalizedTradeData)
signedFinalizedTx, err := wallet.SignTx(accounts.Account{Address: self.coinbase}, finalizedTx, self.config.ChainId)
signedFinalizedTx, err := wallet.SignTx(accounts.Account{Address: w.coinbase}, finalizedTx, w.config.ChainId)
if err != nil {
log.Error("Fail to create lending tx", "error", err)
return
} else {
lendingFinalizedTradeTransaction = signedFinalizedTx
if XDCX.IsSDKNode() {
self.chain.AddFinalizedTrades(lendingFinalizedTradeTransaction.Hash(), updatedTrades)
w.chain.AddFinalizedTrades(lendingFinalizedTradeTransaction.Hash(), updatedTrades)
}
if lendingFinalizedTradeTransaction != nil {
specialTxs = append(specialTxs, lendingFinalizedTradeTransaction)
@ -811,8 +811,8 @@ func (self *worker) commitNewWork() {
XDCxStateRoot := work.tradingState.IntermediateRoot()
LendingStateRoot := work.lendingState.IntermediateRoot()
txData := append(XDCxStateRoot.Bytes(), LendingStateRoot.Bytes()...)
tx := types.NewTransaction(work.state.GetNonce(self.coinbase), common.TradingStateAddrBinary, big.NewInt(0), txMatchGasLimit, big.NewInt(0), txData)
txStateRoot, err := wallet.SignTx(accounts.Account{Address: self.coinbase}, tx, self.config.ChainId)
tx := types.NewTransaction(work.state.GetNonce(w.coinbase), common.TradingStateAddrBinary, big.NewInt(0), txMatchGasLimit, big.NewInt(0), txData)
txStateRoot, err := wallet.SignTx(accounts.Account{Address: w.coinbase}, tx, w.config.ChainId)
if err != nil {
log.Error("Fail to create tx state root", "error", err)
return
@ -820,29 +820,29 @@ func (self *worker) commitNewWork() {
specialTxs = append(specialTxs, txStateRoot)
}
}
work.commitTransactions(self.mux, feeCapacity, txs, specialTxs, self.chain, self.coinbase, &self.pendingLogsFeed)
work.commitTransactions(w.mux, feeCapacity, txs, specialTxs, w.chain, w.coinbase, &w.pendingLogsFeed)
// compute uncles for the new block.
var (
uncles []*types.Header
)
// Create the new block to seal with the consensus engine
if work.Block, err = self.engine.Finalize(self.chain, header, work.state, work.parentState, work.txs, uncles, work.receipts); err != nil {
if work.Block, err = w.engine.Finalize(w.chain, header, work.state, work.parentState, work.txs, uncles, work.receipts); err != nil {
log.Error("Failed to finalize block for sealing", "err", err)
return
}
if atomic.LoadInt32(&self.mining) == 1 {
if atomic.LoadInt32(&w.mining) == 1 {
log.Info("Committing new block", "number", work.Block.Number(), "txs", work.tcount, "special-txs", len(specialTxs), "uncles", len(uncles), "elapsed", common.PrettyDuration(time.Since(tstart)))
self.unconfirmed.Shift(work.Block.NumberU64() - 1)
self.lastParentBlockCommit = parent.Hash().Hex()
w.unconfirmed.Shift(work.Block.NumberU64() - 1)
w.lastParentBlockCommit = parent.Hash().Hex()
}
self.push(work)
self.updateSnapshot()
w.push(work)
w.updateSnapshot()
}
func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Address]*big.Int, txs *types.TransactionsByPriceAndNonce, specialTxs types.Transactions, bc *core.BlockChain, coinbase common.Address, pendingLogsFeed *event.Feed) {
gp := new(core.GasPool).AddGas(env.header.GasLimit)
func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Address]*big.Int, txs *types.TransactionsByPriceAndNonce, specialTxs types.Transactions, bc *core.BlockChain, coinbase common.Address, pendingLogsFeed *event.Feed) {
gp := new(core.GasPool).AddGas(w.header.GasLimit)
balanceUpdated := map[common.Address]*big.Int{}
totalFeeUsed := big.NewInt(0)
var coalescedLogs []*types.Log
@ -850,7 +850,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
for _, tx := range specialTxs {
to := tx.To()
//HF number for black-list
if (env.header.Number.Uint64() >= common.BlackListHFNumber) && !common.IsTestnet {
if (w.header.Number.Uint64() >= common.BlackListHFNumber) && !common.IsTestnet {
from := tx.From()
// check if sender is in black list
if from != nil && common.Blacklist[*from] {
@ -891,12 +891,12 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
// during transaction acceptance is the transaction pool.
//
// We use the eip155 signer regardless of the current hf.
from, _ := types.Sender(env.signer, tx)
from, _ := types.Sender(w.signer, tx)
// Check whether the tx is replay protected. If we're not in the EIP155 hf
// phase, start ignoring the sender until we do.
hash := tx.Hash()
if tx.Protected() && !env.config.IsEIP155(env.header.Number) {
log.Trace("Ignoring reply protected special transaction", "hash", hash, "eip155", env.config.EIP155Block)
if tx.Protected() && !w.config.IsEIP155(w.header.Number) {
log.Trace("Ignoring reply protected special transaction", "hash", hash, "eip155", w.config.EIP155Block)
continue
}
if *to == common.BlockSignersBinary {
@ -905,20 +905,20 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
continue
}
blkNumber := binary.BigEndian.Uint64(data[8:40])
if blkNumber >= env.header.Number.Uint64() || blkNumber <= env.header.Number.Uint64()-env.config.XDPoS.Epoch*2 {
log.Trace("Data special transaction invalid number", "hash", hash, "blkNumber", blkNumber, "miner", env.header.Number)
if blkNumber >= w.header.Number.Uint64() || blkNumber <= w.header.Number.Uint64()-w.config.XDPoS.Epoch*2 {
log.Trace("Data special transaction invalid number", "hash", hash, "blkNumber", blkNumber, "miner", w.header.Number)
continue
}
}
// Start executing the transaction
env.state.Prepare(hash, env.tcount)
w.state.Prepare(hash, w.tcount)
nonce := env.state.GetNonce(from)
nonce := w.state.GetNonce(from)
if nonce != tx.Nonce() && !tx.IsSkipNonceTransaction() {
log.Trace("Skipping account with special transaction invalid nonce", "sender", from, "nonce", nonce, "tx nonce ", tx.Nonce(), "to", to)
continue
}
err, logs, tokenFeeUsed, gas := env.commitTransaction(balanceFee, tx, bc, coinbase, gp)
err, logs, tokenFeeUsed, gas := w.commitTransaction(balanceFee, tx, bc, coinbase, gp)
switch err {
case core.ErrNonceTooLow:
// New head notification data race between the transaction pool and miner, shift
@ -930,7 +930,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
case nil:
// Everything ok, collect the logs and shift in the next transaction from the same account
coalescedLogs = append(coalescedLogs, logs...)
env.tcount++
w.tcount++
default:
// Strange error, discard the transaction and get the next in line (note, the
@ -938,7 +938,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
log.Debug("Add Special Transaction failed, account skipped", "hash", hash, "sender", from, "nonce", tx.Nonce(), "to", to, "err", err)
}
if tokenFeeUsed {
fee := common.GetGasFee(env.header.Number.Uint64(), gas)
fee := common.GetGasFee(w.header.Number.Uint64(), gas)
balanceFee[*to] = new(big.Int).Sub(balanceFee[*to], fee)
balanceUpdated[*to] = balanceFee[*to]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
@ -963,7 +963,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
//HF number for black-list
to := tx.To()
if (env.header.Number.Uint64() >= common.BlackListHFNumber) && !common.IsTestnet {
if (w.header.Number.Uint64() >= common.BlackListHFNumber) && !common.IsTestnet {
from := tx.From()
// check if sender is in black list
if from != nil && common.Blacklist[*from] {
@ -1002,18 +1002,18 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
// during transaction acceptance is the transaction pool.
//
// We use the eip155 signer regardless of the current hf.
from, _ := types.Sender(env.signer, tx)
from, _ := types.Sender(w.signer, tx)
hash := tx.Hash()
// Check whether the tx is replay protected. If we're not in the EIP155 hf
// phase, start ignoring the sender until we do.
if tx.Protected() && !env.config.IsEIP155(env.header.Number) {
log.Trace("Ignoring reply protected transaction", "hash", hash, "eip155", env.config.EIP155Block)
if tx.Protected() && !w.config.IsEIP155(w.header.Number) {
log.Trace("Ignoring reply protected transaction", "hash", hash, "eip155", w.config.EIP155Block)
txs.Pop()
continue
}
// Start executing the transaction
env.state.Prepare(hash, env.tcount)
nonce := env.state.GetNonce(from)
w.state.Prepare(hash, w.tcount)
nonce := w.state.GetNonce(from)
if nonce > tx.Nonce() {
// New head notification data race between the transaction pool and miner, shift
log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Nonce())
@ -1026,7 +1026,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
txs.Pop()
continue
}
err, logs, tokenFeeUsed, gas := env.commitTransaction(balanceFee, tx, bc, coinbase, gp)
err, logs, tokenFeeUsed, gas := w.commitTransaction(balanceFee, tx, bc, coinbase, gp)
switch {
case errors.Is(err, core.ErrGasLimitReached):
// Pop the current out-of-gas transaction without shifting in the next from the account
@ -1046,7 +1046,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
case errors.Is(err, nil):
// Everything ok, collect the logs and shift in the next transaction from the same account
coalescedLogs = append(coalescedLogs, logs...)
env.tcount++
w.tcount++
txs.Shift()
case errors.Is(err, core.ErrTxTypeNotSupported):
@ -1061,13 +1061,13 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
txs.Shift()
}
if tokenFeeUsed {
fee := common.GetGasFee(env.header.Number.Uint64(), gas)
fee := common.GetGasFee(w.header.Number.Uint64(), gas)
balanceFee[*to] = new(big.Int).Sub(balanceFee[*to], fee)
balanceUpdated[*to] = balanceFee[*to]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
}
}
state.UpdateTRC21Fee(env.state, balanceUpdated, totalFeeUsed)
state.UpdateTRC21Fee(w.state, balanceUpdated, totalFeeUsed)
// make a copy, the state caches the logs and these logs get "upgraded" from pending to mined
// logs by filling in the block hash when the block was mined by the local miner. This can
// cause a race condition if a log was "upgraded" before the PendingLogsEvent is processed.
@ -1079,27 +1079,27 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
}
pendingLogsFeed.Send(cpy)
}
if env.tcount > 0 {
if w.tcount > 0 {
go func(tcount int) {
err := mux.Post(core.PendingStateEvent{})
if err != nil {
log.Warn("[commitTransactions] Error when sending PendingStateEvent", "tcount", tcount)
}
}(env.tcount)
}(w.tcount)
}
}
func (env *Work) commitTransaction(balanceFee map[common.Address]*big.Int, tx *types.Transaction, bc *core.BlockChain, coinbase common.Address, gp *core.GasPool) (error, []*types.Log, bool, uint64) {
snap := env.state.Snapshot()
func (w *Work) commitTransaction(balanceFee map[common.Address]*big.Int, tx *types.Transaction, bc *core.BlockChain, coinbase common.Address, gp *core.GasPool) (error, []*types.Log, bool, uint64) {
snap := w.state.Snapshot()
receipt, gas, err, tokenFeeUsed := core.ApplyTransaction(env.config, balanceFee, bc, &coinbase, gp, env.state, env.tradingState, env.header, tx, &env.header.GasUsed, vm.Config{})
receipt, gas, err, tokenFeeUsed := core.ApplyTransaction(w.config, balanceFee, bc, &coinbase, gp, w.state, w.tradingState, w.header, tx, &w.header.GasUsed, vm.Config{})
if err != nil {
env.state.RevertToSnapshot(snap)
w.state.RevertToSnapshot(snap)
return err, nil, false, 0
}
env.txs = append(env.txs, tx)
env.receipts = append(env.receipts, receipt)
w.txs = append(w.txs, tx)
w.receipts = append(w.receipts, receipt)
return nil, receipt.Logs, tokenFeeUsed, gas
}

View file

@ -47,21 +47,21 @@ type Msg struct {
// the given value, which must be a pointer.
//
// For the decoding rules, please see package rlp.
func (msg Msg) Decode(val interface{}) error {
s := rlp.NewStream(msg.Payload, uint64(msg.Size))
func (m Msg) Decode(val interface{}) error {
s := rlp.NewStream(m.Payload, uint64(m.Size))
if err := s.Decode(val); err != nil {
return newPeerError(errInvalidMsg, "(code %x) (size %d) %v", msg.Code, msg.Size, err)
return newPeerError(errInvalidMsg, "(code %x) (size %d) %v", m.Code, m.Size, err)
}
return nil
}
func (msg Msg) String() string {
return fmt.Sprintf("msg #%v (%v bytes)", msg.Code, msg.Size)
func (m Msg) String() string {
return fmt.Sprintf("msg #%v (%v bytes)", m.Code, m.Size)
}
// Discard reads any remaining payload data into a black hole.
func (msg Msg) Discard() error {
_, err := io.Copy(io.Discard, msg.Payload)
func (m Msg) Discard() error {
_, err := io.Copy(io.Discard, m.Payload)
return err
}
@ -119,24 +119,24 @@ type eofSignal struct {
// note: when using eofSignal to detect whether a message payload
// has been read, Read might not be called for zero sized messages.
func (r *eofSignal) Read(buf []byte) (int, error) {
if r.count == 0 {
if r.eof != nil {
r.eof <- struct{}{}
r.eof = nil
func (s *eofSignal) Read(buf []byte) (int, error) {
if s.count == 0 {
if s.eof != nil {
s.eof <- struct{}{}
s.eof = nil
}
return 0, io.EOF
}
max := len(buf)
if int(r.count) < len(buf) {
max = int(r.count)
if int(s.count) < len(buf) {
max = int(s.count)
}
n, err := r.wrapped.Read(buf[:max])
r.count -= uint32(n)
if (err != nil || r.count == 0) && r.eof != nil {
r.eof <- struct{}{} // tell Peer that msg has been consumed
r.eof = nil
n, err := s.wrapped.Read(buf[:max])
s.count -= uint32(n)
if (err != nil || s.count == 0) && s.eof != nil {
s.eof <- struct{}{} // tell Peer that msg has been consumed
s.eof = nil
}
return n, err
}
@ -269,15 +269,15 @@ func newMsgEventer(rw MsgReadWriter, feed *event.Feed, peerID discover.NodeID, p
// ReadMsg reads a message from the underlying MsgReadWriter and emits a
// "message received" event
func (self *msgEventer) ReadMsg() (Msg, error) {
msg, err := self.MsgReadWriter.ReadMsg()
func (e *msgEventer) ReadMsg() (Msg, error) {
msg, err := e.MsgReadWriter.ReadMsg()
if err != nil {
return msg, err
}
self.feed.Send(&PeerEvent{
e.feed.Send(&PeerEvent{
Type: PeerEventTypeMsgRecv,
Peer: self.peerID,
Protocol: self.Protocol,
Peer: e.peerID,
Protocol: e.Protocol,
MsgCode: &msg.Code,
MsgSize: &msg.Size,
})
@ -286,15 +286,15 @@ func (self *msgEventer) ReadMsg() (Msg, error) {
// WriteMsg writes a message to the underlying MsgReadWriter and emits a
// "message sent" event
func (self *msgEventer) WriteMsg(msg Msg) error {
err := self.MsgReadWriter.WriteMsg(msg)
func (e *msgEventer) WriteMsg(msg Msg) error {
err := e.MsgReadWriter.WriteMsg(msg)
if err != nil {
return err
}
self.feed.Send(&PeerEvent{
e.feed.Send(&PeerEvent{
Type: PeerEventTypeMsgSend,
Peer: self.peerID,
Protocol: self.Protocol,
Peer: e.peerID,
Protocol: e.Protocol,
MsgCode: &msg.Code,
MsgSize: &msg.Size,
})
@ -303,8 +303,8 @@ func (self *msgEventer) WriteMsg(msg Msg) error {
// Close closes the underlying MsgReadWriter if it implements the io.Closer
// interface
func (self *msgEventer) Close() error {
if v, ok := self.MsgReadWriter.(io.Closer); ok {
func (e *msgEventer) Close() error {
if v, ok := e.MsgReadWriter.(io.Closer); ok {
return v.Close()
}
return nil

View file

@ -48,8 +48,8 @@ func newPeerError(code int, format string, v ...interface{}) *peerError {
return err
}
func (self *peerError) Error() string {
return self.message
func (e *peerError) Error() string {
return e.message
}
var errProtocolReturned = errors.New("protocol returned")

View file

@ -51,18 +51,18 @@ func NewSimAdapter(services map[string]ServiceFunc) *SimAdapter {
}
// Name returns the name of the adapter for logging purposes
func (s *SimAdapter) Name() string {
func (sa *SimAdapter) Name() string {
return "sim-adapter"
}
// NewNode returns a new SimNode using the given config
func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
s.mtx.Lock()
defer s.mtx.Unlock()
func (sa *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
sa.mtx.Lock()
defer sa.mtx.Unlock()
// check a node with the ID doesn't already exist
id := config.ID
if _, exists := s.nodes[id]; exists {
if _, exists := sa.nodes[id]; exists {
return nil, fmt.Errorf("node already exists: %s", id)
}
@ -71,7 +71,7 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
return nil, errors.New("node must have at least one service")
}
for _, service := range config.Services {
if _, exists := s.services[service]; !exists {
if _, exists := sa.services[service]; !exists {
return nil, fmt.Errorf("unknown node service %q", service)
}
}
@ -81,7 +81,7 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
PrivateKey: config.PrivateKey,
MaxPeers: math.MaxInt32,
NoDiscovery: true,
Dialer: s,
Dialer: sa,
EnableMsgEvents: true,
},
NoUSB: true,
@ -95,18 +95,18 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
ID: id,
config: config,
node: n,
adapter: s,
adapter: sa,
running: make(map[string]node.Service),
connected: make(map[discover.NodeID]bool),
}
s.nodes[id] = simNode
sa.nodes[id] = simNode
return simNode, nil
}
// Dial implements the p2p.NodeDialer interface by connecting to the node using
// an in-memory net.Pipe connection
func (s *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
node, ok := s.GetNode(dest.ID)
func (sa *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
node, ok := sa.GetNode(dest.ID)
if !ok {
return nil, fmt.Errorf("unknown node: %s", dest.ID)
}
@ -125,8 +125,8 @@ func (s *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
// DialRPC implements the RPCDialer interface by creating an in-memory RPC
// client of the given node
func (s *SimAdapter) DialRPC(id discover.NodeID) (*rpc.Client, error) {
node, ok := s.GetNode(id)
func (sa *SimAdapter) DialRPC(id discover.NodeID) (*rpc.Client, error) {
node, ok := sa.GetNode(id)
if !ok {
return nil, fmt.Errorf("unknown node: %s", id)
}
@ -138,10 +138,10 @@ func (s *SimAdapter) DialRPC(id discover.NodeID) (*rpc.Client, error) {
}
// GetNode returns the node with the given ID if it exists
func (s *SimAdapter) GetNode(id discover.NodeID) (*SimNode, bool) {
s.mtx.RLock()
defer s.mtx.RUnlock()
node, ok := s.nodes[id]
func (sa *SimAdapter) GetNode(id discover.NodeID) (*SimNode, bool) {
sa.mtx.RLock()
defer sa.mtx.RUnlock()
node, ok := sa.nodes[id]
return node, ok
}
@ -161,30 +161,30 @@ type SimNode struct {
}
// Addr returns the node's discovery address
func (self *SimNode) Addr() []byte {
return []byte(self.Node().String())
func (sn *SimNode) Addr() []byte {
return []byte(sn.Node().String())
}
// Node returns a discover.Node representing the SimNode
func (self *SimNode) Node() *discover.Node {
return discover.NewNode(self.ID, net.IP{127, 0, 0, 1}, 30303, 30303)
func (sn *SimNode) Node() *discover.Node {
return discover.NewNode(sn.ID, net.IP{127, 0, 0, 1}, 30303, 30303)
}
// Client returns an rpc.Client which can be used to communicate with the
// underlying services (it is set once the node has started)
func (self *SimNode) Client() (*rpc.Client, error) {
self.lock.RLock()
defer self.lock.RUnlock()
if self.client == nil {
func (sn *SimNode) Client() (*rpc.Client, error) {
sn.lock.RLock()
defer sn.lock.RUnlock()
if sn.client == nil {
return nil, errors.New("node not started")
}
return self.client, nil
return sn.client, nil
}
// ServeRPC serves RPC requests over the given connection by creating an
// in-memory client to the node's RPC server
func (self *SimNode) ServeRPC(conn *websocket.Conn) error {
handler, err := self.node.RPCHandler()
func (sn *SimNode) ServeRPC(conn *websocket.Conn) error {
handler, err := sn.node.RPCHandler()
if err != nil {
return err
}
@ -195,13 +195,13 @@ func (self *SimNode) ServeRPC(conn *websocket.Conn) error {
// Snapshots creates snapshots of the services by calling the
// simulation_snapshot RPC method
func (self *SimNode) Snapshots() (map[string][]byte, error) {
self.lock.RLock()
services := make(map[string]node.Service, len(self.running))
for name, service := range self.running {
func (sn *SimNode) Snapshots() (map[string][]byte, error) {
sn.lock.RLock()
services := make(map[string]node.Service, len(sn.running))
for name, service := range sn.running {
services[name] = service
}
self.lock.RUnlock()
sn.lock.RUnlock()
if len(services) == 0 {
return nil, errors.New("no running services")
}
@ -221,23 +221,23 @@ func (self *SimNode) Snapshots() (map[string][]byte, error) {
}
// Start registers the services and starts the underlying devp2p node
func (self *SimNode) Start(snapshots map[string][]byte) error {
func (sn *SimNode) Start(snapshots map[string][]byte) error {
newService := func(name string) func(ctx *node.ServiceContext) (node.Service, error) {
return func(nodeCtx *node.ServiceContext) (node.Service, error) {
ctx := &ServiceContext{
RPCDialer: self.adapter,
RPCDialer: sn.adapter,
NodeContext: nodeCtx,
Config: self.config,
Config: sn.config,
}
if snapshots != nil {
ctx.Snapshot = snapshots[name]
}
serviceFunc := self.adapter.services[name]
serviceFunc := sn.adapter.services[name]
service, err := serviceFunc(ctx)
if err != nil {
return nil, err
}
self.running[name] = service
sn.running[name] = service
return service, nil
}
}
@ -245,9 +245,9 @@ func (self *SimNode) Start(snapshots map[string][]byte) error {
// ensure we only register the services once in the case of the node
// being stopped and then started again
var regErr error
self.registerOnce.Do(func() {
for _, name := range self.config.Services {
if err := self.node.Register(newService(name)); err != nil {
sn.registerOnce.Do(func() {
for _, name := range sn.config.Services {
if err := sn.node.Register(newService(name)); err != nil {
regErr = err
return
}
@ -257,54 +257,54 @@ func (self *SimNode) Start(snapshots map[string][]byte) error {
return regErr
}
if err := self.node.Start(); err != nil {
if err := sn.node.Start(); err != nil {
return err
}
// create an in-process RPC client
handler, err := self.node.RPCHandler()
handler, err := sn.node.RPCHandler()
if err != nil {
return err
}
self.lock.Lock()
self.client = rpc.DialInProc(handler)
self.lock.Unlock()
sn.lock.Lock()
sn.client = rpc.DialInProc(handler)
sn.lock.Unlock()
return nil
}
// Stop closes the RPC client and stops the underlying devp2p node
func (self *SimNode) Stop() error {
self.lock.Lock()
if self.client != nil {
self.client.Close()
self.client = nil
func (sn *SimNode) Stop() error {
sn.lock.Lock()
if sn.client != nil {
sn.client.Close()
sn.client = nil
}
self.lock.Unlock()
return self.node.Stop()
sn.lock.Unlock()
return sn.node.Stop()
}
// Services returns a copy of the underlying services
func (self *SimNode) Services() []node.Service {
self.lock.RLock()
defer self.lock.RUnlock()
services := make([]node.Service, 0, len(self.running))
for _, service := range self.running {
func (sn *SimNode) Services() []node.Service {
sn.lock.RLock()
defer sn.lock.RUnlock()
services := make([]node.Service, 0, len(sn.running))
for _, service := range sn.running {
services = append(services, service)
}
return services
}
// Server returns the underlying p2p.Server
func (self *SimNode) Server() *p2p.Server {
return self.node.Server()
func (sn *SimNode) Server() *p2p.Server {
return sn.node.Server()
}
// SubscribeEvents subscribes the given channel to peer events from the
// underlying p2p.Server
func (self *SimNode) SubscribeEvents(ch chan *p2p.PeerEvent) event.Subscription {
srv := self.Server()
func (sn *SimNode) SubscribeEvents(ch chan *p2p.PeerEvent) event.Subscription {
srv := sn.Server()
if srv == nil {
panic("node not running")
}
@ -312,12 +312,12 @@ func (self *SimNode) SubscribeEvents(ch chan *p2p.PeerEvent) event.Subscription
}
// NodeInfo returns information about the node
func (self *SimNode) NodeInfo() *p2p.NodeInfo {
server := self.Server()
func (sn *SimNode) NodeInfo() *p2p.NodeInfo {
server := sn.Server()
if server == nil {
return &p2p.NodeInfo{
ID: self.ID.String(),
Enode: self.Node().String(),
ID: sn.ID.String(),
Enode: sn.Node().String(),
}
}
return server.NodeInfo()

View file

@ -20,12 +20,12 @@ type SimStateStore struct {
m map[string][]byte
}
func (self *SimStateStore) Load(s string) ([]byte, error) {
return self.m[s], nil
func (sss *SimStateStore) Load(s string) ([]byte, error) {
return sss.m[s], nil
}
func (self *SimStateStore) Save(s string, data []byte) error {
self.m[s] = data
func (sss *SimStateStore) Save(s string, data []byte) error {
sss.m[s] = data
return nil
}

View file

@ -74,22 +74,22 @@ func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network
}
// Events returns the output event feed of the Network.
func (self *Network) Events() *event.Feed {
return &self.events
func (net *Network) Events() *event.Feed {
return &net.events
}
// NewNode adds a new node to the network with a random ID
func (self *Network) NewNode() (*Node, error) {
func (net *Network) NewNode() (*Node, error) {
conf := adapters.RandomNodeConfig()
conf.Services = []string{self.DefaultService}
return self.NewNodeWithConfig(conf)
conf.Services = []string{net.DefaultService}
return net.NewNodeWithConfig(conf)
}
// NewNodeWithConfig adds a new node to the network with the given config,
// returning an error if a node with the same ID or name already exists
func (self *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) {
self.lock.Lock()
defer self.lock.Unlock()
func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) {
net.lock.Lock()
defer net.lock.Unlock()
// create a random ID and PrivateKey if not set
if conf.ID == (discover.NodeID{}) {
@ -100,31 +100,31 @@ func (self *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error)
id := conf.ID
if conf.Reachable == nil {
conf.Reachable = func(otherID discover.NodeID) bool {
_, err := self.InitConn(conf.ID, otherID)
_, err := net.InitConn(conf.ID, otherID)
return err == nil
}
}
// assign a name to the node if not set
if conf.Name == "" {
conf.Name = fmt.Sprintf("node%02d", len(self.Nodes)+1)
conf.Name = fmt.Sprintf("node%02d", len(net.Nodes)+1)
}
// check the node doesn't already exist
if node := self.getNode(id); node != nil {
if node := net.getNode(id); node != nil {
return nil, fmt.Errorf("node with ID %q already exists", id)
}
if node := self.getNodeByName(conf.Name); node != nil {
if node := net.getNodeByName(conf.Name); node != nil {
return nil, fmt.Errorf("node with name %q already exists", conf.Name)
}
// if no services are configured, use the default service
if len(conf.Services) == 0 {
conf.Services = []string{self.DefaultService}
conf.Services = []string{net.DefaultService}
}
// use the NodeAdapter to create the node
adapterNode, err := self.nodeAdapter.NewNode(conf)
adapterNode, err := net.nodeAdapter.NewNode(conf)
if err != nil {
return nil, err
}
@ -133,27 +133,27 @@ func (self *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error)
Config: conf,
}
log.Trace(fmt.Sprintf("node %v created", id))
self.nodeMap[id] = len(self.Nodes)
self.Nodes = append(self.Nodes, node)
net.nodeMap[id] = len(net.Nodes)
net.Nodes = append(net.Nodes, node)
// emit a "control" event
self.events.Send(ControlEvent(node))
net.events.Send(ControlEvent(node))
return node, nil
}
// Config returns the network configuration
func (self *Network) Config() *NetworkConfig {
return &self.NetworkConfig
func (net *Network) Config() *NetworkConfig {
return &net.NetworkConfig
}
// StartAll starts all nodes in the network
func (self *Network) StartAll() error {
for _, node := range self.Nodes {
func (net *Network) StartAll() error {
for _, node := range net.Nodes {
if node.Up {
continue
}
if err := self.Start(node.ID()); err != nil {
if err := net.Start(node.ID()); err != nil {
return err
}
}
@ -161,12 +161,12 @@ func (self *Network) StartAll() error {
}
// StopAll stops all nodes in the network
func (self *Network) StopAll() error {
for _, node := range self.Nodes {
func (net *Network) StopAll() error {
for _, node := range net.Nodes {
if !node.Up {
continue
}
if err := self.Stop(node.ID()); err != nil {
if err := net.Stop(node.ID()); err != nil {
return err
}
}
@ -174,21 +174,21 @@ func (self *Network) StopAll() error {
}
// Start starts the node with the given ID
func (self *Network) Start(id discover.NodeID) error {
return self.startWithSnapshots(id, nil)
func (net *Network) Start(id discover.NodeID) error {
return net.startWithSnapshots(id, nil)
}
// startWithSnapshots starts the node with the given ID using the give
// snapshots
func (self *Network) startWithSnapshots(id discover.NodeID, snapshots map[string][]byte) error {
node := self.GetNode(id)
func (net *Network) startWithSnapshots(id discover.NodeID, snapshots map[string][]byte) error {
node := net.GetNode(id)
if node == nil {
return fmt.Errorf("node %v does not exist", id)
}
if node.Up {
return fmt.Errorf("node %v already up", id)
}
log.Trace(fmt.Sprintf("starting node %v: %v using %v", id, node.Up, self.nodeAdapter.Name()))
log.Trace(fmt.Sprintf("starting node %v: %v using %v", id, node.Up, net.nodeAdapter.Name()))
if err := node.Start(snapshots); err != nil {
log.Warn(fmt.Sprintf("start up failed: %v", err))
return err
@ -196,7 +196,7 @@ func (self *Network) startWithSnapshots(id discover.NodeID, snapshots map[string
node.Up = true
log.Info(fmt.Sprintf("started node %v: %v", id, node.Up))
self.events.Send(NewEvent(node))
net.events.Send(NewEvent(node))
// subscribe to peer events
client, err := node.Client()
@ -208,22 +208,22 @@ func (self *Network) startWithSnapshots(id discover.NodeID, snapshots map[string
if err != nil {
return fmt.Errorf("error getting peer events for node %v: %s", id, err)
}
go self.watchPeerEvents(id, events, sub)
go net.watchPeerEvents(id, events, sub)
return nil
}
// watchPeerEvents reads peer events from the given channel and emits
// corresponding network events
func (self *Network) watchPeerEvents(id discover.NodeID, events chan *p2p.PeerEvent, sub event.Subscription) {
func (net *Network) watchPeerEvents(id discover.NodeID, events chan *p2p.PeerEvent, sub event.Subscription) {
defer func() {
sub.Unsubscribe()
// assume the node is now down
self.lock.Lock()
node := self.getNode(id)
net.lock.Lock()
node := net.getNode(id)
node.Up = false
self.lock.Unlock()
self.events.Send(NewEvent(node))
net.lock.Unlock()
net.events.Send(NewEvent(node))
}()
for {
select {
@ -235,16 +235,16 @@ func (self *Network) watchPeerEvents(id discover.NodeID, events chan *p2p.PeerEv
switch event.Type {
case p2p.PeerEventTypeAdd:
self.DidConnect(id, peer)
net.DidConnect(id, peer)
case p2p.PeerEventTypeDrop:
self.DidDisconnect(id, peer)
net.DidDisconnect(id, peer)
case p2p.PeerEventTypeMsgSend:
self.DidSend(id, peer, event.Protocol, *event.MsgCode)
net.DidSend(id, peer, event.Protocol, *event.MsgCode)
case p2p.PeerEventTypeMsgRecv:
self.DidReceive(peer, id, event.Protocol, *event.MsgCode)
net.DidReceive(peer, id, event.Protocol, *event.MsgCode)
}
@ -258,8 +258,8 @@ func (self *Network) watchPeerEvents(id discover.NodeID, events chan *p2p.PeerEv
}
// Stop stops the node with the given ID
func (self *Network) Stop(id discover.NodeID) error {
node := self.GetNode(id)
func (net *Network) Stop(id discover.NodeID) error {
node := net.GetNode(id)
if node == nil {
return fmt.Errorf("node %v does not exist", id)
}
@ -272,15 +272,15 @@ func (self *Network) Stop(id discover.NodeID) error {
node.Up = false
log.Info(fmt.Sprintf("stop node %v: %v", id, node.Up))
self.events.Send(ControlEvent(node))
net.events.Send(ControlEvent(node))
return nil
}
// Connect connects two nodes together by calling the "admin_addPeer" RPC
// method on the "one" node so that it connects to the "other" node
func (self *Network) Connect(oneID, otherID discover.NodeID) error {
func (net *Network) Connect(oneID, otherID discover.NodeID) error {
log.Debug(fmt.Sprintf("connecting %s to %s", oneID, otherID))
conn, err := self.InitConn(oneID, otherID)
conn, err := net.InitConn(oneID, otherID)
if err != nil {
return err
}
@ -288,14 +288,14 @@ func (self *Network) Connect(oneID, otherID discover.NodeID) error {
if err != nil {
return err
}
self.events.Send(ControlEvent(conn))
net.events.Send(ControlEvent(conn))
return client.Call(nil, "admin_addPeer", string(conn.other.Addr()))
}
// Disconnect disconnects two nodes by calling the "admin_removePeer" RPC
// method on the "one" node so that it disconnects from the "other" node
func (self *Network) Disconnect(oneID, otherID discover.NodeID) error {
conn := self.GetConn(oneID, otherID)
func (net *Network) Disconnect(oneID, otherID discover.NodeID) error {
conn := net.GetConn(oneID, otherID)
if conn == nil {
return fmt.Errorf("connection between %v and %v does not exist", oneID, otherID)
}
@ -306,13 +306,13 @@ func (self *Network) Disconnect(oneID, otherID discover.NodeID) error {
if err != nil {
return err
}
self.events.Send(ControlEvent(conn))
net.events.Send(ControlEvent(conn))
return client.Call(nil, "admin_removePeer", string(conn.other.Addr()))
}
// DidConnect tracks the fact that the "one" node connected to the "other" node
func (self *Network) DidConnect(one, other discover.NodeID) error {
conn, err := self.GetOrCreateConn(one, other)
func (net *Network) DidConnect(one, other discover.NodeID) error {
conn, err := net.GetOrCreateConn(one, other)
if err != nil {
return fmt.Errorf("connection between %v and %v does not exist", one, other)
}
@ -320,14 +320,14 @@ func (self *Network) DidConnect(one, other discover.NodeID) error {
return fmt.Errorf("%v and %v already connected", one, other)
}
conn.Up = true
self.events.Send(NewEvent(conn))
net.events.Send(NewEvent(conn))
return nil
}
// DidDisconnect tracks the fact that the "one" node disconnected from the
// "other" node
func (self *Network) DidDisconnect(one, other discover.NodeID) error {
conn := self.GetConn(one, other)
func (net *Network) DidDisconnect(one, other discover.NodeID) error {
conn := net.GetConn(one, other)
if conn == nil {
return fmt.Errorf("connection between %v and %v does not exist", one, other)
}
@ -336,12 +336,12 @@ func (self *Network) DidDisconnect(one, other discover.NodeID) error {
}
conn.Up = false
conn.initiated = time.Now().Add(-dialBanTimeout)
self.events.Send(NewEvent(conn))
net.events.Send(NewEvent(conn))
return nil
}
// DidSend tracks the fact that "sender" sent a message to "receiver"
func (self *Network) DidSend(sender, receiver discover.NodeID, proto string, code uint64) error {
func (net *Network) DidSend(sender, receiver discover.NodeID, proto string, code uint64) error {
msg := &Msg{
One: sender,
Other: receiver,
@ -349,12 +349,12 @@ func (self *Network) DidSend(sender, receiver discover.NodeID, proto string, cod
Code: code,
Received: false,
}
self.events.Send(NewEvent(msg))
net.events.Send(NewEvent(msg))
return nil
}
// DidReceive tracks the fact that "receiver" received a message from "sender"
func (self *Network) DidReceive(sender, receiver discover.NodeID, proto string, code uint64) error {
func (net *Network) DidReceive(sender, receiver discover.NodeID, proto string, code uint64) error {
msg := &Msg{
One: sender,
Other: receiver,
@ -362,36 +362,36 @@ func (self *Network) DidReceive(sender, receiver discover.NodeID, proto string,
Code: code,
Received: true,
}
self.events.Send(NewEvent(msg))
net.events.Send(NewEvent(msg))
return nil
}
// GetNode gets the node with the given ID, returning nil if the node does not
// exist
func (self *Network) GetNode(id discover.NodeID) *Node {
self.lock.Lock()
defer self.lock.Unlock()
return self.getNode(id)
func (net *Network) GetNode(id discover.NodeID) *Node {
net.lock.Lock()
defer net.lock.Unlock()
return net.getNode(id)
}
// GetNode gets the node with the given name, returning nil if the node does
// not exist
func (self *Network) GetNodeByName(name string) *Node {
self.lock.Lock()
defer self.lock.Unlock()
return self.getNodeByName(name)
func (net *Network) GetNodeByName(name string) *Node {
net.lock.Lock()
defer net.lock.Unlock()
return net.getNodeByName(name)
}
func (self *Network) getNode(id discover.NodeID) *Node {
i, found := self.nodeMap[id]
func (net *Network) getNode(id discover.NodeID) *Node {
i, found := net.nodeMap[id]
if !found {
return nil
}
return self.Nodes[i]
return net.Nodes[i]
}
func (self *Network) getNodeByName(name string) *Node {
for _, node := range self.Nodes {
func (net *Network) getNodeByName(name string) *Node {
for _, node := range net.Nodes {
if node.Config.Name == name {
return node
}
@ -400,40 +400,40 @@ func (self *Network) getNodeByName(name string) *Node {
}
// GetNodes returns the existing nodes
func (self *Network) GetNodes() (nodes []*Node) {
self.lock.Lock()
defer self.lock.Unlock()
func (net *Network) GetNodes() (nodes []*Node) {
net.lock.Lock()
defer net.lock.Unlock()
nodes = append(nodes, self.Nodes...)
nodes = append(nodes, net.Nodes...)
return nodes
}
// GetConn returns the connection which exists between "one" and "other"
// regardless of which node initiated the connection
func (self *Network) GetConn(oneID, otherID discover.NodeID) *Conn {
self.lock.Lock()
defer self.lock.Unlock()
return self.getConn(oneID, otherID)
func (net *Network) GetConn(oneID, otherID discover.NodeID) *Conn {
net.lock.Lock()
defer net.lock.Unlock()
return net.getConn(oneID, otherID)
}
// GetOrCreateConn is like GetConn but creates the connection if it doesn't
// already exist
func (self *Network) GetOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
self.lock.Lock()
defer self.lock.Unlock()
return self.getOrCreateConn(oneID, otherID)
func (net *Network) GetOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
net.lock.Lock()
defer net.lock.Unlock()
return net.getOrCreateConn(oneID, otherID)
}
func (self *Network) getOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
if conn := self.getConn(oneID, otherID); conn != nil {
func (net *Network) getOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
if conn := net.getConn(oneID, otherID); conn != nil {
return conn, nil
}
one := self.getNode(oneID)
one := net.getNode(oneID)
if one == nil {
return nil, fmt.Errorf("node %v does not exist", oneID)
}
other := self.getNode(otherID)
other := net.getNode(otherID)
if other == nil {
return nil, fmt.Errorf("node %v does not exist", otherID)
}
@ -444,18 +444,18 @@ func (self *Network) getOrCreateConn(oneID, otherID discover.NodeID) (*Conn, err
other: other,
}
label := ConnLabel(oneID, otherID)
self.connMap[label] = len(self.Conns)
self.Conns = append(self.Conns, conn)
net.connMap[label] = len(net.Conns)
net.Conns = append(net.Conns, conn)
return conn, nil
}
func (self *Network) getConn(oneID, otherID discover.NodeID) *Conn {
func (net *Network) getConn(oneID, otherID discover.NodeID) *Conn {
label := ConnLabel(oneID, otherID)
i, found := self.connMap[label]
i, found := net.connMap[label]
if !found {
return nil
}
return self.Conns[i]
return net.Conns[i]
}
// InitConn(one, other) retrieves the connectiton model for the connection between
@ -466,13 +466,13 @@ func (self *Network) getConn(oneID, otherID discover.NodeID) *Conn {
// it also checks whether there has been recent attempt to connect the peers
// this is cheating as the simulation is used as an oracle and know about
// remote peers attempt to connect to a node which will then not initiate the connection
func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
self.lock.Lock()
defer self.lock.Unlock()
func (net *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
net.lock.Lock()
defer net.lock.Unlock()
if oneID == otherID {
return nil, fmt.Errorf("refusing to connect to self %v", oneID)
}
conn, err := self.getOrCreateConn(oneID, otherID)
conn, err := net.getOrCreateConn(oneID, otherID)
if err != nil {
return nil, err
}
@ -491,28 +491,28 @@ func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
}
// Shutdown stops all nodes in the network and closes the quit channel
func (self *Network) Shutdown() {
for _, node := range self.Nodes {
func (net *Network) Shutdown() {
for _, node := range net.Nodes {
log.Debug(fmt.Sprintf("stopping node %s", node.ID().TerminalString()))
if err := node.Stop(); err != nil {
log.Warn(fmt.Sprintf("error stopping node %s", node.ID().TerminalString()), "err", err)
}
}
close(self.quitc)
close(net.quitc)
}
//Reset resets all network properties:
//emtpies the nodes and the connection list
func (self *Network) Reset() {
self.lock.Lock()
defer self.lock.Unlock()
func (net *Network) Reset() {
net.lock.Lock()
defer net.lock.Unlock()
//re-initialize the maps
self.connMap = make(map[string]int)
self.nodeMap = make(map[discover.NodeID]int)
net.connMap = make(map[string]int)
net.nodeMap = make(map[discover.NodeID]int)
self.Nodes = nil
self.Conns = nil
net.Nodes = nil
net.Conns = nil
}
// Node is a wrapper around adapters.Node which is used to track the status
@ -528,37 +528,37 @@ type Node struct {
}
// ID returns the ID of the node
func (self *Node) ID() discover.NodeID {
return self.Config.ID
func (n *Node) ID() discover.NodeID {
return n.Config.ID
}
// String returns a log-friendly string
func (self *Node) String() string {
return fmt.Sprintf("Node %v", self.ID().TerminalString())
func (n *Node) String() string {
return fmt.Sprintf("Node %v", n.ID().TerminalString())
}
// NodeInfo returns information about the node
func (self *Node) NodeInfo() *p2p.NodeInfo {
func (n *Node) NodeInfo() *p2p.NodeInfo {
// avoid a panic if the node is not started yet
if self.Node == nil {
if n.Node == nil {
return nil
}
info := self.Node.NodeInfo()
info.Name = self.Config.Name
info := n.Node.NodeInfo()
info.Name = n.Config.Name
return info
}
// MarshalJSON implements the json.Marshaler interface so that the encoded
// JSON includes the NodeInfo
func (self *Node) MarshalJSON() ([]byte, error) {
func (n *Node) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Info *p2p.NodeInfo `json:"info,omitempty"`
Config *adapters.NodeConfig `json:"config,omitempty"`
Up bool `json:"up"`
}{
Info: self.NodeInfo(),
Config: self.Config,
Up: self.Up,
Info: n.NodeInfo(),
Config: n.Config,
Up: n.Up,
})
}
@ -580,19 +580,19 @@ type Conn struct {
}
// nodesUp returns whether both nodes are currently up
func (self *Conn) nodesUp() error {
if !self.one.Up {
return fmt.Errorf("one %v is not up", self.One)
func (c *Conn) nodesUp() error {
if !c.one.Up {
return fmt.Errorf("one %v is not up", c.One)
}
if !self.other.Up {
return fmt.Errorf("other %v is not up", self.Other)
if !c.other.Up {
return fmt.Errorf("other %v is not up", c.Other)
}
return nil
}
// String returns a log-friendly string
func (self *Conn) String() string {
return fmt.Sprintf("Conn %v->%v", self.One.TerminalString(), self.Other.TerminalString())
func (c *Conn) String() string {
return fmt.Sprintf("Conn %v->%v", c.One.TerminalString(), c.Other.TerminalString())
}
// Msg represents a p2p message sent between two nodes in the network
@ -605,8 +605,8 @@ type Msg struct {
}
// String returns a log-friendly string
func (self *Msg) String() string {
return fmt.Sprintf("Msg(%d) %v->%v", self.Code, self.One.TerminalString(), self.Other.TerminalString())
func (m *Msg) String() string {
return fmt.Sprintf("Msg(%d) %v->%v", m.Code, m.One.TerminalString(), m.Other.TerminalString())
}
// ConnLabel generates a deterministic string which represents a connection
@ -640,14 +640,14 @@ type NodeSnapshot struct {
}
// Snapshot creates a network snapshot
func (self *Network) Snapshot() (*Snapshot, error) {
self.lock.Lock()
defer self.lock.Unlock()
func (net *Network) Snapshot() (*Snapshot, error) {
net.lock.Lock()
defer net.lock.Unlock()
snap := &Snapshot{
Nodes: make([]NodeSnapshot, len(self.Nodes)),
Conns: make([]Conn, len(self.Conns)),
Nodes: make([]NodeSnapshot, len(net.Nodes)),
Conns: make([]Conn, len(net.Conns)),
}
for i, node := range self.Nodes {
for i, node := range net.Nodes {
snap.Nodes[i] = NodeSnapshot{Node: *node}
if !node.Up {
continue
@ -658,33 +658,33 @@ func (self *Network) Snapshot() (*Snapshot, error) {
}
snap.Nodes[i].Snapshots = snapshots
}
for i, conn := range self.Conns {
for i, conn := range net.Conns {
snap.Conns[i] = *conn
}
return snap, nil
}
// Load loads a network snapshot
func (self *Network) Load(snap *Snapshot) error {
func (net *Network) Load(snap *Snapshot) error {
for _, n := range snap.Nodes {
if _, err := self.NewNodeWithConfig(n.Node.Config); err != nil {
if _, err := net.NewNodeWithConfig(n.Node.Config); err != nil {
return err
}
if !n.Node.Up {
continue
}
if err := self.startWithSnapshots(n.Node.Config.ID, n.Snapshots); err != nil {
if err := net.startWithSnapshots(n.Node.Config.ID, n.Snapshots); err != nil {
return err
}
}
for _, conn := range snap.Conns {
if !self.GetNode(conn.One).Up || !self.GetNode(conn.Other).Up {
if !net.GetNode(conn.One).Up || !net.GetNode(conn.Other).Up {
//in this case, at least one of the nodes of a connection is not up,
//so it would result in the snapshot `Load` to fail
continue
}
if err := self.Connect(conn.One, conn.Other); err != nil {
if err := net.Connect(conn.One, conn.Other); err != nil {
return err
}
}
@ -692,7 +692,7 @@ func (self *Network) Load(snap *Snapshot) error {
}
// Subscribe reads control events from a channel and executes them
func (self *Network) Subscribe(events chan *Event) {
func (net *Network) Subscribe(events chan *Event) {
for {
select {
case event, ok := <-events:
@ -700,23 +700,23 @@ func (self *Network) Subscribe(events chan *Event) {
return
}
if event.Control {
self.executeControlEvent(event)
net.executeControlEvent(event)
}
case <-self.quitc:
case <-net.quitc:
return
}
}
}
func (self *Network) executeControlEvent(event *Event) {
func (net *Network) executeControlEvent(event *Event) {
log.Trace("execute control event", "type", event.Type, "event", event)
switch event.Type {
case EventTypeNode:
if err := self.executeNodeEvent(event); err != nil {
if err := net.executeNodeEvent(event); err != nil {
log.Error("error executing node event", "event", event, "err", err)
}
case EventTypeConn:
if err := self.executeConnEvent(event); err != nil {
if err := net.executeConnEvent(event); err != nil {
log.Error("error executing conn event", "event", event, "err", err)
}
case EventTypeMsg:
@ -724,21 +724,21 @@ func (self *Network) executeControlEvent(event *Event) {
}
}
func (self *Network) executeNodeEvent(e *Event) error {
func (net *Network) executeNodeEvent(e *Event) error {
if !e.Node.Up {
return self.Stop(e.Node.ID())
return net.Stop(e.Node.ID())
}
if _, err := self.NewNodeWithConfig(e.Node.Config); err != nil {
if _, err := net.NewNodeWithConfig(e.Node.Config); err != nil {
return err
}
return self.Start(e.Node.ID())
return net.Start(e.Node.ID())
}
func (self *Network) executeConnEvent(e *Event) error {
func (net *Network) executeConnEvent(e *Event) error {
if e.Conn.Up {
return self.Connect(e.Conn.One, e.Conn.Other)
return net.Connect(e.Conn.One, e.Conn.Other)
} else {
return self.Disconnect(e.Conn.One, e.Conn.Other)
return net.Disconnect(e.Conn.One, e.Conn.Other)
}
}

View file

@ -39,29 +39,29 @@ func NewTestPeerPool() *TestPeerPool {
return &TestPeerPool{peers: make(map[discover.NodeID]TestPeer)}
}
func (self *TestPeerPool) Add(p TestPeer) {
self.lock.Lock()
defer self.lock.Unlock()
func (pp *TestPeerPool) Add(p TestPeer) {
pp.lock.Lock()
defer pp.lock.Unlock()
log.Trace(fmt.Sprintf("pp add peer %v", p.ID()))
self.peers[p.ID()] = p
pp.peers[p.ID()] = p
}
func (self *TestPeerPool) Remove(p TestPeer) {
self.lock.Lock()
defer self.lock.Unlock()
delete(self.peers, p.ID())
func (pp *TestPeerPool) Remove(p TestPeer) {
pp.lock.Lock()
defer pp.lock.Unlock()
delete(pp.peers, p.ID())
}
func (self *TestPeerPool) Has(id discover.NodeID) bool {
self.lock.Lock()
defer self.lock.Unlock()
_, ok := self.peers[id]
func (pp *TestPeerPool) Has(id discover.NodeID) bool {
pp.lock.Lock()
defer pp.lock.Unlock()
_, ok := pp.peers[id]
return ok
}
func (self *TestPeerPool) Get(id discover.NodeID) TestPeer {
self.lock.Lock()
defer self.lock.Unlock()
return self.peers[id]
func (pp *TestPeerPool) Get(id discover.NodeID) TestPeer {
pp.lock.Lock()
defer pp.lock.Unlock()
return pp.peers[id]
}

View file

@ -78,10 +78,10 @@ type Disconnect struct {
}
// trigger sends messages from peers
func (self *ProtocolSession) trigger(trig Trigger) error {
simNode, ok := self.adapter.GetNode(trig.Peer)
func (ps *ProtocolSession) trigger(trig Trigger) error {
simNode, ok := ps.adapter.GetNode(trig.Peer)
if !ok {
return fmt.Errorf("trigger: peer %v does not exist (1- %v)", trig.Peer, len(self.IDs))
return fmt.Errorf("trigger: peer %v does not exist (1- %v)", trig.Peer, len(ps.IDs))
}
mockNode, ok := simNode.Services()[0].(*mockNode)
if !ok {
@ -107,7 +107,7 @@ func (self *ProtocolSession) trigger(trig Trigger) error {
}
// expect checks an expectation of a message sent out by the pivot node
func (self *ProtocolSession) expect(exps []Expect) error {
func (ps *ProtocolSession) expect(exps []Expect) error {
// construct a map of expectations for each node
peerExpects := make(map[discover.NodeID][]Expect)
for _, exp := range exps {
@ -120,9 +120,9 @@ func (self *ProtocolSession) expect(exps []Expect) error {
// construct a map of mockNodes for each node
mockNodes := make(map[discover.NodeID]*mockNode)
for nodeID := range peerExpects {
simNode, ok := self.adapter.GetNode(nodeID)
simNode, ok := ps.adapter.GetNode(nodeID)
if !ok {
return fmt.Errorf("trigger: peer %v does not exist (1- %v)", nodeID, len(self.IDs))
return fmt.Errorf("trigger: peer %v does not exist (1- %v)", nodeID, len(ps.IDs))
}
mockNode, ok := simNode.Services()[0].(*mockNode)
if !ok {
@ -202,9 +202,9 @@ func (self *ProtocolSession) expect(exps []Expect) error {
}
// TestExchanges tests a series of exchanges against the session
func (self *ProtocolSession) TestExchanges(exchanges ...Exchange) error {
func (ps *ProtocolSession) TestExchanges(exchanges ...Exchange) error {
for i, e := range exchanges {
if err := self.testExchange(e); err != nil {
if err := ps.testExchange(e); err != nil {
return fmt.Errorf("exchange #%d %q: %v", i, e.Label, err)
}
log.Trace(fmt.Sprintf("exchange #%d %q: run successfully", i, e.Label))
@ -214,14 +214,14 @@ func (self *ProtocolSession) TestExchanges(exchanges ...Exchange) error {
// testExchange tests a single Exchange.
// Default timeout value is 2 seconds.
func (self *ProtocolSession) testExchange(e Exchange) error {
func (ps *ProtocolSession) testExchange(e Exchange) error {
errc := make(chan error)
done := make(chan struct{})
defer close(done)
go func() {
for _, trig := range e.Triggers {
err := self.trigger(trig)
err := ps.trigger(trig)
if err != nil {
errc <- err
return
@ -229,7 +229,7 @@ func (self *ProtocolSession) testExchange(e Exchange) error {
}
select {
case errc <- self.expect(e.Expects):
case errc <- ps.expect(e.Expects):
case <-done:
}
}()
@ -250,7 +250,7 @@ func (self *ProtocolSession) testExchange(e Exchange) error {
// TestDisconnected tests the disconnections given as arguments
// the disconnect structs describe what disconnect error is expected on which peer
func (self *ProtocolSession) TestDisconnected(disconnects ...*Disconnect) error {
func (ps *ProtocolSession) TestDisconnected(disconnects ...*Disconnect) error {
expects := make(map[discover.NodeID]error)
for _, disconnect := range disconnects {
expects[disconnect.Peer] = disconnect.Error
@ -259,7 +259,7 @@ func (self *ProtocolSession) TestDisconnected(disconnects ...*Disconnect) error
timeout := time.After(time.Second)
for len(expects) > 0 {
select {
case event := <-self.events:
case event := <-ps.events:
if event.Type != p2p.PeerEventTypeDrop {
continue
}

View file

@ -100,24 +100,24 @@ func NewProtocolTester(t *testing.T, id discover.NodeID, n int, run func(*p2p.Pe
}
// Stop stops the p2p server
func (self *ProtocolTester) Stop() error {
self.Server.Stop()
func (pt *ProtocolTester) Stop() error {
pt.Server.Stop()
return nil
}
// Connect brings up the remote peer node and connects it using the
// p2p/simulations network connection with the in memory network adapter
func (self *ProtocolTester) Connect(selfID discover.NodeID, peers ...*adapters.NodeConfig) {
func (pt *ProtocolTester) Connect(selfID discover.NodeID, peers ...*adapters.NodeConfig) {
for _, peer := range peers {
log.Trace(fmt.Sprintf("start node %v", peer.ID))
if _, err := self.network.NewNodeWithConfig(peer); err != nil {
if _, err := pt.network.NewNodeWithConfig(peer); err != nil {
panic(fmt.Sprintf("error starting peer %v: %v", peer.ID, err))
}
if err := self.network.Start(peer.ID); err != nil {
if err := pt.network.Start(peer.ID); err != nil {
panic(fmt.Sprintf("error starting peer %v: %v", peer.ID, err))
}
log.Trace(fmt.Sprintf("connect to %v", peer.ID))
if err := self.network.Connect(selfID, peer.ID); err != nil {
if err := pt.network.Connect(selfID, peer.ID); err != nil {
panic(fmt.Sprintf("error connecting to peer %v: %v", peer.ID, err))
}
}
@ -130,25 +130,25 @@ type testNode struct {
run func(*p2p.Peer, p2p.MsgReadWriter) error
}
func (t *testNode) Protocols() []p2p.Protocol {
func (tn *testNode) Protocols() []p2p.Protocol {
return []p2p.Protocol{{
Length: 100,
Run: t.run,
Run: tn.run,
}}
}
func (t *testNode) APIs() []rpc.API {
func (tn *testNode) APIs() []rpc.API {
return nil
}
func (t *testNode) Start(server *p2p.Server) error {
func (tn *testNode) Start(server *p2p.Server) error {
return nil
}
func (t *testNode) SaveData() {
func (tn *testNode) SaveData() {
}
func (t *testNode) Stop() error {
func (tn *testNode) Stop() error {
return nil
}
@ -178,34 +178,34 @@ func newMockNode() *mockNode {
// Run is a protocol run function which just loops waiting for tests to
// instruct it to either trigger or expect a message from the peer
func (m *mockNode) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
func (mn *mockNode) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
for {
select {
case trig := <-m.trigger:
m.err <- p2p.Send(rw, trig.Code, trig.Msg)
case exps := <-m.expect:
m.err <- expectMsgs(rw, exps)
case <-m.stop:
case trig := <-mn.trigger:
mn.err <- p2p.Send(rw, trig.Code, trig.Msg)
case exps := <-mn.expect:
mn.err <- expectMsgs(rw, exps)
case <-mn.stop:
return nil
}
}
}
func (m *mockNode) Trigger(trig *Trigger) error {
m.trigger <- trig
return <-m.err
func (mn *mockNode) Trigger(trig *Trigger) error {
mn.trigger <- trig
return <-mn.err
}
func (m *mockNode) Expect(exp ...Expect) error {
m.expect <- exp
return <-m.err
func (mn *mockNode) Expect(exp ...Expect) error {
mn.expect <- exp
return <-mn.err
}
func (m *mockNode) SaveData() {
func (mn *mockNode) SaveData() {
}
func (m *mockNode) Stop() error {
m.stopOnce.Do(func() { close(m.stop) })
func (mn *mockNode) Stop() error {
mn.stopOnce.Do(func() { close(mn.stop) })
return nil
}