mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-28 05:47:27 +08:00
feat: recalibrate self-test on the fly (#221)
This commit is contained in:
parent
99702af0b7
commit
72d730d23f
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
func GetMinimumVersionCutoff() time.Time {
|
||||
return time.Date(2024, time.May, 24, 4, 0, 0, 0, time.UTC)
|
||||
return time.Date(2024, time.May, 28, 3, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
func GetMinimumVersion() []byte {
|
||||
@ -27,3 +27,7 @@ func FormatVersion(version []byte) string {
|
||||
version[0], version[1], version[2],
|
||||
)
|
||||
}
|
||||
|
||||
func GetPatchNumber() byte {
|
||||
return 0x01
|
||||
}
|
||||
|
||||
@ -132,6 +132,8 @@ func (e *MasterClockConsensusEngine) handleSelfTestReport(
|
||||
e.logger.Warn(
|
||||
"received invalid proof from peer",
|
||||
zap.String("peer_id", peer.ID(peerID).String()),
|
||||
zap.Int("proof_size", len(report.Proof)),
|
||||
zap.Uint32("cores", report.Cores),
|
||||
)
|
||||
e.pubSub.SetPeerScore(peerID, -1000)
|
||||
return errors.Wrap(errors.New("invalid report"), "handle self test report")
|
||||
@ -148,6 +150,7 @@ func (e *MasterClockConsensusEngine) handleSelfTestReport(
|
||||
return nil
|
||||
}
|
||||
|
||||
info.DifficultyMetric = report.DifficultyMetric
|
||||
info.MasterHeadFrame = report.MasterHeadFrame
|
||||
|
||||
if info.Bandwidth <= 1048576 {
|
||||
@ -169,7 +172,8 @@ func (e *MasterClockConsensusEngine) handleSelfTestReport(
|
||||
timestamp := binary.BigEndian.Uint64(proof[:8])
|
||||
proof = proof[8:]
|
||||
|
||||
// Ignore outdated reports, give 3 minutes for propagation delay
|
||||
// Ignore outdated reports, give 3 minutes + proof time for propagation
|
||||
// delay
|
||||
if int64(timestamp) < (time.Now().UnixMilli() - (480 * 1000)) {
|
||||
return nil
|
||||
}
|
||||
@ -255,6 +259,7 @@ func (e *MasterClockConsensusEngine) handleSelfTestReport(
|
||||
return nil
|
||||
}
|
||||
|
||||
// This does not publish any longer, frames strictly are picked up from sync
|
||||
func (e *MasterClockConsensusEngine) publishProof(
|
||||
frame *protobufs.ClockFrame,
|
||||
) error {
|
||||
@ -265,17 +270,6 @@ func (e *MasterClockConsensusEngine) publishProof(
|
||||
|
||||
e.masterTimeReel.Insert(frame, false)
|
||||
|
||||
peers, err := e.GetMostAheadPeers()
|
||||
if err != nil || len(peers) == 0 {
|
||||
// publish if we don't see anyone (empty peer list) or if we're the most
|
||||
// ahead:
|
||||
e.report.MasterHeadFrame = frame.FrameNumber
|
||||
|
||||
if err := e.publishMessage(e.filter, e.report); err != nil {
|
||||
e.logger.Debug("error publishing message", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
e.state = consensus.EngineStateCollecting
|
||||
|
||||
return nil
|
||||
|
||||
@ -181,7 +181,8 @@ func (e *MasterClockConsensusEngine) Start() <-chan error {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if head.FrameNumber > newFrame.FrameNumber || newFrame.FrameNumber-head.FrameNumber > 128 {
|
||||
if head.FrameNumber > newFrame.FrameNumber ||
|
||||
newFrame.FrameNumber-head.FrameNumber > 128 {
|
||||
e.logger.Debug(
|
||||
"frame out of range, ignoring",
|
||||
zap.Uint64("number", newFrame.FrameNumber),
|
||||
@ -238,6 +239,8 @@ func (e *MasterClockConsensusEngine) Start() <-chan error {
|
||||
go func() {
|
||||
// Let it sit until we at least have a few more peers inbound
|
||||
time.Sleep(30 * time.Second)
|
||||
difficultyMetric := int64(100000)
|
||||
skew := (difficultyMetric * 12) / 10
|
||||
|
||||
for {
|
||||
head, err := e.masterTimeReel.Head()
|
||||
@ -246,22 +249,31 @@ func (e *MasterClockConsensusEngine) Start() <-chan error {
|
||||
}
|
||||
|
||||
e.report.MasterHeadFrame = head.FrameNumber
|
||||
e.report.DifficultyMetric = difficultyMetric
|
||||
parallelism := e.report.Cores - 1
|
||||
skew := (e.report.DifficultyMetric * 12) / 10
|
||||
|
||||
challenge := binary.BigEndian.AppendUint64(
|
||||
[]byte{},
|
||||
e.report.MasterHeadFrame,
|
||||
)
|
||||
challenge = append(challenge, e.pubSub.GetPeerID()...)
|
||||
|
||||
ts, proofs, err := e.frameProver.CalculateChallengeProof(
|
||||
challenge,
|
||||
parallelism,
|
||||
skew,
|
||||
)
|
||||
ts, proofs, nextDifficultyMetric, err :=
|
||||
e.frameProver.CalculateChallengeProof(
|
||||
challenge,
|
||||
parallelism,
|
||||
skew,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
e.logger.Info(
|
||||
"recalibrating difficulty metric",
|
||||
zap.Int64("previous_difficulty_metric", difficultyMetric),
|
||||
zap.Int64("next_difficulty_metric", nextDifficultyMetric),
|
||||
)
|
||||
difficultyMetric = nextDifficultyMetric
|
||||
skew = (nextDifficultyMetric * 12) / 10
|
||||
|
||||
proof := binary.BigEndian.AppendUint64([]byte{}, uint64(ts))
|
||||
for i := 0; i < len(proofs); i++ {
|
||||
@ -391,6 +403,10 @@ func (e *MasterClockConsensusEngine) performVerifyTest(
|
||||
)
|
||||
e.pubSub.SetPeerScore(challenge.peerID, -1000)
|
||||
} else {
|
||||
e.logger.Debug(
|
||||
"received valid proof from peer",
|
||||
zap.String("peer_id", peer.ID(challenge.peerID).String()),
|
||||
)
|
||||
info := e.peerInfoManager.GetPeerInfo(challenge.peerID)
|
||||
info.LastSeen = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ type FrameProver interface {
|
||||
challenge []byte,
|
||||
parallelism uint32,
|
||||
skew int64,
|
||||
) (int64, [][]byte, error)
|
||||
) (int64, [][]byte, int64, error)
|
||||
VerifyChallengeProof(
|
||||
challenge []byte,
|
||||
timestamp int64,
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/vdf"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/config"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/keys"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/tries"
|
||||
@ -549,7 +550,9 @@ func (w *WesolowskiFrameProver) VerifyWeakRecursiveProof(
|
||||
}
|
||||
|
||||
filter := proof[:len(frame.Filter)]
|
||||
check := binary.BigEndian.Uint64(proof[len(frame.Filter) : len(frame.Filter)+8])
|
||||
check := binary.BigEndian.Uint64(
|
||||
proof[len(frame.Filter) : len(frame.Filter)+8],
|
||||
)
|
||||
timestamp := binary.BigEndian.Uint64(
|
||||
proof[len(frame.Filter)+8 : len(frame.Filter)+16],
|
||||
)
|
||||
@ -600,26 +603,25 @@ func (w *WesolowskiFrameProver) CalculateChallengeProof(
|
||||
challenge []byte,
|
||||
parallelism uint32,
|
||||
skew int64,
|
||||
) (int64, [][]byte, error) {
|
||||
now := time.Now().UnixMilli()
|
||||
input := binary.BigEndian.AppendUint64([]byte{}, uint64(now))
|
||||
) (int64, [][]byte, int64, error) {
|
||||
now := time.Now()
|
||||
nowMs := now.UnixMilli()
|
||||
input := binary.BigEndian.AppendUint64([]byte{}, uint64(nowMs))
|
||||
input = append(input, challenge...)
|
||||
outputs := make([][]byte, parallelism)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(int(parallelism))
|
||||
|
||||
// 4.5 minutes = 270 seconds, one increment should be ten seconds
|
||||
proofDuration := 270 * 1000
|
||||
calibratedDifficulty := (int64(proofDuration) * 10000) / skew
|
||||
for i := uint32(0); i < parallelism; i++ {
|
||||
i := i
|
||||
go func() {
|
||||
instanceInput := binary.BigEndian.AppendUint32([]byte{}, i)
|
||||
instanceInput = append(instanceInput, input...)
|
||||
b := sha3.Sum256(input)
|
||||
|
||||
// 4.5 minutes = 270 seconds, one increment should be ten seconds
|
||||
proofDuration := 270 * 1000
|
||||
calibratedDifficulty := (int64(proofDuration) / skew) * 10000
|
||||
|
||||
b := sha3.Sum256(instanceInput)
|
||||
v := vdf.New(uint32(calibratedDifficulty), b)
|
||||
|
||||
v.Execute()
|
||||
@ -632,7 +634,10 @@ func (w *WesolowskiFrameProver) CalculateChallengeProof(
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return now, outputs, nil
|
||||
after := time.Since(now)
|
||||
nextSkew := (skew * after.Milliseconds()) / int64(proofDuration)
|
||||
|
||||
return nowMs, outputs, nextSkew, nil
|
||||
}
|
||||
|
||||
func (w *WesolowskiFrameProver) VerifyChallengeProof(
|
||||
@ -644,6 +649,10 @@ func (w *WesolowskiFrameProver) VerifyChallengeProof(
|
||||
input := binary.BigEndian.AppendUint64([]byte{}, uint64(timestamp))
|
||||
input = append(input, challenge...)
|
||||
|
||||
if assertedDifficulty < 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := uint32(0); i < uint32(len(proof)); i++ {
|
||||
if len(proof[i]) != 516 {
|
||||
return false
|
||||
@ -651,17 +660,28 @@ func (w *WesolowskiFrameProver) VerifyChallengeProof(
|
||||
|
||||
instanceInput := binary.BigEndian.AppendUint32([]byte{}, i)
|
||||
instanceInput = append(instanceInput, input...)
|
||||
b := sha3.Sum256(input)
|
||||
b := sha3.Sum256(instanceInput)
|
||||
|
||||
// 4.5 minutes = 270 seconds, one increment should be ten seconds
|
||||
proofDuration := 270 * 1000
|
||||
skew := (assertedDifficulty * 12) / 10
|
||||
calibratedDifficulty := (int64(proofDuration) / skew) * 10000
|
||||
calibratedDifficulty := (int64(proofDuration) * 10000) / skew
|
||||
|
||||
v := vdf.New(uint32(calibratedDifficulty), b)
|
||||
check := v.Verify([516]byte(proof[i]))
|
||||
if !check {
|
||||
return false
|
||||
// TODO: Remove after 2024-05-28
|
||||
if time.Now().Before(config.GetMinimumVersionCutoff()) {
|
||||
calibratedDifficulty = (int64(proofDuration) / skew) * 10000
|
||||
|
||||
v = vdf.New(uint32(calibratedDifficulty), sha3.Sum256(input))
|
||||
check = v.Verify([516]byte(proof[i]))
|
||||
if !check {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,10 @@ func TestMasterProve(t *testing.T) {
|
||||
func TestChallengeProof(t *testing.T) {
|
||||
l, _ := zap.NewProduction()
|
||||
w := crypto.NewWesolowskiFrameProver(l)
|
||||
now, proofs, err := w.CalculateChallengeProof([]byte{0x01, 0x02, 0x03}, 3, 120000)
|
||||
now, proofs, nextSkew, err := w.CalculateChallengeProof([]byte{0x01, 0x02, 0x03}, 3, 120000)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, w.VerifyChallengeProof([]byte{0x01, 0x02, 0x03}, now, 100000, proofs))
|
||||
now, proofs, _, err = w.CalculateChallengeProof([]byte{0x01, 0x02, 0x03}, 3, nextSkew*12/10)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, w.VerifyChallengeProof([]byte{0x01, 0x02, 0x03}, now, nextSkew, proofs))
|
||||
}
|
||||
|
||||
@ -735,6 +735,11 @@ func printLogo() {
|
||||
}
|
||||
|
||||
func printVersion() {
|
||||
patch := config.GetPatchNumber()
|
||||
patchString := ""
|
||||
if patch != 0x00 {
|
||||
patchString = fmt.Sprintf("-p%d", patch)
|
||||
}
|
||||
fmt.Println(" ")
|
||||
fmt.Println(" Quilibrium Node - v" + config.GetVersionString() + " – Nebula")
|
||||
fmt.Println(" Quilibrium Node - v" + config.GetVersionString() + patchString + " – Nebula")
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user