mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 13:44:31 +00:00
307 lines
12 KiB
Go
307 lines
12 KiB
Go
// Copyright 2016 The go-ethereum Authors
|
|
// This file is part of the go-ethereum library.
|
|
//
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package tradingstate
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"math/big"
|
|
"testing"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/common"
|
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
|
)
|
|
|
|
func TestEchangeStates(t *testing.T) {
|
|
t.SkipNow()
|
|
orderBook := common.StringToHash("BTC/XDC")
|
|
price := big.NewInt(10000)
|
|
numberOrder := 20
|
|
orderItems := []OrderItem{}
|
|
relayers := []common.Hash{}
|
|
for i := 0; i < numberOrder; i++ {
|
|
relayers = append(relayers, common.BigToHash(big.NewInt(int64(i))))
|
|
id := new(big.Int).SetUint64(uint64(i) + 1)
|
|
orderItems = append(orderItems, OrderItem{OrderID: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Price: big.NewInt(int64(2*i + 1)), Side: Ask, Signature: &Signature{V: 1, R: common.HexToHash("111111"), S: common.HexToHash("222222222222")}})
|
|
orderItems = append(orderItems, OrderItem{OrderID: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Price: big.NewInt(int64(2*i + 1)), Side: Bid, Signature: &Signature{V: 1, R: common.HexToHash("3333333333"), S: common.HexToHash("22222222222222222")}})
|
|
}
|
|
// Create an empty statedb database
|
|
db := rawdb.NewMemoryDatabase()
|
|
stateCache := NewDatabase(db)
|
|
statedb, _ := New(types.EmptyRootHash, stateCache)
|
|
|
|
// Update it with some exchanges
|
|
for i := 0; i < numberOrder; i++ {
|
|
statedb.SetNonce(relayers[i], uint64(1))
|
|
}
|
|
mapPriceSell := map[uint64]uint64{}
|
|
mapPriceBuy := map[uint64]uint64{}
|
|
|
|
for i := 0; i < len(orderItems); i++ {
|
|
amount := orderItems[i].Quantity.Uint64()
|
|
orderIdHash := common.BigToHash(new(big.Int).SetUint64(orderItems[i].OrderID))
|
|
statedb.InsertOrderItem(orderBook, orderIdHash, orderItems[i])
|
|
|
|
switch orderItems[i].Side {
|
|
case Ask:
|
|
old := mapPriceSell[amount]
|
|
mapPriceSell[amount] = old + amount
|
|
case Bid:
|
|
old := mapPriceBuy[amount]
|
|
mapPriceBuy[amount] = old + amount
|
|
default:
|
|
}
|
|
}
|
|
statedb.SetLastPrice(orderBook, price)
|
|
statedb.InsertLiquidationPrice(orderBook, big.NewInt(1), orderBook, 2)
|
|
statedb.InsertLiquidationPrice(orderBook, big.NewInt(2), orderBook, 3)
|
|
statedb.InsertLiquidationPrice(orderBook, big.NewInt(3), orderBook, 1)
|
|
root := statedb.IntermediateRoot()
|
|
statedb.Commit()
|
|
err := stateCache.TrieDB().Commit(root, false)
|
|
if err != nil {
|
|
t.Errorf("Error when commit into database: %v", err)
|
|
}
|
|
stateCache.TrieDB().Reference(root, common.Hash{})
|
|
statedb, err = New(root, stateCache)
|
|
if err != nil {
|
|
t.Fatalf("Error when get trie in database: %s , err: %v", root.Hex(), err)
|
|
}
|
|
liquidationPrice, liquidationData := statedb.GetHighestLiquidationPriceData(orderBook, big.NewInt(1))
|
|
if len(liquidationData) == 0 {
|
|
t.Fatalf("Error when get liquidation data save in database: got : %d , %s ", liquidationPrice, liquidationData)
|
|
}
|
|
fmt.Println("liquidationPrice", liquidationPrice)
|
|
for lendingBook, tradingIds := range liquidationData {
|
|
for _, tradingIdHash := range tradingIds {
|
|
fmt.Println("lendingBook", lendingBook.Hex(), "tradingIdHash", tradingIdHash.Hex())
|
|
err := statedb.RemoveLiquidationPrice(orderBook, liquidationPrice, lendingBook, new(big.Int).SetBytes(tradingIdHash.Bytes()).Uint64())
|
|
if err != nil {
|
|
t.Fatalf("Error when remove liquidation price in database: %s , err: %v", root.Hex(), err)
|
|
}
|
|
}
|
|
}
|
|
statedb.RemoveLiquidationPrice(orderBook, big.NewInt(2), orderBook, 2)
|
|
mapData := statedb.GetAllLowerLiquidationPriceData(orderBook, big.NewInt(2))
|
|
for price, lendingBooks := range mapData {
|
|
for lendingBook, tradeIds := range lendingBooks {
|
|
for _, tradeId := range tradeIds {
|
|
fmt.Println("price", price, "lendingBook", lendingBook.Hex(), "tradeId", tradeId.Hex())
|
|
}
|
|
}
|
|
}
|
|
fmt.Println("mapData", mapData)
|
|
liquidationPrice, liquidationData = statedb.GetHighestLiquidationPriceData(orderBook, big.NewInt(2))
|
|
for lendingBook, tradingIds := range liquidationData {
|
|
for _, tradingIdHash := range tradingIds {
|
|
fmt.Println("liquidationPrice", liquidationPrice, "lendingBook", lendingBook.Hex(), "tradingIdHash", tradingIdHash.Hex())
|
|
}
|
|
}
|
|
gotPrice := statedb.GetLastPrice(orderBook)
|
|
if gotPrice.Cmp(price) != 0 {
|
|
t.Fatalf("Error when get price save in database: got : %d , wanted : %d ", gotPrice, price)
|
|
}
|
|
fmt.Println(gotPrice)
|
|
for i := 0; i < numberOrder; i++ {
|
|
nonce := statedb.GetNonce(relayers[i])
|
|
if nonce != uint64(1) {
|
|
t.Fatalf("Error when get nonce save in database: got : %d , wanted : %d ", nonce, i)
|
|
}
|
|
}
|
|
|
|
minSell := uint64(math.MaxUint64)
|
|
for price, amount := range mapPriceSell {
|
|
data := statedb.GetVolume(orderBook, new(big.Int).SetUint64(price), Ask)
|
|
if data.Uint64() != amount {
|
|
t.Fatalf("Error when get volume save in database: price %d ,got : %d , wanted : %d ", price, data.Uint64(), amount)
|
|
}
|
|
if price < minSell {
|
|
minSell = price
|
|
}
|
|
}
|
|
maxBuy := uint64(0)
|
|
for price, amount := range mapPriceBuy {
|
|
data := statedb.GetVolume(orderBook, new(big.Int).SetUint64(price), Bid)
|
|
if data.Uint64() != amount {
|
|
t.Fatalf("Error when get volume save in database: price %d ,got : %d , wanted : %d ", price, data.Uint64(), amount)
|
|
}
|
|
if price > maxBuy {
|
|
maxBuy = price
|
|
}
|
|
}
|
|
|
|
for i := 0; i < len(orderItems); i++ {
|
|
amount := statedb.GetOrder(orderBook, common.BigToHash(new(big.Int).SetUint64(orderItems[i].OrderID))).Quantity
|
|
if orderItems[i].Quantity.Cmp(amount) != 0 {
|
|
t.Fatalf("Error when get amount save in database: orderId %d , orderType %s,got : %d , wanted : %d ", orderItems[i].OrderID, orderItems[i].Side, amount.Uint64(), orderItems[i].Quantity.Uint64())
|
|
}
|
|
}
|
|
maxPrice, volumeMax := statedb.GetBestBidPrice(orderBook)
|
|
minPrice, volumeMin := statedb.GetBestAskPrice(orderBook)
|
|
fmt.Println("price", minPrice, volumeMin, maxPrice, volumeMax)
|
|
|
|
db.Close()
|
|
}
|
|
|
|
/*
|
|
// This test can not pass PR #25320
|
|
func TestRevertStates(t *testing.T) {
|
|
orderBook := common.StringToHash("BTC/XDC")
|
|
numberOrder := 20
|
|
orderItems := []OrderItem{}
|
|
relayers := []common.Hash{}
|
|
for i := 0; i < numberOrder; i++ {
|
|
relayers = append(relayers, common.BigToHash(big.NewInt(int64(i))))
|
|
id := new(big.Int).SetUint64(uint64(i) + 1)
|
|
orderItems = append(orderItems, OrderItem{OrderID: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Price: big.NewInt(int64(2*i + 1)), Side: Ask, Signature: &Signature{V: 1, R: common.HexToHash("111111"), S: common.HexToHash("222222222222")}})
|
|
orderItems = append(orderItems, OrderItem{OrderID: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Price: big.NewInt(int64(2*i + 1)), Side: Bid, Signature: &Signature{V: 1, R: common.HexToHash("3333333333"), S: common.HexToHash("22222222222222222")}})
|
|
}
|
|
// Create an empty statedb database
|
|
db := rawdb.NewMemoryDatabase()
|
|
stateCache := NewDatabase(db)
|
|
statedb, _ := New(types.EmptyRootHash, stateCache)
|
|
|
|
// Update it with some exchanges
|
|
for i := 0; i < numberOrder; i++ {
|
|
statedb.SetNonce(relayers[i], uint64(1))
|
|
}
|
|
mapPriceSell := map[uint64]uint64{}
|
|
mapPriceBuy := map[uint64]uint64{}
|
|
|
|
for i := 0; i < len(orderItems); i++ {
|
|
amount := orderItems[i].Quantity.Uint64()
|
|
orderIdHash := common.BigToHash(new(big.Int).SetUint64(orderItems[i].OrderID))
|
|
statedb.InsertOrderItem(orderBook, orderIdHash, orderItems[i])
|
|
|
|
switch orderItems[i].Side {
|
|
case Ask:
|
|
old := mapPriceSell[amount]
|
|
mapPriceSell[amount] = old + amount
|
|
case Bid:
|
|
old := mapPriceBuy[amount]
|
|
mapPriceBuy[amount] = old + amount
|
|
default:
|
|
}
|
|
|
|
}
|
|
root := statedb.IntermediateRoot()
|
|
statedb.Commit()
|
|
//err := stateCache.TrieDB().Commit(root, false)
|
|
//if err != nil {
|
|
// t.Errorf("Error when commit into database: %v", err)
|
|
//}
|
|
stateCache.TrieDB().Reference(root, common.Hash{})
|
|
statedb, err := New(root, stateCache)
|
|
if err != nil {
|
|
t.Fatalf("Error when get trie in database: %s , err: %v", root.Hex(), err)
|
|
}
|
|
|
|
orderIdHash := common.BigToHash(new(big.Int).SetUint64(orderItems[0].OrderID))
|
|
order := statedb.GetOrder(orderBook, orderIdHash)
|
|
// sub amount order
|
|
wanted := statedb.GetVolume(orderBook, order.Price, order.Side)
|
|
snap := statedb.Snapshot()
|
|
statedb.SubAmountOrderItem(orderBook, orderIdHash, order.Price, order.Quantity, order.Side)
|
|
statedb.RevertToSnapshot(snap)
|
|
got := statedb.GetVolume(orderBook, order.Price, order.Side)
|
|
if got.Cmp(wanted) != 0 {
|
|
t.Fatalf(" err get volume price : %d after try revert snap shot , got : %d ,want : %d", order.Price, got, wanted)
|
|
}
|
|
// set nonce
|
|
wantedNonce := statedb.GetNonce(relayers[1])
|
|
snap = statedb.Snapshot()
|
|
statedb.SetNonce(relayers[1], 0)
|
|
statedb.RevertToSnapshot(snap)
|
|
gotNonce := statedb.GetNonce(relayers[1])
|
|
if wantedNonce != gotNonce {
|
|
t.Fatalf(" err get nonce addr: %v after try revert snap shot , got : %d ,want : %d", relayers[1].Hex(), gotNonce, wantedNonce)
|
|
}
|
|
|
|
// cancel order
|
|
wantedOrder := statedb.GetOrder(orderBook, orderIdHash)
|
|
snap = statedb.Snapshot()
|
|
statedb.CancelOrder(orderBook, &wantedOrder)
|
|
statedb.RevertToSnapshot(snap)
|
|
gotOrder := statedb.GetOrder(orderBook, orderIdHash)
|
|
if gotOrder.Quantity.Cmp(wantedOrder.Quantity) != 0 {
|
|
t.Fatalf(" err cancel order info : %v after try revert snap shot , got : %v ,want : %v", orderIdHash.Hex(), gotOrder, wantedOrder)
|
|
}
|
|
|
|
// insert order
|
|
i := 2*numberOrder + 1
|
|
id := new(big.Int).SetUint64(uint64(i) + 1)
|
|
testOrder := OrderItem{OrderID: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Price: big.NewInt(int64(2*i + 1)), Side: Ask, Signature: &Signature{V: 1, R: common.HexToHash("111111"), S: common.HexToHash("222222222222")}}
|
|
orderIdHash = common.BigToHash(new(big.Int).SetUint64(testOrder.OrderID))
|
|
snap = statedb.Snapshot()
|
|
statedb.InsertOrderItem(orderBook, orderIdHash, testOrder)
|
|
statedb.RevertToSnapshot(snap)
|
|
gotOrder = statedb.GetOrder(orderBook, orderIdHash)
|
|
if gotOrder.Quantity.Cmp(EmptyOrder.Quantity) != 0 {
|
|
t.Fatalf(" err insert order info : %v after try revert snap shot , got : %v ,want Empty Order", orderIdHash.Hex(), gotOrder)
|
|
}
|
|
// change price
|
|
price := big.NewInt(10000)
|
|
statedb.SetLastPrice(orderBook, price)
|
|
snap = statedb.Snapshot()
|
|
statedb.SetLastPrice(orderBook, big.NewInt(0))
|
|
statedb.RevertToSnapshot(snap)
|
|
gotPrice := statedb.GetLastPrice(orderBook)
|
|
if gotPrice.Cmp(price) != 0 {
|
|
t.Fatalf("Error when get price save in database: got : %d , wanted : %d ", gotPrice, price)
|
|
}
|
|
db.Close()
|
|
}
|
|
|
|
// This test can not pass PR #25320
|
|
func TestDumpState(t *testing.T) {
|
|
orderBook := common.StringToHash("BTC/XDC")
|
|
numberOrder := 5
|
|
orderItems := []OrderItem{}
|
|
for i := 0; i < numberOrder; i++ {
|
|
id := new(big.Int).SetUint64(uint64(i) + 1)
|
|
orderItems = append(orderItems, OrderItem{OrderID: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Price: big.NewInt(int64(2*i + 1)), Side: Ask, Signature: &Signature{V: 1, R: common.HexToHash("111111"), S: common.HexToHash("222222222222")}})
|
|
orderItems = append(orderItems, OrderItem{OrderID: id.Uint64(), Quantity: big.NewInt(int64(2*i + 2)), Price: big.NewInt(int64(2*i + 2)), Side: Bid, Signature: &Signature{V: 1, R: common.HexToHash("3333333333"), S: common.HexToHash("22222222222222222")}})
|
|
}
|
|
// Create an empty statedb database
|
|
db := rawdb.NewMemoryDatabase()
|
|
stateCache := NewDatabase(db)
|
|
statedb, _ := New(types.EmptyRootHash, stateCache)
|
|
|
|
for i := 0; i < len(orderItems); i++ {
|
|
orderIdHash := common.BigToHash(new(big.Int).SetUint64(orderItems[i].OrderID))
|
|
statedb.InsertOrderItem(orderBook, orderIdHash, orderItems[i])
|
|
}
|
|
bidTrie, _ := statedb.DumpAskTrie(orderBook)
|
|
fmt.Println("bidTrie", bidTrie)
|
|
root := statedb.IntermediateRoot()
|
|
statedb.Commit()
|
|
stateCache.TrieDB().Reference(root, common.Hash{})
|
|
statedb, err := New(root, stateCache)
|
|
if err != nil {
|
|
t.Fatalf("Error when get trie in database: %s , err: %v", root.Hex(), err)
|
|
}
|
|
maxPrice, volumeMax := statedb.GetBestBidPrice(orderBook)
|
|
minPrice, volumeMin := statedb.GetBestAskPrice(orderBook)
|
|
fmt.Println("price", minPrice, volumeMin, maxPrice, volumeMax)
|
|
|
|
bidTrie, _ = statedb.DumpBidTrie(orderBook)
|
|
|
|
fmt.Println("bidTrie", bidTrie)
|
|
db.Close()
|
|
}
|
|
*/
|