Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions node/app/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"source.quilibrium.com/quilibrium/monorepo/node/consensus"
"source.quilibrium.com/quilibrium/monorepo/node/consensus/master"
"source.quilibrium.com/quilibrium/monorepo/node/execution"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/ceremony"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/ceremony/application"
"source.quilibrium.com/quilibrium/monorepo/node/keys"
"source.quilibrium.com/quilibrium/monorepo/node/p2p"
Expand Down Expand Up @@ -44,17 +43,14 @@ func newNode(
clockStore store.ClockStore,
keyManager keys.KeyManager,
pubSub p2p.PubSub,
ceremonyExecutionEngine *ceremony.CeremonyExecutionEngine,
// execution engines wire in here
engine consensus.ConsensusEngine,
) (*Node, error) {
if engine == nil {
return nil, errors.New("engine must not be nil")
}

execEngines := make(map[string]execution.ExecutionEngine)
if ceremonyExecutionEngine != nil {
execEngines[ceremonyExecutionEngine.GetName()] = ceremonyExecutionEngine
}

return &Node{
logger,
Expand Down
10 changes: 2 additions & 8 deletions node/app/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions node/consensus/master/broadcast_messaging.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,21 @@ func (e *MasterClockConsensusEngine) handleSelfTestReport(
return errors.Wrap(err, "handle self test report")
}

// minimum proof size is one timestamp, one vdf proof, must match one fewer
// than core count
if len(report.Proof) < 516+8 ||
((len(report.Proof)-8)/516) != int(report.Cores-1) {
return errors.Wrap(errors.New("invalid report"), "handle self test report")
}

info := e.peerInfoManager.GetPeerInfo(peerID)
if info != nil {
if (time.Now().UnixMilli() - info.LastSeen) < (270 * 1000) {
return nil
}

info.MasterHeadFrame = report.MasterHeadFrame

if info.Bandwidth <= 1048576 {
go func() {
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Minute)
Expand All @@ -141,6 +153,36 @@ func (e *MasterClockConsensusEngine) handleSelfTestReport(
}
}()
}

proof := report.Proof
timestamp := binary.BigEndian.Uint64(proof[:8])
proof = proof[8:]

// Ignore outdated reports, give 3 minutes for propagation delay
if int64(timestamp) < (time.Now().UnixMilli() - (480 * 1000)) {
return nil
}

challenge := binary.BigEndian.AppendUint64([]byte{}, report.MasterHeadFrame)
challenge = append(challenge, peerID...)

proofs := make([][]byte, (len(report.Proof)-8)/516)
for i := 0; i < len(proofs); i++ {
proofs[i] = proof[i*516 : (i+1)*516]
}
if !e.frameProver.VerifyChallengeProof(
challenge,
int64(timestamp),
report.DifficultyMetric,
proofs,
) {
return errors.Wrap(
errors.New("invalid report"),
"handle self test report",
)
}

info.LastSeen = time.Now().UnixMilli()
return nil
}

Expand Down Expand Up @@ -202,6 +244,8 @@ func (e *MasterClockConsensusEngine) handleSelfTestReport(
}
}()

info.LastSeen = time.Now().UnixMilli()

return nil
}

Expand Down
25 changes: 24 additions & 1 deletion node/consensus/master/master_clock_consensus_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"io"
"math/big"
Expand Down Expand Up @@ -233,11 +234,32 @@ func (e *MasterClockConsensusEngine) Start() <-chan error {
}

e.report.MasterHeadFrame = head.FrameNumber
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,
)
if err != nil {
panic(err)
}

proof := binary.BigEndian.AppendUint64([]byte{}, uint64(ts))
for i := 0; i < len(proofs); i++ {
proof = append(proof, proofs[i]...)
}
e.report.Proof = proof

if err := e.publishMessage(e.filter, e.report); err != nil {
e.logger.Debug("error publishing message", zap.Error(err))
}
time.Sleep(5 * time.Minute)
}
}()

Expand Down Expand Up @@ -460,6 +482,7 @@ func (
Memory: new(big.Int).SetBytes(peerManifest.Memory).Bytes(),
Storage: new(big.Int).SetBytes(peerManifest.Storage).Bytes(),
MasterHeadFrame: peerManifest.MasterHeadFrame,
LastSeen: peerManifest.LastSeen,
}

for _, capability := range peerManifest.Capabilities {
Expand Down
11 changes: 11 additions & 0 deletions node/crypto/frame_prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,15 @@ type FrameProver interface {
proof []byte,
deepVerifier *protobufs.ClockFrame,
) bool
CalculateChallengeProof(
challenge []byte,
parallelism uint32,
skew int64,
) (int64, [][]byte, error)
VerifyChallengeProof(
challenge []byte,
timestamp int64,
assertedDifficulty int64,
proof [][]byte,
) bool
}
74 changes: 74 additions & 0 deletions node/crypto/wesolowski_frame_prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"crypto/rand"
"encoding/binary"
"math/big"
"sync"
"time"

"github.com/cloudflare/circl/sign/ed448"
"github.com/iden3/go-iden3-crypto/poseidon"
Expand Down Expand Up @@ -593,3 +595,75 @@ func (w *WesolowskiFrameProver) VerifyWeakRecursiveProof(
return false
}
}

func (w *WesolowskiFrameProver) CalculateChallengeProof(
challenge []byte,
parallelism uint32,
skew int64,
) (int64, [][]byte, error) {
now := time.Now().UnixMilli()
input := binary.BigEndian.AppendUint64([]byte{}, uint64(now))
input = append(input, challenge...)
outputs := make([][]byte, parallelism)

wg := sync.WaitGroup{}
wg.Add(int(parallelism))

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

v := vdf.New(uint32(calibratedDifficulty), b)

v.Execute()
o := v.GetOutput()

outputs[i] = make([]byte, 516)
copy(outputs[i][:], o[:])
wg.Done()
}()
}

wg.Wait()
return now, outputs, nil
}

func (w *WesolowskiFrameProver) VerifyChallengeProof(
challenge []byte,
timestamp int64,
assertedDifficulty int64,
proof [][]byte,
) bool {
input := binary.BigEndian.AppendUint64([]byte{}, uint64(timestamp))
input = append(input, challenge...)

for i := uint32(0); i < uint32(len(proof)); i++ {
if len(proof[i]) != 516 {
return false
}

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
skew := (assertedDifficulty * 12) / 10
calibratedDifficulty := (int64(proofDuration) / skew) * 10000

v := vdf.New(uint32(calibratedDifficulty), b)
check := v.Verify([516]byte(proof[i]))
if !check {
return false
}
}

return true
}
8 changes: 8 additions & 0 deletions node/crypto/wesolowski_frame_prover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ func TestMasterProve(t *testing.T) {
err = w.VerifyMasterClockFrame(next)
assert.NoError(t, err)
}

func TestChallengeProof(t *testing.T) {
l, _ := zap.NewProduction()
w := crypto.NewWesolowskiFrameProver(l)
now, proofs, 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))
}
1 change: 1 addition & 0 deletions node/p2p/peer_info_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type PeerManifest struct {
Capabilities []Capability
MasterHeadFrame uint64
Bandwidth uint64
LastSeen int64
}

type InMemoryPeerInfoManager struct {
Expand Down
Loading