diff --git a/.gitignore b/.gitignore index 5255caa..2768a9c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ ceremony-client .DS_Store *.mprof .env +.env.signers +.task +node-tmp-* diff --git a/README.md b/README.md index 83b2b15..88e24b9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Quilibrium - Dawn +# Quilibrium - Aurora Quilibrium is a decentralized alternative to platform as a service providers. This release, mirrored to GitHub, is the Dawn release, which contains the @@ -94,7 +94,7 @@ This section contains community-built clients, applications, guides, etc
< ### 1. The Q Guide - Beginners’ Guide -- A detailed beginners' guide for how to setup a Quilibrium Node (on VPS, Ubuntu 22.04) - [link](https://github.com/demipoet/demipoet.github.io)
+- A detailed beginners' guide for how to setup a Quilibrium Node, created by [@demipoet](https://www.github.com/demipoet) - [link](https://quilibrium.guide/)
## Pull Requests diff --git a/client/cmd/root.go b/client/cmd/root.go index accd8ee..bc272e4 100644 --- a/client/cmd/root.go +++ b/client/cmd/root.go @@ -25,7 +25,7 @@ func init() { rootCmd.PersistentFlags().StringVar( &configDirectory, "config", - "../node/.config/", - "config directory (default is ../node/.config/)", + ".config/", + "config directory (default is .config/)", ) } diff --git a/docker-compose.yml b/docker-compose.yml index 1d93017..10d6265 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,7 @@ services: node: image: ${QUILIBRIUM_IMAGE_NAME:-quilibrium} restart: unless-stopped + command: ["--signature-check=false"] deploy: resources: limits: diff --git a/node/app/db_console.go b/node/app/db_console.go index c82b041..f1bdbdc 100644 --- a/node/app/db_console.go +++ b/node/app/db_console.go @@ -865,26 +865,26 @@ func logoVersion(width int) string { var out string if width >= 83 { - out = " %#########\n" - out += " #############################\n" - out += " ########################################&\n" - out += " ###############################################\n" - out += " &#####################% %######################\n" - out += " ################# #################\n" - out += " ############### ###############\n" - out += " ############# ##############\n" - out += " ############# ############&\n" - out += " ############ ############\n" - out += " ########### ########## &###########\n" - out += " ########### ############## ###########\n" - out += " ########### ############## ##########&\n" - out += " ########## ############## ##########\n" - out += "%########## ########## ##########\n" - out += "########## ##########\n" - out += "########## &#########\n" - out += "########## ####### ####### ##########\n" - out += "%######### &######################### ##########\n" - out += " ########## ##############% ############## &##########\n" + out = " ..-------..\n" + out += " ..---'''' ''''---..\n" + out += " .---'' ''---.\n" + out += " .-' '-.\n" + out += " ..-' ..--'''''''''''%######################\n" + out += " .' .--'' #################\n" + out += " .'' ..-' ###############\n" + out += " ' ' ##############\n" + out += " '' .'' ############&\n" + out += " ' '' ############\n" + out += " ' ' ########## &###########\n" + out += " ' ' ############## ###########\n" + out += " ' ' ############## ##########&\n" + out += " ' ' ############## ##########\n" + out += "' ' ########## ##########\n" + out += "' ' ##########\n" + out += "' ' &#########\n" + out += "' ' ####### ####### ##########\n" + out += "' ' &######################### ##########\n" + out += " ' ' ##############% ############## &##########\n" out += " ' ' &############## ############### ##########\n" out += " ' ' ############### ##############% ###########\n" out += " ' '. ########## ############### ########\n" @@ -899,11 +899,11 @@ func logoVersion(width int) string { out += " ''---.. ...---'' ##\n" out += " ''----------''\n" out += " \n" - out += " Quilibrium Node - v" + config.GetVersionString() + " – Sunset\n" + out += " Quilibrium Node - v" + config.GetVersionString() + " – Nebula\n" out += " \n" out += " DB Console\n" } else { - out = "Quilibrium Node - v" + config.GetVersionString() + " – Sunset - DB Console\n" + out = "Quilibrium Node - v" + config.GetVersionString() + " – Nebula - DB Console\n" } return out } diff --git a/node/app/node.go b/node/app/node.go index e743181..d6e172e 100644 --- a/node/app/node.go +++ b/node/app/node.go @@ -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" @@ -44,7 +43,7 @@ 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 { @@ -52,9 +51,6 @@ func newNode( } execEngines := make(map[string]execution.ExecutionEngine) - if ceremonyExecutionEngine != nil { - execEngines[ceremonyExecutionEngine.GetName()] = ceremonyExecutionEngine - } return &Node{ logger, diff --git a/node/app/wire_gen.go b/node/app/wire_gen.go index 02e3180..232e93d 100644 --- a/node/app/wire_gen.go +++ b/node/app/wire_gen.go @@ -45,13 +45,10 @@ func NewDebugNode(configConfig *config.Config, selfTestReport *protobufs.SelfTes blossomSub := p2p.NewBlossomSub(p2PConfig, zapLogger) engineConfig := configConfig.Engine wesolowskiFrameProver := crypto.NewWesolowskiFrameProver(zapLogger) - kzgInclusionProver := crypto.NewKZGInclusionProver(zapLogger) masterTimeReel := time.NewMasterTimeReel(zapLogger, pebbleClockStore, engineConfig, wesolowskiFrameProver) inMemoryPeerInfoManager := p2p.NewInMemoryPeerInfoManager(zapLogger) - pebbleKeyStore := store.NewPebbleKeyStore(pebbleDB, zapLogger) - ceremonyExecutionEngine := ceremony.NewCeremonyExecutionEngine(zapLogger, engineConfig, fileKeyManager, blossomSub, wesolowskiFrameProver, kzgInclusionProver, pebbleClockStore, masterTimeReel, inMemoryPeerInfoManager, pebbleKeyStore) masterClockConsensusEngine := master.NewMasterClockConsensusEngine(engineConfig, zapLogger, pebbleClockStore, fileKeyManager, blossomSub, wesolowskiFrameProver, masterTimeReel, inMemoryPeerInfoManager, selfTestReport) - node, err := newNode(zapLogger, pebbleClockStore, fileKeyManager, blossomSub, ceremonyExecutionEngine, masterClockConsensusEngine) + node, err := newNode(zapLogger, pebbleClockStore, fileKeyManager, blossomSub, masterClockConsensusEngine) if err != nil { return nil, err } @@ -69,13 +66,10 @@ func NewNode(configConfig *config.Config, selfTestReport *protobufs.SelfTestRepo blossomSub := p2p.NewBlossomSub(p2PConfig, zapLogger) engineConfig := configConfig.Engine wesolowskiFrameProver := crypto.NewWesolowskiFrameProver(zapLogger) - kzgInclusionProver := crypto.NewKZGInclusionProver(zapLogger) masterTimeReel := time.NewMasterTimeReel(zapLogger, pebbleClockStore, engineConfig, wesolowskiFrameProver) inMemoryPeerInfoManager := p2p.NewInMemoryPeerInfoManager(zapLogger) - pebbleKeyStore := store.NewPebbleKeyStore(pebbleDB, zapLogger) - ceremonyExecutionEngine := ceremony.NewCeremonyExecutionEngine(zapLogger, engineConfig, fileKeyManager, blossomSub, wesolowskiFrameProver, kzgInclusionProver, pebbleClockStore, masterTimeReel, inMemoryPeerInfoManager, pebbleKeyStore) masterClockConsensusEngine := master.NewMasterClockConsensusEngine(engineConfig, zapLogger, pebbleClockStore, fileKeyManager, blossomSub, wesolowskiFrameProver, masterTimeReel, inMemoryPeerInfoManager, selfTestReport) - node, err := newNode(zapLogger, pebbleClockStore, fileKeyManager, blossomSub, ceremonyExecutionEngine, masterClockConsensusEngine) + node, err := newNode(zapLogger, pebbleClockStore, fileKeyManager, blossomSub, masterClockConsensusEngine) if err != nil { return nil, err } diff --git a/node/config/config.go b/node/config/config.go index 749401f..414693e 100644 --- a/node/config/config.go +++ b/node/config/config.go @@ -54,16 +54,14 @@ var BootstrapPeers = []string{ "/dns/quidditch.quilibrium.com/udp/8336/quic/p2p/QmbZEGuinaCndj4XLb6fteZmjmP3C1Tsgijmc5BGuUk8Ma", "/dns/quagmire.quilibrium.com/udp/8336/quic/p2p/QmaQ9KAaKtqXhYSQ5ARQNnn8B8474cWGvvD6PgJ4gAtMrx", "/ip4/204.186.74.46/udp/8316/quic/p2p/QmeqBjm3iX7sdTieyto1gys5ruQrQNPKfaTGcVQQWJPYDV", - "/ip4/185.209.178.115/udp/8336/quic/p2p/Qmekz5obb9qCRP5CrZ4D8Tmabbr5mJf6mgBJHTaitrx7Fx", - "/ip4/186.233.187.185/udp/8336/quic/p2p/QmR7jT9NKL3yZ1iRjLxPJjAVNbk38HAfDtAKF5SCZmHdpK", - "/ip4/149.86.224.152/udp/8336/quic/p2p/QmaVaJ93mKaaqDnsYbHGEUBzEtbWhb3s4DAutt6JeJC5Wz", + "/ip4/103.219.170.9/udp/8336/quic/p2p/QmfEdMfmdhNoYuGVhhw5LBApHHG1rbVAHXwGWpW8s9bXeg", + "/ip4/185.143.102.84/udp/8336/quic/p2p/Qmce68gLLq9eMdwCcmd1ptfoC2nVoe861LF1cjdVHC2DwK", "/ip4/65.109.17.13/udp/8336/quic/p2p/Qmc35n99eojSvW3PkbfBczJoSX92WmnnKh3Fg114ok3oo4", "/ip4/65.108.194.84/udp/8336/quic/p2p/QmP8C7g9ZRiWzhqN2AgFu5onS6HwHzR6Vv1TCHxAhnCSnq", "/dns/quil.dfcnodes.eu/udp/8336/quic/p2p/QmQaFmbYVrKSwoen5UQdaqyDq4QhXfSSLDVnYpYD4SF9tX", "/ip4/87.98.167.207/udp/8336/quic/p2p/QmafiAXLu1JWktyfzDtD67i78GRBYCfQ4doTfq7pp7wfQ1", "/ip4/216.244.76.122/udp/8336/quic/p2p/QmUSbMytVBUYiiGE266aZHrHrP17vLx5UJFd7o74HkDoaV", "/ip4/216.244.79.194/udp/8336/quic/p2p/QmQn3bWk5aqaNSv9dwPjBg4qdeGBGNEB72tvuhgEc64Ki5", - "/ip4/5.199.168.233/udp/8336/quic/p2p/QmeV1f11qjPTPaPspkJfdUb7p8kJ3fgsCqqozBtaW4nGFh", // purged peers (keep your node online to return to this list) // "/ip4/204.186.74.47/udp/8317/quic/p2p/Qmd233pLUDvcDW3ama27usfbG1HxKNh1V9dmWVW1SXp1pd", // "/ip4/186.233.184.181/udp/8336/quic/p2p/QmW6QDvKuYqJYYMP5tMZSp12X3nexywK28tZNgqtqNpEDL", @@ -117,6 +115,7 @@ func LoadConfig(configPath string, proverKey string) (*Config, error) { ListenMultiaddr: "/ip4/0.0.0.0/udp/8336/quic", BootstrapPeers: BootstrapPeers, PeerPrivKey: "", + Network: 0, }, Engine: &EngineConfig{ ProvingKeyId: "default-proving-key", diff --git a/node/config/p2p.go b/node/config/p2p.go index 41e7d86..2493c58 100644 --- a/node/config/p2p.go +++ b/node/config/p2p.go @@ -37,4 +37,5 @@ type P2PConfig struct { PeerPrivKey string `yaml:"peerPrivKey"` TraceLogFile string `yaml:"traceLogFile"` MinPeers int `yaml:"minPeers"` + Network uint8 `yaml:"network"` } diff --git a/node/config/version.go b/node/config/version.go index 874a5e8..c5b5200 100644 --- a/node/config/version.go +++ b/node/config/version.go @@ -6,15 +6,15 @@ import ( ) func GetMinimumVersionCutoff() time.Time { - return time.Date(2024, time.April, 4, 6, 20, 0, 0, time.UTC) + return time.Date(2024, time.May, 24, 4, 0, 0, 0, time.UTC) } func GetMinimumVersion() []byte { - return []byte{0x01, 0x04, 0x10} + return []byte{0x01, 0x04, 0x12} } func GetVersion() []byte { - return []byte{0x01, 0x04, 0x11} + return []byte{0x01, 0x04, 0x12} } func GetVersionString() string { diff --git a/node/consensus/master/broadcast_messaging.go b/node/consensus/master/broadcast_messaging.go index ea5c998..b0339ee 100644 --- a/node/consensus/master/broadcast_messaging.go +++ b/node/consensus/master/broadcast_messaging.go @@ -8,6 +8,7 @@ import ( "time" "github.com/iden3/go-iden3-crypto/poseidon" + "github.com/libp2p/go-libp2p/core/peer" "github.com/mr-tron/base58" "github.com/pkg/errors" "go.uber.org/zap" @@ -124,9 +125,31 @@ 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) { + e.logger.Warn( + "received invalid proof from peer", + zap.String("peer_id", peer.ID(peerID).String()), + ) + e.pubSub.SetPeerScore(peerID, -1000) + return errors.Wrap(errors.New("invalid report"), "handle self test report") + } + + e.logger.Debug( + "received proof from peer", + zap.String("peer_id", peer.ID(peerID).String()), + ) + 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) @@ -141,6 +164,42 @@ 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, + ) { + e.logger.Warn( + "received invalid proof from peer", + zap.String("peer_id", peer.ID(peerID).String()), + ) + e.pubSub.SetPeerScore(peerID, -1000) + + return errors.Wrap( + errors.New("invalid report"), + "handle self test report", + ) + } + + info.LastSeen = time.Now().UnixMilli() return nil } diff --git a/node/consensus/master/consensus_frames.go b/node/consensus/master/consensus_frames.go index c0d127d..4243b37 100644 --- a/node/consensus/master/consensus_frames.go +++ b/node/consensus/master/consensus_frames.go @@ -80,7 +80,7 @@ func (e *MasterClockConsensusEngine) collect( for i := 0; i < len(peers); i++ { peer := peers[i] - e.logger.Debug("setting syncing target", zap.Binary("peer_id", peer)) + e.logger.Info("setting syncing target", zap.Binary("peer_id", peer)) cc, err := e.pubSub.GetDirectChannel(peer, "validation") if err != nil { diff --git a/node/consensus/master/master_clock_consensus_engine.go b/node/consensus/master/master_clock_consensus_engine.go index d8c6ae8..b82f4bb 100644 --- a/node/consensus/master/master_clock_consensus_engine.go +++ b/node/consensus/master/master_clock_consensus_engine.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/rand" + "encoding/binary" "encoding/hex" "io" "math/big" @@ -226,18 +227,42 @@ func (e *MasterClockConsensusEngine) Start() <-chan error { time.Sleep(30 * time.Second) for { - e.logger.Info("broadcasting self-test info") head, err := e.masterTimeReel.Head() if err != nil { panic(err) } 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 + e.logger.Info( + "broadcasting self-test info", + zap.Uint64("current_frame", e.report.MasterHeadFrame), + ) if err := e.publishMessage(e.filter, e.report); err != nil { e.logger.Debug("error publishing message", zap.Error(err)) } - time.Sleep(5 * time.Minute) } }() @@ -460,6 +485,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 { @@ -563,6 +589,7 @@ func (e *MasterClockConsensusEngine) addPeerManifestReport( Storage: report.Storage, Capabilities: []p2p.Capability{}, MasterHeadFrame: report.MasterHeadFrame, + LastSeen: time.Now().UnixMilli(), } for _, capability := range manifest.Capabilities { diff --git a/node/crypto/frame_prover.go b/node/crypto/frame_prover.go index ea57e95..71a2e07 100644 --- a/node/crypto/frame_prover.go +++ b/node/crypto/frame_prover.go @@ -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 } diff --git a/node/ceremony.json b/node/crypto/kzg/ceremony.json similarity index 100% rename from node/ceremony.json rename to node/crypto/kzg/ceremony.json diff --git a/node/crypto/kzg/kzg.go b/node/crypto/kzg/kzg.go index 9da890a..5a3c0b2 100644 --- a/node/crypto/kzg/kzg.go +++ b/node/crypto/kzg/kzg.go @@ -1,6 +1,7 @@ package kzg import ( + _ "embed" "encoding/binary" "encoding/hex" "encoding/json" @@ -292,13 +293,11 @@ func TestInit(file string) { } } +//go:embed ceremony.json +var csBytes []byte + func Init() { // start with phase 1 ceremony: - csBytes, err := os.ReadFile("./ceremony.json") - if err != nil { - panic(err) - } - bls48581.Init() cs := &CeremonyState{} diff --git a/node/crypto/kzg/kzg_test.go b/node/crypto/kzg/kzg_test.go index 12eefc2..946e6db 100644 --- a/node/crypto/kzg/kzg_test.go +++ b/node/crypto/kzg/kzg_test.go @@ -17,7 +17,7 @@ import ( ) func TestMain(m *testing.M) { - csBytes, err := os.ReadFile("../../ceremony.json") + csBytes, err := os.ReadFile("./ceremony.json") if err != nil { panic(err) } diff --git a/node/crypto/kzg_inclusion_prover_test.go b/node/crypto/kzg_inclusion_prover_test.go index c869173..2fe608b 100644 --- a/node/crypto/kzg_inclusion_prover_test.go +++ b/node/crypto/kzg_inclusion_prover_test.go @@ -15,7 +15,7 @@ import ( ) func TestKZGVerifyFrame(t *testing.T) { - kzg.TestInit("../ceremony.json") + kzg.TestInit("./kzg/ceremony.json") data := make([]byte, 1024) rand.Read(data) diff --git a/node/crypto/wesolowski_frame_prover.go b/node/crypto/wesolowski_frame_prover.go index 868471c..6b04325 100644 --- a/node/crypto/wesolowski_frame_prover.go +++ b/node/crypto/wesolowski_frame_prover.go @@ -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" @@ -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 +} diff --git a/node/crypto/wesolowski_frame_prover_test.go b/node/crypto/wesolowski_frame_prover_test.go index 8d35e68..78064cb 100644 --- a/node/crypto/wesolowski_frame_prover_test.go +++ b/node/crypto/wesolowski_frame_prover_test.go @@ -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)) +} diff --git a/node/execution/intrinsics/ceremony/ceremony_execution_engine.go b/node/execution/intrinsics/ceremony/ceremony_execution_engine.go index 33fcb60..9ff71c1 100644 --- a/node/execution/intrinsics/ceremony/ceremony_execution_engine.go +++ b/node/execution/intrinsics/ceremony/ceremony_execution_engine.go @@ -4,12 +4,12 @@ import ( "bytes" "crypto" "crypto/rand" + _ "embed" "encoding/base64" "encoding/binary" "encoding/hex" "encoding/json" "fmt" - "os" "strings" "sync" @@ -206,6 +206,11 @@ func ( } } +// 2024-01-03: 1.2.0 +// +//go:embed retroactive_peers.json +var retroactivePeersJsonBinary []byte + // Creates a genesis state for the intrinsic func CreateGenesisState( logger *zap.Logger, @@ -324,12 +329,6 @@ func CreateGenesisState( rewardTrie.Add(addrBytes, 0, 50) } - // 2024-01-03: 1.2.0 - d, err := os.ReadFile("./retroactive_peers.json") - if err != nil { - panic(err) - } - type peerData struct { PeerId string `json:"peer_id"` TokenBalance uint64 `json:"token_balance"` @@ -339,7 +338,7 @@ func CreateGenesisState( } retroEntries := &rewards{} - err = json.Unmarshal(d, retroEntries) + err = json.Unmarshal(retroactivePeersJsonBinary, retroEntries) if err != nil { panic(err) } diff --git a/node/retroactive_peers.json b/node/execution/intrinsics/ceremony/retroactive_peers.json similarity index 100% rename from node/retroactive_peers.json rename to node/execution/intrinsics/ceremony/retroactive_peers.json diff --git a/node/main.go b/node/main.go index 4f90cf1..3d4362e 100644 --- a/node/main.go +++ b/node/main.go @@ -3,6 +3,7 @@ package main import ( + "bytes" "crypto/rand" "encoding/binary" "encoding/hex" @@ -16,10 +17,12 @@ import ( "runtime" "runtime/pprof" "strconv" + "strings" "syscall" "time" "go.uber.org/zap" + "golang.org/x/crypto/sha3" "google.golang.org/protobuf/proto" "source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/ceremony/application" "source.quilibrium.com/quilibrium/monorepo/node/p2p" @@ -27,6 +30,7 @@ import ( "source.quilibrium.com/quilibrium/monorepo/node/store" "source.quilibrium.com/quilibrium/monorepo/node/utils" + "github.com/cloudflare/circl/sign/ed448" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/peer" "github.com/pbnjay/memory" @@ -89,11 +93,109 @@ var ( false, "sets a node to run strictly as a dht bootstrap peer (not full node)", ) + network = flag.Uint( + "network", + 0, + "sets the active network for the node (mainnet = 0, primary testnet = 1)", + ) + signatureCheck = flag.Bool( + "signature-check", + true, + "enables or disables signature validation (default true)", + ) ) +var signatories = []string{ + "b1214da7f355f5a9edb7bcc23d403bdf789f070cca10db2b4cadc22f2d837afb650944853e35d5f42ef3c4105b802b144b4077d5d3253e4100", + "de4cfe7083104bfe32f0d4082fa0200464d8b10804a811653eedda376efcad64dd222f0f0ceb0b8ae58abe830d7a7e3f3b2d79d691318daa00", + "540237a35e124882d6b64e7bb5718273fa338e553f772b77fe90570e45303762b34131bdcb6c0b9f2cf9e393d9c7e0f546eeab0bcbbd881680", + "fbe4166e37f93f90d2ebf06305315ae11b37e501d09596f8bde11ba9d343034fbca80f252205aa2f582a512a72ad293df371baa582da072900", + "4160572e493e1bf15c44e055b11bf75230c76c7d2c67b48066770ab03dfd5ed34c97b9a431ec18578c83a0df9250b8362c38068650e8b01400", + "45170b626884b85d61ae109f2aa9b0e1ecc18b181508431ea6308f3869f2adae49da9799a0a594eaa4ef3ad492518fb1729decd44169d40d00", + "92cd8ee5362f3ae274a75ab9471024dbc144bff441ed8af7d19750ac512ff51e40e7f7b01e4f96b6345dd58878565948c3eb52c53f250b5080", + "001a4cbfce5d9aeb7e20665b0d236721b228a32f0baee62ffa77f45b82ecaf577e8a38b7ef91fcf7d2d2d2b504f085461398d30b24abb1d700", + "65b835071731c6e785bb2d107c7d85d8a537d79c435c3f42bb2f87027f93f858d7b37c598cef267a5db46e345f7a6f81969b465686657d1e00", + "4507626f7164e7d8c304c07ff8d2e23c113fe108b221d2e60672f4d07750345815e2b4b3cc3df4d3466bf2f669c35c3172e06511270612ab00", + "4fb2537345e46be3d5f96340c1441007501702dd5bfaf6dbf6943bbefceca8fb2b94ec0a8a1a2f49850fbe1d10244889a4f40abfa9e0c9e000", + "57be2861faf0fffcbfd122c85c77010dce8f213030905781b85b6f345d912c7b5ace17797d9810899dfb8d13e7c8369595740725ab3dd5bd00", + "61628beef8f6964466fd078d6a2b90a397ab0777a14b9728227fd19f36752f9451b1a8d780740a0b9a8ce3df5f89ca7b9ff17de9274a270980", + "5547afc71b02821e2f5bfdd30fbe1374c3853898deff20a1b5cc729b8e81670fbbb9d1e917f85d153ea4b26bbf6f9c546dc1b64b9916608d80", + "81d63a45f068629f568de812f18be5807bfe828a830097f09cf02330d6acd35e3607401df3fda08b03b68ea6e68afd506b23506b11e87a0f80", + "6e2872f73c4868c4286bef7bfe2f5479a41c42f4e07505efa4883c7950c740252e0eea78eef10c584b19b1dcda01f7767d3135d07c33244100", + "a114b061f8d35e3f3497c8c43d83ba6b4af67aa7b39b743b1b0a35f2d66110b5051dd3d86f69b57122a35b64e624b8180bee63b6152fce4280", +} + func main() { flag.Parse() + if *signatureCheck { + if runtime.GOOS == "windows" { + fmt.Println("Signature check not available for windows yet, skipping...") + } else { + ex, err := os.Executable() + if err != nil { + panic(err) + } + + b, err := os.ReadFile(ex) + if err != nil { + fmt.Println( + "Error encountered during signature check – are you running this " + + "from source? (use --signature-check=false)", + ) + panic(err) + } + + checksum := sha3.Sum256(b) + digest, err := os.ReadFile(ex + ".dgst") + if err != nil { + fmt.Println("Digest file not found") + os.Exit(1) + } + + parts := strings.Split(string(digest), " ") + if len(parts) != 2 { + fmt.Println("Invalid digest file format") + os.Exit(1) + } + + digestBytes, err := hex.DecodeString(parts[1][:64]) + if err != nil { + fmt.Println("Invalid digest file format") + os.Exit(1) + } + + if !bytes.Equal(checksum[:], digestBytes) { + fmt.Println("Invalid digest for node") + os.Exit(1) + } + + count := 0 + + for i := 1; i <= len(signatories); i++ { + signatureFile := fmt.Sprintf(ex+".dgst.sig.%d", i) + sig, err := os.ReadFile(signatureFile) + if err != nil { + continue + } + + pubkey, _ := hex.DecodeString(signatories[i-1]) + if !ed448.Verify(pubkey, digest, sig, "") { + fmt.Printf("Failed signature check for signatory #%d\n", i) + os.Exit(1) + } + count++ + } + + if count < len(signatories)/2 { + fmt.Printf("Quorum on signatures not met") + os.Exit(1) + } + + fmt.Printf("Signature check passed") + } + } + if *memprofile != "" { go func() { for { @@ -173,6 +275,26 @@ func main() { panic(err) } + if *network != 0 { + if nodeConfig.P2P.BootstrapPeers[0] == config.BootstrapPeers[0] { + fmt.Println( + "Node has specified to run outside of mainnet but is still " + + "using default bootstrap list. This will fail. Exiting.", + ) + os.Exit(1) + } + + nodeConfig.Engine.GenesisSeed = fmt.Sprintf( + "%02x%s", + byte(*network), + nodeConfig.Engine.GenesisSeed, + ) + nodeConfig.P2P.Network = uint8(*network) + fmt.Println( + "Node is operating outside of mainnet – be sure you intended to do this.", + ) + } + clearIfTestData(*configDirectory, nodeConfig) if *dbConsole { @@ -185,13 +307,6 @@ func main() { return } - if !*dhtOnly { - fmt.Println("Loading ceremony state and starting node...") - kzg.Init() - } - - report := RunSelfTestIfNeeded(*configDirectory, nodeConfig) - if *dhtOnly { dht, err := app.NewDHTNode(nodeConfig) if err != nil { @@ -207,6 +322,11 @@ func main() { return } + fmt.Println("Loading ceremony state and starting node...") + kzg.Init() + + report := RunSelfTestIfNeeded(*configDirectory, nodeConfig) + var node *app.Node if *debug { node, err = app.NewDebugNode(nodeConfig, report) @@ -579,19 +699,19 @@ func printNodeInfo(cfg *config.Config) { } func printLogo() { - fmt.Println(" %#########") - fmt.Println(" #############################") - fmt.Println(" ########################################&") - fmt.Println(" ###############################################") - fmt.Println(" &#####################% %######################") - fmt.Println(" ################# #################") - fmt.Println(" ############### ###############") - fmt.Println(" ############# ##############") - fmt.Println(" ############# ############&") - fmt.Println(" ############ ############") - fmt.Println(" ########### ########## &###########") - fmt.Println(" ########### ############## ###########") - fmt.Println(" ########### ############## ##########&") + fmt.Println(" ..-------..") + fmt.Println(" ..---'''' ''''---..") + fmt.Println(" .---'' ''---.") + fmt.Println(" .-' '-.") + fmt.Println(" ..-' ..--'''''''''''%######################") + fmt.Println(" .' .--'' #################") + fmt.Println(" .'' ..-' ###############") + fmt.Println(" ' ' ##############") + fmt.Println(" '' .'' ############&") + fmt.Println(" ' '' ############") + fmt.Println(" ' ' ########## &###########") + fmt.Println(" ' ' ############## ###########") + fmt.Println(" ' ' ############## ##########&") fmt.Println(" ' ' ############## ##########") fmt.Println("' ' ########## ##########") fmt.Println("' ' ##########") @@ -616,5 +736,5 @@ func printLogo() { func printVersion() { fmt.Println(" ") - fmt.Println(" Quilibrium Node - v" + config.GetVersionString() + " – Aurora") + fmt.Println(" Quilibrium Node - v" + config.GetVersionString() + " – Nebula") } diff --git a/node/node-1.4.17-darwin-arm64.dgst b/node/node-1.4.17-darwin-arm64.dgst deleted file mode 100644 index 6ff184c..0000000 --- a/node/node-1.4.17-darwin-arm64.dgst +++ /dev/null @@ -1 +0,0 @@ -SHA3-256(node-1.4.17-darwin-arm64.bin)= c9eee4d66e1a98a9d63dbe54cbe043e1d7fc4014bcf7e78e46d56b33b4b7c9da diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.1 b/node/node-1.4.17-darwin-arm64.dgst.sig.1 deleted file mode 100644 index 6919072..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.1 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.11 b/node/node-1.4.17-darwin-arm64.dgst.sig.11 deleted file mode 100644 index e210296..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.11 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.12 b/node/node-1.4.17-darwin-arm64.dgst.sig.12 deleted file mode 100644 index d515303..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.12 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.13 b/node/node-1.4.17-darwin-arm64.dgst.sig.13 deleted file mode 100644 index a123f5b..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.13 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.14 b/node/node-1.4.17-darwin-arm64.dgst.sig.14 deleted file mode 100644 index 36efaef..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.14 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.15 b/node/node-1.4.17-darwin-arm64.dgst.sig.15 deleted file mode 100644 index 92e8a15..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.15 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.16 b/node/node-1.4.17-darwin-arm64.dgst.sig.16 deleted file mode 100644 index 8da1070..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.16 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.3 b/node/node-1.4.17-darwin-arm64.dgst.sig.3 deleted file mode 100644 index 42363ab..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.3 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.4 b/node/node-1.4.17-darwin-arm64.dgst.sig.4 deleted file mode 100644 index 6337ff1..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.4 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.6 b/node/node-1.4.17-darwin-arm64.dgst.sig.6 deleted file mode 100644 index 8789ad1..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.6 and /dev/null differ diff --git a/node/node-1.4.17-darwin-arm64.dgst.sig.8 b/node/node-1.4.17-darwin-arm64.dgst.sig.8 deleted file mode 100644 index 4cd524f..0000000 Binary files a/node/node-1.4.17-darwin-arm64.dgst.sig.8 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst b/node/node-1.4.17-linux-amd64.dgst deleted file mode 100644 index 425b932..0000000 --- a/node/node-1.4.17-linux-amd64.dgst +++ /dev/null @@ -1 +0,0 @@ -SHA3-256(node-1.4.17-linux-amd64.bin)= 06a2ab7dc4e5f2b6ea48e4f056774b5bfadbf4bb261058279ef1f4e6982e1a8f diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.1 b/node/node-1.4.17-linux-amd64.dgst.sig.1 deleted file mode 100644 index 83c4927..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.1 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.11 b/node/node-1.4.17-linux-amd64.dgst.sig.11 deleted file mode 100644 index 1d9fc8f..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.11 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.12 b/node/node-1.4.17-linux-amd64.dgst.sig.12 deleted file mode 100644 index 1c78e30..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.12 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.13 b/node/node-1.4.17-linux-amd64.dgst.sig.13 deleted file mode 100644 index 86c462f..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.13 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.14 b/node/node-1.4.17-linux-amd64.dgst.sig.14 deleted file mode 100644 index a5ad292..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.14 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.15 b/node/node-1.4.17-linux-amd64.dgst.sig.15 deleted file mode 100644 index c1131dc..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.15 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.16 b/node/node-1.4.17-linux-amd64.dgst.sig.16 deleted file mode 100644 index b1ba48a..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.16 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.3 b/node/node-1.4.17-linux-amd64.dgst.sig.3 deleted file mode 100644 index 0cd377c..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.3 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.4 b/node/node-1.4.17-linux-amd64.dgst.sig.4 deleted file mode 100644 index 36eeb73..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.4 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.6 b/node/node-1.4.17-linux-amd64.dgst.sig.6 deleted file mode 100644 index 21938e7..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.6 and /dev/null differ diff --git a/node/node-1.4.17-linux-amd64.dgst.sig.8 b/node/node-1.4.17-linux-amd64.dgst.sig.8 deleted file mode 100644 index 746a080..0000000 Binary files a/node/node-1.4.17-linux-amd64.dgst.sig.8 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst b/node/node-1.4.17-linux-arm64.dgst deleted file mode 100644 index edd4f93..0000000 --- a/node/node-1.4.17-linux-arm64.dgst +++ /dev/null @@ -1 +0,0 @@ -SHA3-256(node-1.4.17-linux-arm64.bin)= ea90251db54105278ef4085d5bd71912b8aa9dae0b79a2c0bfdfdf33180513d3 diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.1 b/node/node-1.4.17-linux-arm64.dgst.sig.1 deleted file mode 100644 index 4094546..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.1 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.11 b/node/node-1.4.17-linux-arm64.dgst.sig.11 deleted file mode 100644 index f7fe60e..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.11 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.12 b/node/node-1.4.17-linux-arm64.dgst.sig.12 deleted file mode 100644 index a054677..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.12 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.13 b/node/node-1.4.17-linux-arm64.dgst.sig.13 deleted file mode 100644 index d0ac292..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.13 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.14 b/node/node-1.4.17-linux-arm64.dgst.sig.14 deleted file mode 100644 index cc80d24..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.14 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.15 b/node/node-1.4.17-linux-arm64.dgst.sig.15 deleted file mode 100644 index a0833d1..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.15 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.16 b/node/node-1.4.17-linux-arm64.dgst.sig.16 deleted file mode 100644 index 85fb52e..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.16 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.3 b/node/node-1.4.17-linux-arm64.dgst.sig.3 deleted file mode 100644 index 11cf43a..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.3 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.4 b/node/node-1.4.17-linux-arm64.dgst.sig.4 deleted file mode 100644 index 112929f..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.4 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.6 b/node/node-1.4.17-linux-arm64.dgst.sig.6 deleted file mode 100644 index d2963fc..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.6 and /dev/null differ diff --git a/node/node-1.4.17-linux-arm64.dgst.sig.8 b/node/node-1.4.17-linux-arm64.dgst.sig.8 deleted file mode 100644 index 487654e..0000000 Binary files a/node/node-1.4.17-linux-arm64.dgst.sig.8 and /dev/null differ diff --git a/node/node-1.4.18-darwin-arm64.dgst b/node/node-1.4.18-darwin-arm64.dgst new file mode 100644 index 0000000..41b56a7 --- /dev/null +++ b/node/node-1.4.18-darwin-arm64.dgst @@ -0,0 +1 @@ +SHA3-256(node-1.4.18-darwin-arm64)= aee64d1d18c8e5567016d51460cf882005c4a873dbebcd7d608b8d3d9e74c682 diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.1 b/node/node-1.4.18-darwin-arm64.dgst.sig.1 new file mode 100644 index 0000000..e04dc24 Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.1 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.13 b/node/node-1.4.18-darwin-arm64.dgst.sig.13 new file mode 100644 index 0000000..4ae193e Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.13 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.14 b/node/node-1.4.18-darwin-arm64.dgst.sig.14 new file mode 100644 index 0000000..a575a90 Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.14 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.16 b/node/node-1.4.18-darwin-arm64.dgst.sig.16 new file mode 100644 index 0000000..a0fb9df Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.16 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.17 b/node/node-1.4.18-darwin-arm64.dgst.sig.17 new file mode 100644 index 0000000..fb6a0f3 Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.17 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.4 b/node/node-1.4.18-darwin-arm64.dgst.sig.4 new file mode 100644 index 0000000..a0e4578 Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.4 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.6 b/node/node-1.4.18-darwin-arm64.dgst.sig.6 new file mode 100644 index 0000000..05d3b24 Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.6 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.7 b/node/node-1.4.18-darwin-arm64.dgst.sig.7 new file mode 100644 index 0000000..6424f62 Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.7 differ diff --git a/node/node-1.4.18-darwin-arm64.dgst.sig.8 b/node/node-1.4.18-darwin-arm64.dgst.sig.8 new file mode 100644 index 0000000..7d6e423 Binary files /dev/null and b/node/node-1.4.18-darwin-arm64.dgst.sig.8 differ diff --git a/node/node-1.4.18-linux-amd64.dgst b/node/node-1.4.18-linux-amd64.dgst new file mode 100644 index 0000000..2e89a8e --- /dev/null +++ b/node/node-1.4.18-linux-amd64.dgst @@ -0,0 +1 @@ +SHA3-256(node-1.4.18-linux-amd64)= e24acbaab0dca79a26c1ac80561eb2dc69abf381fff73b5bb4092084143ba2c9 diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.1 b/node/node-1.4.18-linux-amd64.dgst.sig.1 new file mode 100644 index 0000000..2bfd324 Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.1 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.13 b/node/node-1.4.18-linux-amd64.dgst.sig.13 new file mode 100644 index 0000000..84f6ef2 Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.13 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.14 b/node/node-1.4.18-linux-amd64.dgst.sig.14 new file mode 100644 index 0000000..1199c5a Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.14 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.16 b/node/node-1.4.18-linux-amd64.dgst.sig.16 new file mode 100644 index 0000000..8b6e43b Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.16 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.17 b/node/node-1.4.18-linux-amd64.dgst.sig.17 new file mode 100644 index 0000000..c6f22f1 Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.17 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.4 b/node/node-1.4.18-linux-amd64.dgst.sig.4 new file mode 100644 index 0000000..607379d Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.4 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.6 b/node/node-1.4.18-linux-amd64.dgst.sig.6 new file mode 100644 index 0000000..f161967 Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.6 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.7 b/node/node-1.4.18-linux-amd64.dgst.sig.7 new file mode 100644 index 0000000..07d6302 Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.7 differ diff --git a/node/node-1.4.18-linux-amd64.dgst.sig.8 b/node/node-1.4.18-linux-amd64.dgst.sig.8 new file mode 100644 index 0000000..ea07a8d Binary files /dev/null and b/node/node-1.4.18-linux-amd64.dgst.sig.8 differ diff --git a/node/node-1.4.18-linux-arm64.dgst b/node/node-1.4.18-linux-arm64.dgst new file mode 100644 index 0000000..33f07f5 --- /dev/null +++ b/node/node-1.4.18-linux-arm64.dgst @@ -0,0 +1 @@ +SHA3-256(node-1.4.18-linux-arm64)= 888228bb59dc0b7fc103bd886906cfecdf3877dcedc138a1fd4cf694ab527409 diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.1 b/node/node-1.4.18-linux-arm64.dgst.sig.1 new file mode 100644 index 0000000..01bf4ce Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.1 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.13 b/node/node-1.4.18-linux-arm64.dgst.sig.13 new file mode 100644 index 0000000..e821217 Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.13 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.14 b/node/node-1.4.18-linux-arm64.dgst.sig.14 new file mode 100644 index 0000000..ac0054e Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.14 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.16 b/node/node-1.4.18-linux-arm64.dgst.sig.16 new file mode 100644 index 0000000..2059001 Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.16 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.17 b/node/node-1.4.18-linux-arm64.dgst.sig.17 new file mode 100644 index 0000000..7d61205 Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.17 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.4 b/node/node-1.4.18-linux-arm64.dgst.sig.4 new file mode 100644 index 0000000..be1b26d Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.4 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.6 b/node/node-1.4.18-linux-arm64.dgst.sig.6 new file mode 100644 index 0000000..c1c4b7f Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.6 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.7 b/node/node-1.4.18-linux-arm64.dgst.sig.7 new file mode 100644 index 0000000..d620c27 Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.7 differ diff --git a/node/node-1.4.18-linux-arm64.dgst.sig.8 b/node/node-1.4.18-linux-arm64.dgst.sig.8 new file mode 100644 index 0000000..a424c7c Binary files /dev/null and b/node/node-1.4.18-linux-arm64.dgst.sig.8 differ diff --git a/node/p2p/blossomsub.go b/node/p2p/blossomsub.go index dcc6ad6..f16fe9c 100644 --- a/node/p2p/blossomsub.go +++ b/node/p2p/blossomsub.go @@ -45,6 +45,7 @@ type BlossomSub struct { peerScore map[string]int64 peerScoreMx sync.Mutex isBootstrapPeer bool + network uint8 } var _ PubSub = (*BlossomSub)(nil) @@ -60,7 +61,7 @@ var BITMASK_ALL = []byte{ // While we iterate through these next phases, we're going to aggressively // enforce keeping updated. This will be achieved through announce strings // that will vary with each update -var ANNOUNCE = "quilibrium-1.4.16-sunset-noctilucent" +var ANNOUNCE_PREFIX = "quilibrium-1.4.18-nebula-" func getPeerID(p2pConfig *config.P2PConfig) peer.ID { peerPrivKey, err := hex.DecodeString(p2pConfig.PeerPrivKey) @@ -129,6 +130,7 @@ func NewBlossomSub( signKey: privKey, peerScore: make(map[string]int64), isBootstrapPeer: isBootstrapPeer, + network: p2pConfig.Network, } h, err := libp2p.New(opts...) @@ -140,7 +142,7 @@ func NewBlossomSub( kademliaDHT := initDHT(ctx, p2pConfig, logger, h, isBootstrapPeer) routingDiscovery := routing.NewRoutingDiscovery(kademliaDHT) - util.Advertise(ctx, routingDiscovery, ANNOUNCE) + util.Advertise(ctx, routingDiscovery, getNetworkNamespace(p2pConfig.Network)) discoverPeers(p2pConfig, ctx, logger, h, routingDiscovery) @@ -212,7 +214,8 @@ func NewBlossomSub( } func (b *BlossomSub) PublishToBitmask(bitmask []byte, data []byte) error { - bm, ok := b.bitmaskMap[string(bitmask)] + networkBitmask := append([]byte{b.network}, bitmask...) + bm, ok := b.bitmaskMap[string(networkBitmask)] if !ok { b.logger.Error( "error while publishing to bitmask", @@ -237,19 +240,20 @@ func (b *BlossomSub) Subscribe( raw bool, ) { eval := func(bitmask []byte) error { - _, ok := b.bitmaskMap[string(bitmask)] + networkBitmask := append([]byte{b.network}, bitmask...) + _, ok := b.bitmaskMap[string(networkBitmask)] if ok { return nil } b.logger.Info("joining broadcast") - bm, err := b.ps.Join(bitmask) + bm, err := b.ps.Join(networkBitmask) if err != nil { b.logger.Error("join failed", zap.Error(err)) return errors.Wrap(err, "subscribe") } - b.bitmaskMap[string(bitmask)] = bm + b.bitmaskMap[string(networkBitmask)] = bm b.logger.Info("subscribe to bitmask", zap.Binary("bitmask", bitmask)) sub, err := bm.Subscribe() @@ -293,7 +297,8 @@ func (b *BlossomSub) Subscribe( } func (b *BlossomSub) Unsubscribe(bitmask []byte, raw bool) { - bm, ok := b.bitmaskMap[string(bitmask)] + networkBitmask := append([]byte{b.network}, bitmask...) + bm, ok := b.bitmaskMap[string(networkBitmask)] if !ok { return } @@ -306,7 +311,8 @@ func (b *BlossomSub) GetPeerID() []byte { } func (b *BlossomSub) GetRandomPeer(bitmask []byte) ([]byte, error) { - peers := b.ps.ListPeers(bitmask) + networkBitmask := append([]byte{b.network}, bitmask...) + peers := b.ps.ListPeers(networkBitmask) if len(peers) == 0 { return nil, errors.Wrap( ErrNoPeersAvailable, @@ -351,16 +357,19 @@ func initDHT( ) defaultBootstrapPeers := append([]string{}, p2pConfig.BootstrapPeers...) - for _, peer := range config.BootstrapPeers { - found := false - for _, existing := range defaultBootstrapPeers { - if existing == peer { - found = true - break + + if p2pConfig.Network == 0 { + for _, peer := range config.BootstrapPeers { + found := false + for _, existing := range defaultBootstrapPeers { + if existing == peer { + found = true + break + } + } + if !found { + defaultBootstrapPeers = append(defaultBootstrapPeers, peer) } - } - if !found { - defaultBootstrapPeers = append(defaultBootstrapPeers, peer) } } @@ -379,7 +388,7 @@ func initDHT( if err := h.Connect(ctx, *peerinfo); err != nil { logger.Debug("error while connecting to dht peer", zap.Error(err)) } else { - logger.Info( + logger.Debug( "connected to peer", zap.String("peer_id", peerinfo.ID.String()), ) @@ -417,11 +426,11 @@ func (b *BlossomSub) GetBitmaskPeers() map[string][]string { peers := map[string][]string{} for _, k := range b.bitmaskMap { - peers[fmt.Sprintf("%+x", k.Bitmask())] = []string{} + peers[fmt.Sprintf("%+x", k.Bitmask()[1:])] = []string{} for _, p := range k.ListPeers() { - peers[fmt.Sprintf("%+x", k.Bitmask())] = append( - peers[fmt.Sprintf("%+x", k.Bitmask())], + peers[fmt.Sprintf("%+x", k.Bitmask()[1:])] = append( + peers[fmt.Sprintf("%+x", k.Bitmask()[1:])], p.String(), ) } @@ -502,6 +511,8 @@ func (b *BlossomSub) GetDirectChannel(key []byte, purpose string) ( } }() + // Open question: should we prefix this so a node can run both in mainnet and + // testnet? Feels like a bad idea and would be preferable to discourage. dialCtx, err = grpc.DialContext( b.ctx, base58.Encode(key), @@ -556,7 +567,10 @@ func discoverPeers( logger.Info("initiating peer discovery") discover := func() { - peerChan, err := routingDiscovery.FindPeers(ctx, ANNOUNCE) + peerChan, err := routingDiscovery.FindPeers( + ctx, + getNetworkNamespace(p2pConfig.Network), + ) if err != nil { logger.Error("could not find peers", zap.Error(err)) } @@ -717,3 +731,20 @@ func mergeDefaults(p2pConfig *config.P2PConfig) blossomsub.BlossomSubParams { SlowHeartbeatWarning: 0.1, } } + +func getNetworkNamespace(network uint8) string { + var network_name string + switch network { + case 0: + network_name = "mainnet" + break + case 1: + network_name = "testnet-primary" + break + default: + network_name = fmt.Sprintf("network-%d", network) + break + } + + return ANNOUNCE_PREFIX + network_name +} diff --git a/node/p2p/peer_info_manager.go b/node/p2p/peer_info_manager.go index 3b2dde3..63bd671 100644 --- a/node/p2p/peer_info_manager.go +++ b/node/p2p/peer_info_manager.go @@ -39,6 +39,7 @@ type PeerManifest struct { Capabilities []Capability MasterHeadFrame uint64 Bandwidth uint64 + LastSeen int64 } type InMemoryPeerInfoManager struct { diff --git a/node/poor_mans_cd.sh b/node/poor_mans_cd.sh deleted file mode 100755 index 2beb9e3..0000000 --- a/node/poor_mans_cd.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash - -start_process() { - GOEXPERIMENT=arenas go run ./... & - main_process_id=$! - local child_process_pid=$(pgrep -P $main_process_id) - echo "process started with PID $main_process_id and child PID $child_process_pid" -} - -is_process_running() { - ps -p $main_process_id > /dev/null 2>&1 - return $? -} - -kill_process() { - local process_count=$(ps -ef | grep "exe/node" | grep -v grep | wc -l) - local process_pids=$(ps -ef | grep "exe/node" | grep -v grep | awk '{print $2}' | xargs) - - if [ $process_count -gt 0 ]; then - echo "killing processes $process_pids" - kill $process_pids - - local child_process_count=$(pgrep -P $process_pids | wc -l) - local child_process_pids=$(pgrep -P $process_pids | xargs) - if [ $child_process_count -gt 0 ]; then - echo "killing child processes $child_process_pids" - kill $child_process_pids - else - echo "no child processes running" - fi - else - echo "no processes running" - fi -} - -kill_process - -start_process - -while true; do - if ! is_process_running; then - echo "process crashed or stopped. restarting..." - start_process - fi - - git fetch - - local_head=$(git rev-parse HEAD) - remote_head=$(git rev-parse @{u}) - - if [ "$local_head" != "$remote_head" ]; then - kill_process - - git pull - - start_process - fi - - sleep 60 -done diff --git a/node/protobufs/node.pb.go b/node/protobufs/node.pb.go index 1c0c710..c666428 100644 --- a/node/protobufs/node.pb.go +++ b/node/protobufs/node.pb.go @@ -1094,6 +1094,8 @@ type SelfTestReport struct { Capabilities []*Capability `protobuf:"bytes,14,rep,name=capabilities,proto3" json:"capabilities,omitempty"` // The highest master frame the node has MasterHeadFrame uint64 `protobuf:"varint,15,opt,name=master_head_frame,json=masterHeadFrame,proto3" json:"master_head_frame,omitempty"` + // A challenge proof + Proof []byte `protobuf:"bytes,16,opt,name=proof,proto3" json:"proof,omitempty"` } func (x *SelfTestReport) Reset() { @@ -1233,6 +1235,13 @@ func (x *SelfTestReport) GetMasterHeadFrame() uint64 { return 0 } +func (x *SelfTestReport) GetProof() []byte { + if x != nil { + return x.Proof + } + return nil +} + type ValidationMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1456,6 +1465,8 @@ type PeerManifest struct { Capabilities []*Capability `protobuf:"bytes,15,rep,name=capabilities,proto3" json:"capabilities,omitempty"` // The highest master frame the node has MasterHeadFrame uint64 `protobuf:"varint,16,opt,name=master_head_frame,json=masterHeadFrame,proto3" json:"master_head_frame,omitempty"` + // The last time seen tick + LastSeen int64 `protobuf:"varint,17,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"` } func (x *PeerManifest) Reset() { @@ -1602,6 +1613,13 @@ func (x *PeerManifest) GetMasterHeadFrame() uint64 { return 0 } +func (x *PeerManifest) GetLastSeen() int64 { + if x != nil { + return x.LastSeen + } + return 0 +} + type PeerManifestsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1780,8 +1798,8 @@ var file_node_proto_rawDesc = []byte{ 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xfa, - 0x04, 0x0a, 0x0e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x90, + 0x05, 0x0a, 0x0e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x5f, @@ -1820,151 +1838,154 @@ var file_node_proto_rawDesc = []byte{ 0x79, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x73, 0x74, - 0x65, 0x72, 0x48, 0x65, 0x61, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0x33, 0x0a, 0x11, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x62, 0x0a, 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x53, 0x0a, 0x0e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, - 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, - 0x70, 0x62, 0x2e, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x66, 0x0a, 0x0c, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x65, 0x72, 0x48, 0x65, 0x61, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, + 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x22, 0x33, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x62, 0x0a, 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x53, 0x0a, 0x0e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, - 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0e, 0x66, 0x72, - 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x0a, 0x17, - 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x91, 0x05, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, - 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x65, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, - 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x5f, - 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x64, 0x69, - 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x28, - 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x31, 0x36, 0x5f, 0x6d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x31, 0x36, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x31, 0x32, 0x38, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x31, - 0x30, 0x32, 0x34, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x31, 0x30, 0x32, 0x34, 0x4d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x36, 0x35, 0x35, - 0x33, 0x36, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x11, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x36, 0x35, 0x35, 0x33, 0x36, 0x4d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x31, 0x36, 0x5f, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x31, 0x36, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x31, 0x32, 0x38, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x31, 0x30, - 0x32, 0x34, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x31, 0x30, 0x32, 0x34, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x36, 0x35, 0x35, 0x33, 0x36, 0x5f, - 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x36, 0x35, 0x35, 0x33, 0x36, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x14, - 0x0a, 0x05, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, - 0x6f, 0x72, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x71, + 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0d, 0x66, 0x72, 0x61, + 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x66, 0x0a, 0x0c, 0x53, 0x79, + 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x66, 0x72, + 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x62, 0x2e, 0x43, + 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x52, 0x0e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xae, 0x05, + 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x17, + 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x70, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, + 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x69, 0x66, + 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x69, 0x66, 0x66, 0x69, + 0x63, 0x75, 0x6c, 0x74, 0x79, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x10, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x31, + 0x36, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x31, 0x36, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2a, + 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x31, 0x32, 0x38, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x31, 0x30, 0x32, 0x34, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x31, 0x30, + 0x32, 0x34, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x5f, 0x36, 0x35, 0x35, 0x33, 0x36, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x36, 0x35, 0x35, + 0x33, 0x36, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x5f, 0x31, 0x36, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x31, 0x36, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x6d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x31, 0x32, 0x38, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, + 0x6f, 0x6f, 0x66, 0x5f, 0x31, 0x30, 0x32, 0x34, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x31, 0x30, 0x32, 0x34, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, + 0x36, 0x35, 0x35, 0x33, 0x36, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x36, 0x35, 0x35, 0x33, 0x36, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x47, 0x0a, 0x0c, + 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x70, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x68, 0x65, 0x61, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x48, 0x65, 0x61, 0x64, 0x46, 0x72, 0x61, 0x6d, + 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x11, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x22, 0x65, + 0x0a, 0x15, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x5f, + 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, + 0x66, 0x65, 0x73, 0x74, 0x73, 0x32, 0xd7, 0x01, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x11, 0x50, + 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, - 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x66, - 0x72, 0x61, 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x73, 0x74, - 0x65, 0x72, 0x48, 0x65, 0x61, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0x65, 0x0a, 0x15, 0x50, - 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x6e, - 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x71, - 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, - 0x65, 0x73, 0x74, 0x52, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, - 0x74, 0x73, 0x32, 0xd7, 0x01, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x66, - 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, - 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, - 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x70, 0x62, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x55, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x24, 0x2e, - 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, - 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x32, 0xf6, 0x05, 0x0a, - 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x09, - 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x71, 0x75, 0x69, 0x6c, - 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, - 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x46, - 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, - 0x0c, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x2e, - 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x71, 0x75, - 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50, 0x65, - 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, + 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x55, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, + 0x12, 0x24, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x65, - 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, - 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x2e, + 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x32, + 0xf6, 0x05, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x5f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x71, + 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, + 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, + 0x62, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x68, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x72, + 0x61, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, + 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x47, 0x65, + 0x74, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, + 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, + 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, + 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x71, 0x75, 0x69, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, - 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, - 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x71, 0x75, 0x69, + 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, + 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, + 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x74, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, + 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, + 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xcf, 0x01, 0x0a, 0x09, 0x4e, 0x6f, 0x64, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x60, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x47, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x74, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, - 0x73, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, - 0x74, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, - 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x50, 0x65, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xcf, 0x01, 0x0a, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x73, 0x12, 0x60, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, + 0x50, 0x75, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x75, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x50, 0x65, 0x65, 0x72, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x50, + 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, + 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, + 0x62, 0x2e, 0x50, 0x75, 0x74, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x50, - 0x75, 0x74, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x24, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x75, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3a, 0x5a, 0x38, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x6d, 0x6f, 0x6e, 0x6f, - 0x72, 0x65, 0x70, 0x6f, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3a, 0x5a, 0x38, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x6d, + 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x70, 0x6f, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/node/protobufs/node.proto b/node/protobufs/node.proto index bd783a1..3116196 100644 --- a/node/protobufs/node.proto +++ b/node/protobufs/node.proto @@ -155,6 +155,8 @@ message SelfTestReport { repeated Capability capabilities = 14; // The highest master frame the node has uint64 master_head_frame = 15; + // A challenge proof + bytes proof = 16; } message ValidationMessage { @@ -216,6 +218,8 @@ message PeerManifest { repeated Capability capabilities = 15; // The highest master frame the node has uint64 master_head_frame = 16; + // The last time seen tick + int64 last_seen = 17; } message PeerManifestsResponse { diff --git a/signers/.env.example b/signers/.env.example new file mode 100644 index 0000000..e7b9271 --- /dev/null +++ b/signers/.env.example @@ -0,0 +1,7 @@ +# Full path to your private key, used for signing and also the corresponding pem file number. Both required to generate signatures. +SIGNING_KEY_PATH= +SIGNING_KEY_ID= + +# Full path to your public key, used to generate hex for reference. +SIGNING_PUB_KEY_PATH= + diff --git a/signers/Dockerfile b/signers/Dockerfile new file mode 100644 index 0000000..6b1fce7 --- /dev/null +++ b/signers/Dockerfile @@ -0,0 +1,18 @@ +FROM golang:1.20.14-bookworm + +ENV GOEXPERIMENT=arenas +ENV QUILIBRIUM_DOCKER_CONTAINER=true + +ARG USER_NAME=default +ARG UID=1000 +ARG GID=1000 + +RUN groupadd -g ${GID} ${USER_NAME} \ + && useradd -u ${UID} -g ${USER_NAME} -s /bin/bash ${USER_NAME} + +RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin +RUN apt-get update && apt-get install git + +USER ${USER_NAME} + +WORKDIR /home/${USER_NAME} diff --git a/signers/README.md b/signers/README.md new file mode 100644 index 0000000..d858551 --- /dev/null +++ b/signers/README.md @@ -0,0 +1,20 @@ +# Release Signatories + +Scripts in this folder are tools for release signers to build and sign Quilibrium binaries. + +Requirements: +- bash environment (Ubuntu, macOS, etc.) +- openssl - digests and signatures +- git - to checkout this branch +- Docker - to run a container with golang and compile binaries +- [Taskfile](https://taskfile.dev/installation/) + +Checkout the whole repo from a release branch and then in the `signers` folder you can run `task` commands. Before you +can run commands you have to copy `.env.example` to `.env` and fill it out. You need a local folder with all the pem +files, required by signature verification. + +Important tasks: +- `task build` to build the binaries in a dedicated docker image +- `task verify:build` to verify that you can build the exact same binaries +- `task verify:digest` to verify the digests +- `task verify:signatures` to verify all signatures diff --git a/signers/Taskfile.yaml b/signers/Taskfile.yaml new file mode 100644 index 0000000..dd5b67e --- /dev/null +++ b/signers/Taskfile.yaml @@ -0,0 +1,202 @@ +# https://taskfile.dev + +version: '3' + +dotenv: + - '.env' + +env: + GOEXPERIMENT: arenas + +vars: + VERSION: + sh: cat ../node/config/version.go | grep -A 1 "func GetVersion() \[\]byte {" | grep -Eo '0x[0-9a-fA-F]+' | xargs printf "%d.%d.%d" + MAX_KEY_ID: 15 + QUILIBRIUM_SIGNERS_IMAGE_NAME: 'quilibrium-signers' + USER_NAME: + sh: whoami + PARENT_FOLDER: + sh: dirname $(pwd) + SIGNING_KEYS_PEM_DIR: 'pems' + +tasks: + status: + desc: Display configuration info. + cmds: + - echo -n "Version :" && echo " {{.VERSION}}" + - echo -n "Priv Key Path :" && echo " {{.SIGNING_KEY_PATH}}" + - echo -n "Pub Key Path :" && echo " {{.SIGNING_PUB_KEY_PATH}}" + - echo -n "Key ID :" && echo " {{.SIGNING_KEY_ID}}" + silent: true + + hex: + desc: Print the hex representation of your public key. + cmds: + - cat {{.SIGNING_PUB_KEY_PATH}} | openssl ec -inform pem -pubin -noout -text + + docker:build_image: + desc: Build the Quilibrium Signers docker image, unless it is already built. + aliases: + - image + preconditions: + - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"' + msg: 'This command cannot be run inside the container' + cmds: + - | + docker build \ + --build-arg USER_NAME={{.USER_NAME}} \ + --build-arg UID=$(id -u) \ + --build-arg GID=$(id -g) \ + -t {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}}:latest \ + . + status: + - | + docker image inspect \ + {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} \ + >/dev/null 2>/dev/null + + build: + desc: Build the Quilibrium node binaries by starting a container and starting the build inside the container. + preconditions: + - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"' + msg: 'This command cannot be run inside the container' + deps: + - docker:build_image + cmds: + - docker run --name signers --rm -it -v {{.PARENT_FOLDER}}:/home/{{.USER_NAME}}/ceremonyclient -u {{.USER_NAME}} -w /home/{{.USER_NAME}}/ceremonyclient/signers {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} task build:container + + build:shell: + desc: Start a shell in a build container. + aliases: + - shell + preconditions: + - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"' + msg: 'This command cannot be run inside the container' + deps: + - docker:build_image + cmds: + - docker run --name signers --rm -it -v {{.PARENT_FOLDER}}:/home/{{.USER_NAME}}/ceremonyclient -u {{.USER_NAME}} -w /home/{{.USER_NAME}}/ceremonyclient/signers {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} bash + + build:container: + desc: Build the Quilibrium node binaries, inside the Docker container. + dir: ../node + sources: + - '**/*.go' + generates: + - node-{{.VERSION}}-*.bin + cmds: + - GOOS=darwin go build -ldflags "-s -w" -o node-{{.VERSION}}-darwin-arm64.bin + - GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o node-{{.VERSION}}-linux-amd64.bin + - GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o node-{{.VERSION}}-linux-arm64.bin + + digest: + desc: Generate digests for node binaries. + deps: [build] + dir: ../node + sources: + - node-{{.VERSION}}-*.bin + generates: + - node-{{.VERSION}}-*.dgst + cmds: + - openssl sha3-256 -out node-{{.VERSION}}-darwin-arm64.dgst node-{{.VERSION}}-darwin-arm64.bin + - openssl sha3-256 -out node-{{.VERSION}}-linux-amd64.dgst node-{{.VERSION}}-linux-amd64.bin + - openssl sha3-256 -out node-{{.VERSION}}-linux-arm64.dgst node-{{.VERSION}}-linux-arm64.bin + + sign: + desc: Generate signatures for node binaries. + deps: [digest] + dir: ../node + preconditions: + - sh: 'test -n "$SIGNING_KEY_PATH"' + msg: 'The path to the signing key must be set in SIGNING_KEY_PATH' + - sh: 'test -n "$SIGNING_KEY_ID"' + msg: 'The signing key id must be set in SIGNING_KEY_ID' + sources: + - node-{{.VERSION}}-*.dgst + generates: + - node-{{.VERSION}}-*.dgst.sig.{{.SIGNING_KEY_ID}} + cmds: + - openssl pkeyutl -sign -inkey {{.SIGNING_KEY_PATH}} -rawin -in node-{{.VERSION}}-darwin-arm64.dgst -out node-{{.VERSION}}-darwin-arm64.dgst.sig.{{.SIGNING_KEY_ID}} + - openssl pkeyutl -sign -inkey {{.SIGNING_KEY_PATH}} -rawin -in node-{{.VERSION}}-linux-amd64.dgst -out node-{{.VERSION}}-linux-amd64.dgst.sig.{{.SIGNING_KEY_ID}} + - openssl pkeyutl -sign -inkey {{.SIGNING_KEY_PATH}} -rawin -in node-{{.VERSION}}-linux-arm64.dgst -out node-{{.VERSION}}-linux-arm64.dgst.sig.{{.SIGNING_KEY_ID}} + + verify:build: + desc: Verify that the existing binaries can be rebuilt exactly the same. + dir: ../node + preconditions: + - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"' + msg: 'This command cannot be run inside the container' + deps: + - docker:build_image + cmds: + - docker run --name signers --rm -it -v {{.PARENT_FOLDER}}:/home/{{.USER_NAME}}/ceremonyclient -u {{.USER_NAME}} -w /home/{{.USER_NAME}}/ceremonyclient/signers {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} task verify:build:container + - diff node-{{.VERSION}}-darwin-arm64.bin node-tmp-darwin-arm64.bin + - diff node-{{.VERSION}}-linux-amd64.bin node-tmp-linux-amd64.bin + - diff node-{{.VERSION}}-linux-arm64.bin node-tmp-linux-arm64.bin + + verify:build:container: + desc: Verify that the existing binaries can be rebuilt exactly the same, inside tbe Docker container. + dir: ../node + sources: + - '**/*.go' + generates: + - node-tmp-*.bin + cmds: + - GOOS=darwin go build -ldflags "-s -w" -o node-tmp-darwin-arm64.bin + - GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o node-tmp-linux-amd64.bin + - GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o node-tmp-linux-arm64.bin + - diff node-{{.VERSION}}-darwin-arm64.bin node-tmp-darwin-arm64.bin + - diff node-{{.VERSION}}-linux-amd64.bin node-tmp-linux-amd64.bin + - diff node-{{.VERSION}}-linux-arm64.bin node-tmp-linux-arm64.bin + + verify:digest: + desc: Verify that the existing digests are correct. + dir: ../node + cmds: + - openssl sha3-256 -out node-tmp-darwin-arm64.dgst node-{{.VERSION}}-darwin-arm64.bin + - openssl sha3-256 -out node-tmp-linux-amd64.dgst node-{{.VERSION}}-linux-amd64.bin + - openssl sha3-256 -out node-tmp-linux-arm64.dgst node-{{.VERSION}}-linux-arm64.bin + - diff node-{{.VERSION}}-darwin-arm64.dgst node-tmp-darwin-arm64.dgst + - diff node-{{.VERSION}}-linux-amd64.dgst node-tmp-linux-amd64.dgst + - diff node-{{.VERSION}}-linux-arm64.dgst node-tmp-linux-arm64.dgst + + verify:signatures: + desc: Verify all signatures. + dir: ../node + cmds: + - | + for i in {1..{{.MAX_KEY_ID}}} + do + if [ -f node-{{.VERSION}}-darwin-arm64.dgst.sig.$i ] + then + echo $i + echo "node-{{.VERSION}}-darwin-arm64" + openssl pkeyutl -verify -rawin -inkey {{.SIGNING_KEYS_PEM_DIR}}/$i.pem -pubin -sigfile node-{{.VERSION}}-darwin-arm64.dgst.sig.$i -in node-{{.VERSION}}-darwin-arm64.dgst + echo "node-{{.VERSION}}-linux-amd64" + openssl pkeyutl -verify -rawin -inkey {{.SIGNING_KEYS_PEM_DIR}}/$i.pem -pubin -sigfile node-{{.VERSION}}-linux-amd64.dgst.sig.$i -in node-{{.VERSION}}-linux-amd64.dgst + echo "node-{{.VERSION}}-linux-arm64" + openssl pkeyutl -verify -rawin -inkey {{.SIGNING_KEYS_PEM_DIR}}/$i.pem -pubin -sigfile node-{{.VERSION}}-linux-arm64.dgst.sig.$i -in node-{{.VERSION}}-linux-arm64.dgst + else + if [ -f node-{{.VERSION}}-linux-arm64.dgst.sig.$i ] + then + echo "$i is missing signatures" + else + if [ -f node-{{.VERSION}}-linux-amd64.dgst.sig.$i ] + then + echo "$i is missing signatures" + fi + fi + fi + done + silent: true + + clean: + desc: Remove temporary files, docker containers and image. + dir: ../node + preconditions: + - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"' + msg: 'This command cannot be run inside the container' + cmds: + - rm -f node-tmp-* + - docker container rm -f signers + - docker image rm -f {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} diff --git a/signers/pems/1.pem b/signers/pems/1.pem new file mode 100644 index 0000000..7acb83e --- /dev/null +++ b/signers/pems/1.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAsSFNp/NV9antt7zCPUA733ifBwzKENsrTK3CLy2DevtlCUSF +PjXV9C7zxBBbgCsUS0B31dMlPkEA +-----END PUBLIC KEY----- diff --git a/signers/pems/10.pem b/signers/pems/10.pem new file mode 100644 index 0000000..4cf82b3 --- /dev/null +++ b/signers/pems/10.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoARQdib3Fk59jDBMB/+NLiPBE/4QiyIdLmBnL00HdQNFgV4rSz +zD3000Zr8vZpw1wxcuBlEScGEqsA +-----END PUBLIC KEY----- diff --git a/signers/pems/11.pem b/signers/pems/11.pem new file mode 100644 index 0000000..4cabb8b --- /dev/null +++ b/signers/pems/11.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAT7JTc0Xka+PV+WNAwUQQB1AXAt1b+vbb9pQ7vvzsqPsrlOwK +ihovSYUPvh0QJEiJpPQKv6ngyeAA +-----END PUBLIC KEY----- diff --git a/signers/pems/12.pem b/signers/pems/12.pem new file mode 100644 index 0000000..b4f265d --- /dev/null +++ b/signers/pems/12.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAV74oYfrw//y/0SLIXHcBDc6PITAwkFeBuFtvNF2RLHtazhd5 +fZgQiZ37jRPnyDaVlXQHJas91b0A +-----END PUBLIC KEY----- diff --git a/signers/pems/13.pem b/signers/pems/13.pem new file mode 100644 index 0000000..ceed2f0 --- /dev/null +++ b/signers/pems/13.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAYWKL7vj2lkRm/QeNaiuQo5erB3ehS5coIn/RnzZ1L5RRsajX +gHQKC5qM499ficp7n/F96SdKJwmA +-----END PUBLIC KEY----- diff --git a/signers/pems/14.pem b/signers/pems/14.pem new file mode 100644 index 0000000..4a09da4 --- /dev/null +++ b/signers/pems/14.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAVUevxxsCgh4vW/3TD74TdMOFOJje/yChtcxym46BZw+7udHp +F/hdFT6ksmu/b5xUbcG2S5kWYI2A +-----END PUBLIC KEY----- diff --git a/signers/pems/15.pem b/signers/pems/15.pem new file mode 100644 index 0000000..929e64f --- /dev/null +++ b/signers/pems/15.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAgdY6RfBoYp9WjegS8YvlgHv+goqDAJfwnPAjMNas0142B0Ad +8/2giwO2jqbmiv1QayNQaxHoeg+A +-----END PUBLIC KEY----- diff --git a/signers/pems/2.pem b/signers/pems/2.pem new file mode 100644 index 0000000..37c8a40 --- /dev/null +++ b/signers/pems/2.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoA3kz+cIMQS/4y8NQIL6AgBGTYsQgEqBFlPu3aN278rWTdIi8P +DOsLiuWKvoMNen4/Oy151pExjaoA +-----END PUBLIC KEY----- diff --git a/signers/pems/3.pem b/signers/pems/3.pem new file mode 100644 index 0000000..cfb8ffa --- /dev/null +++ b/signers/pems/3.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAVAI3o14SSILWtk57tXGCc/ozjlU/dyt3/pBXDkUwN2KzQTG9 +y2wLnyz545PZx+D1Ru6rC8u9iBaA +-----END PUBLIC KEY----- diff --git a/signers/pems/4.pem b/signers/pems/4.pem new file mode 100644 index 0000000..7c9a9af --- /dev/null +++ b/signers/pems/4.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoA++QWbjf5P5DS6/BjBTFa4Rs35QHQlZb4veEbqdNDA0+8qA8l +IgWqL1gqUSpyrSk983G6pYLaBykA +-----END PUBLIC KEY----- diff --git a/signers/pems/5.pem b/signers/pems/5.pem new file mode 100644 index 0000000..3135a3c --- /dev/null +++ b/signers/pems/5.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAQWBXLkk+G/FcROBVsRv3UjDHbH0sZ7SAZncKsD39XtNMl7mk +MewYV4yDoN+SULg2LDgGhlDosBQA +-----END PUBLIC KEY----- diff --git a/signers/pems/6.pem b/signers/pems/6.pem new file mode 100644 index 0000000..397f92b --- /dev/null +++ b/signers/pems/6.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoARRcLYmiEuF1hrhCfKqmw4ezBixgVCEMepjCPOGnyra5J2peZ +oKWU6qTvOtSSUY+xcp3s1EFp1A0A +-----END PUBLIC KEY----- diff --git a/signers/pems/7.pem b/signers/pems/7.pem new file mode 100644 index 0000000..416d24a --- /dev/null +++ b/signers/pems/7.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAks2O5TYvOuJ0p1q5RxAk28FEv/RB7Yr30ZdQrFEv9R5A5/ew +Hk+WtjRd1Yh4VllIw+tSxT8lC1CA +-----END PUBLIC KEY----- diff --git a/signers/pems/8.pem b/signers/pems/8.pem new file mode 100644 index 0000000..24a9a22 --- /dev/null +++ b/signers/pems/8.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAABpMv85dmut+IGZbDSNnIbIooy8LruYv+nf0W4Lsr1d+iji3 +75H899LS0rUE8IVGE5jTCySrsdcA +-----END PUBLIC KEY----- diff --git a/signers/pems/9.pem b/signers/pems/9.pem new file mode 100644 index 0000000..a3324b7 --- /dev/null +++ b/signers/pems/9.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAZbg1BxcxxueFuy0QfH2F2KU315xDXD9Cuy+HAn+T+FjXs3xZ +jO8mel20bjRfem+BlptGVoZlfR4A +-----END PUBLIC KEY-----