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
func rpcHandle(w http.ResponseWriter, r *http.Request) { var log = logrus.WithField("module", "api")
req := &jsonrpcMessage{}
resp := &jsonrpcMessage{} func getWorkload(c *gin.Context) {
// 每天的workload获取
if r.Method != "POST" { dateList := make([]string, 0)
w.Write([]byte("method not allowed")) if err := c.ShouldBindJSON(&dateList); err != nil {
w.WriteHeader(http.StatusMethodNotAllowed) c.JSON(200, withError(InvalidParams))
return return
} }
w.Header().Set("Content-Type", "application/json") timestampList := make([]uint64, 0)
contentType := r.Header.Get("Content-Type") for _, date := range dateList {
if contentType != "application/json" { t, err := time.Parse("2006-01-02", date)
resp.Error = &jsonError{ if err != nil {
Code: -32600, c.JSON(200, withError(DateOutOfRange))
Message: "invalid Content-Type header", return
} }
resp.Version = "2.0" utcNow := time.Now().UTC()
_ = json.NewEncoder(w).Encode(resp) if t.After(time.Date(utcNow.Year(), utcNow.Month(), utcNow.Day(), 0, 0, 0, 0, time.UTC)) {
return c.JSON(200, withError(DateOutOfRange))
} 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" { timestampList = append(timestampList, uint64(t.Unix()))
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 { ret, err := validator.GetWorkload(timestampList)
case "getWithdrawProofs": if err != nil {
getWithdrawProofs(req.Params, resp) log.WithError(err).Error("failed to get workload")
_ = json.NewEncoder(w).Encode(resp) c.JSON(200, withError(InternalError))
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
} }
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)
var date string floatReward, _ := new(big.Float).Quo(new(big.Float).SetInt(reward), new(big.Float).SetInt(ether)).Float64()
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{}{ claimedReward, err := claimMonitorCli.GetClaimedAmount(tmp.Address)
"amount": amount, if err != nil {
"proofs": proofs, log.WithError(err).Error("failed to get claimed reward")
c.JSON(200, withError(InternalError))
return
} }
floatClaimedReward, _ := strconv.ParseFloat(claimedReward, 64)
resp.Result, _ = json.Marshal(temp) c.JSON(200, withSuccess(gin.H{
return "total": fmt.Sprintf("%.6f", floatReward),
"claimed": claimedReward,
"unclaimed": fmt.Sprintf("%.6f", floatReward-floatClaimedReward),
}))
} }
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 func withError(msg string) interface{} {
var depth = 1 return map[string]interface{}{
var rootHash common.Hash "code": 1,
"msg": "",
_, err = time.Parse("2006-01-02", paramList[0].(string)) "error": msg,
if err != nil {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
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,
...@@ -54,15 +56,16 @@ func main() { ...@@ -54,15 +56,16 @@ func main() {
func run(ctx *cli.Context) { 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),
PrivateKey: ctx.String(privateKeyFlag.Name), ClaimMonitorServer: ctx.String(claimMonitorServerFlag.Name),
ChainRPC: ctx.String(chainRPCFlag.Name), PrivateKey: ctx.String(privateKeyFlag.Name),
StoreContract: ctx.String(storeContractFlag.Name), ChainRPC: ctx.String(chainRPCFlag.Name),
ValidatorContract: ctx.String(validatorContractFlag.Name), StoreContract: ctx.String(storeContractFlag.Name),
DataDir: ctx.String(dataDirFlag.Name), ValidatorContract: ctx.String(validatorContractFlag.Name),
CommitOffset: ctx.Int(commitOffsetFlag.Name), DataDir: ctx.String(dataDirFlag.Name),
CommitOffset: ctx.Int(commitOffsetFlag.Name),
} }
if cfg.Debug { if cfg.Debug {
...@@ -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)
} }
package conf 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
ValidatorContract string ValidatorContract string
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