mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Merge pull request #686 from gzliudan/fix-st1006
all: fix staticcheck warning ST1006
This commit is contained in:
commit
7b5104576e
43 changed files with 2792 additions and 2773 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
164
bmt/bmt.go
164
bmt/bmt.go
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
186
eth/backend.go
186
eth/backend.go
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = <rInfo{
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
226
light/txpool.go
226
light/txpool.go
|
|
@ -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})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
364
miner/worker.go
364
miner/worker.go
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue