validator.go 3.9 KB
Newer Older
duanjinfei's avatar
duanjinfei committed
1 2 3 4 5 6 7 8 9
package validator

import (
	"context"
	"encoding/json"
	"example.com/m/conf"
	"example.com/m/db"
	"example.com/m/log"
	"example.com/m/operate"
duanjinfei's avatar
duanjinfei committed
10
	nodemanagerv1 "github.com/odysseus/odysseus-protocol/gen/proto/go/nodemanager/v1"
duanjinfei's avatar
duanjinfei committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24
	witnessV1 "github.com/odysseus/odysseus-protocol/gen/proto/go/witness/v1"
	"google.golang.org/grpc"
	"math/rand"
	"time"
)

type ProofWorker struct {
	productProofChan chan *witnessV1.Proof
	consumeProofChan chan []*witnessV1.Proof
	isCommitProof    map[string]bool
}

func NewProofWorker() *ProofWorker {
	return &ProofWorker{
25 26
		productProofChan: make(chan *witnessV1.Proof, 1000),
		consumeProofChan: make(chan []*witnessV1.Proof, 1000),
duanjinfei's avatar
duanjinfei committed
27
		isCommitProof:    make(map[string]bool, 0),
duanjinfei's avatar
duanjinfei committed
28 29 30
	}
}

duanjinfei's avatar
duanjinfei committed
31 32
func (p *ProofWorker) ProductProof(nmResultMsg *nodemanagerv1.ProofTaskResult, taskType uint64, reqHash []byte, respHash []byte, containerSign, minerSign []byte) {
	log.Info("ProductProof received workLoad:", nmResultMsg.Workload)
duanjinfei's avatar
duanjinfei committed
33
	p.productProofChan <- &witnessV1.Proof{
duanjinfei's avatar
duanjinfei committed
34 35
		Workload:           nmResultMsg.Workload,
		TaskId:             nmResultMsg.TaskId,
duanjinfei's avatar
duanjinfei committed
36 37
		ReqHash:            reqHash,
		RespHash:           respHash,
duanjinfei's avatar
duanjinfei committed
38
		ManagerSignature:   nmResultMsg.ManagerSignature,
duanjinfei's avatar
duanjinfei committed
39 40
		ContainerSignature: containerSign,
		MinerSignature:     minerSign,
duanjinfei's avatar
duanjinfei committed
41 42
		TaskType:           taskType,
		Timestamp:          nmResultMsg.Timestamp,
duanjinfei's avatar
duanjinfei committed
43 44 45 46 47 48 49 50 51 52 53 54
	}
}

func (p *ProofWorker) ProofStorage() {
	go func(productProofChan chan *witnessV1.Proof) {
		for {
			select {
			case proof := <-productProofChan:
				{
					proofByte, err := json.Marshal(proof)
					if err != nil {
						log.Error("Failed to marshal proof: ", err)
duanjinfei's avatar
duanjinfei committed
55
						continue
duanjinfei's avatar
duanjinfei committed
56 57 58 59
					}
					err = db.Put(proof.TaskId, proofByte)
					if err != nil {
						log.Error("leveldb put proof failed: ", err)
duanjinfei's avatar
duanjinfei committed
60
						continue
duanjinfei's avatar
duanjinfei committed
61 62 63 64 65 66
					}
					p.isCommitProof[proof.TaskId] = false
				}
			}
		}
	}(p.productProofChan)
duanjinfei's avatar
duanjinfei committed
67

duanjinfei's avatar
duanjinfei committed
68 69
	timer := time.NewTicker(time.Minute)
	randomMinute := getRandInt()
duanjinfei's avatar
duanjinfei committed
70
	for {
duanjinfei's avatar
duanjinfei committed
71 72
		select {
		case <-timer.C:
duanjinfei's avatar
duanjinfei committed
73 74
			nowTime := time.Now()
			min := nowTime.Minute()
duanjinfei's avatar
duanjinfei committed
75 76 77
			if min == 0 {
				randomMinute = getRandInt()
			}
duanjinfei's avatar
duanjinfei committed
78 79 80
			if nowTime.Hour() == 23 {
				randomMinute = 59
			}
duanjinfei's avatar
duanjinfei committed
81 82
			// 检查是否在指定时间范围内(40-59分钟)
			if min >= 40 && min <= 59 && min == randomMinute {
duanjinfei's avatar
duanjinfei committed
83 84 85 86 87 88
				proofs := make([]*witnessV1.Proof, 0)
				iter, err := db.NewIterator()
				if err != nil {
					log.Error("db new iterator failed: ", err)
					continue
				}
duanjinfei's avatar
duanjinfei committed
89 90 91 92
				if iter == nil {
					log.Warn("level db iterator is nil")
					continue
				}
duanjinfei's avatar
duanjinfei committed
93 94 95 96 97
				for iter.Next() {
					proof := &witnessV1.Proof{}
					err := json.Unmarshal(iter.Value(), proof)
					if err != nil {
						log.Error("Error parsing proof from database: ", err)
duanjinfei's avatar
duanjinfei committed
98
						continue
duanjinfei's avatar
duanjinfei committed
99 100 101 102 103 104 105 106 107 108 109 110
					}
					if p.isCommitProof[proof.TaskId] {
						continue
					}
					p.isCommitProof[proof.TaskId] = true
					proofs = append(proofs, proof)
					//err = db.Delete(iter.Key())
					//if err != nil {
					//	log.Error("Error deleting proof from database: ", err)
					//	return
					//}
				}
duanjinfei's avatar
duanjinfei committed
111 112
				if len(proofs) > 0 {
					p.consumeProofChan <- proofs
duanjinfei's avatar
duanjinfei committed
113
					log.Info("---------------------------Storage proof data---------------------------")
duanjinfei's avatar
duanjinfei committed
114
				}
duanjinfei's avatar
duanjinfei committed
115 116 117 118 119 120
			}
		}
	}
}

func (p *ProofWorker) CommitWitness() {
duanjinfei's avatar
duanjinfei committed
121
	validatorClient := operate.ConnValidatorGrpc(conf.GetConfig().ValidatorUrl)
duanjinfei's avatar
duanjinfei committed
122 123 124 125 126 127 128 129 130 131 132
	for {
		select {
		case proofs := <-p.consumeProofChan:
			proofsReq := &witnessV1.PushProofRequest{
				Proofs:        proofs,
				MinerAddress:  conf.GetConfig().SignPublicAddress.Hex(),
				RewardAddress: conf.GetConfig().BenefitAddress,
			}
			pushProof, err := validatorClient.PushProof(context.Background(), proofsReq, grpc.EmptyCallOption{})
			if err != nil {
				log.Error("Push proof failed :", err)
duanjinfei's avatar
duanjinfei committed
133
				continue
duanjinfei's avatar
duanjinfei committed
134 135
			}
			workload := pushProof.GetWorkload()
136
			log.Info("Commit proof time:", time.Now())
duanjinfei's avatar
duanjinfei committed
137
			log.Info("Push proof response received : %v", workload)
duanjinfei's avatar
duanjinfei committed
138
			log.Info("---------------------------Commit witness data---------------------------")
duanjinfei's avatar
duanjinfei committed
139 140 141
		}
	}
}
duanjinfei's avatar
duanjinfei committed
142 143 144 145

func getRandInt() int {
	return rand.Intn(20) + 40
}