Commit 52686069 authored by BRC985's avatar BRC985

init grid validator

parent 3947d56e
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <cuda.h>
#include "sha256.cuh"
#include <dirent.h>
#include <ctype.h>
#include <sys/time.h>
// #include <openssl/sha.h>
#include <time.h>
__global__ void sha256_cuda(int diffcult, int index, BYTE *data, size_t len, long long *result, long long n)
{
long long i = blockIdx.x * blockDim.x + threadIdx.x;
long long start = index * n;
// perform sha256 calculation here
if (i < n)
{
long long offset = start + i;
BYTE idx[8];
idx[0] = (BYTE)(offset & 0xff);
idx[1] = (BYTE)((offset >> 8) & 0xff);
idx[2] = (BYTE)((offset >> 16) & 0xff);
idx[3] = (BYTE)((offset >> 24) & 0xff);
idx[4] = (BYTE)((offset >> 32) & 0xff);
idx[5] = (BYTE)((offset >> 40) & 0xff);
idx[6] = (BYTE)((offset >> 48) & 0xff);
idx[7] = (BYTE)((offset >> 56) & 0xff);
SHA256_CTX ctx;
BYTE hash[32];
sha256_init(&ctx);
sha256_update(&ctx, data, len);
sha256_update(&ctx, idx, 8);
sha256_final(&ctx, hash);
if (checkOutput(hash, diffcult) == 0)
{
*result = offset;
}
}
}
void pre_sha256()
{
// compy symbols
checkCudaErrors(cudaMemcpyToSymbol(dev_k, host_k, sizeof(host_k), 0, cudaMemcpyHostToDevice));
}
void runSha256(int diffcult, int index, BYTE *data, size_t len, long long *result, long long n)
{
int blockSize = 16;
int numBlocks = (n + blockSize - 1) / blockSize;
sha256_cuda<<<numBlocks, blockSize>>>(diffcult, index, data, len, result, n);
}
void byteToHexStr(const unsigned char *source, char *dest, int sourceLen)
{
short i;
unsigned char highByte, lowByte;
for (i = 0; i < sourceLen; i++)
{
highByte = source[i] >> 4;
lowByte = source[i] & 0x0f;
highByte += 0x30;
if (highByte > 0x39)
dest[i * 2] = highByte + 0x07;
else
dest[i * 2] = highByte;
lowByte += 0x30;
if (lowByte > 0x39)
dest[i * 2 + 1] = lowByte + 0x07;
else
dest[i * 2 + 1] = lowByte;
}
return;
}
void printOutput(const unsigned char *output, int len)
{
char *outputHex = (char *)malloc((2 * len + 1) * sizeof(char));
byteToHexStr(output, outputHex, len);
outputHex[2 * len] = '\0';
printf("%s\n", outputHex);
free(outputHex);
return;
}
// long long stringToLong(const char *arr)
// {
// long long res = 0;
// char sign;
// int index = 0;
// if (arr[index] == '-' || arr[index] == '+')
// {
// sign = arr[index++];
// }
// char c = arr[index++];
// while (isdigit(c))
// {
// res = res * 10 + (c - '0');
// c = arr[index++];
// }
// if (sign == '-')
// {
// return -res;
// }
// return res;
// }
extern "C"
{
int generatePOW(char *rand, int len, int diffcult, long long *index)
{
BYTE **inputs;
// BYTE **outputs;
long long **indexes;
long long count = 2 << (diffcult + 1);
int deviceCount;
cudaGetDeviceCount(&deviceCount);
inputs = (BYTE **)malloc(deviceCount * sizeof(BYTE *));
// outputs = (BYTE **)malloc(deviceCount * sizeof(BYTE *));
indexes = (long long **)malloc(deviceCount * sizeof(long long *));
for (int i = 0; i < deviceCount; i++)
{
checkCudaErrors(cudaSetDevice(i));
checkCudaErrors(cudaMallocManaged(&inputs[i], len * sizeof(BYTE)));
// checkCudaErrors(cudaMallocManaged(&outputs[i], 32 * sizeof(BYTE)));
checkCudaErrors(cudaMallocManaged(&indexes[i], sizeof(long long)));
checkCudaErrors(cudaMemcpy(inputs[i], rand, len, cudaMemcpyHostToDevice));
}
for (int i = 0; i < deviceCount; i++)
{
checkCudaErrors(cudaSetDevice(i));
*indexes[i] = -1;
pre_sha256();
runSha256(diffcult, i, inputs[i], len, indexes[i], count / deviceCount);
}
for (int i = 0; i < deviceCount; i++)
{
checkCudaErrors(cudaSetDevice(i));
cudaDeviceSynchronize();
}
// long long proof;
for (int i = 0; i < deviceCount; i++)
if (*indexes[i] != -1)
{
*index = *indexes[i];
break;
}
for (int i = 0; i < deviceCount; i++)
{
checkCudaErrors(cudaSetDevice(i));
cudaFree(inputs[i]);
// cudaFree(outputs[i]);
cudaFree(indexes[i]);
}
free(inputs);
// free(outputs);
free(indexes);
return 0;
}
}
\ No newline at end of file
#ifndef SHA256_H
#define SHA256_H
/****************************** MACROS ******************************/
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
#define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22))
#define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25))
#define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10))
#define checkCudaErrors(x) \
{ \
cudaGetLastError(); \
x; \
cudaError_t err = cudaGetLastError(); \
if (err != cudaSuccess) \
printf("GPU: cudaError %d (%s)\n", err, cudaGetErrorString(err)); \
}
/**************************** DATA TYPES ****************************/
typedef unsigned char BYTE; // 8-bit byte
typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines
typedef struct JOB
{
BYTE *data;
unsigned long long size;
BYTE digest[64];
char fname[128];
} JOB;
typedef struct
{
BYTE data[64];
WORD datalen;
unsigned long long bitlen;
WORD state[8];
} SHA256_CTX;
__constant__ WORD dev_k[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
static const WORD host_k[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
/*********************** FUNCTION DECLARATIONS **********************/
char *print_sha(BYTE *buff);
__device__ void sha256_init(SHA256_CTX *ctx);
__device__ void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
__device__ void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
char *hash_to_string(BYTE *buff)
{
char *string = (char *)malloc(70);
int k, i;
for (i = 0, k = 0; i < 32; i++, k += 2)
{
sprintf(string + k, "%.2x", buff[i]);
// printf("%02x", buff[i]);
}
string[64] = 0;
return string;
}
void print_job(JOB *j)
{
printf("%s %s\n", hash_to_string(j->digest), j->fname);
}
void print_jobs(JOB **jobs, int n)
{
for (int i = 0; i < n; i++)
{
print_job(jobs[i]);
// printf("@ %p JOB[%i] \n", jobs[i], i);
// printf("\t @ 0x%p data = %x \n", jobs[i]->data, (jobs[i]->data == 0)? 0 : jobs[i]->data[0]);
// printf("\t @ 0x%p size = %llu \n", &(jobs[i]->size), jobs[i]->size);
// printf("\t @ 0x%p fname = %s \n", &(jobs[i]->fname), jobs[i]->fname);
// printf("\t @ 0x%p digest = %s \n------\n", jobs[i]->digest, hash_to_string(jobs[i]->digest));
}
}
__device__ int checkOutput(BYTE hash[32], int diffcult)
{
if (diffcult > 256)
return -1;
int n = diffcult / 8;
BYTE remain = ~(0xff >> (diffcult % 8));
for (int i = 0; i < n; i++)
if (hash[i] != 0)
return -1;
if ((hash[n] & remain) != 0)
return -1;
return 0;
}
__device__ void
mycpy12(uint32_t *d, const uint32_t *s)
{
#pragma unroll 3
for (int k = 0; k < 3; k++)
d[k] = s[k];
}
__device__ void mycpy16(uint32_t *d, const uint32_t *s)
{
#pragma unroll 4
for (int k = 0; k < 4; k++)
d[k] = s[k];
}
__device__ void mycpy32(uint32_t *d, const uint32_t *s)
{
#pragma unroll 8
for (int k = 0; k < 8; k++)
d[k] = s[k];
}
__device__ void mycpy44(uint32_t *d, const uint32_t *s)
{
#pragma unroll 11
for (int k = 0; k < 11; k++)
d[k] = s[k];
}
__device__ void mycpy48(uint32_t *d, const uint32_t *s)
{
#pragma unroll 12
for (int k = 0; k < 12; k++)
d[k] = s[k];
}
__device__ void mycpy64(uint32_t *d, const uint32_t *s)
{
#pragma unroll 16
for (int k = 0; k < 16; k++)
d[k] = s[k];
}
__device__ void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
WORD S[8];
// mycpy32(S, ctx->state);
#pragma unroll 16
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
#pragma unroll 64
for (; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
#pragma unroll 64
for (i = 0; i < 64; ++i)
{
t1 = h + EP1(e) + CH(e, f, g) + dev_k[i] + m[i];
t2 = EP0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
__device__ void sha256_init(SHA256_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
__device__ void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
WORD i;
// for each byte in message
for (i = 0; i < len; ++i)
{
// ctx->data == message 512 bit chunk
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64)
{
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
__device__ void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
WORD i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56)
{
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else
{
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i = 0; i < 4; ++i)
{
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
#endif // SHA256_H
package cmd
import (
"context"
"grid-prover/core/validator"
"grid-prover/database"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/gin-gonic/gin"
"github.com/urfave/cli/v2"
)
var provider1 = "0x867F691B053B61490F8eB74c2df63745CfC0A973"
var ValidatorCmd = &cli.Command{
Name: "validator",
Usage: "grid validator node",
Subcommands: []*cli.Command{
// validatorNodeRunCmd,
validatorNodeTestCmd,
},
}
var validatorNodeTestCmd = &cli.Command{
Name: "run",
Usage: "run meeda store node",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "endpoint",
Aliases: []string{"e"},
Usage: "input your endpoint",
Value: ":8081",
},
&cli.StringFlag{
Name: "sk",
Usage: "input your private key",
Value: "",
},
&cli.StringFlag{
Name: "chain",
Usage: "input chain name, e.g.(dev)",
Value: "product",
},
},
Action: func(ctx *cli.Context) error {
endPoint := ctx.String("endpoint")
sk := ctx.String("sk")
chain := ctx.String("chain")
privateKey, err := crypto.HexToECDSA(sk)
if err != nil {
privateKey, err = crypto.GenerateKey()
if err != nil {
return err
}
}
err = InitTestDataBase("~/grid")
if err != nil {
return err
}
validator, err := validator.NewGRIDValidator(chain, privateKey)
if err != nil {
return err
}
go validator.Start(context.TODO())
server, err := NewValidatorServer(validator, endPoint)
if err != nil {
return err
}
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down server...")
if err := server.Shutdown(context.TODO()); err != nil {
log.Fatal("Server forced to shutdown: ", err)
}
validator.Stop()
log.Println("Server exiting")
return nil
},
}
func NewValidatorServer(validator *validator.GRIDValidator, endpoint string) (*http.Server, error) {
gin.SetMode(gin.ReleaseMode)
router := gin.Default()
router.MaxMultipartMemory = 8 << 20 // 8 MiB
router.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Welcome GRID Validator Node")
})
validator.LoadValidatorModule(router.Group("/v1"))
return &http.Server{
Addr: endpoint,
Handler: router,
}, nil
}
func InitTestDataBase(path string) error {
err := database.RemoveDataBase(path)
if err != nil {
return err
}
err = database.InitDatabase(path)
if err != nil {
return err
}
provider := database.Provider{
Address: provider1,
Name: "test",
IP: "127.0.0.1",
Port: "40",
}
err = provider.CreateProvider()
if err != nil {
return err
}
node := database.Node{
Address: provider1,
Id: 1,
CPUPrice: 10,
CPUModel: "AMD 7309",
GPUPrice: 20,
GPUModel: "NIVIDA 3060",
MemPrice: 5,
MemCapacity: 20,
DiskPrice: 1,
DiskCapacity: 1000,
}
err = node.CreateNode()
if err != nil {
return err
}
order := database.Order{
Address: provider1,
Id: 1,
ActivateTime: time.Now(),
StartTime: time.Now().Add(30 * time.Second),
EndTime: time.Now().Add(2 * time.Hour),
Probation: 30,
Duration: 7170,
}
err = order.CreateOrder()
if err != nil {
return err
}
profit := database.Profit{
Address: provider1,
Balance: 0,
Profit: 10000000,
Penalty: 0,
LastTime: time.Now(),
EndTime: time.Now().Add(10 * time.Hour),
}
return profit.CreateProfit()
}
package cmd
import (
"fmt"
"github.com/urfave/cli/v2"
)
var Version = "0.0.1"
var BuildFlag string
var VersionCmd = &cli.Command{
Name: "version",
Usage: "print version",
Aliases: []string{"V"},
Action: func(_ *cli.Context) error {
fmt.Println(Version + "+" + BuildFlag)
return nil
},
}
This diff is collapsed.
package client
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"grid-prover/core/types"
"io"
"net/http"
"golang.org/x/xerrors"
)
type GRIDClient struct {
baseUrl string
}
func NewGRIDClient(url string) *GRIDClient {
return &GRIDClient{
baseUrl: url,
}
}
type rndResult struct {
Rnd string
}
func (c *GRIDClient) GetRND(ctx context.Context) ([32]byte, error) {
var url = c.baseUrl + "/rnd"
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return [32]byte{}, err
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return [32]byte{}, err
}
if res.StatusCode != http.StatusOK {
return [32]byte{}, xerrors.Errorf("Failed to get rnd, status [%d]", res.StatusCode)
}
body, err := io.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
return [32]byte{}, err
}
var rndRes rndResult
err = json.Unmarshal(body, &rndRes)
if err != nil {
return [32]byte{}, err
}
rndBytes, err := hex.DecodeString(rndRes.Rnd)
if err != nil {
return [32]byte{}, err
}
var rnd [32]byte
copy(rnd[:], rndBytes)
return rnd, nil
}
func (c *GRIDClient) SubmitProof(ctx context.Context, proof types.Proof) error {
var url = c.baseUrl + "/proof"
payload := make(map[string]interface{})
payload["address"] = proof.Address
payload["id"] = proof.ID
payload["nonce"] = proof.Nonce
b, err := json.Marshal(payload)
if err != nil {
return err
}
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(b))
if err != nil {
return err
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return xerrors.Errorf("Failed to submit proof, status [%d]", res.StatusCode)
}
return nil
}
package core
import (
"grid-prover/database"
"grid-prover/logs"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)
var (
// blockNumber = big.NewInt(0)
logger = logs.Logger("dumper")
)
type Dumper struct {
endpoint string
contractABI []abi.ABI
contractAddress []common.Address
// store MapStore
blockNumber *big.Int
eventNameMap map[common.Hash]string
indexedMap map[common.Hash]abi.Arguments
}
func NewGRIDDumper(chain string, contractAddress common.Address) (dumper *Dumper, err error) {
dumper = &Dumper{
// store: store,
eventNameMap: make(map[common.Hash]string),
indexedMap: make(map[common.Hash]abi.Arguments),
}
dumper.contractAddress = []common.Address{contractAddress}
fpContractABI, err := abi.JSON(strings.NewReader(GRIDABI))
if err != nil {
return dumper, err
}
dumper.contractABI = []abi.ABI{fpContractABI}
for _, ABI := range dumper.contractABI {
for name, event := range ABI.Events {
dumper.eventNameMap[event.ID] = name
var indexed abi.Arguments
for _, arg := range ABI.Events[name].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
dumper.indexedMap[event.ID] = indexed
}
}
blockNumber, err := database.GetBlockNumber()
if err != nil {
blockNumber = 0
}
dumper.blockNumber = big.NewInt(blockNumber)
return dumper, nil
}
package types
import (
"encoding/binary"
"github.com/ethereum/go-ethereum/common"
)
type NodeID struct {
Address string `json:"address"`
ID int64 `json:"id"`
}
func (n *NodeID) ToBytes() []byte {
var buf = make([]byte, 8)
binary.LittleEndian.PutUint64(buf, uint64(n.ID))
return append(common.Hex2Bytes(n.Address), buf...)
}
type Proof struct {
NodeID
Nonce int64 `json:"nonce"`
}
func (p *Proof) ToBytes() []byte {
var nonceBuf = make([]byte, 8)
binary.LittleEndian.PutUint64(nonceBuf, uint64(p.Nonce))
buf := p.NodeID.ToBytes()
return append(buf, nonceBuf...)
}
type Result struct {
NodeID
Success bool
}
package validator
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"grid-prover/core/types"
"net/http"
"github.com/gin-gonic/gin"
)
func (v *GRIDValidator) LoadValidatorModule(g *gin.RouterGroup) {
g.GET("/rnd", v.GetRNDHandler)
g.GET("/withdraw/signature", v.GetWithdrawSignatureHandler)
g.POST("/proof", v.SubmitProofHandler)
fmt.Println("load light node moudle success!")
}
func (v *GRIDValidator) GetRNDHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"rnd": hex.EncodeToString(RND[:]),
})
}
// func GetSettingInfo(c *gin.Context) {
// }
func (v *GRIDValidator) SubmitProofHandler(c *gin.Context) {
var proof types.Proof
err := c.BindJSON(&proof)
if err != nil {
logger.Error(err)
c.AbortWithStatusJSON(500, err.Error())
return
}
if !v.IsProveTime() {
logger.Error("Failure to submit proof within the proof time")
c.AbortWithStatusJSON(400, "Failure to submit proof within the proof time")
return
}
hash := sha256.New()
hash.Write(RND[:])
hash.Write(proof.ToBytes())
result := hash.Sum(nil)
diffcult, err := getDiffcultByProviderId(proof.NodeID)
if err != nil {
logger.Error(err)
c.AbortWithStatusJSON(500, err.Error())
return
}
if !checkPOWResult(result, diffcult) {
logger.Error("Verify Proof Failed:", hex.EncodeToString(result))
c.AbortWithStatusJSON(400, "Verify Proof Failed")
return
}
resultChan <- types.Result{
NodeID: proof.NodeID,
Success: true,
}
c.JSON(http.StatusOK, "Verify Proof Success")
}
func (v *GRIDValidator) GetProfitInfo(c *gin.Context) {
}
func (v *GRIDValidator) GetWithdrawSignatureHandler(c *gin.Context) {
address := c.Query("address")
amount := c.Query("amount")
if len(address) == 0 || len(amount) == 0 {
logger.Error("field address or amount is not set")
c.AbortWithStatusJSON(400, "field address or amount is not set")
return
}
}
func getDiffcultByProviderId(nodeID types.NodeID) (int, error) {
return 8, nil
}
func checkPOWResult(hash []byte, diffcult int) bool {
if diffcult >= 256 {
return false
}
n := diffcult / 8
var remain byte = 0xff ^ (0xff >> (diffcult % 8))
for i := 0; i < n; i++ {
if hash[i] != 0 {
return false
}
}
if hash[n]&remain != 0 {
return false
}
return true
}
package validator
import (
"context"
"crypto/ecdsa"
"grid-prover/database"
"grid-prover/logs"
"math/rand"
"time"
"grid-prover/core/types"
)
var logger = logs.Logger("grid validator")
// var proofChan = make(chan Proof, 100)
var resultChan = make(chan types.Result, 100)
var RND [32]byte
type GRIDValidator struct {
last int64
prepareInterval time.Duration
proveInterval time.Duration
waitInterval time.Duration
sk *ecdsa.PrivateKey
done chan struct{}
doned bool
}
func NewGRIDValidator(chain string, sk *ecdsa.PrivateKey) (*GRIDValidator, error) {
// get time information from contract
prepareInterval := 10 * time.Second
proveInterval := 10 * time.Second
waitInterval := 2*time.Minute - prepareInterval - proveInterval
return &GRIDValidator{
last: 0,
prepareInterval: prepareInterval,
proveInterval: proveInterval,
waitInterval: waitInterval,
sk: sk,
done: make(chan struct{}),
doned: false,
}, nil
}
func (v *GRIDValidator) Start(ctx context.Context) {
for {
// 等待下一个prepare时期
wait, nextTime := v.CalculateWatingToPrepare()
select {
case <-ctx.Done():
v.doned = true
return
case <-v.done:
v.doned = true
return
case <-time.After(wait):
}
err := v.GenerateRND(ctx)
if err != nil {
logger.Error(err.Error())
continue
}
// 等待下一个prove时期
wait, _ = v.CalculateWatingToProve()
select {
case <-ctx.Done():
return
case <-v.done:
v.doned = true
return
case <-time.After(wait):
}
resultMap, err := v.GetChallengeNode(ctx)
if err != nil {
logger.Error(err.Error())
continue
}
res, err := v.HandleResult(ctx, resultMap)
if err != nil {
logger.Error(err.Error())
continue
}
logger.Info("Start update profits")
err = v.AddPenalty(ctx, res)
if err != nil {
logger.Error(err.Error())
continue
}
v.last = nextTime
}
}
func (v *GRIDValidator) Stop() {
close(v.done)
for !v.doned {
time.Sleep(200 * time.Millisecond)
}
}
func (v *GRIDValidator) IsProveTime() bool {
challengeCycleSeconds := int64((v.prepareInterval + v.proveInterval + v.waitInterval).Seconds())
now := time.Now().Unix()
duration := now - v.last
over := duration % challengeCycleSeconds
if over >= int64(v.prepareInterval.Seconds()) && over <= int64((v.prepareInterval+v.proveInterval).Seconds()) {
return true
}
return false
}
func (v *GRIDValidator) CalculateWatingToPrepare() (time.Duration, int64) {
challengeCycleSeconds := int64((v.prepareInterval + v.proveInterval + v.waitInterval).Seconds())
now := time.Now().Unix()
duration := now - v.last
over := duration % challengeCycleSeconds
var waitingSeconds int64 = 0
if over >= int64(v.prepareInterval.Seconds()) {
waitingSeconds = challengeCycleSeconds - over
}
v.last = now - over
next := v.last + challengeCycleSeconds
return time.Duration(waitingSeconds) * time.Second, next
}
func (v *GRIDValidator) CalculateWatingToProve() (time.Duration, int64) {
challengeCycleSeconds := int64((v.prepareInterval + v.proveInterval + v.waitInterval).Seconds())
now := time.Now().Unix()
duration := now - v.last
over := duration % challengeCycleSeconds
var waitingSeconds int64 = 0
if over < int64(v.prepareInterval.Seconds()) {
waitingSeconds = int64(v.prepareInterval.Seconds()) - over
v.last = now - over
} else if over > int64((v.prepareInterval + v.proveInterval).Seconds()) {
waitingSeconds = challengeCycleSeconds + int64(v.prepareInterval.Seconds()) - over
v.last = now - over + challengeCycleSeconds
}
next := v.last + challengeCycleSeconds
return time.Duration(waitingSeconds) * time.Second, next
}
func (v *GRIDValidator) GenerateRND(ctx context.Context) error {
// TODO: call the contract
for index := range RND {
RND[index] = byte(rand.Int())
}
return nil
}
func (v *GRIDValidator) GetChallengeNode(ctx context.Context) (map[types.NodeID]bool, error) {
orders, err := database.ListAllActivedOrder()
if err != nil {
return nil, err
}
var resultMap = make(map[types.NodeID]bool)
for _, order := range orders {
resultMap[types.NodeID{
Address: order.Address,
ID: order.Id,
}] = false
}
return resultMap, nil
}
func (v *GRIDValidator) HandleResult(ctx context.Context, resultMap map[types.NodeID]bool) (map[types.NodeID]bool, error) {
var channel = make(chan struct{})
logger.Info("start handle result")
go func() {
select {
case <-ctx.Done():
channel <- struct{}{}
return
case <-v.done:
channel <- struct{}{}
return
case <-time.After(v.proveInterval):
channel <- struct{}{}
return
}
}()
for {
select {
case <-channel:
logger.Info("end handle result")
return resultMap, nil
case result := <-resultChan:
resultMap[result.NodeID] = true
}
}
// return resultMap, nil
}
func (v *GRIDValidator) AddPenalty(ctx context.Context, res map[types.NodeID]bool) error {
for nodeID, result := range res {
profitInfo, err := database.GetProfitByAddress(nodeID.Address)
if err != nil {
return err
}
reward := profitInfo.Profit * (v.last - profitInfo.LastTime.Unix()) / (profitInfo.EndTime.Unix() - profitInfo.LastTime.Unix())
remain := profitInfo.Profit - reward
var penalty int64 = 0
if !result {
penalty = remain / 100
}
profitInfo.LastTime = time.Unix(v.last, 0)
profitInfo.Balance += reward
profitInfo.Profit = remain - penalty
profitInfo.Penalty += penalty
logger.Infof("Balance: %d, Profit: %d, penalty: %d", profitInfo.Balance, profitInfo.Profit, profitInfo.Penalty)
err = profitInfo.UpdateProfit()
if err != nil {
return err
}
}
return nil
}
package database
import (
// "database/sql"
"grid-prover/logs"
"os"
"path/filepath"
"time"
// "gorm.io/driver/mysql"
// _ "github.com/go-sql-driver/mysql"
"github.com/mitchellh/go-homedir"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var GlobalDataBase *gorm.DB
var logger = logs.Logger("database")
func InitDatabase(path string) error {
dir, err := homedir.Expand(path)
if err != nil {
return err
}
if _, err := os.Stat(dir); os.IsNotExist(err) {
err := os.MkdirAll(dir, 0666)
if err != nil {
return err
}
}
// dsn := "root@tcp(127.0.0.1:3306)/grid?charset=utf8mb4&parseTime=True&loc=Local"
// mysqlDB, err := sql.Open("mysql", dsn)
// if err != nil {
// return err
// }
db, err := gorm.Open(sqlite.Open(filepath.Join(dir, "grid.db")), &gorm.Config{})
if err != nil {
return err
}
sqlDB, err := db.DB()
if err != nil {
return err
}
// 设置连接池中空闲连接的最大数量。
sqlDB.SetMaxIdleConns(10)
// 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)
// 设置超时时间
sqlDB.SetConnMaxLifetime(time.Second * 30)
err = sqlDB.Ping()
if err != nil {
return err
}
db.AutoMigrate(&Order{}, &Profit{}, &BlockNumber{}, &Provider{}, &Node{})
GlobalDataBase = db
logger.Info("init database success")
return nil
}
func RemoveDataBase(path string) error {
dir, err := homedir.Expand(path)
if err != nil {
return err
}
databasePath := filepath.Join(dir, "grid.db")
if _, err := os.Stat(databasePath); os.IsExist(err) {
if err := os.Remove(databasePath); err != nil {
return err
}
}
return nil
}
package database
import "time"
type Order struct {
Address string
Id int64
ActivateTime time.Time `gorm:"column:activate"`
StartTime time.Time `gorm:"column:start"`
EndTime time.Time `gorm:"column:end"`
Probation int64
Duration int64
}
func InitOrder() error {
return GlobalDataBase.AutoMigrate(&Order{})
}
func (o *Order) CreateOrder() error {
o.StartTime = o.ActivateTime.Add(time.Duration(o.Probation) * time.Second)
o.EndTime = o.StartTime.Add(time.Duration(o.Duration) * time.Second)
return GlobalDataBase.Create(o).Error
}
func GetOrderByAddressAndId(address string, id int64) (Order, error) {
var order Order
err := GlobalDataBase.Model(&Order{}).Where("address = ? AND id = ?", address, id).Last(&order).Error
if err != nil {
return Order{}, err
}
return order, nil
}
func ListAllActivedOrder() ([]Order, error) {
var now = time.Now()
var orders []Order
err := GlobalDataBase.Model(&Order{}).Where("start < ? AND end > ?", now, now).Find(&orders).Error
if err != nil {
return nil, err
}
return orders, nil
}
package database
import "time"
type Profit struct {
Address string `gorm:"primarykey"` // CPU/GPU供应商ID
// ID int64
Balance int64 // 余额
Profit int64 // 分润值
Penalty int64 // 惩罚值
LastTime time.Time // 上次更新时间
EndTime time.Time // 可以取出全部分润值时间
}
func InitProfit() error {
return GlobalDataBase.AutoMigrate(&Profit{})
}
func (p *Profit) CreateProfit() error {
return GlobalDataBase.Create(p).Error
}
func (p *Profit) UpdateProfit() error {
return GlobalDataBase.Model(&Profit{}).Where("address = ?", p.Address).Save(p).Error
}
func GetProfitByAddress(address string) (Profit, error) {
var profit Profit
err := GlobalDataBase.Model(&Profit{}).Where("address = ?", address).First(&profit).Error
if err != nil {
return Profit{}, err
}
return profit, nil
}
var blockNumberKey = "block_number_key"
type BlockNumber struct {
BlockNumberKey string `gorm:"primarykey;column:key"`
BlockNumber int64
}
func SetBlockNumber(blockNumber int64) error {
var daBlockNumber = BlockNumber{
BlockNumberKey: blockNumberKey,
BlockNumber: blockNumber,
}
return GlobalDataBase.Save(&daBlockNumber).Error
}
func GetBlockNumber() (int64, error) {
var blockNumber BlockNumber
err := GlobalDataBase.Model(&BlockNumber{}).First(&blockNumber).Error
return blockNumber.BlockNumber, err
}
package database
type Provider struct {
Address string `gorm:"primarykey"`
Name string
IP string
Port string
}
type Node struct {
Address string `gorm:"primaryKey"`
Id int `gorm:"primaryKey"`
CPUPrice int64
CPUModel string
GPUPrice int64
GPUModel string
MemPrice int64
MemCapacity int64
DiskPrice int64
DiskCapacity int64
}
func InitProvider() error {
return GlobalDataBase.AutoMigrate(&Provider{})
}
func (p *Provider) CreateProvider() error {
return GlobalDataBase.Create(p).Error
}
func (p *Provider) GetProviderByAddress(address string) (Provider, error) {
var provider Provider
err := GlobalDataBase.Model(&Provider{}).Where("address = ?", address).First(&provider).Error
if err != nil {
return Provider{}, err
}
return provider, nil
}
func InitNode() error {
return GlobalDataBase.AutoMigrate(&Node{})
}
func (n *Node) CreateNode() error {
return GlobalDataBase.Create(n).Error
}
func (n *Node) GetNodeByAddressAndId(address string, id int64) (Node, error) {
var node Node
err := GlobalDataBase.Model(&Node{}).Where("address = ? AND id = ?", address, id).First(&node).Error
if err != nil {
return node, err
}
return node, nil
}
module grid-prover
go 1.22.3
require (
github.com/ethereum/go-ethereum v1.14.11
github.com/gin-gonic/gin v1.10.0
github.com/mitchellh/go-homedir v1.1.0
github.com/urfave/cli/v2 v2.25.7
go.uber.org/zap v1.27.0
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.12
)
require (
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // 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/goccy/go-json v0.10.2 // indirect
github.com/holiman/uint256 v1.3.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // 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-20201216005158-039620a65673 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
This diff is collapsed.
package logs
import (
"fmt"
"net/http"
)
type StorageError struct {
Storage string
Message string
}
func (e StorageError) Error() string {
return e.Storage + ":" + e.Message
}
type NotImplemented struct {
Message string
}
func (e NotImplemented) Error() string {
return e.Message
}
type StorageNotSupport struct{}
func (e StorageNotSupport) Error() string {
return "storage not support"
}
type AddressError struct {
Message string
}
func (e AddressError) Error() string {
return e.Message
}
type AuthenticationFailed struct {
Message string
}
func (e AuthenticationFailed) Error() string {
return e.Message
}
type EthError struct {
Message string
}
func (e EthError) Error() string {
return e.Message
}
type ContractError struct {
Message string
}
func (e ContractError) Error() string {
return e.Message
}
type ServerError struct {
Message string
}
func (e ServerError) Error() string {
return e.Message
}
type GatewayError struct {
Message string
}
func (e GatewayError) Error() string {
return e.Message
}
type ConfigError struct {
Message string
}
func (e ConfigError) Error() string {
return e.Message
}
type DataBaseError struct {
Message string
}
func (e DataBaseError) Error() string {
return e.Message
}
type DataStoreError struct {
Message string
}
func (e DataStoreError) Error() string {
return e.Message
}
type ControllerError struct {
Message string
}
func (e ControllerError) Error() string {
return e.Message
}
type NoPermission struct {
Message string
}
func (e NoPermission) Error() string {
return e.Message
}
type WalletError struct {
Message string
}
func (e WalletError) Error() string {
return e.Message
}
type APIError struct {
Code string
Description string
HTTPStatusCode int
}
type APIErrorCode int
type errorCodeMap map[APIErrorCode]APIError
const (
ErrNone APIErrorCode = iota
ErrInternal
ErrNotImplemented
ErrStorage
ErrAddress
ErrStorageNotSupport
ErrAuthenticationFailed
ErrContract
ErrEth
ErrServer
ErrGateway
ErrConfig
ErrDataBase
ErrDataStore
ErrController
ErrNoPermission
ErrWallet
)
func (e errorCodeMap) ToAPIErrWithErr(errCode APIErrorCode, err error) APIError {
apiErr, ok := e[errCode]
if !ok {
apiErr = e[ErrAddress]
}
if err != nil {
apiErr.Description = fmt.Sprintf("%s (%s)", apiErr.Description, err.Error())
}
return apiErr
}
func (e errorCodeMap) ToAPIErr(errCode APIErrorCode) APIError {
return e.ToAPIErrWithErr(errCode, nil)
}
var ErrorCodes = errorCodeMap{
ErrInternal: {
Code: "InternalError",
Description: "We encountered an internal error, please try again.",
HTTPStatusCode: http.StatusInternalServerError,
},
ErrNotImplemented: {
Code: "NotImplemented",
Description: "A header you provided implies functionality that is not implemented",
HTTPStatusCode: http.StatusNotImplemented,
},
ErrStorage: {
Code: "Storage",
Description: "Error storing file",
HTTPStatusCode: 516,
},
ErrAddress: {
Code: "Address",
Description: "Address Error",
HTTPStatusCode: 517,
},
ErrStorageNotSupport: {
Code: "Storage",
Description: "Storage Error",
HTTPStatusCode: 518,
},
ErrAuthenticationFailed: {
Code: "Authentication",
Description: "Authentication Failed",
HTTPStatusCode: 401,
},
ErrContract: {
Code: "contract",
Description: "contract Error",
HTTPStatusCode: 519,
},
ErrEth: {
Code: "Eth",
Description: "Eth Error",
HTTPStatusCode: 520,
},
ErrServer: {
Code: "ServerError",
Description: "Server Error",
HTTPStatusCode: 521,
},
ErrGateway: {
Code: "GatewayError",
Description: "Gateway Error",
HTTPStatusCode: 522,
},
ErrConfig: {
Code: "ConfigError",
Description: "Config Error",
HTTPStatusCode: 523,
},
ErrDataBase: {
Code: "DataBaseError",
Description: "DataBase Error",
HTTPStatusCode: 524,
},
ErrController: {
Code: "ControllerError",
Description: "Controller Error",
HTTPStatusCode: 525,
},
ErrNoPermission: {
Code: "Permission",
Description: "You don't have access to the resource",
HTTPStatusCode: 526,
},
ErrWallet: {
Code: "Wallet",
Description: "Wallet error",
HTTPStatusCode: 527,
},
ErrDataStore: {
Code: "datastore",
Description: "datastore error",
HTTPStatusCode: 528,
},
}
func ToAPIErrorCode(err error) APIError {
if err == nil {
return ErrorCodes.ToAPIErr(ErrNone)
}
var apiErr APIErrorCode
switch err.(type) {
case NotImplemented:
apiErr = ErrNotImplemented
case StorageError:
apiErr = ErrStorage
case AddressError:
apiErr = ErrAddress
case StorageNotSupport:
apiErr = ErrStorageNotSupport
case AuthenticationFailed:
apiErr = ErrAuthenticationFailed
case ContractError:
apiErr = ErrContract
case EthError:
apiErr = ErrEth
case ServerError:
apiErr = ErrServer
case GatewayError:
apiErr = ErrGateway
case ConfigError:
apiErr = ErrConfig
case DataBaseError:
apiErr = ErrDataBase
case ControllerError:
apiErr = ErrController
case NoPermission:
apiErr = ErrNoPermission
case WalletError:
apiErr = ErrWallet
case *DataStoreError:
apiErr = ErrDataStore
default:
apiErr = ErrInternal
}
return ErrorCodes.ToAPIErrWithErr(apiErr, err)
}
var (
ErrAlreadyExist = fmt.Errorf("already exist")
ErrNotExist = fmt.Errorf("not exist")
)
type ErrResponse struct {
Package string
Err error
}
package logs
import (
"fmt"
"os"
"sync"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
var mLogger *zap.SugaredLogger
var mLoglevel zap.AtomicLevel
var lk sync.Mutex
func Logger(name string) *zap.SugaredLogger {
lk.Lock()
defer lk.Unlock()
return mLogger.Named(name)
}
// StartLogger starts
func init() {
mLoglevel = zap.NewAtomicLevel()
outputs := []string{"stdout"}
debugWriter, _, err := zap.Open(outputs...)
if err != nil {
panic(fmt.Sprintf("unable to open logging output: %v", err))
}
lf := os.Getenv("MEFS_LOG_FILE")
if lf != "" {
debugWriter = getLogWriter(lf)
}
encoder := getEncoder()
core := zapcore.NewCore(encoder, debugWriter, mLoglevel)
// NewProduction
logger := zap.New(core, zap.AddCaller())
mLogger = logger.Sugar()
l := getLogLevel(os.Getenv("MEFS_LOG_LEVEL"))
mLoglevel.SetLevel(l)
}
func getEncoder() zapcore.Encoder {
encoderConfig := zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
NameKey: "sub",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.RFC3339TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
return zapcore.NewJSONEncoder(encoderConfig)
}
func getLogWriter(filename string) zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: filename + ".log",
MaxSize: 100, //MB
MaxBackups: 3,
MaxAge: 30, //days
Compress: false,
}
return zapcore.AddSync(lumberJackLogger)
}
func getLogLevel(level string) zapcore.Level {
l := zapcore.InfoLevel
switch level {
case "debug", "DEBUG":
l = zapcore.DebugLevel
case "info", "INFO", "": // make the zero value useful
l = zapcore.InfoLevel
case "warn", "WARN":
l = zapcore.WarnLevel
case "error", "ERROR":
l = zapcore.ErrorLevel
case "dpanic", "DPANIC":
l = zapcore.DPanicLevel
case "panic", "PANIC":
l = zapcore.PanicLevel
case "fatal", "FATAL":
l = zapcore.FatalLevel
}
return l
}
func SetLogLevel(level string) error {
l := getLogLevel(level)
lk.Lock()
defer lk.Unlock()
mLoglevel.SetLevel(l)
return nil
}
package main
import (
"fmt"
"grid-prover/cmd"
"os"
"github.com/urfave/cli/v2"
)
func main() {
local := make([]*cli.Command, 0, 1)
local = append(local, cmd.ValidatorCmd, cmd.VersionCmd)
app := cli.App{
Commands: local,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "version",
Aliases: []string{"v"},
Usage: "Show application version",
},
},
Action: func(ctx *cli.Context) error {
if ctx.Bool("version") {
fmt.Println(cmd.Version + "+" + cmd.BuildFlag)
}
return nil
},
}
app.Setup()
err := app.Run(os.Args)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err) // nolint:errcheck
os.Exit(1)
}
}
APP_NAME=meeda
LIB_NAME=libpow.so
# GIT_COMMIT=$(shell git rev-parse --short HEAD)
BUILD_TIME=$(shell TZ=Asia/Shanghai date +'%Y-%m-%d.%H:%M:%S%Z')
BUILD_FLAGS=-ldflags "-X 'github.com/memoio/meeda-node/cmd.BuildFlag=$(BUILD_TIME)'"
all: clean cuda build
clean:
rm -f ${APP_NAME} ${LIB_NAME}
cuda:
nvcc --ptxas-options=-v --compiler-options '-fPIC' -o ${LIB_NAME} --shared CudaSha256/pow.cu
build:
go build $(BUILD_FLAGS) -o ${APP_NAME}
install:
mv ${APP_NAME} /usr/local/bin
.PHONY: all clean cuda build
\ No newline at end of file
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