Skip to content

Commit b9eefaf

Browse files
committed
add : user assets file check
1 parent 796f994 commit b9eefaf

File tree

5 files changed

+227
-2
lines changed

5 files changed

+227
-2
lines changed

client/tools.go

+12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func ToolCommand() *cobra.Command {
1515
ToolCleanKvrocks(),
1616
ToolCheckProverStatus(),
1717
ToolQueryCexAssets(),
18+
ToolCheckUserAssetsFile(),
1819
)
1920
return cmd
2021
}
@@ -51,3 +52,14 @@ func ToolQueryCexAssets() *cobra.Command {
5152
}
5253
return cmd
5354
}
55+
56+
func ToolCheckUserAssetsFile() *cobra.Command {
57+
cmd := &cobra.Command{
58+
Use: "check_user_assets_file",
59+
Short: "check user assets file csv",
60+
Run: func(cmd *cobra.Command, args []string) {
61+
tool_service.CheckUserFiles()
62+
},
63+
}
64+
return cmd
65+
}

go.mod

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ require (
99
github.com/consensys/gnark v0.7.0
1010
github.com/consensys/gnark-crypto v0.10.0
1111
github.com/gatechain/gate-zk-smt v1.0.1
12+
github.com/go-redis/redis/v8 v8.11.5
1213
github.com/gocarina/gocsv v0.0.0-20230123225133-763e25b40669
1314
github.com/shopspring/decimal v1.3.1
15+
github.com/spf13/cobra v1.7.0
1416
github.com/zeromicro/go-zero v1.4.4
17+
golang.org/x/sync v0.2.0
1518
gorm.io/driver/mysql v1.4.7
1619
gorm.io/gorm v1.24.5
1720
)
@@ -35,7 +38,6 @@ require (
3538
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
3639
github.com/go-logr/logr v1.2.3 // indirect
3740
github.com/go-logr/stdr v1.2.2 // indirect
38-
github.com/go-redis/redis/v8 v8.11.5 // indirect
3941
github.com/go-sql-driver/mysql v1.7.0 // indirect
4042
github.com/golang/protobuf v1.5.3 // indirect
4143
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
@@ -59,7 +61,6 @@ require (
5961
github.com/prometheus/procfs v0.10.1 // indirect
6062
github.com/rs/zerolog v1.26.1 // indirect
6163
github.com/spaolacci/murmur3 v1.1.0 // indirect
62-
github.com/spf13/cobra v1.7.0 // indirect
6364
github.com/spf13/pflag v1.0.5 // indirect
6465
github.com/x448/float16 v0.8.4 // indirect
6566
go.opentelemetry.io/otel v1.11.0 // indirect

go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
10861086
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
10871087
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
10881088
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
1089+
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
10891090
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
10901091
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
10911092
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

service/tool_service/service.go

+17
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,20 @@ func QueryCexAssets() {
121121
cexAssetsInfoBytes, _ := json.Marshal(newAssetsInfo)
122122
fmt.Println(string(cexAssetsInfoBytes))
123123
}
124+
125+
func CheckUserFiles() {
126+
global.Cfg = &config.Config{}
127+
jsonFile, err := ioutil.ReadFile("./config/config.json")
128+
if err != nil {
129+
panic(fmt.Sprintf("load config err : %s", err.Error()))
130+
}
131+
err = json.Unmarshal(jsonFile, global.Cfg)
132+
if err != nil {
133+
panic(err.Error())
134+
}
135+
136+
_, _, err = utils.ReadUserAssetsV1(global.Cfg.UserDataFile)
137+
if err != nil {
138+
panic(err.Error())
139+
}
140+
}

utils/tools.go

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package utils
2+
3+
import (
4+
"encoding/csv"
5+
"encoding/hex"
6+
"fmt"
7+
"github.com/consensys/gnark-crypto/ecc/bn254/fr"
8+
"golang.org/x/sync/syncmap"
9+
"io/ioutil"
10+
"math/big"
11+
"os"
12+
"path/filepath"
13+
"runtime"
14+
"strings"
15+
"time"
16+
)
17+
18+
var UserIDS syncmap.Map
19+
20+
func ReadUserAssetsV1(dirname string) ([]AccountInfo, []CexAssetInfo, error) {
21+
userFiles, err := ioutil.ReadDir(dirname)
22+
if err != nil {
23+
return nil, nil, err
24+
}
25+
var accountInfo []AccountInfo
26+
var cexAssetInfo []CexAssetInfo
27+
28+
workersNum := 8
29+
userFileNames := make([]string, 0)
30+
31+
type UserParseRes struct {
32+
accounts []AccountInfo
33+
cex []CexAssetInfo
34+
index int
35+
}
36+
results := make([]chan UserParseRes, workersNum)
37+
for i := 0; i < workersNum; i++ {
38+
results[i] = make(chan UserParseRes, 1)
39+
}
40+
for _, userFile := range userFiles {
41+
if strings.Index(userFile.Name(), ".csv") == -1 {
42+
continue
43+
}
44+
userFileNames = append(userFileNames, filepath.Join(dirname, userFile.Name()))
45+
}
46+
for i := 0; i < workersNum; i++ {
47+
go func(workerId int) {
48+
for j := workerId; j < len(userFileNames); j += workersNum {
49+
if j >= len(userFileNames) {
50+
break
51+
}
52+
tmpAccountInfo, tmpCexAssetInfo, err := ReadUserDataFromCsvFileV1(userFileNames[j])
53+
if err != nil {
54+
panic(err.Error())
55+
}
56+
results[workerId] <- UserParseRes{
57+
accounts: tmpAccountInfo,
58+
cex: tmpCexAssetInfo,
59+
}
60+
}
61+
}(i)
62+
}
63+
64+
gcQuitChan := make(chan bool)
65+
go func() {
66+
for {
67+
select {
68+
case <-time.After(time.Second * 10):
69+
runtime.GC()
70+
case <-gcQuitChan:
71+
return
72+
}
73+
}
74+
}()
75+
76+
quit := make(chan bool)
77+
go func() {
78+
for i := 0; i < len(userFileNames); i++ {
79+
res := <-results[i%workersNum]
80+
if i != 0 {
81+
for j := 0; j < len(res.accounts); j++ {
82+
res.accounts[j].AccountIndex += uint32(len(accountInfo))
83+
}
84+
}
85+
accountInfo = append(accountInfo, res.accounts...)
86+
if len(cexAssetInfo) == 0 {
87+
cexAssetInfo = res.cex
88+
}
89+
}
90+
quit <- true
91+
}()
92+
<-quit
93+
gcQuitChan <- true
94+
return accountInfo, cexAssetInfo, nil
95+
}
96+
97+
func ReadUserDataFromCsvFileV1(name string) ([]AccountInfo, []CexAssetInfo, error) {
98+
f, err := os.Open(name)
99+
if err != nil {
100+
return nil, nil, err
101+
}
102+
defer f.Close()
103+
csvReader := csv.NewReader(f)
104+
data, err := csvReader.ReadAll()
105+
accountIndex := 0
106+
cexAssetsInfo := make([]CexAssetInfo, AssetCounts)
107+
accounts := make([]AccountInfo, len(data)-1)
108+
assetCounts := (len(data[0]) - 3) / 4
109+
symbols := data[0]
110+
data = data[1:]
111+
for i := 0; i < assetCounts; i++ {
112+
cexAssetsInfo[i].Symbol = symbols[i*3+4]
113+
cexAssetsInfo[i].Index = uint32(i)
114+
multiplier := int64(100000000)
115+
if AssetTypeForTwoDigits[cexAssetsInfo[i].Symbol] {
116+
multiplier = 100000000000000
117+
}
118+
119+
cexAssetsInfo[i].BasePrice, err = ConvertFloatStrToUint64(data[0][assetCounts*3+i+2], multiplier)
120+
if err != nil {
121+
fmt.Println("asset data wrong:", data[0][assetCounts*3+i+2], err.Error())
122+
continue
123+
}
124+
}
125+
126+
invalidCounts := 0
127+
for i := 0; i < len(data); i++ {
128+
// check userid is unique
129+
_, ok := UserIDS.Load(data[i][1])
130+
if ok {
131+
panic("accountId is Repeated : " + data[i][1])
132+
}
133+
UserIDS.Store(data[i][1], true)
134+
135+
var account AccountInfo
136+
assets := make([]AccountAsset, 0, 8)
137+
account.TotalEquity = new(big.Int).SetInt64(0)
138+
account.TotalDebt = new(big.Int).SetInt64(0)
139+
// first element of data[i] is ID. we use accountIndex instead
140+
account.AccountIndex = uint32(accountIndex)
141+
accountId, err := hex.DecodeString(data[i][1])
142+
if err != nil || len(accountId) != 32 {
143+
panic("accountId is invalid: " + data[i][1])
144+
}
145+
account.AccountId = new(fr.Element).SetBytes(accountId).Marshal()
146+
var tmpAsset AccountAsset
147+
for j := 0; j < assetCounts; j++ {
148+
multiplier := int64(100000000)
149+
if AssetTypeForTwoDigits[cexAssetsInfo[j].Symbol] {
150+
multiplier = 100
151+
}
152+
equity, err := ConvertFloatStrToUint64(data[i][j*3+2], multiplier)
153+
if err != nil {
154+
fmt.Println("account", data[i][1], "the symbol is ", cexAssetsInfo[j].Symbol, " ", data[i][j*3+2], " equity data wrong:", err.Error())
155+
invalidCounts += 1
156+
continue
157+
}
158+
159+
debt, err := ConvertFloatStrToUint64(data[i][j*3+3], multiplier)
160+
if err != nil {
161+
fmt.Println("account", data[i][1], "the debt symbol is ", cexAssetsInfo[j].Symbol, " ", data[i][j*3+3], " debt data wrong:", err.Error())
162+
invalidCounts += 1
163+
continue
164+
}
165+
if equity != 0 || debt != 0 {
166+
tmpAsset.Index = uint16(j)
167+
tmpAsset.Equity = equity
168+
tmpAsset.Debt = debt
169+
assets = append(assets, tmpAsset)
170+
171+
account.TotalEquity = new(big.Int).Add(account.TotalEquity,
172+
new(big.Int).Mul(new(big.Int).SetUint64(tmpAsset.Equity), new(big.Int).SetUint64(cexAssetsInfo[j].BasePrice)))
173+
account.TotalDebt = new(big.Int).Add(account.TotalDebt,
174+
new(big.Int).Mul(new(big.Int).SetUint64(tmpAsset.Debt), new(big.Int).SetUint64(cexAssetsInfo[j].BasePrice)))
175+
}
176+
}
177+
178+
account.Assets = assets
179+
if account.TotalEquity.Cmp(account.TotalDebt) >= 0 {
180+
accounts[accountIndex] = account
181+
accountIndex += 1
182+
} else {
183+
invalidCounts += 1
184+
fmt.Println("account", data[i][1], "data wrong: total debt is bigger than equity:", account.TotalDebt, account.TotalEquity)
185+
}
186+
if i%100000 == 0 {
187+
runtime.GC()
188+
}
189+
}
190+
accounts = accounts[:accountIndex]
191+
fmt.Println("The invalid accounts number is ", invalidCounts)
192+
fmt.Println("The valid accounts number is ", len(accounts))
193+
return accounts, cexAssetsInfo, nil
194+
}

0 commit comments

Comments
 (0)