Commit 5ebc93d3 authored by 贾浩@五瓣科技's avatar 贾浩@五瓣科技

update api

parent c09f8572
package api
const (
InvalidParams = "invalid params"
DateOutOfRange = "date out of range"
InternalError = "internal error"
)
package api
import (
"encoding/json"
"net/http"
"time"
"github.com/ethereum/go-ethereum/common"
)
func rpcHandle(w http.ResponseWriter, r *http.Request) {
req := &jsonrpcMessage{}
resp := &jsonrpcMessage{}
if r.Method != "POST" {
w.Write([]byte("method not allowed"))
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "application/json")
contentType := r.Header.Get("Content-Type")
if contentType != "application/json" {
resp.Error = &jsonError{
Code: -32600,
Message: "invalid Content-Type header",
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return
}
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
resp.Error = &jsonError{
Code: -32603,
Message: err.Error(),
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return
}
if req.Version != "2.0" {
resp.Error = &jsonError{
Code: -32600,
Message: "invalid jsonrpc version",
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return
}
resp.Version = req.Version
resp.ID = req.ID
switch req.Method {
case "getWithdrawProofs":
getWithdrawProofs(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
return
case "getPendingWorkload":
getPendingWorkload(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
return
case "getDailyMerkleNodes":
getDailyMerkleNodes(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
case "getDailyMerkleSumNodes":
getDailyMerkleSumNodes(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
default:
resp.Error = &jsonError{
Code: -32601,
Message: "method not found",
}
_ = json.NewEncoder(w).Encode(resp)
return
}
}
func getWithdrawProofs(params []byte, resp *jsonrpcMessage) {
paramList := make([]string, 0)
err := json.Unmarshal(params, &paramList)
if err != nil || len(paramList) < 1 || len(paramList) > 2 {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
if !common.IsHexAddress(paramList[0]) {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
var date string
if len(paramList) > 1 {
_, err = time.Parse("2006-01-02", paramList[1])
if err != nil {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
date = paramList[1]
}
amount, proofs := validator.GetMerkleProof(common.HexToAddress(paramList[0]), date)
temp := map[string]interface{}{
"amount": amount,
"proofs": proofs,
}
resp.Result, _ = json.Marshal(temp)
return
}
func getPendingWorkload(params []byte, resp *jsonrpcMessage) {
addressList := make([]string, 0)
err := json.Unmarshal(params, &addressList)
if err != nil || len(addressList) != 1 {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
if !common.IsHexAddress(addressList[0]) {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
workload, globalWorkload := validator.GetPendingWorkload(common.HexToAddress(addressList[0]))
temp := map[string]interface{}{
"workload": workload,
"global_workload": globalWorkload,
}
resp.Result, _ = json.Marshal(temp)
return
}
func getDailyMerkleNodes(params []byte, resp *jsonrpcMessage) {
// date string, depth int, rootHash common.Hash
paramList := make([]interface{}, 0)
err := json.Unmarshal(params, &paramList)
if err != nil || len(paramList) < 1 || len(paramList) > 3 {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
var date string
var depth = 1
var rootHash common.Hash
_, err = time.Parse("2006-01-02", paramList[0].(string))
if err != nil {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
date = paramList[0].(string)
if len(paramList) >= 2 {
_depth, ok := paramList[1].(float64)
if !ok {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
depth = int(uint(_depth))
}
if len(paramList) >= 3 {
rootHash = common.HexToHash(paramList[2].(string))
}
nodes := validator.GetDailyMerkleNodes(date, depth, rootHash)
resp.Result, _ = json.Marshal(nodes)
}
func getDailyMerkleSumNodes(params []byte, resp *jsonrpcMessage) {
// date string, depth int, rootHash common.Hash
paramList := make([]interface{}, 0)
err := json.Unmarshal(params, &paramList)
if err != nil || len(paramList) < 1 || len(paramList) > 3 {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
var date string
var depth = 1
var rootHash common.Hash
_, err = time.Parse("2006-01-02", paramList[0].(string))
if err != nil {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
date = paramList[0].(string)
if len(paramList) >= 2 {
_depth, ok := paramList[1].(float64)
if !ok {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
depth = int(uint(_depth))
}
if len(paramList) >= 3 {
rootHash = common.HexToHash(paramList[2].(string))
}
nodes, vals := validator.GetDailyMerkleSumNodes(date, depth, rootHash)
resp.Result, _ = json.Marshal(map[string]interface{}{
"nodes": nodes,
"values": vals,
})
}
package api
import (
"github.com/gin-gonic/gin"
)
func initRouter(engine *gin.Engine) {
g := engine.Group("/api/v1")
g.POST("/workload", getWorkload)
g.POST("/reward", getReward)
g.POST("/record", getRecord)
}
\ No newline at end of file
package api package api
import ( import (
"encoding/json" "fmt"
"net/http" "math/big"
"strconv"
"time" "time"
"validator/claim_monitor"
"validator/core" "validator/core"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
log "github.com/sirupsen/logrus" "github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
) )
var validator *core.Validator var validator *core.Validator
var claimMonitorCli *claim_monitor.Client
var log = logrus.WithField("module", "api")
func rpcHandle(w http.ResponseWriter, r *http.Request) { func getWorkload(c *gin.Context) {
req := &jsonrpcMessage{} // 每天的workload获取
resp := &jsonrpcMessage{} dateList := make([]string, 0)
if err := c.ShouldBindJSON(&dateList); err != nil {
if r.Method != "POST" { c.JSON(200, withError(InvalidParams))
w.Write([]byte("method not allowed"))
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "application/json")
contentType := r.Header.Get("Content-Type")
if contentType != "application/json" {
resp.Error = &jsonError{
Code: -32600,
Message: "invalid Content-Type header",
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return return
} }
err := json.NewDecoder(r.Body).Decode(req) timestampList := make([]uint64, 0)
for _, date := range dateList {
t, err := time.Parse("2006-01-02", date)
if err != nil { if err != nil {
resp.Error = &jsonError{ c.JSON(200, withError(DateOutOfRange))
Code: -32603,
Message: err.Error(),
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return return
} }
utcNow := time.Now().UTC()
if req.Version != "2.0" { if t.After(time.Date(utcNow.Year(), utcNow.Month(), utcNow.Day(), 0, 0, 0, 0, time.UTC)) {
resp.Error = &jsonError{ c.JSON(200, withError(DateOutOfRange))
Code: -32600,
Message: "invalid jsonrpc version",
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return return
} }
resp.Version = req.Version
resp.ID = req.ID
switch req.Method { timestampList = append(timestampList, uint64(t.Unix()))
case "getWithdrawProofs":
getWithdrawProofs(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
return
case "getPendingWorkload":
getPendingWorkload(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
return
case "getDailyMerkleNodes":
getDailyMerkleNodes(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
case "getDailyMerkleSumNodes":
getDailyMerkleSumNodes(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
default:
resp.Error = &jsonError{
Code: -32601,
Message: "method not found",
} }
_ = json.NewEncoder(w).Encode(resp)
return ret, err := validator.GetWorkload(timestampList)
if err != nil {
log.WithError(err).Error("failed to get workload")
c.JSON(200, withError(InternalError))
} }
c.JSON(200, withSuccess(ret))
} }
func getWithdrawProofs(params []byte, resp *jsonrpcMessage) { func getReward(c *gin.Context) {
paramList := make([]string, 0) // 在这里获取全部,再通过api获取已领取的
err := json.Unmarshal(params, &paramList) tmp := struct {
if err != nil || len(paramList) < 1 || len(paramList) > 2 { Address string `json:"address"`
resp.Error = &jsonError{ }{}
Code: -32602, if err := c.ShouldBindJSON(&tmp); err != nil {
Message: "invalid params", c.JSON(200, withError(InvalidParams))
}
return return
} }
if !common.IsHexAddress(tmp.Address) {
if !common.IsHexAddress(paramList[0]) { c.JSON(200, withError(InvalidParams))
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return return
} }
reward := validator.GetReward(common.HexToAddress(tmp.Address))
ether := big.NewInt(1000000000000000000)
floatReward, _ := new(big.Float).Quo(new(big.Float).SetInt(reward), new(big.Float).SetInt(ether)).Float64()
var date string claimedReward, err := claimMonitorCli.GetClaimedAmount(tmp.Address)
if len(paramList) > 1 {
_, err = time.Parse("2006-01-02", paramList[1])
if err != nil { if err != nil {
resp.Error = &jsonError{ log.WithError(err).Error("failed to get claimed reward")
Code: -32602, c.JSON(200, withError(InternalError))
Message: "invalid params",
}
return return
} }
date = paramList[1] floatClaimedReward, _ := strconv.ParseFloat(claimedReward, 64)
}
amount, proofs := validator.GetMerkleProof(common.HexToAddress(paramList[0]), date) c.JSON(200, withSuccess(gin.H{
"total": fmt.Sprintf("%.6f", floatReward),
temp := map[string]interface{}{ "claimed": claimedReward,
"amount": amount, "unclaimed": fmt.Sprintf("%.6f", floatReward-floatClaimedReward),
"proofs": proofs, }))
}
resp.Result, _ = json.Marshal(temp)
return
} }
func getPendingWorkload(params []byte, resp *jsonrpcMessage) { func getRecord(c *gin.Context) {
addressList := make([]string, 0) // 通过api获取
err := json.Unmarshal(params, &addressList) tmp := struct {
if err != nil || len(addressList) != 1 { Address string `json:"address"`
resp.Error = &jsonError{ Page int `json:"page"`
Code: -32602, PageSize int `json:"pageSize"`
Message: "invalid params", }{}
}
return
}
if !common.IsHexAddress(addressList[0]) { if err := c.ShouldBindJSON(&tmp); err != nil {
resp.Error = &jsonError{ c.JSON(200, withError(InvalidParams))
Code: -32602,
Message: "invalid params",
}
return return
} }
if !common.IsHexAddress(tmp.Address) {
workload, globalWorkload := validator.GetPendingWorkload(common.HexToAddress(addressList[0])) c.JSON(200, withError(InvalidParams))
temp := map[string]interface{}{
"workload": workload,
"global_workload": globalWorkload,
}
resp.Result, _ = json.Marshal(temp)
return
}
func getDailyMerkleNodes(params []byte, resp *jsonrpcMessage) {
// date string, depth int, rootHash common.Hash
paramList := make([]interface{}, 0)
err := json.Unmarshal(params, &paramList)
if err != nil || len(paramList) < 1 || len(paramList) > 3 {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return return
} }
data, err := claimMonitorCli.GetClaimRecord(tmp.Address, tmp.Page, tmp.PageSize)
var date string
var depth = 1
var rootHash common.Hash
_, err = time.Parse("2006-01-02", paramList[0].(string))
if err != nil { if err != nil {
resp.Error = &jsonError{ log.WithError(err).Error("failed to get claim record")
Code: -32602, c.JSON(200, withError(InternalError))
Message: "invalid params",
}
return return
} }
date = paramList[0].(string) c.Data(200, "application/json", data)
if len(paramList) >= 2 {
_depth, ok := paramList[1].(float64)
if !ok {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
depth = int(uint(_depth))
}
if len(paramList) >= 3 {
rootHash = common.HexToHash(paramList[2].(string))
}
nodes := validator.GetDailyMerkleNodes(date, depth, rootHash)
resp.Result, _ = json.Marshal(nodes)
} }
func getDailyMerkleSumNodes(params []byte, resp *jsonrpcMessage) { func withSuccess(data interface{}) interface{} {
// date string, depth int, rootHash common.Hash return map[string]interface{}{
paramList := make([]interface{}, 0) "code": 0,
err := json.Unmarshal(params, &paramList) "msg": "ok",
if err != nil || len(paramList) < 1 || len(paramList) > 3 { "data": data,
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
} }
return }
}
var date string
var depth = 1
var rootHash common.Hash
_, err = time.Parse("2006-01-02", paramList[0].(string)) func withError(msg string) interface{} {
if err != nil { return map[string]interface{}{
resp.Error = &jsonError{ "code": 1,
Code: -32602, "msg": "",
Message: "invalid params", "error": msg,
}
return
} }
date = paramList[0].(string) }
if len(paramList) >= 2 { func StartServer(listenAddress string, v *core.Validator, c *claim_monitor.Client) {
_depth, ok := paramList[1].(float64) validator = v
if !ok { claimMonitorCli = c
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
depth = int(uint(_depth))
}
if len(paramList) >= 3 { engine := gin.Default()
rootHash = common.HexToHash(paramList[2].(string)) engine.Use(cors.Default())
} initRouter(engine)
nodes, vals := validator.GetDailyMerkleSumNodes(date, depth, rootHash) log.WithField("listen", listenAddress).Info("start api server")
resp.Result, _ = json.Marshal(map[string]interface{}{
"nodes": nodes,
"values": vals,
})
}
func StartJSONRPC(listenAddress string, w *core.Validator) { err := engine.Run(listenAddress)
validator = w
http.HandleFunc("/", rpcHandle)
log.WithField("listen", listenAddress).Info("start JSON-RPC server")
err := http.ListenAndServe(listenAddress, nil)
if err != nil { if err != nil {
log.WithError(err).Fatal("failed to start JSON-RPC server") log.WithError(err).Fatal("failed to start api server")
} }
} }
package claim_monitor
import (
"fmt"
"io"
"net/http"
"github.com/tidwall/gjson"
)
type Client struct {
Server string
}
func NewClient(server string) *Client {
return &Client{
Server: server,
}
}
func (cli *Client) GetClaimedAmount(address string) (string, error) {
resp, err := http.DefaultClient.Get(fmt.Sprintf("%s/api/v1/claimed?address=%s", cli.Server, address))
if err != nil {
return "0", err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return "0", err
}
if gjson.Get(string(data), "code").Int() != 0 {
return "0", fmt.Errorf(string(data))
}
return gjson.Get(string(data), "data.claimed").String(), nil
}
func (cli *Client) GetClaimRecord(address string, page, pageSize int) ([]byte, error) {
resp, err := http.DefaultClient.Get(fmt.Sprintf("%s/api/v1/record?address=%s&page=%d&pageSize=%d", cli.Server, address, page, pageSize))
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
...@@ -34,12 +34,17 @@ var ( ...@@ -34,12 +34,17 @@ var (
Value: "0.0.0.0:20010", Value: "0.0.0.0:20010",
} }
rpcListenAddrFlag = &cli.StringFlag{ apiListenAddrFlag = &cli.StringFlag{
Name: "rpc-listen", Name: "api-listen",
Usage: "The listen address of the jsonrpc server", Usage: "The listen address of the api server",
Value: "0.0.0.0:20012", Value: "0.0.0.0:20012",
} }
claimMonitorServerFlag = &cli.StringFlag{
Name: "claim-monitor-server",
Usage: "The host of the claim monitor server",
}
privateKeyFlag = &cli.StringFlag{ privateKeyFlag = &cli.StringFlag{
Name: "private-key", Name: "private-key",
Usage: "The private key of the account", Usage: "The private key of the account",
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"net/http" "net/http"
"os" "os"
"validator/api" "validator/api"
"validator/claim_monitor"
"validator/conf" "validator/conf"
"validator/core" "validator/core"
"validator/quest" "validator/quest"
...@@ -20,7 +21,8 @@ var ( ...@@ -20,7 +21,8 @@ var (
dataDirFlag, dataDirFlag,
metricsListenAddrFlag, metricsListenAddrFlag,
debugFlag, debugFlag,
rpcListenAddrFlag, apiListenAddrFlag,
claimMonitorServerFlag,
privateKeyFlag, privateKeyFlag,
chainRPCFlag, chainRPCFlag,
storeContractFlag, storeContractFlag,
...@@ -56,7 +58,8 @@ func run(ctx *cli.Context) { ...@@ -56,7 +58,8 @@ func run(ctx *cli.Context) {
cfg := &conf.Config{ cfg := &conf.Config{
MetricsListenAddr: ctx.String(metricsListenAddrFlag.Name), MetricsListenAddr: ctx.String(metricsListenAddrFlag.Name),
Debug: ctx.Bool(debugFlag.Name), Debug: ctx.Bool(debugFlag.Name),
RPCListenAddr: ctx.String(rpcListenAddrFlag.Name), APIListenAddr: ctx.String(apiListenAddrFlag.Name),
ClaimMonitorServer: ctx.String(claimMonitorServerFlag.Name),
PrivateKey: ctx.String(privateKeyFlag.Name), PrivateKey: ctx.String(privateKeyFlag.Name),
ChainRPC: ctx.String(chainRPCFlag.Name), ChainRPC: ctx.String(chainRPCFlag.Name),
StoreContract: ctx.String(storeContractFlag.Name), StoreContract: ctx.String(storeContractFlag.Name),
...@@ -83,7 +86,8 @@ func run(ctx *cli.Context) { ...@@ -83,7 +86,8 @@ func run(ctx *cli.Context) {
w := core.RunValidator(q, cfg) w := core.RunValidator(q, cfg)
// runGrpcServer(cfg.GRPCListenAddr, w) // runGrpcServer(cfg.GRPCListenAddr, w)
runJSONRPCServer(cfg.RPCListenAddr, w) monitorCli := claim_monitor.NewClient(cfg.ClaimMonitorServer)
runAPIServer(cfg.APIListenAddr, w, monitorCli)
select {} select {}
} }
...@@ -97,6 +101,6 @@ func runMetrics(listen string) { ...@@ -97,6 +101,6 @@ func runMetrics(listen string) {
}() }()
} }
func runJSONRPCServer(listen string, w *core.Validator) { func runAPIServer(listen string, w *core.Validator, c *claim_monitor.Client) {
go api.StartJSONRPC(listen, w) go api.StartServer(listen, w, c)
} }
...@@ -3,7 +3,7 @@ package conf ...@@ -3,7 +3,7 @@ package conf
type Config struct { type Config struct {
MetricsListenAddr string MetricsListenAddr string
Debug bool Debug bool
RPCListenAddr string APIListenAddr string
ChainRPC string ChainRPC string
PrivateKey string PrivateKey string
StoreContract string StoreContract string
...@@ -11,6 +11,7 @@ type Config struct { ...@@ -11,6 +11,7 @@ type Config struct {
RewardContract string RewardContract string
DataDir string DataDir string
CommitOffset int CommitOffset int
ClaimMonitorServer string
} }
type QuestConfig struct { type QuestConfig struct {
......
...@@ -4,15 +4,17 @@ data-dir = "./data" ...@@ -4,15 +4,17 @@ data-dir = "./data"
metrics-listen = "0.0.0.0:20010" metrics-listen = "0.0.0.0:20010"
rpc-listen = "0.0.0.0:20012" api-listen = "0.0.0.0:20012"
private-key = "529f4efb80ac534f17d873104c71881c0970dbd5a886f183f63c5c6bb7a1fcd9" private-key = "529f4efb80ac534f17d873104c71881c0970dbd5a886f183f63c5c6bb7a1fcd9"
chain-rpc = "https://dev.rpc.agicoin.ai" chain-rpc = "https://dev.rpc.agicoin.ai"
store-contract = "0xfFb096e2B90324FFcCbaf987BdD724462c0aE18c" store-contract = "0xA0ec84eCa14CD23afD5D7ba973390E83F0Cbe89A"
validator-contract = "0x2A03bA42139860aF46263755f6e5CBAe8195bB92" # 测试版本 不会revert validator-contract = "0x7CBD03ecfA9093F83150E9625A25B00F555c81F7" # 测试版本 不会revert
claim-monitor-server = ""
commit-offset = 3600 # utc + n seconds commit-offset = 3600 # utc + n seconds
......
This diff is collapsed.
...@@ -77,11 +77,29 @@ func (r *ChainRPC) GetNMAddresses() (addrs []common.Address, err error) { ...@@ -77,11 +77,29 @@ func (r *ChainRPC) GetNMAddresses() (addrs []common.Address, err error) {
} }
func (r *ChainRPC) GetWorkloadThreshold(totalWorkload uint64) (threshold *big.Int, err error) { func (r *ChainRPC) GetWorkloadThreshold(totalWorkload uint64) (threshold *big.Int, err error) {
return r.validatorContract.GetWorkloadDistribution(nil, big.NewInt(int64(totalWorkload))) return r.validatorContract.GetWorkloadReward(nil, big.NewInt(int64(totalWorkload)))
}
// GetWeiPerWorkload 给定日期,获取当天的总奖励,总工作量,每工作量奖励
func (r *ChainRPC) GetWeiPerWorkload(timestamp uint64) (reward, workload, weiPerWorkload *big.Int, err error) {
rewardDay, err := r.validatorContract.GetRewardByDate(nil, big.NewInt(int64(timestamp)))
if err != nil {
return
}
workloadDay, err := r.validatorContract.GetWorkloadByDate(nil, big.NewInt(int64(timestamp)))
if err != nil {
return
}
if big.NewInt(0).Cmp(workloadDay) == 0 || big.NewInt(0).Cmp(rewardDay) == 0 {
err = errors.New("workload or reward is zero")
return
}
return rewardDay, workloadDay, big.NewInt(0).Quo(rewardDay, workloadDay), nil
} }
// SubmitProofs 调用合约提交root // SubmitProofs 调用合约提交root
func (r *ChainRPC) SubmitProofs(dateTimestamp int64, merkleSumTreeRoot, merkleTreeRoot common.Hash) (txHash common.Hash, err error) { func (r *ChainRPC) SubmitProofs(dateTimestamp int64, merkleSumTreeRoot, merkleTreeRoot common.Hash, totalWorkload uint64) (txHash common.Hash, err error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute) ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel() defer cancel()
opts, err := bind.NewKeyedTransactorWithChainID(r.privateKey, r.chainID) opts, err := bind.NewKeyedTransactorWithChainID(r.privateKey, r.chainID)
...@@ -91,7 +109,7 @@ func (r *ChainRPC) SubmitProofs(dateTimestamp int64, merkleSumTreeRoot, merkleTr ...@@ -91,7 +109,7 @@ func (r *ChainRPC) SubmitProofs(dateTimestamp int64, merkleSumTreeRoot, merkleTr
opts.GasLimit = 500000 opts.GasLimit = 500000
opts.Context = ctx opts.Context = ctx
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
signedTx, err := r.validatorContract.SubmitMerkleRoot(opts, big.NewInt(dateTimestamp), merkleSumTreeRoot, merkleTreeRoot) signedTx, err := r.validatorContract.SubmitMerkleRoot(opts, big.NewInt(dateTimestamp), merkleSumTreeRoot, merkleTreeRoot, big.NewInt(0).SetUint64(totalWorkload))
if err != nil { if err != nil {
log.WithError(err).Error("submit root, call contract failed, retry after 3 seconds") log.WithError(err).Error("submit root, call contract failed, retry after 3 seconds")
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
......
...@@ -138,3 +138,31 @@ func (v *Validator) GetDailyMerkleSumNodes(date string, depth int, rootHash comm ...@@ -138,3 +138,31 @@ func (v *Validator) GetDailyMerkleSumNodes(date string, depth int, rootHash comm
} }
return nodesHash, nodesVal return nodesHash, nodesVal
} }
// GetWorkload /api/v1/workload
func (v *Validator) GetWorkload(timestampList []uint64) (ret []map[string]string, err error) {
for _, timestamp := range timestampList {
r, w, wei, err := v.rpc.GetWeiPerWorkload(timestamp)
if err != nil {
return nil, err
}
ret = append(ret, map[string]string{
"date": v.timestampToDate(int64(timestamp)),
"weiPerWorkload": wei.String(),
"reward": w.String(),
"workload": r.String(),
})
}
return ret, nil
}
// GetReward /api/v1/reward
func (v *Validator) GetReward(address common.Address) (reward *big.Int) {
object := v.state.GetMinerObject(address)
if object == nil {
return big.NewInt(0)
}
b, _ := big.NewInt(0).SetString(object.Balance, 10)
return b
}
...@@ -75,7 +75,7 @@ func RunValidator(q *quest.Quest, cfg *conf.Config) *Validator { ...@@ -75,7 +75,7 @@ func RunValidator(q *quest.Quest, cfg *conf.Config) *Validator {
} }
// v.date = 3, 如果当前时间超过提交昨天的时间,需要提交昨天的 // v.date = 3, 如果当前时间超过提交昨天的时间,需要提交昨天的
if v.dateToTimestamp(v.date) < v.yesterdayTimestamp() && if v.dateToTimestamp(v.date) < v.yesterdayTimestamp() &&
time.Now().After(time.Unix(v.todayTimestamp()+int64(cfg.CommitOffset), 0)) { time.Now().UTC().After(time.Unix(v.todayTimestamp()+int64(cfg.CommitOffset), 0)) {
if err = v.SyncDayJob(v.dateToTimestamp(v.date)+86400, true); err != nil { if err = v.SyncDayJob(v.dateToTimestamp(v.date)+86400, true); err != nil {
return nil return nil
} }
...@@ -146,7 +146,7 @@ func (v *Validator) ProcessDayJob() { ...@@ -146,7 +146,7 @@ func (v *Validator) ProcessDayJob() {
}).Debug("process day job") }).Debug("process day job")
v.LoadPendingProofs(v.yesterdayTimestamp(), v.todayTimestamp()) v.LoadPendingProofs(v.yesterdayTimestamp(), v.todayTimestamp())
v.date = v.yesterdayString() v.date = v.yesterdayString()
dayProof := v.Commit() dayProof, totalWorkload := v.Commit()
mstRoot, _, err := v.CommitMST(dayProof) mstRoot, _, err := v.CommitMST(dayProof)
if err != nil { if err != nil {
log.WithError(err).Error("failed to commit merkle sum tree") log.WithError(err).Error("failed to commit merkle sum tree")
...@@ -158,7 +158,7 @@ func (v *Validator) ProcessDayJob() { ...@@ -158,7 +158,7 @@ func (v *Validator) ProcessDayJob() {
log.WithError(err).Error("failed to commit merkle tree") log.WithError(err).Error("failed to commit merkle tree")
return return
} }
txHash, err := v.rpc.SubmitProofs(v.dateToTimestamp(v.date), mstRoot, mtRoot) txHash, err := v.rpc.SubmitProofs(v.dateToTimestamp(v.date), mstRoot, mtRoot, totalWorkload)
if err != nil { if err != nil {
log.WithError(err).Error("submit proofs") log.WithError(err).Error("submit proofs")
return return
...@@ -190,7 +190,7 @@ func (v *Validator) SyncDayJob(dateTimestamp int64, commitToChain bool) (err err ...@@ -190,7 +190,7 @@ func (v *Validator) SyncDayJob(dateTimestamp int64, commitToChain bool) (err err
}).Debug("sync day job") }).Debug("sync day job")
v.LoadPendingProofs(dateTimestamp, dateTimestamp+86400) v.LoadPendingProofs(dateTimestamp, dateTimestamp+86400)
v.date = v.timestampToDate(dateTimestamp) v.date = v.timestampToDate(dateTimestamp)
dayProof := v.Commit() dayProof, totalWorkload := v.Commit()
mstRoot, _, err := v.CommitMST(dayProof) mstRoot, _, err := v.CommitMST(dayProof)
if err != nil { if err != nil {
log.WithError(err).Error("failed to commit merkle sum tree") log.WithError(err).Error("failed to commit merkle sum tree")
...@@ -204,7 +204,7 @@ func (v *Validator) SyncDayJob(dateTimestamp int64, commitToChain bool) (err err ...@@ -204,7 +204,7 @@ func (v *Validator) SyncDayJob(dateTimestamp int64, commitToChain bool) (err err
} }
var txHash common.Hash var txHash common.Hash
if commitToChain { if commitToChain {
txHash, err = v.rpc.SubmitProofs(dateTimestamp, mstRoot, mtRoot) txHash, err = v.rpc.SubmitProofs(dateTimestamp, mstRoot, mtRoot, totalWorkload)
if err != nil { if err != nil {
log.WithError(err).Error("submit proofs") log.WithError(err).Error("submit proofs")
return return
...@@ -226,7 +226,7 @@ func (v *Validator) SyncDayJob(dateTimestamp int64, commitToChain bool) (err err ...@@ -226,7 +226,7 @@ func (v *Validator) SyncDayJob(dateTimestamp int64, commitToChain bool) (err err
} }
// Commit statedb提交 // Commit statedb提交
func (v *Validator) Commit() (dayProofs map[common.Address]*validatorv1.ValidatedProof) { func (v *Validator) Commit() (dayProofs map[common.Address]*validatorv1.ValidatedProof, totalWorkload uint64) {
st := time.Now() st := time.Now()
proof, totalWorkload := v.RefreshPendingProof() proof, totalWorkload := v.RefreshPendingProof()
balancePerWorkload, err := v.rpc.GetWorkloadThreshold(totalWorkload) balancePerWorkload, err := v.rpc.GetWorkloadThreshold(totalWorkload)
...@@ -259,7 +259,7 @@ func (v *Validator) Commit() (dayProofs map[common.Address]*validatorv1.Validate ...@@ -259,7 +259,7 @@ func (v *Validator) Commit() (dayProofs map[common.Address]*validatorv1.Validate
return return
} }
v.state, _ = NewStateDB(v.lvdb, root) v.state, _ = NewStateDB(v.lvdb, root)
return proof return proof, totalWorkload
} }
func (v *Validator) SealProof(miner common.Address, proof *validatorv1.ValidatedProof) (err error) { func (v *Validator) SealProof(miner common.Address, proof *validatorv1.ValidatedProof) (err error) {
...@@ -298,7 +298,7 @@ func (v *Validator) RefreshPendingProof() (proof map[common.Address]*validatorv1 ...@@ -298,7 +298,7 @@ func (v *Validator) RefreshPendingProof() (proof map[common.Address]*validatorv1
func (v *Validator) Ticker() { func (v *Validator) Ticker() {
executionTime := time.Unix(v.todayTimestamp()+86400+int64(v.cfg.CommitOffset), 0) executionTime := time.Unix(v.todayTimestamp()+86400+int64(v.cfg.CommitOffset), 0)
// executionTime := time.Now().Add(time.Second * 3) for test // executionTime := time.Now().Add(time.Second * 3) for test
waitTime := executionTime.Sub(time.Now()) waitTime := executionTime.Sub(time.Now().UTC())
timer := time.NewTimer(waitTime) timer := time.NewTimer(waitTime)
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"execution_time": executionTime.UTC().String(), "execution_time": executionTime.UTC().String(),
...@@ -308,7 +308,7 @@ func (v *Validator) Ticker() { ...@@ -308,7 +308,7 @@ func (v *Validator) Ticker() {
<-timer.C <-timer.C
v.ProcessDayJob() v.ProcessDayJob()
executionTime = executionTime.Add(v.duration()) executionTime = executionTime.Add(v.duration())
waitTime = executionTime.Sub(time.Now()) waitTime = executionTime.Sub(time.Now().UTC())
timer.Reset(waitTime) timer.Reset(waitTime)
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"execution_time": executionTime.UTC().String(), "execution_time": executionTime.UTC().String(),
...@@ -373,7 +373,10 @@ func (v *Validator) yesterdayTimestamp() int64 { ...@@ -373,7 +373,10 @@ func (v *Validator) yesterdayTimestamp() int64 {
} }
func (v *Validator) dateToTimestamp(date string) int64 { func (v *Validator) dateToTimestamp(date string) int64 {
t, _ := time.ParseInLocation("2006-01-02", date, time.UTC) t, err := time.ParseInLocation("2006-01-02", date, time.UTC)
if err != nil {
return 0
}
return t.Unix() return t.Unix()
} }
......
...@@ -5,11 +5,14 @@ go 1.21 ...@@ -5,11 +5,14 @@ go 1.21
require ( require (
github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/ethereum/go-ethereum v1.13.5-0.20231027145059-2d7dba024d76 github.com/ethereum/go-ethereum v1.13.5-0.20231027145059-2d7dba024d76
github.com/gin-contrib/cors v1.7.2
github.com/gin-gonic/gin v1.9.1
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/odysseus/odysseus-protocol v0.0.0-00010101000000-000000000000 github.com/odysseus/odysseus-protocol v0.0.0-00010101000000-000000000000
github.com/prometheus/client_golang v1.18.0 github.com/prometheus/client_golang v1.18.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
github.com/tidwall/gjson v1.17.1
github.com/urfave/cli/v2 v2.27.1 github.com/urfave/cli/v2 v2.27.1
gorm.io/driver/postgres v1.5.6 gorm.io/driver/postgres v1.5.6
gorm.io/gorm v1.25.7 gorm.io/gorm v1.25.7
...@@ -22,8 +25,12 @@ require ( ...@@ -22,8 +25,12 @@ require (
github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cespare/cp v1.1.1 // indirect github.com/cespare/cp v1.1.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/errors v1.9.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect
...@@ -37,10 +44,16 @@ require ( ...@@ -37,10 +44,16 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect github.com/go-stack/stack v1.8.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/flock v0.8.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
...@@ -53,14 +66,20 @@ require ( ...@@ -53,14 +66,20 @@ require (
github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.6 // indirect github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/gomega v1.30.0 // indirect github.com/onsi/gomega v1.30.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_model v0.6.0 // indirect github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.47.0 // indirect github.com/prometheus/common v0.47.0 // indirect
...@@ -70,21 +89,26 @@ require ( ...@@ -70,21 +89,26 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/supranational/blst v0.3.11 // indirect github.com/supranational/blst v0.3.11 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect github.com/tklauser/numcpus v0.6.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.20.0 // indirect golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
golang.org/x/mod v0.15.0 // indirect golang.org/x/mod v0.15.0 // indirect
golang.org/x/net v0.21.0 // indirect golang.org/x/net v0.24.0 // indirect
golang.org/x/sync v0.6.0 // indirect golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.18.0 // indirect golang.org/x/tools v0.18.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect
google.golang.org/grpc v1.60.1 // indirect google.golang.org/grpc v1.60.1 // indirect
google.golang.org/protobuf v1.32.0 // indirect google.golang.org/protobuf v1.34.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect rsc.io/tmplfunc v0.0.3 // indirect
) )
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment