Merge pull request #686 from gzliudan/fix-st1006

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -100,45 +100,45 @@ func ensNode(name string) common.Hash {
return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) return crypto.Keccak256Hash(parentNode[:], parentLabel[:])
} }
func (self *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) { func (e *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) {
resolverAddr, err := self.Resolver(node) resolverAddr, err := e.Resolver(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resolver, err := contract.NewPublicResolver(resolverAddr, self.contractBackend) resolver, err := contract.NewPublicResolver(resolverAddr, e.contractBackend)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &contract.PublicResolverSession{ return &contract.PublicResolverSession{
Contract: resolver, Contract: resolver,
TransactOpts: self.TransactOpts, TransactOpts: e.TransactOpts,
}, nil }, nil
} }
func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) { func (e *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) {
registrarAddr, err := self.Owner(node) registrarAddr, err := e.Owner(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }
registrar, err := contract.NewFIFSRegistrar(registrarAddr, self.contractBackend) registrar, err := contract.NewFIFSRegistrar(registrarAddr, e.contractBackend)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &contract.FIFSRegistrarSession{ return &contract.FIFSRegistrarSession{
Contract: registrar, Contract: registrar,
TransactOpts: self.TransactOpts, TransactOpts: e.TransactOpts,
}, nil }, nil
} }
// Resolve is a non-transactional call that returns the content hash associated with a name. // 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) node := ensNode(name)
resolver, err := self.getResolver(node) resolver, err := e.getResolver(node)
if err != nil { if err != nil {
return common.Hash{}, err 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. // 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. // 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) parentNode, label := ensParentNode(name)
registrar, err := self.getRegistrar(parentNode) registrar, err := e.getRegistrar(parentNode)
if err != nil { if err != nil {
return nil, err 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 // 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. // 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) node := ensNode(name)
resolver, err := self.getResolver(node) resolver, err := e.getResolver(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }
opts := self.TransactOpts opts := e.TransactOpts
opts.GasLimit = 200000 opts.GasLimit = 200000
return resolver.Contract.SetContent(&opts, node, hash) return resolver.Contract.SetContent(&opts, node, hash)
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -50,47 +50,47 @@ func NewLesTxRelay(ps *peerSet, reqDist *requestDistributor) *LesTxRelay {
return r return r
} }
func (self *LesTxRelay) registerPeer(p *peer) { func (l *LesTxRelay) registerPeer(p *peer) {
self.lock.Lock() l.lock.Lock()
defer self.lock.Unlock() defer l.lock.Unlock()
self.peerList = self.ps.AllPeers() l.peerList = l.ps.AllPeers()
} }
func (self *LesTxRelay) unregisterPeer(p *peer) { func (l *LesTxRelay) unregisterPeer(p *peer) {
self.lock.Lock() l.lock.Lock()
defer self.lock.Unlock() 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 // 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 // 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) sendTo := make(map[*peer]types.Transactions)
self.peerStartPos++ // rotate the starting position of the peer list l.peerStartPos++ // rotate the starting position of the peer list
if self.peerStartPos >= len(self.peerList) { if l.peerStartPos >= len(l.peerList) {
self.peerStartPos = 0 l.peerStartPos = 0
} }
for _, tx := range txs { for _, tx := range txs {
hash := tx.Hash() hash := tx.Hash()
ltr, ok := self.txSent[hash] ltr, ok := l.txSent[hash]
if !ok { if !ok {
ltr = &ltrInfo{ ltr = &ltrInfo{
tx: tx, tx: tx,
sentTo: make(map[*peer]struct{}), sentTo: make(map[*peer]struct{}),
} }
self.txSent[hash] = ltr l.txSent[hash] = ltr
self.txPending[hash] = struct{}{} l.txPending[hash] = struct{}{}
} }
if len(self.peerList) > 0 { if len(l.peerList) > 0 {
cnt := count cnt := count
pos := self.peerStartPos pos := l.peerStartPos
for { for {
peer := self.peerList[pos] peer := l.peerList[pos]
if _, ok := ltr.sentTo[peer]; !ok { if _, ok := ltr.sentTo[peer]; !ok {
sendTo[peer] = append(sendTo[peer], tx) sendTo[peer] = append(sendTo[peer], tx)
ltr.sentTo[peer] = struct{}{} 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 break // sent it to the desired number of peers
} }
pos++ pos++
if pos == len(self.peerList) { if pos == len(l.peerList) {
pos = 0 pos = 0
} }
if pos == self.peerStartPos { if pos == l.peerStartPos {
break // tried all available peers 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) } return func() { peer.SendTxs(reqID, cost, ll) }
}, },
} }
self.reqDist.queue(rq) l.reqDist.queue(rq)
} }
} }
func (self *LesTxRelay) Send(txs types.Transactions) { func (l *LesTxRelay) Send(txs types.Transactions) {
self.lock.Lock() l.lock.Lock()
defer self.lock.Unlock() 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) { func (l *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) {
self.lock.Lock() l.lock.Lock()
defer self.lock.Unlock() defer l.lock.Unlock()
for _, hash := range mined { for _, hash := range mined {
delete(self.txPending, hash) delete(l.txPending, hash)
} }
for _, hash := range rollback { for _, hash := range rollback {
self.txPending[hash] = struct{}{} l.txPending[hash] = struct{}{}
} }
if len(self.txPending) > 0 { if len(l.txPending) > 0 {
txs := make(types.Transactions, len(self.txPending)) txs := make(types.Transactions, len(l.txPending))
i := 0 i := 0
for hash := range self.txPending { for hash := range l.txPending {
txs[i] = self.txSent[hash].tx txs[i] = l.txSent[hash].tx
i++ i++
} }
self.send(txs, 1) l.send(txs, 1)
} }
} }
func (self *LesTxRelay) Discard(hashes []common.Hash) { func (l *LesTxRelay) Discard(hashes []common.Hash) {
self.lock.Lock() l.lock.Lock()
defer self.lock.Unlock() defer l.lock.Unlock()
for _, hash := range hashes { for _, hash := range hashes {
delete(self.txSent, hash) delete(l.txSent, hash)
delete(self.txPending, hash) delete(l.txPending, hash)
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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