Merge branch 'develop' into v2.0.5

This commit is contained in:
Cassandra Heart 2024-12-03 18:59:41 -06:00
commit 99bc683145
No known key found for this signature in database
GPG Key ID: 6352152859385958
69 changed files with 3376 additions and 2047 deletions

241
channel/channel_test.go Normal file
View File

@ -0,0 +1,241 @@
package channel_test
import (
"bytes"
"crypto/rand"
"encoding/base64"
"fmt"
"sort"
"testing"
"github.com/stretchr/testify/assert"
"source.quilibrium.com/quilibrium/monorepo/channel"
generated "source.quilibrium.com/quilibrium/monorepo/channel/generated/channel"
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves"
)
type peer struct {
privKey *curves.ScalarEd448
pubKey *curves.PointEd448
pubKeyB64 string
identityKey *curves.ScalarEd448
identityPubKey *curves.PointEd448
signedPreKey *curves.ScalarEd448
signedPrePubKey *curves.PointEd448
}
func generatePeer() *peer {
privKey := &curves.ScalarEd448{}
privKey = privKey.Random(rand.Reader).(*curves.ScalarEd448)
identityKey := &curves.ScalarEd448{}
identityKey = identityKey.Random(rand.Reader).(*curves.ScalarEd448)
signedPreKey := &curves.ScalarEd448{}
signedPreKey = signedPreKey.Random(rand.Reader).(*curves.ScalarEd448)
pubkey := privKey.Point().Generator().Mul(privKey).(*curves.PointEd448)
pubKeyB64 := base64.StdEncoding.EncodeToString(pubkey.ToAffineCompressed())
return &peer{
privKey: privKey,
pubKey: pubkey,
pubKeyB64: pubKeyB64,
identityKey: identityKey,
identityPubKey: identityKey.Point().Generator().Mul(identityKey).(*curves.PointEd448),
signedPreKey: signedPreKey,
signedPrePubKey: signedPreKey.Point().Generator().Mul(signedPreKey).(*curves.PointEd448),
}
}
func remapOutputs(maps map[string]map[string]string) map[string]map[string]string {
out := map[string]map[string]string{}
for k := range maps {
out[k] = map[string]string{}
}
for k := range maps {
for ik, iv := range maps[k] {
out[ik][k] = iv
}
}
return out
}
func TestChannel(t *testing.T) {
peers := []*peer{}
for i := 0; i < 4; i++ {
peers = append(peers, generatePeer())
}
sort.Slice(peers, func(i, j int) bool {
return bytes.Compare(peers[i].pubKey.ToAffineCompressed(), peers[j].pubKey.ToAffineCompressed()) <= 0
})
trs := map[string]*generated.TripleRatchetStateAndMetadata{}
peerids := [][]byte{}
outs := map[string]map[string]string{}
for i := 0; i < 4; i++ {
outs[peers[i].pubKeyB64] = make(map[string]string)
peerids = append(peerids,
append(
append(
append([]byte{}, peers[i].pubKey.ToAffineCompressed()...),
peers[i].identityPubKey.ToAffineCompressed()...,
),
peers[i].signedPrePubKey.ToAffineCompressed()...,
),
)
}
for i := 0; i < 4; i++ {
otherPeerIds := [][]byte{}
for j := 0; j < 4; j++ {
if i != j {
otherPeerIds = append(otherPeerIds, peerids[j])
}
}
tr := channel.NewTripleRatchet(
otherPeerIds,
peers[i].privKey.Bytes(),
peers[i].identityKey.Bytes(),
peers[i].signedPreKey.Bytes(),
2,
true,
)
trs[peers[i].pubKeyB64] = &tr
outs[peers[i].pubKeyB64] = trs[peers[i].pubKeyB64].Metadata
}
outs = remapOutputs(outs)
for k := range trs {
for ik := range trs[k].Metadata {
delete(trs[k].Metadata, ik)
}
for ik, iv := range outs[k] {
trs[k].Metadata[ik] = iv
}
}
// round 1
next := map[string]*generated.TripleRatchetStateAndMetadata{}
outs = map[string]map[string]string{}
for i := 0; i < 4; i++ {
tr := channel.TripleRatchetInitRound1(
*trs[peers[i].pubKeyB64],
)
next[peers[i].pubKeyB64] = &tr
outs[peers[i].pubKeyB64] = next[peers[i].pubKeyB64].Metadata
}
trs = next
outs = remapOutputs(outs)
for k, _ := range trs {
for ik := range trs[k].Metadata {
delete(trs[k].Metadata, ik)
}
for ik, iv := range outs[k] {
trs[k].Metadata[ik] = iv
}
}
// round 2
next = map[string]*generated.TripleRatchetStateAndMetadata{}
outs = map[string]map[string]string{}
for i := 0; i < 4; i++ {
tr := channel.TripleRatchetInitRound2(
*trs[peers[i].pubKeyB64],
)
next[peers[i].pubKeyB64] = &tr
outs[peers[i].pubKeyB64] = next[peers[i].pubKeyB64].Metadata
}
trs = next
outs = remapOutputs(outs)
for k := range trs {
for ik := range trs[k].Metadata {
delete(trs[k].Metadata, ik)
}
for ik, iv := range outs[k] {
trs[k].Metadata[ik] = iv
}
}
// round 3
next = map[string]*generated.TripleRatchetStateAndMetadata{}
outs = map[string]map[string]string{}
for i := 0; i < 4; i++ {
tr := channel.TripleRatchetInitRound3(
*trs[peers[i].pubKeyB64],
)
next[peers[i].pubKeyB64] = &tr
outs[peers[i].pubKeyB64] = next[peers[i].pubKeyB64].Metadata
}
trs = next
outs = remapOutputs(outs)
for k := range trs {
for ik := range trs[k].Metadata {
delete(trs[k].Metadata, ik)
}
for ik, iv := range outs[k] {
trs[k].Metadata[ik] = iv
}
}
// round 4
next = map[string]*generated.TripleRatchetStateAndMetadata{}
outs = map[string]map[string]string{}
for i := 0; i < 4; i++ {
tr := channel.TripleRatchetInitRound4(
*trs[peers[i].pubKeyB64],
)
next[peers[i].pubKeyB64] = &tr
outs[peers[i].pubKeyB64] = next[peers[i].pubKeyB64].Metadata
}
trs = next
outs = remapOutputs(outs)
for k := range trs {
for ik := range trs[k].Metadata {
delete(trs[k].Metadata, ik)
}
for ik, iv := range outs[k] {
trs[k].Metadata[ik] = iv
}
}
for i := 0; i < 4; i++ {
send := channel.TripleRatchetEncrypt(
generated.TripleRatchetStateAndMessage{
RatchetState: trs[peers[i].pubKeyB64].RatchetState,
Message: []byte(fmt.Sprintf("hi-%d", i)),
},
)
trs[peers[i].pubKeyB64].RatchetState = send.RatchetState
for j := 0; j < 4; j++ {
if i != j {
msg := channel.TripleRatchetDecrypt(
generated.TripleRatchetStateAndEnvelope{
RatchetState: trs[peers[j].pubKeyB64].RatchetState,
Envelope: send.Envelope,
},
)
trs[peers[j].pubKeyB64].RatchetState = msg.RatchetState
if !bytes.Equal(msg.Message, []byte(fmt.Sprintf("hi-%d", i))) {
assert.FailNow(t, "mismatch messages")
}
}
}
}
}

View File

@ -8,6 +8,19 @@ replace source.quilibrium.com/quilibrium/monorepo/nekryptology => ../nekryptolog
require github.com/stretchr/testify v1.9.0
require (
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401 // indirect
github.com/bwesterb/go-ristretto v1.2.3 // indirect
github.com/consensys/gnark-crypto v0.5.3 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
require (
github.com/cloudflare/circl v1.3.3
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/crypto v0.24.0 // indirect

View File

@ -1,13 +1,84 @@
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401 h1:0tjUthKCaF8zwF9Qg7lfnep0xdo4n8WiFUfQPaMHX6g=
github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/consensys/bavard v0.1.8-0.20210915155054-088da2f7f54a/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.5.3 h1:4xLFGZR3NWEH2zy+YzvzHicpToQR8FXFbfLNvpGB+rE=
github.com/consensys/gnark-crypto v0.5.3/go.mod h1:hOdPlWQV1gDLp7faZVeg8Y0iEPFaOUnCc4XeCCk96p0=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=

View File

@ -89,8 +89,9 @@ var allCmd = &cobra.Command{
panic(errors.Wrap(err, "error getting peer id"))
}
ctx := context.Background()
resume := make([]byte, 32)
cc, err := pubSub.GetDirectChannel([]byte(bpeerId), "worker")
cc, err := pubSub.GetDirectChannel(ctx, []byte(bpeerId), "worker")
if err != nil {
logger.Info(
"could not establish direct channel, waiting...",
@ -100,7 +101,7 @@ var allCmd = &cobra.Command{
}
for {
if cc == nil {
cc, err = pubSub.GetDirectChannel([]byte(bpeerId), "worker")
cc, err = pubSub.GetDirectChannel(ctx, []byte(bpeerId), "worker")
if err != nil {
logger.Info(
"could not establish direct channel, waiting...",

View File

@ -14,8 +14,6 @@ replace github.com/multiformats/go-multiaddr => ../go-multiaddr
replace github.com/multiformats/go-multiaddr-dns => ../go-multiaddr-dns
replace github.com/libp2p/go-buffer-pool => ../go-buffer-pool
replace github.com/libp2p/go-libp2p => ../go-libp2p
replace github.com/libp2p/go-libp2p-kad-dht => ../go-libp2p-kad-dht
@ -87,7 +85,7 @@ require (
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
@ -166,7 +164,7 @@ require (
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
gonum.org/v1/gonum v0.13.0 // indirect

View File

@ -248,8 +248,10 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/klauspost/reedsolomon v1.12.4 h1:5aDr3ZGoJbgu/8+j45KtUJxzYm8k08JGtB9Wx1VQ4OA=
github.com/klauspost/reedsolomon v1.12.4/go.mod h1:d3CzOMOt0JXGIFZm1StgkyF14EYr3xneR2rNWo7NcMU=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -263,6 +265,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
@ -662,8 +666,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@ -6,26 +6,33 @@ use protocols::{doubleratchet::{DoubleRatchetParticipant, P2PChannelEnvelope}, t
pub(crate) mod protocols;
uniffi::include_scaffolding!("lib");
#[derive(Clone, PartialEq)]
pub struct DoubleRatchetStateAndEnvelope {
pub ratchet_state: String,
pub envelope: String,
}
#[derive(Clone, PartialEq)]
pub struct DoubleRatchetStateAndMessage {
pub ratchet_state: String,
pub message: Vec<u8>,
}
#[derive(Clone, PartialEq)]
pub struct TripleRatchetStateAndMetadata {
pub ratchet_state: String,
pub metadata: HashMap<String, String>,
}
#[derive(Clone, PartialEq)]
pub struct TripleRatchetStateAndEnvelope {
pub ratchet_state: String,
pub envelope: String,
}
#[derive(Clone, PartialEq)]
pub struct TripleRatchetStateAndMessage {
pub ratchet_state: String,
pub message: Vec<u8>,
@ -156,35 +163,35 @@ pub fn double_ratchet_decrypt(ratchet_state_and_envelope: DoubleRatchetStateAndE
pub fn new_triple_ratchet(peers: &Vec<Vec<u8>>, peer_key: &Vec<u8>, identity_key: &Vec<u8>, signed_pre_key: &Vec<u8>, threshold: u64, async_dkg_ratchet: bool) -> TripleRatchetStateAndMetadata {
if peer_key.len() != 56 {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: "invalid peerkey".to_string(),
metadata: HashMap::new(),
};
}
if identity_key.len() != 56 {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: "invalid idk".to_string(),
metadata: HashMap::new(),
};
}
if signed_pre_key.len() != 56 {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: "invalid spk".to_string(),
metadata: HashMap::new(),
};
}
if peers.len() < 3 {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: "invalid peer count".to_string(),
metadata: HashMap::new(),
};
}
if threshold > peers.len() as u64 {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: "invalid threshold".to_string(),
metadata: HashMap::new(),
};
}
@ -205,7 +212,7 @@ pub fn new_triple_ratchet(peers: &Vec<Vec<u8>>, peer_key: &Vec<u8>, identity_key
for pk in peers.iter() {
if pk.len() != 171 {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: "invalid peer key size".to_string(),
metadata: HashMap::new(),
};
}
@ -228,7 +235,7 @@ pub fn new_triple_ratchet(peers: &Vec<Vec<u8>>, peer_key: &Vec<u8>, identity_key
if participant.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: participant.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -239,7 +246,7 @@ pub fn new_triple_ratchet(peers: &Vec<Vec<u8>>, peer_key: &Vec<u8>, identity_key
if participant_json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: "".to_string(),
ratchet_state: participant_json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -261,7 +268,7 @@ fn metadata_to_json(ratchet_state: &String, metadata: HashMap<Vec<u8>, P2PChanne
let env = v.to_json();
if env.is_err() {
return Err(TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state.to_string(),
ratchet_state: env.err().unwrap().to_string(),
metadata: HashMap::new(),
});
}
@ -276,9 +283,15 @@ fn json_to_metadata(ratchet_state_and_metadata: TripleRatchetStateAndMetadata, r
for (k,v) in ratchet_state_and_metadata.metadata {
let env = P2PChannelEnvelope::from_json(v);
let kb = BASE64_STANDARD.decode(k);
if env.is_err() || kb.is_err() {
if env.is_err() {
return Err(TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state.clone(),
ratchet_state: env.err().unwrap().to_string(),
metadata: HashMap::new(),
});
}
if kb.is_err() {
return Err(TripleRatchetStateAndMetadata{
ratchet_state: kb.err().unwrap().to_string(),
metadata: HashMap::new(),
});
}
@ -293,7 +306,7 @@ pub fn triple_ratchet_init_round_1(ratchet_state_and_metadata: TripleRatchetStat
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -307,7 +320,7 @@ pub fn triple_ratchet_init_round_1(ratchet_state_and_metadata: TripleRatchetStat
let result = trp.initialize(&metadata);
if result.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: result.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -321,7 +334,7 @@ pub fn triple_ratchet_init_round_1(ratchet_state_and_metadata: TripleRatchetStat
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -337,7 +350,7 @@ pub fn triple_ratchet_init_round_2(ratchet_state_and_metadata: TripleRatchetStat
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -353,7 +366,7 @@ pub fn triple_ratchet_init_round_2(ratchet_state_and_metadata: TripleRatchetStat
let r = trp.receive_poly_frag(&k, &v);
if r.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: r.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -372,7 +385,7 @@ pub fn triple_ratchet_init_round_2(ratchet_state_and_metadata: TripleRatchetStat
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -388,7 +401,7 @@ pub fn triple_ratchet_init_round_3(ratchet_state_and_metadata: TripleRatchetStat
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -404,7 +417,7 @@ pub fn triple_ratchet_init_round_3(ratchet_state_and_metadata: TripleRatchetStat
let r = trp.receive_commitment(&k, &v);
if r.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: r.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -423,7 +436,7 @@ pub fn triple_ratchet_init_round_3(ratchet_state_and_metadata: TripleRatchetStat
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -439,7 +452,7 @@ pub fn triple_ratchet_init_round_4(ratchet_state_and_metadata: TripleRatchetStat
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -455,7 +468,7 @@ pub fn triple_ratchet_init_round_4(ratchet_state_and_metadata: TripleRatchetStat
let r = trp.recombine(&k, &v);
if r.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: r.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -469,7 +482,7 @@ pub fn triple_ratchet_init_round_4(ratchet_state_and_metadata: TripleRatchetStat
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: ratchet_state,
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
@ -485,7 +498,7 @@ pub fn triple_ratchet_encrypt(ratchet_state_and_message: TripleRatchetStateAndMe
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: ratchet_state,
ratchet_state: tr.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
@ -495,7 +508,7 @@ pub fn triple_ratchet_encrypt(ratchet_state_and_message: TripleRatchetStateAndMe
if result.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: ratchet_state,
ratchet_state: result.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
@ -505,7 +518,7 @@ pub fn triple_ratchet_encrypt(ratchet_state_and_message: TripleRatchetStateAndMe
if envelope_json.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: ratchet_state,
ratchet_state: envelope_json.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
@ -513,7 +526,7 @@ pub fn triple_ratchet_encrypt(ratchet_state_and_message: TripleRatchetStateAndMe
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: ratchet_state,
ratchet_state: json.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
@ -529,7 +542,7 @@ pub fn triple_ratchet_decrypt(ratchet_state_and_envelope: TripleRatchetStateAndE
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: ratchet_state,
ratchet_state: tr.err().unwrap().to_string(),
message: vec![],
};
}
@ -538,7 +551,7 @@ pub fn triple_ratchet_decrypt(ratchet_state_and_envelope: TripleRatchetStateAndE
let env = P2PChannelEnvelope::from_json(ratchet_state_and_envelope.envelope);
if env.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: ratchet_state,
ratchet_state: env.err().unwrap().to_string(),
message: vec![],
};
}
@ -547,7 +560,7 @@ pub fn triple_ratchet_decrypt(ratchet_state_and_envelope: TripleRatchetStateAndE
if result.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: ratchet_state,
ratchet_state: result.err().unwrap().to_string(),
message: vec![],
};
}
@ -557,7 +570,7 @@ pub fn triple_ratchet_decrypt(ratchet_state_and_envelope: TripleRatchetStateAndE
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: ratchet_state,
ratchet_state: json.err().unwrap().to_string(),
message: vec![],
};
}

View File

@ -307,7 +307,6 @@ impl DoubleRatchetParticipant {
}
let (header, should_ratchet) = self.decrypt_header(&envelope.message_header, &self.current_receiving_header_key)?;
let (receiving_ephemeral_key, previous_receiving_chain_length, current_receiving_chain_length) =
self.decode_header(&header)?;

View File

@ -408,13 +408,23 @@ impl TripleRatchetParticipant {
pub fn initialize(&mut self, init_messages: &HashMap<Vec<u8>, P2PChannelEnvelope>)
-> Result<HashMap<Vec<u8>, P2PChannelEnvelope>, TripleRatchetError> {
for (k, m) in init_messages {
let msg = self.peer_channels.get_mut(k).unwrap().ratchet_decrypt(m).unwrap();
if msg != b"init" {
let channel = self.peer_channels.get_mut(k);
if channel.is_none() {
return Err(TripleRatchetError::InvalidData("Invalid peer channel".into()))
}
let msg = channel.unwrap().ratchet_decrypt(m);
if msg.is_err() {
return Err(TripleRatchetError::CryptoError(msg.err().unwrap().to_string()))
}
if msg.unwrap() != b"init" {
return Err(TripleRatchetError::InvalidData("Invalid init message".into()));
}
}
self.dkg_ratchet.sample_polynomial(&mut OsRng);
let maybeerr = self.dkg_ratchet.sample_polynomial(&mut OsRng);
if maybeerr.is_err() {
return Err(TripleRatchetError::InvalidData(maybeerr.err().unwrap().to_string().into()))
}
let result = self.dkg_ratchet.get_poly_frags().unwrap();
@ -435,11 +445,18 @@ impl TripleRatchetParticipant {
pub fn receive_poly_frag(&mut self, peer_id: &[u8], frag: &P2PChannelEnvelope)
-> Result<Option<HashMap<Vec<u8>, P2PChannelEnvelope>>, TripleRatchetError> {
let b = self.peer_channels.get_mut(peer_id).unwrap().ratchet_decrypt(frag).unwrap();
let channel = self.peer_channels.get_mut(peer_id);
if channel.is_none() {
return Err(TripleRatchetError::InvalidData("Invalid peer channel".into()))
}
let b = channel.unwrap().ratchet_decrypt(frag);
if b.is_err() {
return Err(TripleRatchetError::CryptoError(b.err().unwrap().to_string()))
}
let result = self.dkg_ratchet.set_poly_frag_for_party(
*self.peer_id_map.get(peer_id).unwrap(),
&b,
&b.unwrap(),
).unwrap();
if result.is_some() {
@ -457,11 +474,18 @@ impl TripleRatchetParticipant {
pub fn receive_commitment(&mut self, peer_id: &[u8], zkcommit: &P2PChannelEnvelope)
-> Result<Option<HashMap<Vec<u8>, P2PChannelEnvelope>>, TripleRatchetError> {
let b = self.peer_channels.get_mut(peer_id).unwrap().ratchet_decrypt(zkcommit).unwrap();
let channel = self.peer_channels.get_mut(peer_id);
if channel.is_none() {
return Err(TripleRatchetError::InvalidData("Invalid peer channel".into()))
}
let b = channel.unwrap().ratchet_decrypt(zkcommit);
if b.is_err() {
return Err(TripleRatchetError::CryptoError(b.err().unwrap().to_string()))
}
let result = self.dkg_ratchet.receive_commitments(
*self.peer_id_map.get(peer_id).unwrap(),
&b,
&b.unwrap(),
).unwrap();
if let Some(reveal) = result {
@ -478,9 +502,16 @@ impl TripleRatchetParticipant {
}
pub fn recombine(&mut self, peer_id: &[u8], reveal: &P2PChannelEnvelope) -> Result<(), Box<dyn std::error::Error>> {
let b = self.peer_channels.get_mut(peer_id).unwrap().ratchet_decrypt(reveal).unwrap();
let channel = self.peer_channels.get_mut(peer_id);
if channel.is_none() {
return Err("Invalid peer channel".into())
}
let b = channel.unwrap().ratchet_decrypt(reveal);
if b.is_err() {
return Err(Box::new(TripleRatchetError::CryptoError(b.err().unwrap().to_string())))
}
let rev: FeldmanReveal = serde_json::from_slice(&b).unwrap();
let rev: FeldmanReveal = serde_json::from_slice(&b.unwrap()).unwrap();
let done = self.dkg_ratchet.recombine(
*self.peer_id_map.get(peer_id).unwrap(),

View File

@ -192,6 +192,13 @@
"regex": "AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABAA(.*)",
"renamePattern": "Data Peer Announcements$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments$1"
}
}
],
"type": "timeseries"
@ -323,6 +330,13 @@
"regex": "AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABAA(.*)",
"renamePattern": "Data Peer Announcements$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments$1"
}
}
],
"type": "timeseries"
@ -454,6 +468,13 @@
"regex": "AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABAA(.*)",
"renamePattern": "Data Peer Announcements$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments$1"
}
}
],
"type": "timeseries"
@ -585,6 +606,13 @@
"regex": "AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABAA(.*)",
"renamePattern": "Data Peer Announcements$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments$1"
}
}
],
"type": "timeseries"
@ -894,6 +922,27 @@
"renamePattern": "Data Peer Announcements Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 1$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 2$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
@ -1196,6 +1245,27 @@
"renamePattern": "Data Peer Announcements Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 1$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 2$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
@ -1497,6 +1567,27 @@
"renamePattern": "Data Peer Announcements Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 1$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 2$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
@ -1507,6 +1598,264 @@
],
"type": "timeseries"
},
{
"datasource": {
"default": false,
"type": "prometheus",
"uid": "${datasource}"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "pps"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 47
},
"id": 23,
"options": {
"legend": {
"calcs": [
"lastNotNull",
"min",
"max",
"mean"
],
"displayMode": "table",
"placement": "bottom",
"showLegend": true,
"sortBy": "Name",
"sortDesc": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(rate(blossomsub_iwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"drop\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Dropped",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(rate(blossomsub_iwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"recv\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Received",
"range": true,
"refId": "B"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(rate(blossomsub_iwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"send\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Sent",
"range": true,
"refId": "C"
}
],
"title": "IWANT message rates",
"type": "timeseries"
},
{
"datasource": {
"default": false,
"type": "prometheus",
"uid": "${datasource}"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "pps"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 47
},
"id": 24,
"options": {
"legend": {
"calcs": [
"lastNotNull",
"min",
"max",
"mean"
],
"displayMode": "table",
"placement": "bottom",
"showLegend": true,
"sortBy": "Name",
"sortDesc": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(rate(blossomsub_ihave_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"drop\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Dropped",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(rate(blossomsub_ihave_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"recv\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Received",
"range": true,
"refId": "B"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(rate(blossomsub_ihave_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"send\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Sent",
"range": true,
"refId": "C"
}
],
"title": "IHAVE message rates",
"type": "timeseries"
},
{
"datasource": {
"default": false,
@ -1570,7 +1919,7 @@
"h": 9,
"w": 12,
"x": 0,
"y": 47
"y": 56
},
"id": 19,
"options": {
@ -1698,7 +2047,7 @@
"h": 9,
"w": 12,
"x": 12,
"y": 47
"y": 56
},
"id": 20,
"options": {
@ -1825,7 +2174,7 @@
"h": 9,
"w": 12,
"x": 0,
"y": 56
"y": 65
},
"id": 21,
"options": {
@ -1953,7 +2302,7 @@
"h": 9,
"w": 12,
"x": 12,
"y": 56
"y": 65
},
"id": 22,
"options": {
@ -1982,7 +2331,7 @@
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "rate(blossomsub_idontwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"drop\"}[$__rate_interval])",
"expr": "sum(rate(blossomsub_idontwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"drop\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Dropped",
@ -1995,7 +2344,7 @@
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "rate(blossomsub_idontwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"recv\"}[$__rate_interval])",
"expr": "sum(rate(blossomsub_idontwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"recv\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Received",
@ -2008,7 +2357,7 @@
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "rate(blossomsub_idontwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"send\"}[$__rate_interval])",
"expr": "sum(rate(blossomsub_idontwant_messages_count{job=~\"$job\", instance=~\"$host\", direction=\"send\"}[$__rate_interval]))",
"hide": false,
"instant": false,
"legendFormat": "Sent",
@ -2025,7 +2374,7 @@
"h": 1,
"w": 24,
"x": 0,
"y": 65
"y": 74
},
"id": 8,
"panels": [],
@ -2093,7 +2442,7 @@
"h": 9,
"w": 24,
"x": 0,
"y": 66
"y": 75
},
"id": 11,
"options": {
@ -2194,6 +2543,27 @@
"renamePattern": "Data Peer Announcements Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 1$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 2$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
@ -2266,7 +2636,7 @@
"h": 9,
"w": 12,
"x": 0,
"y": 75
"y": 84
},
"id": 9,
"options": {
@ -2367,6 +2737,27 @@
"renamePattern": "Data Peer Announcements Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 1$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 2$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
@ -2439,7 +2830,7 @@
"h": 9,
"w": 12,
"x": 12,
"y": 75
"y": 84
},
"id": 10,
"options": {
@ -2540,6 +2931,27 @@
"renamePattern": "Data Peer Announcements Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 1$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA(.*)",
"renamePattern": "Data Frame Fragments Shard 2$1"
}
},
{
"id": "renameByRegex",
"options": {
"regex": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA(.*)",
"renamePattern": "Data Frame Fragments Shard 3$1"
}
},
{
"id": "renameByRegex",
"options": {
@ -2556,7 +2968,7 @@
"h": 1,
"w": 24,
"x": 0,
"y": 84
"y": 93
},
"id": 6,
"panels": [],
@ -2612,8 +3024,7 @@
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
"color": "green"
}
]
},
@ -2625,7 +3036,7 @@
"h": 9,
"w": 24,
"x": 0,
"y": 85
"y": 94
},
"id": 7,
"options": {
@ -2768,6 +3179,6 @@
"timezone": "browser",
"title": "BlossomSub",
"uid": "ee47pcfax962ob",
"version": 45,
"version": 55,
"weekStart": ""
}

View File

@ -1,18 +0,0 @@
name: Go Checks
on:
pull_request:
push:
branches: ["master"]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
go-check:
uses: ipdxco/unified-github-workflows/.github/workflows/go-check.yml@v1.0

View File

@ -1,20 +0,0 @@
name: Go Test
on:
pull_request:
push:
branches: ["master"]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
go-test:
uses: ipdxco/unified-github-workflows/.github/workflows/go-test.yml@v1.0
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@ -1,19 +0,0 @@
name: Release Checker
on:
pull_request_target:
paths: [ 'version.json' ]
types: [ opened, synchronize, reopened, labeled, unlabeled ]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
release-check:
uses: ipdxco/unified-github-workflows/.github/workflows/release-check.yml@v1.0

View File

@ -1,17 +0,0 @@
name: Releaser
on:
push:
paths: [ 'version.json' ]
workflow_dispatch:
permissions:
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.sha }}
cancel-in-progress: true
jobs:
releaser:
uses: ipdxco/unified-github-workflows/.github/workflows/releaser.yml@v1.0

View File

@ -1,13 +0,0 @@
name: Close and mark stale issue
on:
schedule:
- cron: '0 0 * * *'
permissions:
issues: write
pull-requests: write
jobs:
stale:
uses: pl-strflt/.github/.github/workflows/reusable-stale-issue.yml@v0.3

View File

@ -1,18 +0,0 @@
name: Tag Push Checker
on:
push:
tags:
- v*
permissions:
contents: read
issues: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
releaser:
uses: ipdxco/unified-github-workflows/.github/workflows/tagpush.yml@v1.0

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Juan Batiz-Benet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,29 +0,0 @@
### Applies to buffer.go and buffer_test.go ###
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,56 +0,0 @@
go-buffer-pool
==================
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai)
[![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](https://libp2p.io/)
[![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23libp2p)
[![codecov](https://codecov.io/gh/libp2p/go-buffer-pool/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-buffer-pool)
[![Travis CI](https://travis-ci.org/libp2p/go-buffer-pool.svg?branch=master)](https://travis-ci.org/libp2p/go-buffer-pool)
[![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io)
> A variable size buffer pool for go.
## Table of Contents
- [About](#about)
- [Advantages over GC](#advantages-over-gc)
- [Disadvantages over GC:](#disadvantages-over-gc)
- [Contribute](#contribute)
- [License](#license)
## About
This library provides:
1. `BufferPool`: A pool for re-using byte slices of varied sizes. This pool will always return a slice with at least the size requested and a capacity up to the next power of two. Each size class is pooled independently which makes the `BufferPool` more space efficient than a plain `sync.Pool` when used in situations where data size may vary over an arbitrary range.
2. `Buffer`: a buffer compatible with `bytes.Buffer` but backed by a `BufferPool`. Unlike `bytes.Buffer`, `Buffer` will automatically "shrink" on read, using the buffer pool to avoid causing too much work for the allocator. This is primarily useful for long lived buffers that usually sit empty.
### Advantages over GC
* Reduces Memory Usage:
* We don't have to wait for a GC to run before we can reuse memory. This is essential if you're repeatedly allocating large short-lived buffers.
* Reduces CPU usage:
* It takes some load off of the GC (due to buffer reuse).
* We don't have to zero buffers (fewer wasteful memory writes).
### Disadvantages over GC:
* Can leak memory contents. Unlike the go GC, we *don't* zero memory.
* All buffers have a capacity of a power of 2. This is fine if you either expect these buffers to be temporary or you need buffers of this size.
* Requires that buffers be explicitly put back into the pool. This can lead to race conditions and memory corruption if the buffer is released while it's still in use.
## Contribute
PRs are welcome!
Small note: If editing the Readme, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
## License
MIT © Protocol Labs
BSD © The Go Authors
---
The last gx published version of this module was: 0.1.3: QmQDvJoB6aJWN3sjr3xsgXqKCXf4jU5zdMXpDMsBkYVNqa

View File

@ -1,302 +0,0 @@
// This is a derivitive work of Go's bytes.Buffer implementation.
//
// Originally copyright 2009 The Go Authors. All rights reserved.
//
// Modifications copyright 2018 Steven Allen. All rights reserved.
//
// Use of this source code is governed by both a BSD-style and an MIT-style
// license that can be found in the LICENSE_BSD and LICENSE files.
package pool
import (
"io"
)
// Buffer is a buffer like bytes.Buffer that:
//
// 1. Uses a buffer pool.
// 2. Frees memory on read.
//
// If you only have a few buffers and read/write at a steady rate, *don't* use
// this package, it'll be slower.
//
// However:
//
// 1. If you frequently create/destroy buffers, this implementation will be
// significantly nicer to the allocator.
// 2. If you have many buffers with bursty traffic, this implementation will use
// significantly less memory.
type Buffer struct {
// Pool is the buffer pool to use. If nil, this Buffer will use the
// global buffer pool.
Pool *BufferPool
buf []byte
rOff int
// Preallocated slice for samll reads/writes.
// This is *really* important for performance and only costs 8 words.
bootstrap [64]byte
}
// NewBuffer constructs a new buffer initialized to `buf`.
// Unlike `bytes.Buffer`, we *copy* the buffer but don't reuse it (to ensure
// that we *only* use buffers from the pool).
func NewBuffer(buf []byte) *Buffer {
b := new(Buffer)
if len(buf) > 0 {
b.buf = b.getBuf(len(buf))
copy(b.buf, buf)
}
return b
}
// NewBufferString is identical to NewBuffer *except* that it allows one to
// initialize the buffer from a string (without having to allocate an
// intermediate bytes slice).
func NewBufferString(buf string) *Buffer {
b := new(Buffer)
if len(buf) > 0 {
b.buf = b.getBuf(len(buf))
copy(b.buf, buf)
}
return b
}
func (b *Buffer) grow(n int) int {
wOff := len(b.buf)
bCap := cap(b.buf)
if bCap >= wOff+n {
b.buf = b.buf[:wOff+n]
return wOff
}
bSize := b.Len()
minCap := 2*bSize + n
// Slide if cap >= minCap.
// Reallocate otherwise.
if bCap >= minCap {
copy(b.buf, b.buf[b.rOff:])
} else {
// Needs new buffer.
newBuf := b.getBuf(minCap)
copy(newBuf, b.buf[b.rOff:])
b.returnBuf()
b.buf = newBuf
}
b.rOff = 0
b.buf = b.buf[:bSize+n]
return bSize
}
func (b *Buffer) getPool() *BufferPool {
if b.Pool == nil {
return GlobalPool
}
return b.Pool
}
func (b *Buffer) returnBuf() {
if cap(b.buf) > len(b.bootstrap) {
b.getPool().Put(b.buf)
}
b.buf = nil
}
func (b *Buffer) getBuf(n int) []byte {
if n <= len(b.bootstrap) {
return b.bootstrap[:n]
}
return b.getPool().Get(n)
}
// Len returns the number of bytes that can be read from this buffer.
func (b *Buffer) Len() int {
return len(b.buf) - b.rOff
}
// Cap returns the current capacity of the buffer.
//
// Note: Buffer *may* re-allocate when writing (or growing by) `n` bytes even if
// `Cap() < Len() + n` to avoid excessive copying.
func (b *Buffer) Cap() int {
return cap(b.buf)
}
// Bytes returns the slice of bytes currently buffered in the Buffer.
//
// The buffer returned by Bytes is valid until the next call grow, truncate,
// read, or write. Really, just don't touch the Buffer until you're done with
// the return value of this function.
func (b *Buffer) Bytes() []byte {
return b.buf[b.rOff:]
}
// String returns the string representation of the buffer.
//
// It returns `<nil>` the buffer is a nil pointer.
func (b *Buffer) String() string {
if b == nil {
return "<nil>"
}
return string(b.buf[b.rOff:])
}
// WriteString writes a string to the buffer.
//
// This function is identical to Write except that it allows one to write a
// string directly without allocating an intermediate byte slice.
func (b *Buffer) WriteString(buf string) (int, error) {
wOff := b.grow(len(buf))
return copy(b.buf[wOff:], buf), nil
}
// Truncate truncates the Buffer.
//
// Panics if `n > b.Len()`.
//
// This function may free memory by shrinking the internal buffer.
func (b *Buffer) Truncate(n int) {
if n < 0 || n > b.Len() {
panic("truncation out of range")
}
b.buf = b.buf[:b.rOff+n]
b.shrink()
}
// Reset is equivalent to Truncate(0).
func (b *Buffer) Reset() {
b.returnBuf()
b.rOff = 0
}
// ReadByte reads a single byte from the Buffer.
func (b *Buffer) ReadByte() (byte, error) {
if b.rOff >= len(b.buf) {
return 0, io.EOF
}
c := b.buf[b.rOff]
b.rOff++
return c, nil
}
// WriteByte writes a single byte to the Buffer.
func (b *Buffer) WriteByte(c byte) error {
wOff := b.grow(1)
b.buf[wOff] = c
return nil
}
// Grow grows the internal buffer such that `n` bytes can be written without
// reallocating.
func (b *Buffer) Grow(n int) {
wOff := b.grow(n)
b.buf = b.buf[:wOff]
}
// Next is an alternative to `Read` that returns a byte slice instead of taking
// one.
//
// The returned byte slice is valid until the next read, write, grow, or
// truncate.
func (b *Buffer) Next(n int) []byte {
m := b.Len()
if m < n {
n = m
}
data := b.buf[b.rOff : b.rOff+n]
b.rOff += n
return data
}
// Write writes the byte slice to the buffer.
func (b *Buffer) Write(buf []byte) (int, error) {
wOff := b.grow(len(buf))
return copy(b.buf[wOff:], buf), nil
}
// WriteTo copies from the buffer into the given writer until the buffer is
// empty.
func (b *Buffer) WriteTo(w io.Writer) (int64, error) {
if b.rOff < len(b.buf) {
n, err := w.Write(b.buf[b.rOff:])
b.rOff += n
if b.rOff > len(b.buf) {
panic("invalid write count")
}
b.shrink()
return int64(n), err
}
return 0, nil
}
// MinRead is the minimum slice size passed to a Read call by
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
// what is required to hold the contents of r, ReadFrom will not grow the
// underlying buffer.
const MinRead = 512
// ReadFrom reads from the given reader into the buffer.
func (b *Buffer) ReadFrom(r io.Reader) (int64, error) {
n := int64(0)
for {
wOff := b.grow(MinRead)
// Use *entire* buffer.
b.buf = b.buf[:cap(b.buf)]
read, err := r.Read(b.buf[wOff:])
b.buf = b.buf[:wOff+read]
n += int64(read)
switch err {
case nil:
case io.EOF:
err = nil
fallthrough
default:
b.shrink()
return n, err
}
}
}
// Read reads at most `len(buf)` bytes from the internal buffer into the given
// buffer.
func (b *Buffer) Read(buf []byte) (int, error) {
if len(buf) == 0 {
return 0, nil
}
if b.rOff >= len(b.buf) {
return 0, io.EOF
}
n := copy(buf, b.buf[b.rOff:])
b.rOff += n
b.shrink()
return n, nil
}
func (b *Buffer) shrink() {
c := b.Cap()
// Either nil or bootstrap.
if c <= len(b.bootstrap) {
return
}
l := b.Len()
if l == 0 {
// Shortcut if empty.
b.returnBuf()
b.rOff = 0
} else if l*8 < c {
// Only shrink when capacity > 8x length. Avoids shrinking too aggressively.
newBuf := b.getBuf(l)
copy(newBuf, b.buf[b.rOff:])
b.returnBuf()
b.rOff = 0
b.buf = newBuf[:l]
}
}

View File

@ -1,400 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Modified by stebalien, 2018
package pool
import (
"bytes"
"math/rand"
"runtime"
"testing"
)
const N = 10000 // make this bigger for a larger (and slower) test
var data string // test data for write tests
var testBytes []byte // test data; same as data but as a slice.
func init() {
testBytes = make([]byte, N)
for i := 0; i < N; i++ {
testBytes[i] = 'a' + byte(i%26)
}
data = string(testBytes)
}
// Verify that contents of buf match the string s.
func check(t *testing.T, testname string, buf *Buffer, s string) {
bytes := buf.Bytes()
str := buf.String()
if buf.Len() != len(bytes) {
t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes))
}
if buf.Len() != len(str) {
t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str))
}
if buf.Len() != len(s) {
t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s))
}
if string(bytes) != s {
t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s)
}
}
// Fill buf through n writes of string fus.
// The initial contents of buf corresponds to the string s;
// the result is the final contents of buf returned as a string.
func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus string) string {
check(t, testname+" (fill 1)", buf, s)
for ; n > 0; n-- {
m, err := buf.WriteString(fus)
if m != len(fus) {
t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fus))
}
if err != nil {
t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err)
}
s += fus
check(t, testname+" (fill 4)", buf, s)
}
return s
}
// Fill buf through n writes of byte slice fub.
// The initial contents of buf corresponds to the string s;
// the result is the final contents of buf returned as a string.
func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string {
check(t, testname+" (fill 1)", buf, s)
for ; n > 0; n-- {
m, err := buf.Write(fub)
if m != len(fub) {
t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub))
}
if err != nil {
t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err)
}
s += string(fub)
check(t, testname+" (fill 4)", buf, s)
}
return s
}
func TestNewBuffer(t *testing.T) {
buf := NewBuffer(testBytes)
check(t, "NewBuffer", buf, data)
}
func TestNewBufferString(t *testing.T) {
buf := NewBufferString(data)
check(t, "NewBufferString", buf, data)
}
// Empty buf through repeated reads into fub.
// The initial contents of buf corresponds to the string s.
func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) {
check(t, testname+" (empty 1)", buf, s)
for {
n, err := buf.Read(fub)
if n == 0 {
break
}
if err != nil {
t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err)
}
s = s[n:]
check(t, testname+" (empty 3)", buf, s)
}
check(t, testname+" (empty 4)", buf, "")
}
func TestBasicOperations(t *testing.T) {
var buf Buffer
for i := 0; i < 5; i++ {
check(t, "TestBasicOperations (1)", &buf, "")
buf.Reset()
check(t, "TestBasicOperations (2)", &buf, "")
buf.Truncate(0)
check(t, "TestBasicOperations (3)", &buf, "")
n, err := buf.Write([]byte(data[0:1]))
if n != 1 {
t.Errorf("wrote 1 byte, but n == %d", n)
}
if err != nil {
t.Errorf("err should always be nil, but err == %s", err)
}
check(t, "TestBasicOperations (4)", &buf, "a")
buf.WriteByte(data[1])
check(t, "TestBasicOperations (5)", &buf, "ab")
n, err = buf.Write([]byte(data[2:26]))
if err != nil {
t.Fatal(err)
}
if n != 24 {
t.Errorf("wrote 25 bytes, but n == %d", n)
}
check(t, "TestBasicOperations (6)", &buf, string(data[0:26]))
buf.Truncate(26)
check(t, "TestBasicOperations (7)", &buf, string(data[0:26]))
buf.Truncate(20)
check(t, "TestBasicOperations (8)", &buf, string(data[0:20]))
empty(t, "TestBasicOperations (9)", &buf, string(data[0:20]), make([]byte, 5))
empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100))
buf.WriteByte(data[1])
c, err := buf.ReadByte()
if err != nil {
t.Error("ReadByte unexpected eof")
}
if c != data[1] {
t.Errorf("ReadByte wrong value c=%v", c)
}
if _, err = buf.ReadByte(); err == nil {
t.Error("ReadByte unexpected not eof")
}
}
}
func TestLargeStringWrites(t *testing.T) {
var buf Buffer
limit := 30
if testing.Short() {
limit = 9
}
for i := 3; i < limit; i += 3 {
s := fillString(t, "TestLargeWrites (1)", &buf, "", 5, data)
empty(t, "TestLargeStringWrites (2)", &buf, s, make([]byte, len(data)/i))
}
check(t, "TestLargeStringWrites (3)", &buf, "")
}
func TestLargeByteWrites(t *testing.T) {
var buf Buffer
limit := 30
if testing.Short() {
limit = 9
}
for i := 3; i < limit; i += 3 {
s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes)
empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i))
}
check(t, "TestLargeByteWrites (3)", &buf, "")
}
func TestLargeStringReads(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillString(t, "TestLargeReads (1)", &buf, "", 5, data[0:len(data)/i])
empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data)))
}
check(t, "TestLargeStringReads (3)", &buf, "")
}
func TestLargeByteReads(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data)))
}
check(t, "TestLargeByteReads (3)", &buf, "")
}
func TestMixedReadsAndWrites(t *testing.T) {
var buf Buffer
s := ""
for i := 0; i < 50; i++ {
wlen := rand.Intn(len(data))
if i%2 == 0 {
s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen])
} else {
s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen])
}
rlen := rand.Intn(len(data))
fub := make([]byte, rlen)
n, _ := buf.Read(fub)
s = s[n:]
}
empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len()))
}
func TestNil(t *testing.T) {
var b *Buffer
if b.String() != "<nil>" {
t.Errorf("expected <nil>; got %q", b.String())
}
}
func TestReadFrom(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
var b Buffer
b.ReadFrom(&buf)
empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data)))
}
}
func TestWriteTo(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
var b Buffer
buf.WriteTo(&b)
empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(data)))
}
}
func TestNext(t *testing.T) {
b := []byte{0, 1, 2, 3, 4}
tmp := make([]byte, 5)
for i := 0; i <= 5; i++ {
for j := i; j <= 5; j++ {
for k := 0; k <= 6; k++ {
// 0 <= i <= j <= 5; 0 <= k <= 6
// Check that if we start with a buffer
// of length j at offset i and ask for
// Next(k), we get the right bytes.
buf := NewBuffer(b[0:j])
n, _ := buf.Read(tmp[0:i])
if n != i {
t.Fatalf("Read %d returned %d", i, n)
}
bb := buf.Next(k)
want := k
if want > j-i {
want = j - i
}
if len(bb) != want {
t.Fatalf("in %d,%d: len(Next(%d)) == %d", i, j, k, len(bb))
}
for l, v := range bb {
if v != byte(l+i) {
t.Fatalf("in %d,%d: Next(%d)[%d] = %d, want %d", i, j, k, l, v, l+i)
}
}
}
}
}
}
func TestGrow(t *testing.T) {
x := []byte{'x'}
y := []byte{'y'}
tmp := make([]byte, 72)
for _, startLen := range []int{0, 100, 1000, 10000, 100000} {
xBytes := bytes.Repeat(x, startLen)
for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
buf := NewBuffer(xBytes)
// If we read, this affects buf.off, which is good to test.
readBytes, _ := buf.Read(tmp)
buf.Grow(growLen)
yBytes := bytes.Repeat(y, growLen)
// Check no allocation occurs in write, as long as we're single-threaded.
var m1, m2 runtime.MemStats
runtime.ReadMemStats(&m1)
buf.Write(yBytes)
runtime.ReadMemStats(&m2)
if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs {
t.Errorf("allocation occurred during write")
}
// Check that buffer has correct data.
if !bytes.Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) {
t.Errorf("bad initial data at %d %d", startLen, growLen)
}
if !bytes.Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) {
t.Errorf("bad written data at %d %d", startLen, growLen)
}
}
}
}
// Was a bug: used to give EOF reading empty slice at EOF.
func TestReadEmptyAtEOF(t *testing.T) {
b := new(Buffer)
slice := make([]byte, 0)
n, err := b.Read(slice)
if err != nil {
t.Errorf("read error: %v", err)
}
if n != 0 {
t.Errorf("wrong count; got %d want 0", n)
}
}
// Tests that we occasionally compact. Issue 5154.
func TestBufferGrowth(t *testing.T) {
var b Buffer
buf := make([]byte, 1024)
b.Write(buf[0:1])
var cap0 int
for i := 0; i < 5<<10; i++ {
b.Write(buf)
b.Read(buf)
if i == 0 {
cap0 = b.Cap()
}
}
cap1 := b.Cap()
// (*Buffer).grow allows for 2x capacity slop before sliding,
// so set our error threshold at 3x.
if cap1 > cap0*3 {
t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0)
}
}
func BenchmarkWriteByte(b *testing.B) {
const n = 4 << 10
b.SetBytes(n)
buf := NewBuffer(make([]byte, n))
for i := 0; i < b.N; i++ {
buf.Reset()
for i := 0; i < n; i++ {
buf.WriteByte('x')
}
}
}
// From Issue 5154.
func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
buf := make([]byte, 1024)
for i := 0; i < b.N; i++ {
var b Buffer
b.Write(buf[0:1])
for i := 0; i < 5<<10; i++ {
b.Write(buf)
b.Read(buf)
}
}
}
// Check that we don't compact too often. From Issue 5154.
func BenchmarkBufferFullSmallReads(b *testing.B) {
buf := make([]byte, 1024)
for i := 0; i < b.N; i++ {
var b Buffer
b.Write(buf)
for b.Len()+20 < b.Cap() {
b.Write(buf[:10])
}
for i := 0; i < 5<<10; i++ {
b.Read(buf[:1])
b.Write(buf[:1])
}
}
}

View File

@ -1,3 +0,0 @@
coverage:
range: "50...100"
comment: off

View File

@ -1,3 +0,0 @@
module github.com/libp2p/go-buffer-pool
go 1.22

View File

@ -1,103 +0,0 @@
// Package pool provides a sync.Pool equivalent that buckets incoming
// requests to one of 32 sub-pools, one for each power of 2, 0-32.
//
// import (pool "github.com/libp2p/go-buffer-pool")
// var p pool.BufferPool
//
// small := make([]byte, 1024)
// large := make([]byte, 4194304)
// p.Put(small)
// p.Put(large)
//
// small2 := p.Get(1024)
// large2 := p.Get(4194304)
// fmt.Println("small2 len:", len(small2))
// fmt.Println("large2 len:", len(large2))
//
// // Output:
// // small2 len: 1024
// // large2 len: 4194304
package pool
import (
"math"
"math/bits"
"sync"
)
// GlobalPool is a static Pool for reusing byteslices of various sizes.
var GlobalPool = new(BufferPool)
// MaxLength is the maximum length of an element that can be added to the Pool.
const MaxLength = math.MaxInt32
// BufferPool is a pool to handle cases of reusing elements of varying sizes. It
// maintains 32 internal pools, for each power of 2 in 0-32.
//
// You should generally just call the package level Get and Put methods or use
// the GlobalPool BufferPool instead of constructing your own.
//
// You MUST NOT copy Pool after using.
type BufferPool struct {
pools [32]sync.Pool // a list of singlePools
}
// Get retrieves a buffer of the appropriate length from the buffer pool or
// allocates a new one. Get may choose to ignore the pool and treat it as empty.
// Callers should not assume any relation between values passed to Put and the
// values returned by Get.
//
// If no suitable buffer exists in the pool, Get creates one.
func (p *BufferPool) Get(length int) []byte {
if length == 0 {
return nil
}
// Calling this function with a negative length is invalid.
// make will panic if length is negative, so we don't have to.
if length > MaxLength || length < 0 {
return make([]byte, length)
}
idx := nextLogBase2(uint32(length))
if ptr := p.pools[idx].Get(); ptr != nil {
buf := ptr.([]byte)
buf = buf[:uint32(length)]
return buf
}
return make([]byte, 1<<idx)[:uint32(length)]
}
// Put adds x to the pool.
func (p *BufferPool) Put(buf []byte) {
capacity := cap(buf)
if capacity == 0 || capacity > MaxLength {
return // drop it
}
idx := prevLogBase2(uint32(capacity))
// nolint: staticcheck
p.pools[idx].Put(buf)
}
// Get retrieves a buffer of the appropriate length from the global buffer pool
// (or allocates a new one).
func Get(length int) []byte {
return GlobalPool.Get(length)
}
// Put returns a buffer to the global buffer pool.
func Put(slice []byte) {
GlobalPool.Put(slice)
}
// Log of base two, round up (for v > 0).
func nextLogBase2(v uint32) uint32 {
return uint32(bits.Len32(v - 1))
}
// Log of base two, round down (for v > 0)
func prevLogBase2(num uint32) uint32 {
next := nextLogBase2(num)
if num == (1 << uint32(next)) {
return next
}
return next - 1
}

View File

@ -1,185 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Pool is no-op under race detector, so all these tests do not work.
//go:build !race
package pool
import (
"bytes"
"fmt"
"math/rand"
"runtime"
"runtime/debug"
"testing"
)
func TestRange(t *testing.T) {
min := nextLogBase2(1)
max := nextLogBase2(uint32(MaxLength))
if int(max) != len(GlobalPool.pools)-1 {
t.Errorf("expected %d pools, found %d", max, len(GlobalPool.pools))
}
if min != 0 {
t.Errorf("unused min pool")
}
}
func TestPool(t *testing.T) {
// disable GC so we can control when it happens.
defer debug.SetGCPercent(debug.SetGCPercent(-1))
var p BufferPool
a := make([]byte, 21)
a[0] = 1
b := make([]byte, 2050)
b[0] = 2
p.Put(a)
p.Put(b)
if g := p.Get(16); &g[0] != &a[0] {
t.Fatalf("got [%d,...]; want [1,...]", g[0])
}
if g := p.Get(2048); &g[0] != &b[0] {
t.Fatalf("got [%d,...]; want [2,...]", g[0])
}
if g := p.Get(16); cap(g) != 16 || !bytes.Equal(g[:16], make([]byte, 16)) {
t.Fatalf("got existing slice; want new slice")
}
if g := p.Get(2048); cap(g) != 2048 || !bytes.Equal(g[:2048], make([]byte, 2048)) {
t.Fatalf("got existing slice; want new slice")
}
if g := p.Get(1); cap(g) != 1 || !bytes.Equal(g[:1], make([]byte, 1)) {
t.Fatalf("got existing slice; want new slice")
}
d := make([]byte, 1023)
d[0] = 3
p.Put(d)
if g := p.Get(1024); cap(g) != 1024 || !bytes.Equal(g, make([]byte, 1024)) {
t.Fatalf("got existing slice; want new slice")
}
if g := p.Get(512); cap(g) != 1023 || g[0] != 3 {
t.Fatalf("got [%d,...]; want [3,...]", g[0])
}
p.Put(a)
debug.SetGCPercent(100) // to allow following GC to actually run
runtime.GC()
// For some reason, you need to run GC twice on go 1.16 if you want it to reliably work.
runtime.GC()
if g := p.Get(10); &g[0] == &a[0] {
t.Fatalf("got a; want new slice after GC")
}
}
func TestPoolStressByteSlicePool(t *testing.T) {
var p BufferPool
const P = 10
chs := 10
maxSize := 1 << 16
N := int(1e4)
if testing.Short() {
N /= 100
}
done := make(chan bool)
errs := make(chan error)
for i := 0; i < P; i++ {
go func() {
ch := make(chan []byte, chs+1)
for i := 0; i < chs; i++ {
j := rand.Int() % maxSize
ch <- p.Get(j)
}
for j := 0; j < N; j++ {
r := 0
for i := 0; i < chs; i++ {
v := <-ch
p.Put(v)
r = rand.Int() % maxSize
v = p.Get(r)
if len(v) < r {
errs <- fmt.Errorf("expect len(v) >= %d, got %d", j, len(v))
}
ch <- v
}
if r%1000 == 0 {
runtime.GC()
}
}
done <- true
}()
}
for i := 0; i < P; {
select {
case <-done:
i++
case err := <-errs:
t.Error(err)
}
}
}
func BenchmarkPool(b *testing.B) {
var p BufferPool
b.RunParallel(func(pb *testing.PB) {
i := 7
for pb.Next() {
if i > 1<<20 {
i = 7
} else {
i = i << 1
}
b := p.Get(i)
b[0] = byte(i)
p.Put(b)
}
})
}
func BenchmarkAlloc(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
i := 7
for pb.Next() {
if i > 1<<20 {
i = 7
} else {
i = i << 1
}
b := make([]byte, i)
b[1] = byte(i)
}
})
}
func BenchmarkPoolOverlflow(b *testing.B) {
var p BufferPool
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
bufs := make([][]byte, 2100)
for pow := uint32(0); pow < 21; pow++ {
for i := 0; i < 100; i++ {
bufs = append(bufs, p.Get(1<<pow))
}
}
for _, b := range bufs {
p.Put(b)
}
}
})
}
func ExampleGet() {
buf := Get(100)
fmt.Println("length", len(buf))
fmt.Println("capacity", cap(buf))
Put(buf)
// Output:
// length 100
// capacity 128
}

View File

@ -1,3 +0,0 @@
{
"version": "v0.1.0"
}

View File

@ -1,119 +0,0 @@
package pool
import (
"bufio"
"io"
"sync"
)
const WriterBufferSize = 4096
var bufioWriterPool = sync.Pool{
New: func() interface{} {
return bufio.NewWriterSize(nil, WriterBufferSize)
},
}
// Writer is a buffered writer that returns its internal buffer in a pool when
// not in use.
type Writer struct {
W io.Writer
bufw *bufio.Writer
}
func (w *Writer) ensureBuffer() {
if w.bufw == nil {
w.bufw = bufioWriterPool.Get().(*bufio.Writer)
w.bufw.Reset(w.W)
}
}
// Write writes the given byte slice to the underlying connection.
//
// Note: Write won't return the write buffer to the pool even if it ends up
// being empty after the write. You must call Flush() to do that.
func (w *Writer) Write(b []byte) (int, error) {
if w.bufw == nil {
if len(b) >= WriterBufferSize {
return w.W.Write(b)
}
w.bufw = bufioWriterPool.Get().(*bufio.Writer)
w.bufw.Reset(w.W)
}
return w.bufw.Write(b)
}
// Size returns the size of the underlying buffer.
func (w *Writer) Size() int {
return WriterBufferSize
}
// Available returns the amount buffer space available.
func (w *Writer) Available() int {
if w.bufw != nil {
return w.bufw.Available()
}
return WriterBufferSize
}
// Buffered returns the amount of data buffered.
func (w *Writer) Buffered() int {
if w.bufw != nil {
return w.bufw.Buffered()
}
return 0
}
// WriteByte writes a single byte.
func (w *Writer) WriteByte(b byte) error {
w.ensureBuffer()
return w.bufw.WriteByte(b)
}
// WriteRune writes a single rune, returning the number of bytes written.
func (w *Writer) WriteRune(r rune) (int, error) {
w.ensureBuffer()
return w.bufw.WriteRune(r)
}
// WriteString writes a string, returning the number of bytes written.
func (w *Writer) WriteString(s string) (int, error) {
w.ensureBuffer()
return w.bufw.WriteString(s)
}
// Flush flushes the write buffer, if any, and returns it to the pool.
func (w *Writer) Flush() error {
if w.bufw == nil {
return nil
}
if err := w.bufw.Flush(); err != nil {
return err
}
w.bufw.Reset(nil)
bufioWriterPool.Put(w.bufw)
w.bufw = nil
return nil
}
// Close flushes the underlying writer and closes it if it implements the
// io.Closer interface.
//
// Note: Close() closes the writer even if Flush() fails to avoid leaking system
// resources. If you want to make sure Flush() succeeds, call it first.
func (w *Writer) Close() error {
var (
ferr, cerr error
)
ferr = w.Flush()
// always close even if flush fails.
if closer, ok := w.W.(io.Closer); ok {
cerr = closer.Close()
}
if ferr != nil {
return ferr
}
return cerr
}

View File

@ -1,91 +0,0 @@
package pool
import (
"bytes"
"testing"
)
func checkSize(t *testing.T, w *Writer) {
if w.Size()-w.Buffered() != w.Available() {
t.Fatalf("size (%d), buffered (%d), available (%d) mismatch", w.Size(), w.Buffered(), w.Available())
}
}
func TestWriter(t *testing.T) {
var b bytes.Buffer
w := Writer{W: &b}
n, err := w.Write([]byte("foobar"))
checkSize(t, &w)
if err != nil || n != 6 {
t.Fatalf("write failed: %d, %s", n, err)
}
if b.Len() != 0 {
t.Fatal("expected the buffer to be empty")
}
if w.Buffered() != 6 {
t.Fatalf("expected 6 bytes to be buffered, got %d", w.Buffered())
}
checkSize(t, &w)
if err := w.Flush(); err != nil {
t.Fatal(err)
}
checkSize(t, &w)
if err := w.Flush(); err != nil {
t.Fatal(err)
}
checkSize(t, &w)
if b.String() != "foobar" {
t.Fatal("expected to have written foobar")
}
b.Reset()
buf := make([]byte, WriterBufferSize)
n, err = w.Write(buf)
if n != WriterBufferSize || err != nil {
t.Fatalf("write failed: %d, %s", n, err)
}
checkSize(t, &w)
if b.Len() != WriterBufferSize {
t.Fatal("large write should have gone through directly")
}
if err := w.Flush(); err != nil {
t.Fatal(err)
}
checkSize(t, &w)
b.Reset()
if err := w.WriteByte(1); err != nil {
t.Fatal(err)
}
if w.Buffered() != 1 {
t.Fatalf("expected 1 byte to be buffered, got %d", w.Buffered())
}
if n, err := w.WriteRune('1'); err != nil || n != 1 {
t.Fatal(err)
}
if w.Buffered() != 2 {
t.Fatalf("expected 2 bytes to be buffered, got %d", w.Buffered())
}
checkSize(t, &w)
if n, err := w.WriteString("foobar"); err != nil || n != 6 {
t.Fatal(err)
}
if w.Buffered() != 8 {
t.Fatalf("expected 8 bytes to be buffered, got %d", w.Buffered())
}
checkSize(t, &w)
if b.Len() != 0 {
t.Fatal("write should have been buffered")
}
n, err = w.Write(buf)
if n != WriterBufferSize || err != nil {
t.Fatalf("write failed: %d, %s", n, err)
}
if b.Len() != WriterBufferSize || b.Bytes()[0] != 1 || b.String()[1:8] != "1foobar" {
t.Fatalf("failed to flush properly: len:%d, prefix:%#v", b.Len(), b.Bytes()[:10])
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
}

View File

@ -13,6 +13,9 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
)
// DefaultSubscriptionQueueSize is the default size of the subscription queue.
const DefaultSubscriptionQueueSize = 16384
// ErrBitmaskClosed is returned if a Bitmask is utilized after it has been closed
var ErrBitmaskClosed = errors.New("this Bitmask is closed, try opening a new one")
@ -167,7 +170,7 @@ func (t *Bitmask) Subscribe(opts ...SubOpt) (*Subscription, error) {
}
if sub.ch == nil {
sub.ch = make(chan *Message, 32)
sub.ch = make(chan *Message, DefaultSubscriptionQueueSize)
}
out := make(chan *Subscription, 1)

View File

@ -37,8 +37,8 @@ var (
BlossomSubDhi = 12
BlossomSubDscore = 4
BlossomSubDout = 2
BlossomSubHistoryLength = 5
BlossomSubHistoryGossip = 3
BlossomSubHistoryLength = 9
BlossomSubHistoryGossip = 6
BlossomSubDlazy = 6
BlossomSubGossipFactor = 0.25
BlossomSubGossipRetransmission = 3

View File

@ -56,10 +56,29 @@ func (p *PubSub) handleNewStream(s network.Stream) {
p.inboundStreamsMx.Unlock()
r := msgio.NewVarintReaderSize(s, p.hardMaxMessageSize)
for {
msgbytes, err := r.ReadMsg()
read := func() (*RPC, error) {
n, err := r.NextMsgLen()
if err != nil {
return nil, err
}
if n == 0 {
_, err := r.Read(nil)
return nil, err
}
buf := poolGet(n, p.softMaxMessageSize)
defer poolPut(buf, p.softMaxMessageSize)
if _, err := r.Read(buf); err != nil {
return nil, err
}
rpc := new(pb.RPC)
if err := rpc.Unmarshal(buf); err != nil {
return nil, err
}
return &RPC{RPC: rpc, from: peer}, nil
}
for {
rpc, err := read()
if err != nil {
r.ReleaseMsg(msgbytes)
if err != io.EOF {
s.Reset()
log.Debugf("error reading rpc from %s: %s", s.Conn().RemotePeer(), err)
@ -76,28 +95,10 @@ func (p *PubSub) handleNewStream(s network.Stream) {
p.inboundStreamsMx.Unlock()
return
}
if len(msgbytes) == 0 {
r.ReleaseMsg(msgbytes)
if rpc == nil {
continue
}
rpc := &RPC{
RPC: new(pb.RPC),
}
err = rpc.Unmarshal(msgbytes)
r.ReleaseMsg(msgbytes)
if err != nil {
s.Reset()
log.Warnf("bogus rpc from %s: %s", s.Conn().RemotePeer(), err)
p.inboundStreamsMx.Lock()
if p.inboundStreams[peer] == s {
delete(p.inboundStreams, peer)
}
p.inboundStreamsMx.Unlock()
return
}
rpc.from = peer
select {
case p.incoming <- rpc:
case <-p.ctx.Done():
@ -171,8 +172,8 @@ func (p *PubSub) handlePeerDead(s network.Stream) {
func (p *PubSub) handleSendingMessages(ctx context.Context, s network.Stream, q *rpcQueue) {
writeRPC := func(rpc *RPC) error {
size := uint64(rpc.Size())
buf := pool.Get(varint.UvarintSize(size) + int(size))
defer pool.Put(buf)
buf := poolGet(varint.UvarintSize(size)+int(size), p.softMaxMessageSize)
defer poolPut(buf, p.softMaxMessageSize)
n := binary.PutUvarint(buf, size)
_, err := rpc.MarshalTo(buf[n:])
if err != nil {
@ -234,3 +235,19 @@ func copyRPC(rpc *RPC) *RPC {
res.RPC = (proto.Clone(rpc.RPC)).(*pb.RPC)
return res
}
// poolGet returns a buffer of length n from the pool if n < limit, otherwise it allocates a new buffer.
func poolGet(n int, limit int) []byte {
if n >= limit {
return make([]byte, n)
}
return pool.Get(n)
}
// poolPut returns a buffer to the pool if its length is less than limit.
func poolPut(buf []byte, limit int) {
if len(buf) >= limit {
return
}
pool.Put(buf)
}

View File

@ -8,8 +8,6 @@ replace github.com/multiformats/go-multiaddr => ../go-multiaddr
replace github.com/multiformats/go-multiaddr-dns => ../go-multiaddr-dns
replace github.com/libp2p/go-buffer-pool => ../go-buffer-pool
replace github.com/libp2p/go-libp2p => ../go-libp2p
replace github.com/libp2p/go-libp2p-gostream => ../go-libp2p-gostream

View File

@ -140,6 +140,8 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=

View File

@ -26,12 +26,15 @@ import (
logging "github.com/ipfs/go-log/v2"
)
// DefaultSoftMaxMessageSize is 10 MiB.
const DefaultSoftMaxMessageSize = 10 << 20
// DefaultSoftMaxMessageSize is 1 MiB.
const DefaultSoftMaxMessageSize = 1 << 20
// DefaultHardMaxMessageSize is 20 MB.
const DefaultHardMaxMessageSize = 10 << 21
// DefaultPeerOutboundQueueSize is the default size of the outbound message channel that we maintain for each peer.
const DefaultPeerOutboundQueueSize = 128
var (
// TimeCacheDuration specifies how long a message ID will be remembered as seen.
// Use WithSeenMessagesTTL to configure this per pubsub instance, instead of overriding the global default.

View File

@ -10,8 +10,6 @@ replace github.com/multiformats/go-multiaddr => ../go-multiaddr
replace github.com/multiformats/go-multiaddr-dns => ../go-multiaddr-dns
replace github.com/libp2p/go-buffer-pool => ../go-buffer-pool
replace github.com/libp2p/go-libp2p => ../go-libp2p
require (

View File

@ -246,6 +246,10 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=

View File

@ -6,8 +6,6 @@ toolchain go1.22.5
retract v0.26.1 // Tag was applied incorrectly due to a bug in the release workflow.
replace github.com/libp2p/go-buffer-pool => ../go-buffer-pool
replace github.com/multiformats/go-multiaddr => ../go-multiaddr
replace github.com/multiformats/go-multiaddr-dns => ../go-multiaddr-dns

View File

@ -186,6 +186,8 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=

View File

@ -2,6 +2,70 @@ package config
import "time"
type FramePublishFragmentationReedSolomonConfig struct {
// The number of data shards to use for Reed-Solomon encoding and decoding.
DataShards int `yaml:"dataShards"`
// The number of parity shards to use for Reed-Solomon encoding and decoding.
ParityShards int `yaml:"parityShards"`
}
// WithDefaults sets default values for any fields that are not set.
func (c FramePublishFragmentationReedSolomonConfig) WithDefaults() FramePublishFragmentationReedSolomonConfig {
cpy := c
if cpy.DataShards == 0 {
cpy.DataShards = 224
}
if cpy.ParityShards == 0 {
cpy.ParityShards = 32
}
return cpy
}
type FramePublishFragmentationConfig struct {
// The algorithm to use for fragmenting and reassembling frames.
// Options: "reed-solomon".
Algorithm string `yaml:"algorithm"`
// The configuration for Reed-Solomon fragmentation.
ReedSolomon FramePublishFragmentationReedSolomonConfig `yaml:"reedSolomon"`
}
// WithDefaults sets default values for any fields that are not set.
func (c FramePublishFragmentationConfig) WithDefaults() FramePublishFragmentationConfig {
cpy := c
if cpy.Algorithm == "" {
cpy.Algorithm = "reed-solomon"
}
cpy.ReedSolomon = cpy.ReedSolomon.WithDefaults()
return cpy
}
type FramePublishConfig struct {
// The publish mode to use for the node.
// Options: "full", "fragmented", "dual", "threshold".
Mode string `yaml:"mode"`
// The threshold for switching between full and fragmented frame publishing.
Threshold int `yaml:"threshold"`
// The configuration for frame fragmentation.
Fragmentation FramePublishFragmentationConfig `yaml:"fragmentation"`
// The size of the ballast added to a frame.
// NOTE: This option exists solely for testing purposes and should not be
// modified in production.
BallastSize int `yaml:"ballastSize"`
}
// WithDefaults sets default values for any fields that are not set.
func (c FramePublishConfig) WithDefaults() FramePublishConfig {
cpy := c
if cpy.Mode == "" {
cpy.Mode = "full"
}
if cpy.Threshold == 0 {
cpy.Threshold = 1 * 1024 * 1024
}
cpy.Fragmentation = cpy.Fragmentation.WithDefaults()
return cpy
}
type EngineConfig struct {
ProvingKeyId string `yaml:"provingKeyId"`
Filter string `yaml:"filter"`
@ -36,4 +100,7 @@ type EngineConfig struct {
Difficulty uint32 `yaml:"difficulty"`
// Whether to allow GOMAXPROCS values above the number of physical cores.
AllowExcessiveGOMAXPROCS bool `yaml:"allowExcessiveGOMAXPROCS"`
// EXPERIMENTAL: The configuration for frame publishing.
FramePublish FramePublishConfig `yaml:"framePublish"`
}

View File

@ -53,4 +53,6 @@ type P2PConfig struct {
PingAttempts int `yaml:"pingAttempts"`
ValidateQueueSize int `yaml:"validateQueueSize"`
ValidateWorkers int `yaml:"validateWorkers"`
SubscriptionQueueSize int `yaml:"subscriptionQueueSize"`
PeerOutboundQueueSize int `yaml:"peerOutboundQueueSize"`
}

View File

@ -13,15 +13,15 @@ func GetMinimumVersionCutoff() time.Time {
// if there is something in the patch update that is needed to cut off unupgraded
// peers. Be sure to update this to 0x00 for any new minor release
func GetMinimumPatchVersion() byte {
return 0x02
return 0x00
}
func GetMinimumVersion() []byte {
return []byte{0x02, 0x00, 0x04}
return []byte{0x02, 0x00, 0x05}
}
func GetVersion() []byte {
return []byte{0x02, 0x00, 0x04}
return []byte{0x02, 0x00, 0x05}
}
func GetVersionString() string {
@ -43,9 +43,9 @@ func FormatVersion(version []byte) string {
}
func GetPatchNumber() byte {
return 0x02
return 0x00
}
func GetRCNumber() byte {
return 0x02
return 0x00
}

View File

@ -1,7 +1,11 @@
package data
import (
"crypto"
"crypto/rand"
mrand "math/rand"
"strings"
"sync"
"time"
"github.com/iden3/go-iden3-crypto/poseidon"
@ -11,6 +15,8 @@ import (
"google.golang.org/protobuf/types/known/anypb"
"source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb"
"source.quilibrium.com/quilibrium/monorepo/node/config"
"source.quilibrium.com/quilibrium/monorepo/node/consensus/data/fragmentation"
qruntime "source.quilibrium.com/quilibrium/monorepo/node/internal/runtime"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
)
@ -27,6 +33,19 @@ func (e *DataClockConsensusEngine) handleFrameMessage(
return nil
}
func (e *DataClockConsensusEngine) handleFrameFragmentMessage(
message *pb.Message,
) error {
select {
case <-e.ctx.Done():
return e.ctx.Err()
case e.frameFragmentMessageProcessorCh <- message:
default:
e.logger.Warn("dropping frame fragment message")
}
return nil
}
func (e *DataClockConsensusEngine) handleTxMessage(
message *pb.Message,
) error {
@ -62,6 +81,7 @@ func (e *DataClockConsensusEngine) publishProof(
)
timestamp := time.Now().UnixMilli()
reachability := e.pubSub.Reachability()
e.peerMapMx.Lock()
e.peerMap[string(e.pubSub.GetPeerID())] = &peerInfo{
@ -74,7 +94,97 @@ func (e *DataClockConsensusEngine) publishProof(
totalDistance: e.dataTimeReel.GetTotalDistance().FillBytes(
make([]byte, 256),
),
reachability: reachability,
}
e.peerMapMx.Unlock()
cfg := e.config.Engine.FramePublish.WithDefaults()
if cfg.BallastSize > 0 {
frame = proto.Clone(frame).(*protobufs.ClockFrame)
frame.Padding = make([]byte, cfg.BallastSize)
}
publishFragmented := func() error {
var splitter fragmentation.ClockFrameSplitter
switch cfg := cfg.Fragmentation; cfg.Algorithm {
case "reed-solomon":
var err error
splitter, err = fragmentation.NewReedSolomonClockFrameSplitter(
cfg.ReedSolomon.DataShards,
cfg.ReedSolomon.ParityShards,
)
if err != nil {
return errors.Wrap(err, "creating reed-solomon splitter")
}
default:
return errors.Errorf("unsupported fragmentation algorithm: %s", cfg.Algorithm)
}
fragments, err := splitter.SplitClockFrame(frame)
if err != nil {
return errors.Wrap(err, "splitting clock frame")
}
mrand.Shuffle(len(fragments), func(i, j int) {
fragments[i], fragments[j] = fragments[j], fragments[i]
})
sign := func(b []byte) ([]byte, error) {
return e.provingKey.Sign(rand.Reader, b, crypto.Hash(0))
}
var wg sync.WaitGroup
defer wg.Wait()
throttle := make(chan struct{}, qruntime.WorkerCount(0, false))
for _, fragment := range fragments {
throttle <- struct{}{}
wg.Add(1)
go func(fragment *protobufs.ClockFrameFragment) {
defer func() { <-throttle }()
defer wg.Done()
if err := fragment.SignED448(e.provingKeyBytes, sign); err != nil {
e.logger.Error("error signing clock frame fragment", zap.Error(err))
return
}
if err := e.publishMessage(e.frameFragmentFilter, fragment); err != nil {
e.logger.Error("error publishing clock frame fragment", zap.Error(err))
}
}(fragment)
}
return nil
}
publishFull := func() error {
if err := e.publishMessage(e.frameFilter, frame); err != nil {
e.logger.Error("error publishing clock frame", zap.Error(err))
}
return nil
}
switch cfg.Mode {
case "full":
if err := publishFull(); err != nil {
return err
}
case "fragmented":
if err := publishFragmented(); err != nil {
return err
}
case "dual":
if err := publishFragmented(); err != nil {
return err
}
if err := publishFull(); err != nil {
return err
}
case "threshold":
if proto.Size(frame) >= cfg.Threshold {
if err := publishFragmented(); err != nil {
return err
}
} else {
if err := publishFull(); err != nil {
return err
}
}
default:
return errors.Errorf("unsupported frame publish mode: %s", cfg.Mode)
}
list := &protobufs.DataPeerListAnnounce{
Peer: &protobufs.DataPeer{
PeerId: nil,
@ -86,15 +196,13 @@ func (e *DataClockConsensusEngine) publishProof(
TotalDistance: e.dataTimeReel.GetTotalDistance().FillBytes(
make([]byte, 256),
),
ExternallyReachable: reachability,
},
}
e.peerMapMx.Unlock()
if err := e.publishMessage(e.infoFilter, list); err != nil {
e.logger.Debug("error publishing message", zap.Error(err))
e.logger.Debug("error publishing data peer list announce", zap.Error(err))
}
e.publishMessage(e.frameFilter, frame)
return nil
}

View File

@ -3,6 +3,7 @@ package data
import (
"bytes"
"context"
"slices"
"time"
"golang.org/x/crypto/sha3"
@ -219,19 +220,25 @@ func (e *DataClockConsensusEngine) prove(
}
func (e *DataClockConsensusEngine) GetAheadPeers(frameNumber uint64) []internal.PeerCandidate {
if e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) {
if e.FrameProverTrieContains(0, e.provingKeyAddress) {
return nil
}
e.peerMapMx.RLock()
peerMapLen, uncooperativePeerMapLen := len(e.peerMap), len(e.uncooperativePeersMap)
e.peerMapMx.RUnlock()
e.logger.Debug(
"checking peer list",
zap.Int("peers", len(e.peerMap)),
zap.Int("uncooperative_peers", len(e.uncooperativePeersMap)),
zap.Int("peers", peerMapLen),
zap.Int("uncooperative_peers", uncooperativePeerMapLen),
zap.Uint64("current_head_frame", frameNumber),
)
candidates := make([]internal.WeightedPeerCandidate, 0, len(e.peerMap))
maxDiff := uint64(0)
nearCandidates, nearMaxDiff := make([]internal.WeightedPeerCandidate, 0, peerMapLen), uint64(0)
reachableCandidates, reachableMaxDiff := make([]internal.WeightedPeerCandidate, 0, peerMapLen), uint64(0)
unreachableCandidates, unreachableMaxDiff := make([]internal.WeightedPeerCandidate, 0, peerMapLen), uint64(0)
unknownCandidates, unknownMaxDiff := make([]internal.WeightedPeerCandidate, 0, peerMapLen), uint64(0)
e.peerMapMx.RLock()
for _, v := range e.peerMap {
@ -254,24 +261,54 @@ func (e *DataClockConsensusEngine) GetAheadPeers(frameNumber uint64) []internal.
if bytes.Compare(v.version, config.GetMinimumVersion()) < 0 {
continue
}
maxDiff = max(maxDiff, v.maxFrame-frameNumber)
candidates = append(candidates, internal.WeightedPeerCandidate{
candidate, diff := internal.WeightedPeerCandidate{
PeerCandidate: internal.PeerCandidate{
PeerID: v.peerId,
MaxFrame: v.maxFrame,
},
})
}, v.maxFrame-frameNumber
switch {
case e.pubSub.IsPeerConnected(v.peerId):
nearMaxDiff = max(nearMaxDiff, diff)
nearCandidates = append(nearCandidates, candidate)
case v.reachability == nil:
unknownMaxDiff = max(unknownMaxDiff, diff)
unknownCandidates = append(unknownCandidates, candidate)
case v.reachability.Value:
reachableMaxDiff = max(reachableMaxDiff, diff)
reachableCandidates = append(reachableCandidates, candidate)
default:
unreachableMaxDiff = max(unreachableMaxDiff, diff)
unreachableCandidates = append(unreachableCandidates, candidate)
}
}
e.peerMapMx.RUnlock()
if len(candidates) == 0 {
if len(nearCandidates)+len(reachableCandidates)+len(unreachableCandidates)+len(unknownCandidates) == 0 {
return nil
}
for _, pair := range []struct {
maxDiff uint64
candidates []internal.WeightedPeerCandidate
}{
{nearMaxDiff, nearCandidates},
{reachableMaxDiff, reachableCandidates},
{unknownMaxDiff, unknownCandidates},
{unreachableMaxDiff, unreachableCandidates},
} {
maxDiff, candidates := pair.maxDiff, pair.candidates
for i := range candidates {
candidates[i].Weight = float64(candidates[i].MaxFrame-frameNumber) / float64(maxDiff)
}
return internal.WeightedSampleWithoutReplacement(candidates, len(candidates))
}
return slices.Concat(
internal.WeightedSampleWithoutReplacement(nearCandidates, len(nearCandidates)),
internal.WeightedSampleWithoutReplacement(reachableCandidates, len(reachableCandidates)),
internal.WeightedSampleWithoutReplacement(unknownCandidates, len(unknownCandidates)),
internal.WeightedSampleWithoutReplacement(unreachableCandidates, len(unreachableCandidates)),
)
}
func (e *DataClockConsensusEngine) syncWithPeer(
@ -288,6 +325,7 @@ func (e *DataClockConsensusEngine) syncWithPeer(
zap.Uint64("current_frame", latest.FrameNumber),
zap.Uint64("max_frame", maxFrame),
)
var cooperative bool = true
defer func() {
if cooperative {
@ -301,7 +339,15 @@ func (e *DataClockConsensusEngine) syncWithPeer(
delete(e.peerMap, string(peerId))
}
}()
cc, err := e.pubSub.GetDirectChannel(peerId, "sync")
syncTimeout := e.config.Engine.SyncTimeout
if syncTimeout == 0 {
syncTimeout = defaultSyncTimeout
}
dialCtx, cancelDial := context.WithTimeout(e.ctx, syncTimeout)
defer cancelDial()
cc, err := e.pubSub.GetDirectChannel(dialCtx, peerId, "sync")
if err != nil {
e.logger.Debug(
"could not establish direct channel",
@ -317,22 +363,16 @@ func (e *DataClockConsensusEngine) syncWithPeer(
}()
client := protobufs.NewDataServiceClient(cc)
syncTimeout := e.config.Engine.SyncTimeout
if syncTimeout == 0 {
syncTimeout = defaultSyncTimeout
}
for {
ctx, cancel := context.WithTimeout(e.ctx, syncTimeout)
getCtx, cancelGet := context.WithTimeout(e.ctx, syncTimeout)
response, err := client.GetDataFrame(
ctx,
getCtx,
&protobufs.GetDataFrameRequest{
FrameNumber: latest.FrameNumber + 1,
},
grpc.MaxCallRecvMsgSize(600*1024*1024),
)
cancel()
cancelGet()
if err != nil {
e.logger.Debug(
"could not get frame",

View File

@ -21,9 +21,11 @@ import (
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/wrapperspb"
"source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb"
"source.quilibrium.com/quilibrium/monorepo/node/config"
"source.quilibrium.com/quilibrium/monorepo/node/consensus"
"source.quilibrium.com/quilibrium/monorepo/node/consensus/data/fragmentation"
qtime "source.quilibrium.com/quilibrium/monorepo/node/consensus/time"
qcrypto "source.quilibrium.com/quilibrium/monorepo/node/crypto"
"source.quilibrium.com/quilibrium/monorepo/node/execution"
@ -58,6 +60,7 @@ type peerInfo struct {
version []byte
patchVersion byte
totalDistance []byte
reachability *wrapperspb.BoolValue
}
type ChannelServer = protobufs.DataService_GetPublicChannelServer
@ -111,6 +114,7 @@ type DataClockConsensusEngine struct {
txFilter []byte
infoFilter []byte
frameFilter []byte
frameFragmentFilter []byte
input []byte
parentSelector []byte
syncingStatus SyncStatusType
@ -129,6 +133,7 @@ type DataClockConsensusEngine struct {
peerMap map[string]*peerInfo
uncooperativePeersMap map[string]*peerInfo
frameMessageProcessorCh chan *pb.Message
frameFragmentMessageProcessorCh chan *pb.Message
txMessageProcessorCh chan *pb.Message
infoMessageProcessorCh chan *pb.Message
report *protobufs.SelfTestReport
@ -138,6 +143,7 @@ type DataClockConsensusEngine struct {
previousTree *mt.MerkleTree
clientReconnectTest int
requestSyncCh chan struct{}
clockFrameFragmentBuffer fragmentation.ClockFrameFragmentBuffer
}
var _ consensus.DataConsensusEngine = (*DataClockConsensusEngine)(nil)
@ -227,6 +233,14 @@ func NewDataClockConsensusEngine(
rateLimit = 10
}
clockFrameFragmentBuffer, err := fragmentation.NewClockFrameFragmentCircularBuffer(
fragmentation.NewReedSolomonClockFrameFragmentBuffer,
16,
)
if err != nil {
panic(err)
}
ctx, cancel := context.WithCancel(context.Background())
e := &DataClockConsensusEngine{
ctx: ctx,
@ -263,6 +277,7 @@ func NewDataClockConsensusEngine(
dataTimeReel: dataTimeReel,
peerInfoManager: peerInfoManager,
frameMessageProcessorCh: make(chan *pb.Message, 65536),
frameFragmentMessageProcessorCh: make(chan *pb.Message, 65536),
txMessageProcessorCh: make(chan *pb.Message, 65536),
infoMessageProcessorCh: make(chan *pb.Message, 65536),
config: cfg,
@ -273,6 +288,7 @@ func NewDataClockConsensusEngine(
),
requestSyncCh: make(chan struct{}, 1),
validationFilter: map[string]struct{}{},
clockFrameFragmentBuffer: clockFrameFragmentBuffer,
}
logger.Info("constructing consensus engine")
@ -285,6 +301,7 @@ func NewDataClockConsensusEngine(
e.txFilter = append([]byte{0x00}, e.filter...)
e.infoFilter = append([]byte{0x00, 0x00}, e.filter...)
e.frameFilter = append([]byte{0x00, 0x00, 0x00}, e.filter...)
e.frameFragmentFilter = append([]byte{0x00, 0x00, 0x00, 0x00}, e.filter...)
e.input = seed
e.provingKey = signer
e.provingKeyType = keyType
@ -317,22 +334,25 @@ func (e *DataClockConsensusEngine) Start() <-chan error {
panic(err)
}
e.wg.Add(3)
e.wg.Add(4)
go e.runFrameMessageHandler()
go e.runFrameFragmentMessageHandler()
go e.runTxMessageHandler()
go e.runInfoMessageHandler()
e.logger.Info("subscribing to pubsub messages")
e.pubSub.RegisterValidator(e.frameFilter, e.validateFrameMessage, true)
e.pubSub.RegisterValidator(e.frameFragmentFilter, e.validateFrameFragmentMessage, true)
e.pubSub.RegisterValidator(e.txFilter, e.validateTxMessage, true)
e.pubSub.RegisterValidator(e.infoFilter, e.validateInfoMessage, true)
e.pubSub.Subscribe(e.frameFilter, e.handleFrameMessage)
e.pubSub.Subscribe(e.frameFragmentFilter, e.handleFrameFragmentMessage)
e.pubSub.Subscribe(e.txFilter, e.handleTxMessage)
e.pubSub.Subscribe(e.infoFilter, e.handleInfoMessage)
go func() {
server := qgrpc.NewServer(
grpc.MaxSendMsgSize(20*1024*1024),
grpc.MaxRecvMsgSize(20*1024*1024),
grpc.MaxSendMsgSize(40*1024*1024),
grpc.MaxRecvMsgSize(40*1024*1024),
)
protobufs.RegisterDataServiceServer(server, e)
if err := e.pubSub.StartDirectChannelListener(
@ -431,6 +451,8 @@ func (e *DataClockConsensusEngine) Start() <-chan error {
frame = nextFrame
timestamp := time.Now().UnixMilli()
reachability := e.pubSub.Reachability()
list := &protobufs.DataPeerListAnnounce{
Peer: &protobufs.DataPeer{
PeerId: nil,
@ -442,6 +464,7 @@ func (e *DataClockConsensusEngine) Start() <-chan error {
TotalDistance: e.dataTimeReel.GetTotalDistance().FillBytes(
make([]byte, 256),
),
ExternallyReachable: reachability,
},
}
@ -463,6 +486,7 @@ func (e *DataClockConsensusEngine) Start() <-chan error {
totalDistance: e.dataTimeReel.GetTotalDistance().FillBytes(
make([]byte, 256),
),
reachability: reachability,
}
deletes := []*peerInfo{}
for _, v := range e.peerMap {
@ -498,7 +522,7 @@ func (e *DataClockConsensusEngine) Start() <-chan error {
)
if err := e.publishMessage(e.infoFilter, list); err != nil {
e.logger.Debug("error publishing message", zap.Error(err))
e.logger.Debug("error publishing data peer list announce", zap.Error(err))
}
if thresholdBeforeConfirming > 0 {
@ -656,7 +680,9 @@ func (e *DataClockConsensusEngine) Stop(force bool) <-chan error {
panic(err)
}
e.publishMessage(e.txFilter, pause.TokenRequest())
if err := e.publishMessage(e.txFilter, pause.TokenRequest()); err != nil {
e.logger.Warn("error publishing prover pause", zap.Error(err))
}
wg := sync.WaitGroup{}
wg.Add(len(e.executionEngines))
@ -678,9 +704,11 @@ func (e *DataClockConsensusEngine) Stop(force bool) <-chan error {
}
e.pubSub.Unsubscribe(e.frameFilter, false)
e.pubSub.Unsubscribe(e.frameFragmentFilter, false)
e.pubSub.Unsubscribe(e.txFilter, false)
e.pubSub.Unsubscribe(e.infoFilter, false)
e.pubSub.UnregisterValidator(e.frameFilter)
e.pubSub.UnregisterValidator(e.frameFragmentFilter)
e.pubSub.UnregisterValidator(e.txFilter)
e.pubSub.UnregisterValidator(e.infoFilter)

View File

@ -0,0 +1,371 @@
package fragmentation
import (
"bytes"
"errors"
"github.com/klauspost/reedsolomon"
"google.golang.org/protobuf/proto"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
)
// ClockFrameSplitter is an interface for splitting a ClockFrame into fragments.
type ClockFrameSplitter interface {
// SplitClockFrame splits a ClockFrame into fragments.
// The fragments are unsigned, and must be signed before being sent.
SplitClockFrame(frame *protobufs.ClockFrame) ([]*protobufs.ClockFrameFragment, error)
}
type reedSolomonClockFrameSplitter struct {
dataShardCount int
parityShardCount int
}
// NewReedSolomonClockFrameSplitter creates a new ReedSolomonClockFrameSplitter.
func NewReedSolomonClockFrameSplitter(
dataShardCount int,
parityShardCount int,
) (ClockFrameSplitter, error) {
if dataShardCount == 0 {
return nil, errors.New("dataShardCount must be greater than 0")
}
if parityShardCount == 0 {
return nil, errors.New("parityShardCount must be greater than 0")
}
if dataShardCount+parityShardCount > 256 {
return nil, errors.New("dataShardCount + parityShardCount must be less than or equal to 256")
}
return &reedSolomonClockFrameSplitter{
dataShardCount: dataShardCount,
parityShardCount: parityShardCount,
}, nil
}
// SplitClockFrame implements ClockFrameSplitter.
func (r *reedSolomonClockFrameSplitter) SplitClockFrame(frame *protobufs.ClockFrame) ([]*protobufs.ClockFrameFragment, error) {
bs, err := proto.Marshal(frame)
if err != nil {
return nil, err
}
fragmentSize := len(bs) / r.dataShardCount
if len(bs)%r.dataShardCount != 0 {
fragmentSize++
}
if fragmentSize == 0 {
return nil, errors.New("ClockFrame is too small")
}
if n := fragmentSize % 64; n != 0 {
fragmentSize += 64 - n
}
shards := make([][]byte, r.dataShardCount+r.parityShardCount)
for i := 0; i < len(bs); i += fragmentSize {
shard := bs[i:]
if len(shard) > fragmentSize {
shard = shard[:fragmentSize]
}
shards[i/fragmentSize] = shard
}
for i := len(bs) / fragmentSize; i < r.dataShardCount; i++ {
if n := len(shards[i]); n < fragmentSize {
shards[i] = append(shards[i], make([]byte, fragmentSize-n)...)
}
}
for i := r.dataShardCount; i < r.dataShardCount+r.parityShardCount; i++ {
shards[i] = make([]byte, fragmentSize)
}
enc, err := reedsolomon.New(
r.dataShardCount,
r.parityShardCount,
reedsolomon.WithAutoGoroutines(fragmentSize),
)
if err != nil {
return nil, err
}
if err := enc.Encode(shards); err != nil {
return nil, err
}
h := hash(bs)
fragments := make([]*protobufs.ClockFrameFragment, r.dataShardCount+r.parityShardCount)
for i, shard := range shards {
fragments[i] = &protobufs.ClockFrameFragment{
Filter: frame.Filter,
FrameNumber: frame.FrameNumber,
Timestamp: frame.Timestamp,
FrameHash: h,
Encoding: &protobufs.ClockFrameFragment_ReedSolomon{
ReedSolomon: &protobufs.ClockFrameFragment_ReedSolomonEncoding{
FrameSize: uint64(len(bs)),
FragmentShard: uint64(i),
FragmentDataShardCount: uint64(r.dataShardCount),
FragmentParityShardCount: uint64(r.parityShardCount),
FragmentData: shard,
},
},
}
}
return fragments, nil
}
// ClockFrameAssembler is an interface for assembling a ClockFrame from fragments.
type ClockFrameAssembler interface {
// AssembleClockFrame assembles a ClockFrame from fragments.
AssembleClockFrame(fragments []*protobufs.ClockFrameFragment) (*protobufs.ClockFrame, error)
}
type reedSolomonClockFrameAssembler struct{}
// NewReedSolomonClockFrameAssembler creates a new ReedSolomonClockFrameAssembler.
func NewReedSolomonClockFrameAssembler() ClockFrameAssembler {
return &reedSolomonClockFrameAssembler{}
}
// AssembleClockFrame implements ClockFrameAssembler.
func (r *reedSolomonClockFrameAssembler) AssembleClockFrame(fragments []*protobufs.ClockFrameFragment) (*protobufs.ClockFrame, error) {
if len(fragments) == 0 {
return nil, errors.New("no fragments")
}
var (
frameNumber uint64
filter []byte
timestamp int64
frameHash []byte
dataShardCount, parityShardCount int
fragmentSize int
frameSize int
)
for _, fragment := range fragments {
if fragment == nil {
return nil, errors.New("fragment is nil")
}
switch {
case frameNumber == 0:
frameNumber = fragment.FrameNumber
case frameNumber != fragment.FrameNumber:
return nil, errors.New("inconsistent frame number")
case len(filter) == 0:
filter = fragment.Filter
case !bytes.Equal(filter, fragment.Filter):
return nil, errors.New("inconsistent filter")
case timestamp == 0:
timestamp = fragment.Timestamp
case timestamp != fragment.Timestamp:
return nil, errors.New("inconsistent timestamp")
case len(frameHash) == 0:
frameHash = fragment.FrameHash
case !bytes.Equal(frameHash, fragment.FrameHash):
return nil, errors.New("inconsistent frame hash")
}
fragment := fragment.GetReedSolomon()
if fragment == nil {
return nil, errors.New("fragment is not ReedSolomon")
}
switch {
case dataShardCount == 0:
dataShardCount = int(fragment.FragmentDataShardCount)
parityShardCount = int(fragment.FragmentParityShardCount)
case dataShardCount != int(fragment.FragmentDataShardCount):
return nil, errors.New("inconsistent data shard count")
case parityShardCount != int(fragment.FragmentParityShardCount):
return nil, errors.New("inconsistent parity shard count")
case dataShardCount+parityShardCount <= int(fragment.FragmentShard):
return nil, errors.New("shard out of bounds")
case fragmentSize == 0:
fragmentSize = len(fragment.FragmentData)
case len(fragment.FragmentData) != fragmentSize:
return nil, errors.New("inconsistent fragment size")
case frameSize == 0:
frameSize = int(fragment.FrameSize)
case int(fragment.FrameSize) != frameSize:
return nil, errors.New("inconsistent frame size")
}
}
shards := make([][]byte, dataShardCount+parityShardCount)
for _, fragment := range fragments {
fragment := fragment.GetReedSolomon()
shard := fragment.FragmentShard
if shards[shard] != nil {
return nil, errors.New("duplicate shard")
}
shards[shard] = fragment.FragmentData
}
enc, err := reedsolomon.New(
dataShardCount,
parityShardCount,
reedsolomon.WithAutoGoroutines(fragmentSize),
)
if err != nil {
return nil, err
}
if err := enc.ReconstructData(shards); err != nil {
return nil, err
}
bs := make([]byte, 0, dataShardCount*fragmentSize)
for _, shard := range shards[:dataShardCount] {
bs = append(bs, shard...)
}
bs = bs[:frameSize]
if h := hash(bs); !bytes.Equal(h, frameHash) {
return nil, errors.New("frame hash mismatch")
}
frame := &protobufs.ClockFrame{}
if err := proto.Unmarshal(bs, frame); err != nil {
return nil, err
}
return frame, nil
}
// ClockFrameFragmentBuffer is an interface for buffering ClockFrameFragments and assembling ClockFrames.
type ClockFrameFragmentBuffer interface {
// AccumulateClockFrameFragment accumulates a ClockFrameFragment.
// If sufficient fragments are available, the ClockFrame is returned.
// How fragments from different frames are handled is implementation-specific.
AccumulateClockFrameFragment(fragment *protobufs.ClockFrameFragment) (*protobufs.ClockFrame, error)
}
type clockFrameFragmentCircularBuffer struct {
newBuffer func() ClockFrameFragmentBuffer
maxSize int
buffers map[[hashSize]byte]ClockFrameFragmentBuffer
keys [][hashSize]byte
built map[[hashSize]byte]struct{}
builtKeys [][hashSize]byte
}
// NewClockFrameFragmentCircularBuffer creates a new ClockFrameFragmentBuffer.
// The newBuffer function is called to create a new ClockFrameFragmentBuffer.
// The maxSize parameter specifies the maximum number of buffers to keep.
// If maxSize buffers are already in use, the oldest buffer is removed.
func NewClockFrameFragmentCircularBuffer(
newBuffer func() ClockFrameFragmentBuffer,
maxSize int,
) (ClockFrameFragmentBuffer, error) {
if newBuffer == nil {
return nil, errors.New("newBuffer is nil")
}
if maxSize <= 0 {
return nil, errors.New("maxSize must be greater than 0")
}
return &clockFrameFragmentCircularBuffer{
newBuffer: newBuffer,
maxSize: maxSize,
buffers: make(map[[hashSize]byte]ClockFrameFragmentBuffer, maxSize),
keys: make([][hashSize]byte, 0, maxSize),
built: make(map[[hashSize]byte]struct{}, maxSize),
builtKeys: make([][hashSize]byte, 0, maxSize),
}, nil
}
// AccumulateClockFrameFragment implements ClockFrameFragmentBuffer.
func (c *clockFrameFragmentCircularBuffer) AccumulateClockFrameFragment(fragment *protobufs.ClockFrameFragment) (*protobufs.ClockFrame, error) {
if fragment == nil {
return nil, errors.New("fragment is nil")
}
if len(fragment.FrameHash) != hashSize {
return nil, errors.New("invalid frame hash size")
}
key := [hashSize]byte(fragment.FrameHash)
if _, ok := c.built[key]; ok {
return nil, nil
}
buffer, ok := c.buffers[key]
if !ok {
if len(c.buffers) == c.maxSize {
delete(c.buffers, c.keys[0])
c.keys = append(c.keys[:0], c.keys[1:]...)
}
buffer = c.newBuffer()
c.buffers[key] = buffer
c.keys = append(c.keys, key)
}
frame, err := buffer.AccumulateClockFrameFragment(fragment)
if err != nil {
return nil, err
}
if frame != nil {
delete(c.buffers, key)
for i, k := range c.keys {
if k == key {
c.keys = append(c.keys[:i], c.keys[i+1:]...)
break
}
}
if len(c.built) == c.maxSize {
delete(c.built, c.builtKeys[0])
c.builtKeys = append(c.builtKeys[:0], c.builtKeys[1:]...)
}
c.built[key] = struct{}{}
c.builtKeys = append(c.builtKeys, key)
}
return frame, nil
}
type reedSolomonClockFrameFragmentBuffer struct {
fragments []*protobufs.ClockFrameFragment
have map[uint64]struct{}
}
// NewReedSolomonClockFrameFragmentBuffer creates a new ReedSolomonClockFrameFragmentBuffer.
func NewReedSolomonClockFrameFragmentBuffer() ClockFrameFragmentBuffer {
return &reedSolomonClockFrameFragmentBuffer{
fragments: make([]*protobufs.ClockFrameFragment, 0, 256),
have: make(map[uint64]struct{}, 256),
}
}
// AccumulateClockFrameFragment implements ClockFrameFragmentBuffer.
func (r *reedSolomonClockFrameFragmentBuffer) AccumulateClockFrameFragment(fragment *protobufs.ClockFrameFragment) (*protobufs.ClockFrame, error) {
if fragment == nil {
return nil, errors.New("fragment is nil")
}
if fragment.GetReedSolomon() == nil {
return nil, errors.New("fragment is not ReedSolomon")
}
var templateRS *protobufs.ClockFrameFragment_ReedSolomonEncoding
if len(r.fragments) == 0 {
templateRS = fragment.GetReedSolomon()
} else {
template := r.fragments[0]
if !bytes.Equal(template.Filter, fragment.Filter) {
return nil, errors.New("inconsistent filter")
}
if template.FrameNumber != fragment.FrameNumber {
return nil, errors.New("inconsistent frame number")
}
if template.Timestamp != fragment.Timestamp {
return nil, errors.New("inconsistent timestamp")
}
if !bytes.Equal(template.FrameHash, fragment.FrameHash) {
return nil, errors.New("inconsistent frame hash")
}
templateRS = template.GetReedSolomon()
fragmentRS := fragment.GetReedSolomon()
if templateRS.FrameSize != fragmentRS.FrameSize {
return nil, errors.New("inconsistent frame size")
}
if templateRS.FragmentDataShardCount+templateRS.FragmentParityShardCount <= fragmentRS.FragmentShard {
return nil, errors.New("shard out of bounds")
}
if _, ok := r.have[fragmentRS.FragmentShard]; ok {
return nil, errors.New("duplicate shard")
}
if templateRS.FragmentDataShardCount != fragmentRS.FragmentDataShardCount {
return nil, errors.New("inconsistent data shard count")
}
if templateRS.FragmentParityShardCount != fragmentRS.FragmentParityShardCount {
return nil, errors.New("inconsistent parity shard count")
}
if len(templateRS.FragmentData) != len(fragmentRS.FragmentData) {
return nil, errors.New("inconsistent fragment size")
}
}
r.fragments = append(r.fragments, fragment)
r.have[templateRS.FragmentShard] = struct{}{}
if len(r.fragments) < int(templateRS.FragmentDataShardCount) {
return nil, nil
}
assembler := NewReedSolomonClockFrameAssembler()
frame, err := assembler.AssembleClockFrame(r.fragments)
r.fragments = r.fragments[:0]
clear(r.have)
return frame, err
}

View File

@ -0,0 +1,414 @@
package fragmentation_test
import (
"bytes"
"crypto/rand"
"fmt"
mrand "math/rand"
"slices"
"testing"
"google.golang.org/protobuf/proto"
"source.quilibrium.com/quilibrium/monorepo/node/consensus/data/fragmentation"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
)
func BenchmarkReedSolomonClockFrameFragmentation(b *testing.B) {
frame := &protobufs.ClockFrame{
Filter: bytes.Repeat([]byte{0x01}, 32),
FrameNumber: 123,
Timestamp: 456,
Padding: make([]byte, 20*1024*1024),
}
if _, err := rand.Read(frame.Padding); err != nil {
b.Fatal(err)
}
benchmarkCases := []struct {
dataShardCount int
parityShardCount int
}{
{
dataShardCount: 4,
parityShardCount: 2,
},
{
dataShardCount: 8,
parityShardCount: 4,
},
{
dataShardCount: 16,
parityShardCount: 8,
},
{
dataShardCount: 32,
parityShardCount: 16,
},
{
dataShardCount: 48,
parityShardCount: 16,
},
{
dataShardCount: 64,
parityShardCount: 32,
},
{
dataShardCount: 128,
parityShardCount: 64,
},
{
dataShardCount: 192,
parityShardCount: 64,
},
{
dataShardCount: 224,
parityShardCount: 32,
},
}
b.Run("Splitter", func(b *testing.B) {
for _, bc := range benchmarkCases {
b.Run(fmt.Sprintf("DS_%d/PS_%d", bc.dataShardCount, bc.parityShardCount), func(b *testing.B) {
for i := 0; i < b.N; i++ {
splitter, err := fragmentation.NewReedSolomonClockFrameSplitter(bc.dataShardCount, bc.parityShardCount)
if err != nil {
b.Fatal(err)
}
if _, err := splitter.SplitClockFrame(frame); err != nil {
b.Fatal(err)
}
}
})
}
})
b.Run("Assembler", func(b *testing.B) {
for _, bc := range benchmarkCases {
b.Run(fmt.Sprintf("DS_%d/PS_%d", bc.dataShardCount, bc.parityShardCount), func(b *testing.B) {
splitter, err := fragmentation.NewReedSolomonClockFrameSplitter(bc.dataShardCount, bc.parityShardCount)
if err != nil {
b.Fatal(err)
}
fragments, err := splitter.SplitClockFrame(frame)
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
assembler := fragmentation.NewReedSolomonClockFrameAssembler()
if _, err := assembler.AssembleClockFrame(fragments); err != nil {
b.Fatal(err)
}
}
})
}
})
}
func TestReedSolomonClockFrameFragmentation(t *testing.T) {
splitter, err := fragmentation.NewReedSolomonClockFrameSplitter(4, 2)
if err != nil {
t.Fatal(err)
}
originalFrame := &protobufs.ClockFrame{
Filter: bytes.Repeat([]byte{0x01}, 32),
FrameNumber: 123,
Timestamp: 456,
Padding: make([]byte, 20*1024*1024),
}
if _, err := rand.Read(originalFrame.Padding); err != nil {
t.Fatal(err)
}
fragments, err := splitter.SplitClockFrame(originalFrame)
if err != nil {
t.Fatal(err)
}
if len(fragments) != 6 {
t.Fatalf("fragment count mismatch: %d, expected %d", len(fragments), 5)
}
for _, fragment := range fragments {
if fragment.FrameNumber != 123 {
t.Fatalf("frame number mismatch: %d, expected %d", fragment.FrameNumber, 123)
}
if !bytes.Equal(fragment.Filter, bytes.Repeat([]byte{0x01}, 32)) {
t.Fatalf("filter mismatch")
}
if fragment.Timestamp != 456 {
t.Fatalf("timestamp mismatch: %d, expected %d", fragment.Timestamp, 456)
}
}
for _, tc := range []struct {
name string
erase []int
expectError bool
}{
{
name: "no erasures",
erase: nil,
expectError: false,
},
{
name: "one erasure",
erase: []int{0},
expectError: false,
},
{
name: "two erasures",
erase: []int{2, 0},
expectError: false,
},
{
name: "three erasures",
erase: []int{2, 4, 0},
expectError: true,
},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
fragments := slices.Clone(fragments)
for _, idx := range tc.erase {
fragments[idx] = nil
}
for i, fragment := range fragments {
if fragment == nil {
fragments = append(fragments[:i], fragments[i+1:]...)
}
}
assembler := fragmentation.NewReedSolomonClockFrameAssembler()
assembledFrame, err := assembler.AssembleClockFrame(fragments)
switch {
case tc.expectError:
if err == nil {
t.Fatal("expected error")
}
return
case err != nil:
t.Fatal(err)
}
if !proto.Equal(assembledFrame, originalFrame) {
t.Fatalf("frame mismatch")
}
})
}
}
func TestClockFrameFragmentCircularBuffer(t *testing.T) {
t.Parallel()
splitter, err := fragmentation.NewReedSolomonClockFrameSplitter(4, 2)
if err != nil {
t.Fatal(err)
}
originalFrames := []*protobufs.ClockFrame{
{
Filter: bytes.Repeat([]byte{0x01}, 32),
FrameNumber: 123,
Timestamp: 456,
Padding: make([]byte, 20*1024*1024),
},
{
Filter: bytes.Repeat([]byte{0x02}, 32),
FrameNumber: 124,
Timestamp: 457,
Padding: make([]byte, 20*1024*1024),
},
{
Filter: bytes.Repeat([]byte{0x03}, 32),
FrameNumber: 125,
Timestamp: 458,
Padding: make([]byte, 20*1024*1024),
},
}
fragments := make([][]*protobufs.ClockFrameFragment, len(originalFrames))
for i, originalFrame := range originalFrames {
if _, err := rand.Read(originalFrame.Padding); err != nil {
t.Fatal(err)
}
fragments[i], err = splitter.SplitClockFrame(originalFrame)
if err != nil {
t.Fatal(err)
}
}
allFragments := slices.Concat(fragments...)
mrand.Shuffle(len(allFragments), func(i, j int) {
allFragments[i], allFragments[j] = allFragments[j], allFragments[i]
})
buffer, err := fragmentation.NewClockFrameFragmentCircularBuffer(
fragmentation.NewReedSolomonClockFrameFragmentBuffer,
3,
)
if err != nil {
t.Fatal(err)
}
var seen [3]bool
for _, fragment := range allFragments {
frame, err := buffer.AccumulateClockFrameFragment(fragment)
if err != nil {
t.Fatal(err)
}
if frame == nil {
continue
}
if !proto.Equal(frame, originalFrames[frame.FrameNumber-123]) {
t.Fatalf("frame mismatch")
}
if seen[frame.FrameNumber-123] {
t.Fatal("duplicate frame")
}
seen[frame.FrameNumber-123] = true
}
for i := range seen {
if !seen[i] {
t.Fatalf("missing frame: %d", i+123)
}
}
buffer, err = fragmentation.NewClockFrameFragmentCircularBuffer(
fragmentation.NewReedSolomonClockFrameFragmentBuffer,
2,
)
if err != nil {
t.Fatal(err)
}
clear(seen[:])
for _, fragments := range fragments {
for _, fragment := range fragments {
frame, err := buffer.AccumulateClockFrameFragment(fragment)
if err != nil {
t.Fatal(err)
}
if frame == nil {
continue
}
if !proto.Equal(frame, originalFrames[frame.FrameNumber-123]) {
t.Fatalf("frame mismatch")
}
if seen[frame.FrameNumber-123] {
t.Fatal("duplicate frame")
}
seen[frame.FrameNumber-123] = true
}
}
for i := range seen {
if !seen[i] {
t.Fatalf("missing frame: %d", i+123)
}
}
}
func TestReedSolomonClockFrameFragmentBuffer(t *testing.T) {
splitter, err := fragmentation.NewReedSolomonClockFrameSplitter(4, 2)
if err != nil {
t.Fatal(err)
}
originalFrame := &protobufs.ClockFrame{
Filter: bytes.Repeat([]byte{0x01}, 32),
FrameNumber: 123,
Timestamp: 456,
Padding: make([]byte, 20*1024*1024),
}
if _, err := rand.Read(originalFrame.Padding); err != nil {
t.Fatal(err)
}
fragments, err := splitter.SplitClockFrame(originalFrame)
if err != nil {
t.Fatal(err)
}
for _, tc := range []struct {
name string
fragments []*protobufs.ClockFrameFragment
errorIdx int
frameIdx int
}{
{
name: "one insert",
fragments: []*protobufs.ClockFrameFragment{
fragments[0],
},
errorIdx: -1,
frameIdx: -1,
},
{
name: "two insert",
fragments: []*protobufs.ClockFrameFragment{
fragments[0], fragments[2],
},
errorIdx: -1,
frameIdx: -1,
},
{
name: "three insert",
fragments: []*protobufs.ClockFrameFragment{
fragments[0], fragments[4], fragments[2],
},
errorIdx: -1,
frameIdx: -1,
},
{
name: "four insert",
fragments: []*protobufs.ClockFrameFragment{
fragments[0], fragments[4], fragments[1], fragments[2],
},
errorIdx: -1,
frameIdx: 3,
},
{
name: "one insert, one bogus",
fragments: []*protobufs.ClockFrameFragment{
fragments[0],
{
FrameNumber: 123,
Filter: bytes.Repeat([]byte{0x01}, 32),
Timestamp: 456,
},
},
errorIdx: 1,
frameIdx: -1,
},
{
name: "one insert, one duplicate",
fragments: []*protobufs.ClockFrameFragment{
fragments[0], fragments[0],
},
errorIdx: 1,
frameIdx: -1,
},
{
name: "four insert, one bogus",
fragments: []*protobufs.ClockFrameFragment{
fragments[0], fragments[2], fragments[4],
{
FrameNumber: 123,
Filter: bytes.Repeat([]byte{0x01}, 32),
Timestamp: 456,
},
fragments[1],
},
errorIdx: 3,
frameIdx: 4,
},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
buffer := fragmentation.NewReedSolomonClockFrameFragmentBuffer()
for i, fragment := range tc.fragments {
frame, err := buffer.AccumulateClockFrameFragment(fragment)
switch {
case tc.errorIdx == i:
if err == nil {
t.Fatal("expected error")
}
continue
case err != nil:
t.Fatal(err)
}
switch {
case tc.frameIdx == i:
if frame == nil {
t.Fatal("expected frame")
}
if !proto.Equal(frame, originalFrame) {
t.Fatalf("frame mismatch")
}
case frame != nil:
t.Fatal("unexpected frame")
}
}
})
}
}

View File

@ -0,0 +1,10 @@
package fragmentation
import "crypto/sha256"
const hashSize = 32
func hash(b []byte) []byte {
var h [hashSize]byte = sha256.Sum256(b)
return h[:]
}

View File

@ -0,0 +1,100 @@
package fragmentation_test
import (
"crypto/rand"
"crypto/sha256"
"testing"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/sha3"
)
func BenchmarkHashFunctions(b *testing.B) {
data := make([]byte, 20*1024*1024)
if _, err := rand.Read(data); err != nil {
b.Fatal(err)
}
for _, bc := range []struct {
name string
f func([]byte) []byte
}{
{
name: "SHA256-224",
f: func(data []byte) []byte {
b := sha256.Sum224(data)
return b[:]
},
},
{
name: "SHA256-256",
f: func(data []byte) []byte {
b := sha256.Sum256(data)
return b[:]
},
},
{
name: "SHA3-224",
f: func(data []byte) []byte {
b := sha3.Sum224(data)
return b[:]
},
},
{
name: "SHA3-256",
f: func(data []byte) []byte {
b := sha3.Sum256(data)
return b[:]
},
},
{
name: "SHA3-384",
f: func(data []byte) []byte {
b := sha3.Sum384(data)
return b[:]
},
},
{
name: "SHA3-512",
f: func(data []byte) []byte {
b := sha3.Sum512(data)
return b[:]
},
},
{
name: "BLAKE2b-256",
f: func(data []byte) []byte {
b := blake2b.Sum256(data)
return b[:]
},
},
{
name: "BLAKE2b-384",
f: func(data []byte) []byte {
b := blake2b.Sum384(data)
return b[:]
},
},
{
name: "BLAKE2b-512",
f: func(data []byte) []byte {
b := blake2b.Sum512(data)
return b[:]
},
},
{
name: "BLAKE2s-256",
f: func(data []byte) []byte {
b := blake2s.Sum256(data)
return b[:]
},
},
} {
b.Run(bc.name, func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = bc.f(data)
}
})
}
}

View File

@ -42,10 +42,52 @@ func (
return frameProverTries
}
func (e *DataClockConsensusEngine) GetFrameProverTrie(i int) *tries.RollingFrecencyCritbitTrie {
e.frameProverTriesMx.RLock()
defer e.frameProverTriesMx.RUnlock()
newTrie := &tries.RollingFrecencyCritbitTrie{}
if i < 0 || i >= len(e.frameProverTries) {
return newTrie
}
b, err := e.frameProverTries[i].Serialize()
if err != nil {
panic(err)
}
if err := newTrie.Deserialize(b); err != nil {
panic(err)
}
return newTrie
}
func (e *DataClockConsensusEngine) FrameProverTriesContains(
key []byte,
) bool {
e.frameProverTriesMx.RLock()
defer e.frameProverTriesMx.RUnlock()
for _, trie := range e.frameProverTries {
if trie.Contains(key) {
return true
}
}
return false
}
func (e *DataClockConsensusEngine) FrameProverTrieContains(
i int,
key []byte,
) bool {
e.frameProverTriesMx.RLock()
defer e.frameProverTriesMx.RUnlock()
if i < 0 || i >= len(e.frameProverTries) {
return false
}
return e.frameProverTries[i].Contains(key)
}
func (e *DataClockConsensusEngine) runFramePruning() {
defer e.wg.Done()
// A full prover should _never_ do this
if e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) ||
if e.FrameProverTrieContains(0, e.provingKeyAddress) ||
e.config.Engine.MaxFrames == -1 || e.config.Engine.FullProver {
e.logger.Info("frame pruning not enabled")
return
@ -88,7 +130,7 @@ func (e *DataClockConsensusEngine) runFramePruning() {
func (e *DataClockConsensusEngine) runSync() {
defer e.wg.Done()
// small optimization, beacon should never collect for now:
if e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) {
if e.FrameProverTrieContains(0, e.provingKeyAddress) {
return
}
@ -130,7 +172,7 @@ func (e *DataClockConsensusEngine) runLoop() {
}
if runOnce {
if e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) {
if e.FrameProverTrieContains(0, e.provingKeyAddress) {
dataFrame, err := e.dataTimeReel.Head()
if err != nil {
panic(err)
@ -148,9 +190,9 @@ func (e *DataClockConsensusEngine) runLoop() {
e.validationFilterMx.Lock()
e.validationFilter = make(map[string]struct{}, len(e.validationFilter))
e.validationFilterMx.Unlock()
if e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) {
if err = e.publishProof(dataFrame); err != nil {
e.logger.Error("could not publish", zap.Error(err))
if e.FrameProverTrieContains(0, e.provingKeyAddress) {
if err := e.publishProof(dataFrame); err != nil {
e.logger.Error("could not publish proof", zap.Error(err))
e.stateMx.Lock()
if e.state < consensus.EngineStateStopping {
e.state = consensus.EngineStateCollecting
@ -174,7 +216,7 @@ func (e *DataClockConsensusEngine) processFrame(
zap.Duration("frame_age", frametime.Since(dataFrame)),
)
var err error
if !e.GetFrameProverTries()[0].Contains(e.provingKeyBytes) {
if !e.FrameProverTrieContains(0, e.provingKeyAddress) {
select {
case e.requestSyncCh <- struct{}{}:
default:
@ -190,7 +232,7 @@ func (e *DataClockConsensusEngine) processFrame(
e.frameProverTries = e.dataTimeReel.GetFrameProverTries()
e.frameProverTriesMx.Unlock()
trie := e.GetFrameProverTries()[0]
trie := e.GetFrameProverTrie(0)
selBI, _ := dataFrame.GetSelector()
sel := make([]byte, 32)
sel = selBI.FillBytes(sel)
@ -234,8 +276,8 @@ func (e *DataClockConsensusEngine) processFrame(
peerProvingKeyAddress := h.FillBytes(make([]byte, 32))
ring := -1
if len(e.GetFrameProverTries()) > 1 {
for i, tries := range e.GetFrameProverTries()[1:] {
if tries := e.GetFrameProverTries(); len(tries) > 1 {
for i, tries := range tries[1:] {
i := i
if tries.Contains(peerProvingKeyAddress) {
ring = i
@ -333,7 +375,9 @@ func (e *DataClockConsensusEngine) processFrame(
zap.Duration("frame_age", frametime.Since(latestFrame)),
)
e.publishMessage(e.txFilter, mint.TokenRequest())
if err := e.publishMessage(e.txFilter, mint.TokenRequest()); err != nil {
e.logger.Error("could not publish mint", zap.Error(err))
}
if e.config.Engine.AutoMergeCoins {
_, addrs, _, err := e.coinStore.GetCoinsForOwner(
@ -370,7 +414,9 @@ func (e *DataClockConsensusEngine) processFrame(
return latestFrame
}
e.publishMessage(e.txFilter, merge.TokenRequest())
if err := e.publishMessage(e.txFilter, merge.TokenRequest()); err != nil {
e.logger.Warn("could not publish merge", zap.Error(err))
}
}
}
}

View File

@ -30,13 +30,13 @@ func (e *DataClockConsensusEngine) runFrameMessageHandler() {
msg := &protobufs.Message{}
if err := proto.Unmarshal(message.Data, msg); err != nil {
e.logger.Debug("bad message")
e.logger.Debug("cannot unmarshal data", zap.Error(err))
continue
}
a := &anypb.Any{}
if err := proto.Unmarshal(msg.Payload, a); err != nil {
e.logger.Error("error while unmarshaling", zap.Error(err))
e.logger.Debug("cannot unmarshal payload", zap.Error(err))
continue
}
@ -46,7 +46,6 @@ func (e *DataClockConsensusEngine) runFrameMessageHandler() {
message.From,
msg.Address,
a,
false,
); err != nil {
e.logger.Debug("could not handle clock frame data", zap.Error(err))
}
@ -55,6 +54,41 @@ func (e *DataClockConsensusEngine) runFrameMessageHandler() {
}
}
func (e *DataClockConsensusEngine) runFrameFragmentMessageHandler() {
defer e.wg.Done()
for {
select {
case <-e.ctx.Done():
return
case message := <-e.frameFragmentMessageProcessorCh:
e.logger.Debug("handling frame fragment message")
msg := &protobufs.Message{}
if err := proto.Unmarshal(message.Data, msg); err != nil {
e.logger.Debug("cannot unmarshal data", zap.Error(err))
continue
}
a := &anypb.Any{}
if err := proto.Unmarshal(msg.Payload, a); err != nil {
e.logger.Debug("cannot unmarshal payload", zap.Error(err))
continue
}
switch a.TypeUrl {
case protobufs.ClockFrameFragmentType:
if err := e.handleClockFrameFragmentData(
message.From,
msg.Address,
a,
); err != nil {
e.logger.Debug("could not handle clock frame fragment data", zap.Error(err))
}
}
}
}
}
func (e *DataClockConsensusEngine) runTxMessageHandler() {
defer e.wg.Done()
for {
@ -66,12 +100,13 @@ func (e *DataClockConsensusEngine) runTxMessageHandler() {
msg := &protobufs.Message{}
if err := proto.Unmarshal(message.Data, msg); err != nil {
e.logger.Debug("bad message")
e.logger.Debug("could not unmarshal data", zap.Error(err))
continue
}
a := &anypb.Any{}
if err := proto.Unmarshal(msg.Payload, a); err != nil {
e.logger.Debug("could not unmarshal payload", zap.Error(err))
continue
}
@ -142,13 +177,13 @@ func (e *DataClockConsensusEngine) runInfoMessageHandler() {
msg := &protobufs.Message{}
if err := proto.Unmarshal(message.Data, msg); err != nil {
e.logger.Debug("bad message")
e.logger.Debug("could not unmarshal data", zap.Error(err))
continue
}
a := &anypb.Any{}
if err := proto.Unmarshal(msg.Payload, a); err != nil {
e.logger.Error("error while unmarshaling", zap.Error(err))
e.logger.Debug("could not unmarshal payload", zap.Error(err))
continue
}
@ -182,8 +217,7 @@ func (e *DataClockConsensusEngine) handleClockFrame(
return errors.Wrap(err, "handle clock frame data")
}
trie := e.GetFrameProverTries()[0]
if !trie.Contains(addr.FillBytes(make([]byte, 32))) {
if !e.FrameProverTrieContains(0, addr.FillBytes(make([]byte, 32))) {
e.logger.Debug(
"prover not in trie at frame, address may be in fork",
zap.Binary("address", address),
@ -225,35 +259,103 @@ func (e *DataClockConsensusEngine) handleClockFrame(
return nil
}
func (e *DataClockConsensusEngine) handleClockFrameFragment(
peerID []byte,
address []byte,
fragment *protobufs.ClockFrameFragment,
) error {
if fragment == nil {
return errors.Wrap(errors.New("fragment is nil"), "handle clock frame fragment")
}
addr, err := poseidon.HashBytes(
fragment.GetPublicKeySignatureEd448().PublicKey.KeyValue,
)
if err != nil {
return errors.Wrap(err, "handle clock frame fragment data")
}
if !e.FrameProverTrieContains(0, addr.FillBytes(make([]byte, 32))) {
e.logger.Debug(
"prover not in trie at frame fragment, address may be in fork",
zap.Binary("address", address),
zap.Binary("filter", fragment.Filter),
zap.Uint64("frame_number", fragment.FrameNumber),
)
return nil
}
e.logger.Debug(
"got clock frame fragment",
zap.Binary("address", address),
zap.Binary("filter", fragment.Filter),
zap.Uint64("frame_number", fragment.FrameNumber),
)
frame, err := e.clockFrameFragmentBuffer.AccumulateClockFrameFragment(fragment)
if err != nil {
e.logger.Debug("could not accumulate clock frame fragment", zap.Error(err))
return errors.Wrap(err, "handle clock frame fragment data")
}
if frame == nil {
return nil
}
e.logger.Info(
"accumulated clock frame",
zap.Binary("address", address),
zap.Binary("filter", frame.Filter),
zap.Uint64("frame_number", frame.FrameNumber),
)
return e.handleClockFrame(peerID, address, frame)
}
func (e *DataClockConsensusEngine) handleClockFrameData(
peerID []byte,
address []byte,
any *anypb.Any,
isSync bool,
a *anypb.Any,
) error {
if bytes.Equal(peerID, e.pubSub.GetPeerID()) {
return nil
}
frame := &protobufs.ClockFrame{}
if err := any.UnmarshalTo(frame); err != nil {
if err := a.UnmarshalTo(frame); err != nil {
return errors.Wrap(err, "handle clock frame data")
}
return e.handleClockFrame(peerID, address, frame)
}
func (e *DataClockConsensusEngine) handleClockFrameFragmentData(
peerID []byte,
address []byte,
a *anypb.Any,
) error {
if bytes.Equal(peerID, e.pubSub.GetPeerID()) {
return nil
}
fragment := &protobufs.ClockFrameFragment{}
if err := a.UnmarshalTo(fragment); err != nil {
return errors.Wrap(err, "handle clock frame fragment data")
}
return e.handleClockFrameFragment(peerID, address, fragment)
}
func (e *DataClockConsensusEngine) handleDataPeerListAnnounce(
peerID []byte,
address []byte,
any *anypb.Any,
a *anypb.Any,
) error {
if bytes.Equal(peerID, e.pubSub.GetPeerID()) {
return nil
}
announce := &protobufs.DataPeerListAnnounce{}
if err := any.UnmarshalTo(announce); err != nil {
if err := a.UnmarshalTo(announce); err != nil {
return errors.Wrap(err, "handle data peer list announce")
}
@ -314,6 +416,7 @@ func (e *DataClockConsensusEngine) handleDataPeerListAnnounce(
version: p.Version,
patchVersion: patchVersion,
totalDistance: p.TotalDistance,
reachability: p.ExternallyReachable,
}
e.peerMapMx.Unlock()
@ -369,7 +472,7 @@ func TokenRequestIdentifiers(transition *protobufs.TokenRequest) []string {
func (e *DataClockConsensusEngine) handleTokenRequest(
transition *protobufs.TokenRequest,
) error {
if e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) {
if e.FrameProverTrieContains(0, e.provingKeyAddress) {
identifiers := TokenRequestIdentifiers(transition)
e.stagedTransactionsMx.Lock()

View File

@ -37,6 +37,33 @@ func (e *DataClockConsensusEngine) validateFrameMessage(peerID peer.ID, message
}
}
func (e *DataClockConsensusEngine) validateFrameFragmentMessage(peerID peer.ID, message *pb.Message) p2p.ValidationResult {
msg := &protobufs.Message{}
if err := proto.Unmarshal(message.Data, msg); err != nil {
return p2p.ValidationResultReject
}
a := &anypb.Any{}
if err := proto.Unmarshal(msg.Payload, a); err != nil {
return p2p.ValidationResultReject
}
switch a.TypeUrl {
case protobufs.ClockFrameFragmentType:
fragment := &protobufs.ClockFrameFragment{}
if err := proto.Unmarshal(a.Value, fragment); err != nil {
return p2p.ValidationResultReject
}
if err := fragment.Validate(); err != nil {
return p2p.ValidationResultReject
}
if ts := time.UnixMilli(fragment.Timestamp); time.Since(ts) > 2*time.Minute {
return p2p.ValidationResultIgnore
}
return p2p.ValidationResultAccept
default:
return p2p.ValidationResultReject
}
}
func (e *DataClockConsensusEngine) validateTxMessage(peerID peer.ID, message *pb.Message) p2p.ValidationResult {
msg := &protobufs.Message{}
if err := proto.Unmarshal(message.Data, msg); err != nil {
@ -94,11 +121,6 @@ func (e *DataClockConsensusEngine) validateTxMessage(peerID peer.ID, message *pb
return p2p.ValidationResultIgnore
}
}
if tx.Timestamp == 0 {
// NOTE: The timestamp was added in later versions of the protocol,
// and as such it is possible to receive requests without it.
return p2p.ValidationResultAccept
}
if ts := time.UnixMilli(tx.Timestamp); time.Since(ts) > 10*time.Minute {
return p2p.ValidationResultIgnore
}

View File

@ -128,7 +128,7 @@ func (e *DataClockConsensusEngine) GetPreMidnightMintStatus(
ctx context.Context,
t *protobufs.PreMidnightMintStatusRequest,
) (*protobufs.PreMidnightMintResponse, error) {
if !e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) {
if !e.FrameProverTrieContains(0, e.provingKeyAddress) {
return nil, errors.Wrap(
errors.New("wrong destination"),
"get pre midnight mint status",
@ -182,7 +182,7 @@ func (e *DataClockConsensusEngine) GetPreMidnightMintStatus(
func (e *DataClockConsensusEngine) handleMint(
t *protobufs.MintCoinRequest,
) ([]byte, error) {
if !e.GetFrameProverTries()[0].Contains(e.provingKeyAddress) {
if !e.FrameProverTrieContains(0, e.provingKeyAddress) {
return nil, errors.Wrap(errors.New("wrong destination"), "handle mint")
}
@ -243,7 +243,7 @@ func (e *DataClockConsensusEngine) handleMint(
t.Proofs[0],
[]byte("pre-dusk"),
) && (!bytes.Equal(t.Proofs[1], make([]byte, 32)) ||
time.Now().Unix() < 1730523600) && e.GetFrameProverTries()[0].Contains(
time.Now().Unix() < 1730523600) && e.FrameProverTrieContains(0,
e.provingKeyAddress,
) {
prevInput := []byte{}
@ -636,7 +636,7 @@ func (e *DataClockConsensusEngine) GetPublicChannelForProvingKey(
)
}
} else {
cc, err := e.pubSub.GetDirectChannel(peerID, base58.Encode(provingKey))
cc, err := e.pubSub.GetDirectChannel(e.ctx, peerID, base58.Encode(provingKey))
if err != nil {
e.logger.Error(
"could not get public channel for proving key",

View File

@ -85,7 +85,7 @@ func (e *DataClockConsensusEngine) runPreMidnightProofWorker() {
}
resume := make([]byte, 32)
cc, err := e.pubSub.GetDirectChannel([]byte(peerId), "worker")
cc, err := e.pubSub.GetDirectChannel(e.ctx, []byte(peerId), "worker")
if err != nil {
e.logger.Info(
"could not establish direct channel, waiting...",
@ -110,7 +110,7 @@ func (e *DataClockConsensusEngine) runPreMidnightProofWorker() {
}
if cc == nil {
cc, err = e.pubSub.GetDirectChannel([]byte(peerId), "worker")
cc, err = e.pubSub.GetDirectChannel(e.ctx, []byte(peerId), "worker")
if err != nil {
e.logger.Info(
"could not establish direct channel, waiting...",

View File

@ -55,13 +55,6 @@ func (e *DataClockConsensusEngine) IsInProverTrie(key []byte) bool {
if err != nil {
return false
}
provingKeyAddress := h.FillBytes(make([]byte, 32))
for _, tries := range e.GetFrameProverTries() {
if tries.Contains(provingKeyAddress) {
return true
}
}
return false
return e.FrameProverTriesContains(provingKeyAddress)
}

View File

@ -21,6 +21,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/wrapperspb"
"source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb"
"source.quilibrium.com/quilibrium/monorepo/node/consensus"
qtime "source.quilibrium.com/quilibrium/monorepo/node/consensus/time"
@ -64,7 +65,7 @@ func (pubsub) StartDirectChannelListener(
) error {
return nil
}
func (pubsub) GetDirectChannel(peerId []byte, purpose string) (*grpc.ClientConn, error) {
func (pubsub) GetDirectChannel(ctx context.Context, peerId []byte, purpose string) (*grpc.ClientConn, error) {
return nil, nil
}
func (pubsub) GetNetworkInfo() *protobufs.NetworkInfoResponse {
@ -80,6 +81,8 @@ func (pubsub) AddPeerScore(peerId []byte, scoreDelta int64) {}
func (pubsub) Reconnect(peerId []byte) error { return nil }
func (pubsub) Bootstrap(context.Context) error { return nil }
func (pubsub) DiscoverPeers(context.Context) error { return nil }
func (pubsub) IsPeerConnected(peerId []byte) bool { return false }
func (pubsub) Reachability() *wrapperspb.BoolValue { return nil }
type outputs struct {
difficulty uint32
@ -137,6 +140,7 @@ func TestHandlePreMidnightMint(t *testing.T) {
dataTimeReel: &qtime.DataTimeReel{},
peerInfoManager: nil,
frameMessageProcessorCh: make(chan *pb.Message),
frameFragmentMessageProcessorCh: make(chan *pb.Message),
txMessageProcessorCh: make(chan *pb.Message),
infoMessageProcessorCh: make(chan *pb.Message),
config: nil,

View File

@ -391,10 +391,12 @@ func NewTokenExecutionEngine(
}
}
}
e.publishMessage(
if err := e.publishMessage(
append([]byte{0x00}, e.intrinsicFilter...),
resume.TokenRequest(),
)
); err != nil {
e.logger.Warn("error while publishing resume message", zap.Error(err))
}
}
}()
@ -473,7 +475,7 @@ func (e *TokenExecutionEngine) ProcessMessage(
switch a.TypeUrl {
case protobufs.TokenRequestType:
if e.clock.IsInProverTrie(e.proverPublicKey) {
if e.clock.FrameProverTriesContains(e.provingKeyAddress) {
payload, err := proto.Marshal(a)
if err != nil {
return nil, errors.Wrap(err, "process message")
@ -1436,10 +1438,12 @@ func (e *TokenExecutionEngine) AnnounceProverJoin() {
panic(err)
}
e.publishMessage(
if err := e.publishMessage(
append([]byte{0x00}, e.intrinsicFilter...),
join.TokenRequest(),
)
); err != nil {
e.logger.Warn("error publishing join message", zap.Error(err))
}
}
func (e *TokenExecutionEngine) GetRingPosition() int {

View File

@ -15,8 +15,6 @@ replace github.com/multiformats/go-multiaddr => ../go-multiaddr
replace github.com/multiformats/go-multiaddr-dns => ../go-multiaddr-dns
replace github.com/libp2p/go-buffer-pool => ../go-buffer-pool
replace github.com/libp2p/go-libp2p => ../go-libp2p
replace github.com/libp2p/go-libp2p-kad-dht => ../go-libp2p-kad-dht
@ -29,6 +27,7 @@ require (
github.com/cockroachdb/pebble v0.0.0-20231210175920-b4d301aeb46a
github.com/deiu/rdf2go v0.0.0-20240619132609-81222e324bb9
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
github.com/klauspost/reedsolomon v1.12.4
github.com/libp2p/go-libp2p v0.35.4
github.com/libp2p/go-libp2p-kad-dht v0.23.0
github.com/shopspring/decimal v1.4.0
@ -144,7 +143,7 @@ require (
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
@ -201,7 +200,7 @@ require (
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.21.0
golang.org/x/sys v0.27.0
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
gonum.org/v1/gonum v0.13.0 // indirect

View File

@ -260,8 +260,10 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/klauspost/reedsolomon v1.12.4 h1:5aDr3ZGoJbgu/8+j45KtUJxzYm8k08JGtB9Wx1VQ4OA=
github.com/klauspost/reedsolomon v1.12.4/go.mod h1:d3CzOMOt0JXGIFZm1StgkyF14EYr3xneR2rNWo7NcMU=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -275,6 +277,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
@ -691,8 +695,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@ -406,7 +406,6 @@ func main() {
}
if *core != 0 {
rdebug.SetGCPercent(9999)
rdebug.SetMemoryLimit(nodeConfig.Engine.DataWorkerMemoryLimit)
if *parentProcess == 0 && len(nodeConfig.Engine.DataWorkerMultiaddrs) == 0 {
@ -458,9 +457,6 @@ func main() {
fmt.Println("The memory available to the node, unallocated to the data workers, is less than 8GiB.")
fmt.Println("You are at risk of running out of memory during runtime.")
default:
if _, explicitGOGC := os.LookupEnv("GOGC"); !explicitGOGC {
rdebug.SetGCPercent(9999)
}
if _, explicitGOMEMLIMIT := os.LookupEnv("GOMEMLIMIT"); !explicitGOMEMLIMIT {
rdebug.SetMemoryLimit(availableOverhead * 8 / 10)
}

View File

@ -11,6 +11,7 @@ import (
"math/bits"
"net"
"sync"
"sync/atomic"
"time"
"github.com/libp2p/go-libp2p"
@ -38,6 +39,7 @@ import (
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/types/known/wrapperspb"
blossomsub "source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub"
"source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb"
"source.quilibrium.com/quilibrium/monorepo/node/config"
@ -80,9 +82,10 @@ type BlossomSub struct {
signKey crypto.PrivKey
peerScore map[string]*appScore
peerScoreMx sync.Mutex
network uint8
bootstrap internal.PeerConnector
discovery internal.PeerConnector
reachability atomic.Pointer[network.Reachability]
p2pConfig config.P2PConfig
}
var _ PubSub = (*BlossomSub)(nil)
@ -157,7 +160,7 @@ func NewBlossomSubStreamer(
bitmaskMap: make(map[string]*blossomsub.Bitmask),
signKey: privKey,
peerScore: make(map[string]*appScore),
network: p2pConfig.Network,
p2pConfig: *p2pConfig,
}
h, err := libp2p.New(opts...)
@ -311,7 +314,7 @@ func NewBlossomSub(
bitmaskMap: make(map[string]*blossomsub.Bitmask),
signKey: privKey,
peerScore: make(map[string]*appScore),
network: p2pConfig.Network,
p2pConfig: *p2pConfig,
}
h, err := libp2p.New(opts...)
@ -337,7 +340,9 @@ func NewBlossomSub(
if !ok {
return
}
switch state := evt.(event.EvtLocalReachabilityChanged).Reachability; state {
state := evt.(event.EvtLocalReachabilityChanged).Reachability
bs.reachability.Store(&state)
switch state {
case network.ReachabilityPublic:
logger.Info("node is externally reachable")
case network.ReachabilityPrivate:
@ -471,6 +476,7 @@ func NewBlossomSub(
blossomOpts = append(blossomOpts,
blossomsub.WithValidateQueueSize(p2pConfig.ValidateQueueSize),
blossomsub.WithValidateWorkers(p2pConfig.ValidateWorkers),
blossomsub.WithPeerOutboundQueueSize(p2pConfig.PeerOutboundQueueSize),
)
blossomOpts = append(blossomOpts, observability.WithPrometheusRawTracer())
blossomOpts = append(blossomOpts, blossomsub.WithPeerFilter(internal.NewStaticPeerFilter(
@ -488,7 +494,7 @@ func NewBlossomSub(
))
params := toBlossomSubParams(p2pConfig)
rt := blossomsub.NewBlossomSubRouter(h, params, bs.network)
rt := blossomsub.NewBlossomSubRouter(h, params, bs.p2pConfig.Network)
blossomOpts = append(blossomOpts, rt.WithDefaultTagTracer())
pubsub, err := blossomsub.NewBlossomSubWithRouter(ctx, h, rt, blossomOpts...)
if err != nil {
@ -652,7 +658,7 @@ func (b *BlossomSub) Subscribe(
b.logger.Info("subscribe to bitmask", zap.Binary("bitmask", bitmask))
subs := []*blossomsub.Subscription{}
for _, bit := range bm {
sub, err := bit.Subscribe()
sub, err := bit.Subscribe(blossomsub.WithBufferSize(b.p2pConfig.SubscriptionQueueSize))
if err != nil {
b.logger.Error("subscription failed", zap.Error(err))
return errors.Wrap(err, "subscribe")
@ -696,7 +702,9 @@ func (b *BlossomSub) Subscribe(
}
func (b *BlossomSub) Unsubscribe(bitmask []byte, raw bool) {
networkBitmask := append([]byte{b.network}, bitmask...)
// TODO: Fix this, it is broken - the bitmask parameter is not sliced, and the
// network is not pre-pended to the bitmask.
networkBitmask := append([]byte{b.p2pConfig.Network}, bitmask...)
bm, ok := b.bitmaskMap[string(networkBitmask)]
if !ok {
return
@ -735,7 +743,9 @@ func (b *BlossomSub) GetPeerID() []byte {
}
func (b *BlossomSub) GetRandomPeer(bitmask []byte) ([]byte, error) {
networkBitmask := append([]byte{b.network}, bitmask...)
// TODO: Fix this, it is broken - the bitmask parameter is not sliced, and the
// network is not pre-pended to the bitmask.
networkBitmask := append([]byte{b.p2pConfig.Network}, bitmask...)
peers := b.ps.ListPeers(networkBitmask)
if len(peers) == 0 {
return nil, errors.Wrap(
@ -752,6 +762,27 @@ func (b *BlossomSub) GetRandomPeer(bitmask []byte) ([]byte, error) {
return []byte(peers[sel.Int64()]), nil
}
func (b *BlossomSub) IsPeerConnected(peerId []byte) bool {
peerID := peer.ID(peerId)
connectedness := b.h.Network().Connectedness(peerID)
return connectedness == network.Connected || connectedness == network.Limited
}
func (b *BlossomSub) Reachability() *wrapperspb.BoolValue {
reachability := b.reachability.Load()
if reachability == nil {
return nil
}
switch *reachability {
case network.ReachabilityPublic:
return wrapperspb.Bool(true)
case network.ReachabilityPrivate:
return wrapperspb.Bool(false)
default:
return nil
}
}
func initDHT(
ctx context.Context,
logger *zap.Logger,
@ -849,6 +880,8 @@ func (b *BlossomSub) AddPeerScore(peerId []byte, scoreDelta int64) {
func (b *BlossomSub) GetBitmaskPeers() map[string][]string {
peers := map[string][]string{}
// TODO: Fix this, it is broken - the bitmask parameter is not sliced, and the
// network is not pre-pended to the bitmask.
for _, k := range b.bitmaskMap {
peers[fmt.Sprintf("%+x", k.Bitmask()[1:])] = []string{}
@ -905,7 +938,7 @@ func (b *BlossomSub) GetMultiaddrOfPeer(peerId []byte) string {
}
func (b *BlossomSub) GetNetwork() uint {
return uint(b.network)
return uint(b.p2pConfig.Network)
}
func (b *BlossomSub) StartDirectChannelListener(
@ -937,7 +970,7 @@ func (c *extraCloseConn) Close() error {
return err
}
func (b *BlossomSub) GetDirectChannel(peerID []byte, purpose string) (
func (b *BlossomSub) GetDirectChannel(ctx context.Context, peerID []byte, purpose string) (
cc *grpc.ClientConn, err error,
) {
// Kind of a weird hack, but gostream can induce panics if the peer drops at
@ -954,7 +987,7 @@ func (b *BlossomSub) GetDirectChannel(peerID []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.
cc, err = qgrpc.DialContext(
b.ctx,
ctx,
"passthrough:///",
grpc.WithContextDialer(
func(ctx context.Context, _ string) (net.Conn, error) {
@ -991,6 +1024,7 @@ func (b *BlossomSub) GetDirectChannel(peerID []byte, purpose string) (
},
),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
)
if err != nil {
return nil, errors.Wrap(err, "dial context")
@ -1138,6 +1172,12 @@ func withDefaults(p2pConfig *config.P2PConfig) *config.P2PConfig {
if p2pConfig.ValidateWorkers == 0 {
p2pConfig.ValidateWorkers = qruntime.WorkerCount(0, false)
}
if p2pConfig.SubscriptionQueueSize == 0 {
p2pConfig.SubscriptionQueueSize = blossomsub.DefaultSubscriptionQueueSize
}
if p2pConfig.PeerOutboundQueueSize == 0 {
p2pConfig.PeerOutboundQueueSize = blossomsub.DefaultPeerOutboundQueueSize
}
return p2pConfig
}

View File

@ -6,6 +6,7 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/wrapperspb"
"source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
)
@ -44,7 +45,7 @@ type PubSub interface {
purpose string,
server *grpc.Server,
) error
GetDirectChannel(peerId []byte, purpose string) (*grpc.ClientConn, error)
GetDirectChannel(ctx context.Context, peerId []byte, purpose string) (*grpc.ClientConn, error)
GetNetworkInfo() *protobufs.NetworkInfoResponse
SignMessage(msg []byte) ([]byte, error)
GetPublicKey() []byte
@ -55,4 +56,6 @@ type PubSub interface {
Bootstrap(ctx context.Context) error
DiscoverPeers(ctx context.Context) error
GetNetwork() uint
IsPeerConnected(peerId []byte) bool
Reachability() *wrapperspb.BoolValue
}

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.30.0
// protoc v3.21.12
// protoc-gen-go v1.34.1
// protoc v5.27.0
// source: clock.proto
package protobufs
@ -78,6 +78,8 @@ type ClockFrame struct {
//
// *ClockFrame_PublicKeySignatureEd448
PublicKeySignature isClockFrame_PublicKeySignature `protobuf_oneof:"public_key_signature"`
// Padding is used in tests in order to simulate large clock frames.
Padding []byte `protobuf:"bytes,99,opt,name=padding,proto3" json:"padding,omitempty"`
}
func (x *ClockFrame) Reset() {
@ -182,6 +184,13 @@ func (x *ClockFrame) GetPublicKeySignatureEd448() *Ed448Signature {
return nil
}
func (x *ClockFrame) GetPadding() []byte {
if x != nil {
return x.Padding
}
return nil
}
type isClockFrame_PublicKeySignature interface {
isClockFrame_PublicKeySignature()
}
@ -192,6 +201,138 @@ type ClockFrame_PublicKeySignatureEd448 struct {
func (*ClockFrame_PublicKeySignatureEd448) isClockFrame_PublicKeySignature() {}
// Represents a clock frame fragment for a given filter. Clock frame fragments
// are used to disseminate clock frame data across the network in a more
// efficient manner. This is particularly useful for large clock frames, where
// the frame data can be split into smaller fragments and sent across the
// network in parallel.
type ClockFrameFragment struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Filter []byte `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"`
FrameNumber uint64 `protobuf:"varint,2,opt,name=frame_number,json=frameNumber,proto3" json:"frame_number,omitempty"`
Timestamp int64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
FrameHash []byte `protobuf:"bytes,4,opt,name=frame_hash,json=frameHash,proto3" json:"frame_hash,omitempty"`
// Types that are assignable to Encoding:
//
// *ClockFrameFragment_ReedSolomon
Encoding isClockFrameFragment_Encoding `protobuf_oneof:"encoding"`
// Types that are assignable to PublicKeySignature:
//
// *ClockFrameFragment_PublicKeySignatureEd448
PublicKeySignature isClockFrameFragment_PublicKeySignature `protobuf_oneof:"public_key_signature"`
}
func (x *ClockFrameFragment) Reset() {
*x = ClockFrameFragment{}
if protoimpl.UnsafeEnabled {
mi := &file_clock_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ClockFrameFragment) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ClockFrameFragment) ProtoMessage() {}
func (x *ClockFrameFragment) ProtoReflect() protoreflect.Message {
mi := &file_clock_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ClockFrameFragment.ProtoReflect.Descriptor instead.
func (*ClockFrameFragment) Descriptor() ([]byte, []int) {
return file_clock_proto_rawDescGZIP(), []int{1}
}
func (x *ClockFrameFragment) GetFilter() []byte {
if x != nil {
return x.Filter
}
return nil
}
func (x *ClockFrameFragment) GetFrameNumber() uint64 {
if x != nil {
return x.FrameNumber
}
return 0
}
func (x *ClockFrameFragment) GetTimestamp() int64 {
if x != nil {
return x.Timestamp
}
return 0
}
func (x *ClockFrameFragment) GetFrameHash() []byte {
if x != nil {
return x.FrameHash
}
return nil
}
func (m *ClockFrameFragment) GetEncoding() isClockFrameFragment_Encoding {
if m != nil {
return m.Encoding
}
return nil
}
func (x *ClockFrameFragment) GetReedSolomon() *ClockFrameFragment_ReedSolomonEncoding {
if x, ok := x.GetEncoding().(*ClockFrameFragment_ReedSolomon); ok {
return x.ReedSolomon
}
return nil
}
func (m *ClockFrameFragment) GetPublicKeySignature() isClockFrameFragment_PublicKeySignature {
if m != nil {
return m.PublicKeySignature
}
return nil
}
func (x *ClockFrameFragment) GetPublicKeySignatureEd448() *Ed448Signature {
if x, ok := x.GetPublicKeySignature().(*ClockFrameFragment_PublicKeySignatureEd448); ok {
return x.PublicKeySignatureEd448
}
return nil
}
type isClockFrameFragment_Encoding interface {
isClockFrameFragment_Encoding()
}
type ClockFrameFragment_ReedSolomon struct {
ReedSolomon *ClockFrameFragment_ReedSolomonEncoding `protobuf:"bytes,5,opt,name=reed_solomon,json=reedSolomon,proto3,oneof"`
}
func (*ClockFrameFragment_ReedSolomon) isClockFrameFragment_Encoding() {}
type isClockFrameFragment_PublicKeySignature interface {
isClockFrameFragment_PublicKeySignature()
}
type ClockFrameFragment_PublicKeySignatureEd448 struct {
PublicKeySignatureEd448 *Ed448Signature `protobuf:"bytes,6,opt,name=public_key_signature_ed448,json=publicKeySignatureEd448,proto3,oneof"`
}
func (*ClockFrameFragment_PublicKeySignatureEd448) isClockFrameFragment_PublicKeySignature() {}
type ClockFrameParentSelectors struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -204,7 +345,7 @@ type ClockFrameParentSelectors struct {
func (x *ClockFrameParentSelectors) Reset() {
*x = ClockFrameParentSelectors{}
if protoimpl.UnsafeEnabled {
mi := &file_clock_proto_msgTypes[1]
mi := &file_clock_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -217,7 +358,7 @@ func (x *ClockFrameParentSelectors) String() string {
func (*ClockFrameParentSelectors) ProtoMessage() {}
func (x *ClockFrameParentSelectors) ProtoReflect() protoreflect.Message {
mi := &file_clock_proto_msgTypes[1]
mi := &file_clock_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -230,7 +371,7 @@ func (x *ClockFrameParentSelectors) ProtoReflect() protoreflect.Message {
// Deprecated: Use ClockFrameParentSelectors.ProtoReflect.Descriptor instead.
func (*ClockFrameParentSelectors) Descriptor() ([]byte, []int) {
return file_clock_proto_rawDescGZIP(), []int{1}
return file_clock_proto_rawDescGZIP(), []int{2}
}
func (x *ClockFrameParentSelectors) GetFrameNumber() uint64 {
@ -272,7 +413,7 @@ type ClockFramesRequest struct {
func (x *ClockFramesRequest) Reset() {
*x = ClockFramesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_clock_proto_msgTypes[2]
mi := &file_clock_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -285,7 +426,7 @@ func (x *ClockFramesRequest) String() string {
func (*ClockFramesRequest) ProtoMessage() {}
func (x *ClockFramesRequest) ProtoReflect() protoreflect.Message {
mi := &file_clock_proto_msgTypes[2]
mi := &file_clock_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -298,7 +439,7 @@ func (x *ClockFramesRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ClockFramesRequest.ProtoReflect.Descriptor instead.
func (*ClockFramesRequest) Descriptor() ([]byte, []int) {
return file_clock_proto_rawDescGZIP(), []int{2}
return file_clock_proto_rawDescGZIP(), []int{3}
}
func (x *ClockFramesRequest) GetFilter() []byte {
@ -347,7 +488,7 @@ type ClockFramesPreflight struct {
func (x *ClockFramesPreflight) Reset() {
*x = ClockFramesPreflight{}
if protoimpl.UnsafeEnabled {
mi := &file_clock_proto_msgTypes[3]
mi := &file_clock_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -360,7 +501,7 @@ func (x *ClockFramesPreflight) String() string {
func (*ClockFramesPreflight) ProtoMessage() {}
func (x *ClockFramesPreflight) ProtoReflect() protoreflect.Message {
mi := &file_clock_proto_msgTypes[3]
mi := &file_clock_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -373,7 +514,7 @@ func (x *ClockFramesPreflight) ProtoReflect() protoreflect.Message {
// Deprecated: Use ClockFramesPreflight.ProtoReflect.Descriptor instead.
func (*ClockFramesPreflight) Descriptor() ([]byte, []int) {
return file_clock_proto_rawDescGZIP(), []int{3}
return file_clock_proto_rawDescGZIP(), []int{4}
}
func (x *ClockFramesPreflight) GetRangeParentSelectors() []*ClockFrameParentSelectors {
@ -404,7 +545,7 @@ type ClockFramesResponse struct {
func (x *ClockFramesResponse) Reset() {
*x = ClockFramesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_clock_proto_msgTypes[4]
mi := &file_clock_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -417,7 +558,7 @@ func (x *ClockFramesResponse) String() string {
func (*ClockFramesResponse) ProtoMessage() {}
func (x *ClockFramesResponse) ProtoReflect() protoreflect.Message {
mi := &file_clock_proto_msgTypes[4]
mi := &file_clock_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -430,7 +571,7 @@ func (x *ClockFramesResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ClockFramesResponse.ProtoReflect.Descriptor instead.
func (*ClockFramesResponse) Descriptor() ([]byte, []int) {
return file_clock_proto_rawDescGZIP(), []int{4}
return file_clock_proto_rawDescGZIP(), []int{5}
}
func (x *ClockFramesResponse) GetFilter() []byte {
@ -461,6 +602,85 @@ func (x *ClockFramesResponse) GetClockFrames() []*ClockFrame {
return nil
}
type ClockFrameFragment_ReedSolomonEncoding struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FrameSize uint64 `protobuf:"varint,1,opt,name=frame_size,json=frameSize,proto3" json:"frame_size,omitempty"`
FragmentShard uint64 `protobuf:"varint,2,opt,name=fragment_shard,json=fragmentShard,proto3" json:"fragment_shard,omitempty"`
FragmentDataShardCount uint64 `protobuf:"varint,3,opt,name=fragment_data_shard_count,json=fragmentDataShardCount,proto3" json:"fragment_data_shard_count,omitempty"`
FragmentParityShardCount uint64 `protobuf:"varint,4,opt,name=fragment_parity_shard_count,json=fragmentParityShardCount,proto3" json:"fragment_parity_shard_count,omitempty"`
FragmentData []byte `protobuf:"bytes,5,opt,name=fragment_data,json=fragmentData,proto3" json:"fragment_data,omitempty"`
}
func (x *ClockFrameFragment_ReedSolomonEncoding) Reset() {
*x = ClockFrameFragment_ReedSolomonEncoding{}
if protoimpl.UnsafeEnabled {
mi := &file_clock_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ClockFrameFragment_ReedSolomonEncoding) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ClockFrameFragment_ReedSolomonEncoding) ProtoMessage() {}
func (x *ClockFrameFragment_ReedSolomonEncoding) ProtoReflect() protoreflect.Message {
mi := &file_clock_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ClockFrameFragment_ReedSolomonEncoding.ProtoReflect.Descriptor instead.
func (*ClockFrameFragment_ReedSolomonEncoding) Descriptor() ([]byte, []int) {
return file_clock_proto_rawDescGZIP(), []int{1, 0}
}
func (x *ClockFrameFragment_ReedSolomonEncoding) GetFrameSize() uint64 {
if x != nil {
return x.FrameSize
}
return 0
}
func (x *ClockFrameFragment_ReedSolomonEncoding) GetFragmentShard() uint64 {
if x != nil {
return x.FragmentShard
}
return 0
}
func (x *ClockFrameFragment_ReedSolomonEncoding) GetFragmentDataShardCount() uint64 {
if x != nil {
return x.FragmentDataShardCount
}
return 0
}
func (x *ClockFrameFragment_ReedSolomonEncoding) GetFragmentParityShardCount() uint64 {
if x != nil {
return x.FragmentParityShardCount
}
return 0
}
func (x *ClockFrameFragment_ReedSolomonEncoding) GetFragmentData() []byte {
if x != nil {
return x.FragmentData
}
return nil
}
var File_clock_proto protoreflect.FileDescriptor
var file_clock_proto_rawDesc = []byte{
@ -468,7 +688,7 @@ var file_clock_proto_rawDesc = []byte{
0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x63,
0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x62, 0x1a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0a, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0xbc, 0x03, 0x0a, 0x0a, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d,
0x74, 0x6f, 0x22, 0xd6, 0x03, 0x0a, 0x0a, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61,
0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
@ -494,58 +714,99 @@ var file_clock_proto_rawDesc = []byte{
0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x62, 0x2e,
0x45, 0x64, 0x34, 0x34, 0x38, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00,
0x52, 0x17, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61,
0x74, 0x75, 0x72, 0x65, 0x45, 0x64, 0x34, 0x34, 0x38, 0x42, 0x16, 0x0a, 0x14, 0x70, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
0x65, 0x22, 0x67, 0x0a, 0x19, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x50,
0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x21,
0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
0x72, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65,
0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65,
0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x94, 0x02, 0x0a, 0x12, 0x43,
0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x72, 0x6f,
0x6d, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e,
0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6f, 0x5f, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d,
0x74, 0x6f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x27, 0x0a,
0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65,
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x69, 0x0a, 0x16, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f,
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73,
0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 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, 0x50, 0x61, 0x72, 0x65,
0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x14, 0x72, 0x61, 0x6e,
0x67, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72,
0x73, 0x22, 0x81, 0x01, 0x0a, 0x14, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x50, 0x72, 0x65, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x69, 0x0a, 0x16, 0x72, 0x61,
0x6e, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 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,
0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52,
0x14, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65,
0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xca, 0x01, 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a,
0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66,
0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x66, 0x72,
0x74, 0x75, 0x72, 0x65, 0x45, 0x64, 0x34, 0x34, 0x38, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x64,
0x64, 0x69, 0x6e, 0x67, 0x18, 0x63, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x64, 0x64,
0x69, 0x6e, 0x67, 0x42, 0x16, 0x0a, 0x14, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65,
0x79, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xfc, 0x04, 0x0a, 0x12,
0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65,
0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72,
0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
0x52, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
0x72, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6f, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75,
0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x6f, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x47, 0x0a, 0x0c, 0x63, 0x6c, 0x6f,
0x63, 0x6b, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x24, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64,
0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a,
0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x66,
0x72, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x65, 0x0a, 0x0c, 0x72, 0x65,
0x65, 0x64, 0x5f, 0x73, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x40, 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, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52,
0x65, 0x65, 0x64, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69,
0x6e, 0x67, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x65, 0x65, 0x64, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f,
0x6e, 0x12, 0x66, 0x0a, 0x1a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f,
0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x65, 0x64, 0x34, 0x34, 0x38, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69,
0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x62, 0x2e,
0x45, 0x64, 0x34, 0x34, 0x38, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x01,
0x52, 0x17, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61,
0x74, 0x75, 0x72, 0x65, 0x45, 0x64, 0x34, 0x34, 0x38, 0x1a, 0xfa, 0x01, 0x0a, 0x13, 0x52, 0x65,
0x65, 0x64, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e,
0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x7a, 0x65,
0x12, 0x25, 0x0a, 0x0e, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x68, 0x61,
0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65,
0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x39, 0x0a, 0x19, 0x66, 0x72, 0x61, 0x67, 0x6d,
0x65, 0x6e, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x66, 0x72, 0x61, 0x67,
0x6d, 0x65, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x75,
0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x1b, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x70,
0x61, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
0x74, 0x50, 0x61, 0x72, 0x69, 0x74, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x75, 0x6e,
0x74, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x61,
0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65,
0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x42, 0x0a, 0x0a, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69,
0x6e, 0x67, 0x42, 0x16, 0x0a, 0x14, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79,
0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x67, 0x0a, 0x19, 0x43, 0x6c,
0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65,
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66,
0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x6f, 0x72, 0x22, 0x94, 0x02, 0x0a, 0x12, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69,
0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74,
0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x66,
0x72, 0x6f, 0x6d, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26,
0x0a, 0x0f, 0x74, 0x6f, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65,
0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x6f, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12,
0x69, 0x0a, 0x16, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f,
0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x33, 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, 0x52, 0x0b, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 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,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x6f, 0x72, 0x73, 0x52, 0x14, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e,
0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x14, 0x43,
0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x72, 0x65, 0x66, 0x6c, 0x69,
0x67, 0x68, 0x74, 0x12, 0x69, 0x0a, 0x16, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x33, 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, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x14, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x50,
0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xca,
0x01, 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x2a,
0x0a, 0x11, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d,
0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6f,
0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20,
0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x6f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62,
0x65, 0x72, 0x12, 0x47, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 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, 0x52, 0x0b,
0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 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 (
@ -560,27 +821,31 @@ func file_clock_proto_rawDescGZIP() []byte {
return file_clock_proto_rawDescData
}
var file_clock_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_clock_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_clock_proto_goTypes = []interface{}{
(*ClockFrame)(nil), // 0: quilibrium.node.clock.pb.ClockFrame
(*ClockFrameParentSelectors)(nil), // 1: quilibrium.node.clock.pb.ClockFrameParentSelectors
(*ClockFramesRequest)(nil), // 2: quilibrium.node.clock.pb.ClockFramesRequest
(*ClockFramesPreflight)(nil), // 3: quilibrium.node.clock.pb.ClockFramesPreflight
(*ClockFramesResponse)(nil), // 4: quilibrium.node.clock.pb.ClockFramesResponse
(*InclusionAggregateProof)(nil), // 5: quilibrium.node.channel.pb.InclusionAggregateProof
(*Ed448Signature)(nil), // 6: quilibrium.node.keys.pb.Ed448Signature
(*ClockFrameFragment)(nil), // 1: quilibrium.node.clock.pb.ClockFrameFragment
(*ClockFrameParentSelectors)(nil), // 2: quilibrium.node.clock.pb.ClockFrameParentSelectors
(*ClockFramesRequest)(nil), // 3: quilibrium.node.clock.pb.ClockFramesRequest
(*ClockFramesPreflight)(nil), // 4: quilibrium.node.clock.pb.ClockFramesPreflight
(*ClockFramesResponse)(nil), // 5: quilibrium.node.clock.pb.ClockFramesResponse
(*ClockFrameFragment_ReedSolomonEncoding)(nil), // 6: quilibrium.node.clock.pb.ClockFrameFragment.ReedSolomonEncoding
(*InclusionAggregateProof)(nil), // 7: quilibrium.node.channel.pb.InclusionAggregateProof
(*Ed448Signature)(nil), // 8: quilibrium.node.keys.pb.Ed448Signature
}
var file_clock_proto_depIdxs = []int32{
5, // 0: quilibrium.node.clock.pb.ClockFrame.aggregate_proofs:type_name -> quilibrium.node.channel.pb.InclusionAggregateProof
6, // 1: quilibrium.node.clock.pb.ClockFrame.public_key_signature_ed448:type_name -> quilibrium.node.keys.pb.Ed448Signature
1, // 2: quilibrium.node.clock.pb.ClockFramesRequest.range_parent_selectors:type_name -> quilibrium.node.clock.pb.ClockFrameParentSelectors
1, // 3: quilibrium.node.clock.pb.ClockFramesPreflight.range_parent_selectors:type_name -> quilibrium.node.clock.pb.ClockFrameParentSelectors
0, // 4: quilibrium.node.clock.pb.ClockFramesResponse.clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
7, // 0: quilibrium.node.clock.pb.ClockFrame.aggregate_proofs:type_name -> quilibrium.node.channel.pb.InclusionAggregateProof
8, // 1: quilibrium.node.clock.pb.ClockFrame.public_key_signature_ed448:type_name -> quilibrium.node.keys.pb.Ed448Signature
6, // 2: quilibrium.node.clock.pb.ClockFrameFragment.reed_solomon:type_name -> quilibrium.node.clock.pb.ClockFrameFragment.ReedSolomonEncoding
8, // 3: quilibrium.node.clock.pb.ClockFrameFragment.public_key_signature_ed448:type_name -> quilibrium.node.keys.pb.Ed448Signature
2, // 4: quilibrium.node.clock.pb.ClockFramesRequest.range_parent_selectors:type_name -> quilibrium.node.clock.pb.ClockFrameParentSelectors
2, // 5: quilibrium.node.clock.pb.ClockFramesPreflight.range_parent_selectors:type_name -> quilibrium.node.clock.pb.ClockFrameParentSelectors
0, // 6: quilibrium.node.clock.pb.ClockFramesResponse.clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_clock_proto_init() }
@ -604,7 +869,7 @@ func file_clock_proto_init() {
}
}
file_clock_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ClockFrameParentSelectors); i {
switch v := v.(*ClockFrameFragment); i {
case 0:
return &v.state
case 1:
@ -616,7 +881,7 @@ func file_clock_proto_init() {
}
}
file_clock_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ClockFramesRequest); i {
switch v := v.(*ClockFrameParentSelectors); i {
case 0:
return &v.state
case 1:
@ -628,7 +893,7 @@ func file_clock_proto_init() {
}
}
file_clock_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ClockFramesPreflight); i {
switch v := v.(*ClockFramesRequest); i {
case 0:
return &v.state
case 1:
@ -640,6 +905,18 @@ func file_clock_proto_init() {
}
}
file_clock_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ClockFramesPreflight); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_clock_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ClockFramesResponse); i {
case 0:
return &v.state
@ -651,17 +928,33 @@ func file_clock_proto_init() {
return nil
}
}
file_clock_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ClockFrameFragment_ReedSolomonEncoding); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_clock_proto_msgTypes[0].OneofWrappers = []interface{}{
(*ClockFrame_PublicKeySignatureEd448)(nil),
}
file_clock_proto_msgTypes[1].OneofWrappers = []interface{}{
(*ClockFrameFragment_ReedSolomon)(nil),
(*ClockFrameFragment_PublicKeySignatureEd448)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_clock_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumMessages: 7,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -59,6 +59,33 @@ message ClockFrame {
oneof public_key_signature {
quilibrium.node.keys.pb.Ed448Signature public_key_signature_ed448 = 9;
}
// Padding is used in tests in order to simulate large clock frames.
bytes padding = 99;
}
// Represents a clock frame fragment for a given filter. Clock frame fragments
// are used to disseminate clock frame data across the network in a more
// efficient manner. This is particularly useful for large clock frames, where
// the frame data can be split into smaller fragments and sent across the
// network in parallel.
message ClockFrameFragment {
bytes filter = 1;
uint64 frame_number = 2;
int64 timestamp = 3;
bytes frame_hash = 4;
message ReedSolomonEncoding {
uint64 frame_size = 1;
uint64 fragment_shard = 2;
uint64 fragment_data_shard_count = 3;
uint64 fragment_parity_shard_count = 4;
bytes fragment_data = 5;
}
oneof encoding {
ReedSolomonEncoding reed_solomon = 5;
}
oneof public_key_signature {
quilibrium.node.keys.pb.Ed448Signature public_key_signature_ed448 = 6;
}
}
message ClockFrameParentSelectors {

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.30.0
// protoc v3.21.12
// protoc-gen-go v1.34.1
// protoc v5.27.0
// source: data.proto
package protobufs
@ -9,6 +9,7 @@ package protobufs
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
reflect "reflect"
sync "sync"
)
@ -79,6 +80,7 @@ type DataPeer struct {
Version []byte `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"`
TotalDistance []byte `protobuf:"bytes,8,opt,name=total_distance,json=totalDistance,proto3" json:"total_distance,omitempty"`
PatchVersion []byte `protobuf:"bytes,9,opt,name=patch_version,json=patchVersion,proto3" json:"patch_version,omitempty"`
ExternallyReachable *wrapperspb.BoolValue `protobuf:"bytes,10,opt,name=externally_reachable,json=externallyReachable,proto3" json:"externally_reachable,omitempty"`
}
func (x *DataPeer) Reset() {
@ -162,6 +164,13 @@ func (x *DataPeer) GetPatchVersion() []byte {
return nil
}
func (x *DataPeer) GetExternallyReachable() *wrapperspb.BoolValue {
if x != nil {
return x.ExternallyReachable
}
return nil
}
type DataCompressedSync struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -1086,7 +1095,9 @@ var File_data_proto protoreflect.FileDescriptor
var file_data_proto_rawDesc = []byte{
0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x71, 0x75,
0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61,
0x74, 0x61, 0x2e, 0x70, 0x62, 0x1a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x70,
0x74, 0x61, 0x2e, 0x70, 0x62, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0b, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x0a, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0a, 0x6e,
0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5e, 0x0a, 0x14, 0x44, 0x61, 0x74,
@ -1095,7 +1106,7 @@ var file_data_proto_rawDesc = []byte{
0x21, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64,
0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x50, 0x65,
0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x52, 0x09,
0x70, 0x65, 0x65, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x85, 0x02, 0x0a, 0x08, 0x44, 0x61,
0x70, 0x65, 0x65, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xd4, 0x02, 0x0a, 0x08, 0x44, 0x61,
0x74, 0x61, 0x50, 0x65, 0x65, 0x72, 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,
0x1c, 0x0a, 0x09, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01,
@ -1109,204 +1120,209 @@ var file_data_proto_rawDesc = []byte{
0x61, 0x6e, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x74, 0x6f, 0x74, 0x61,
0x6c, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x74,
0x63, 0x68, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x0c, 0x70, 0x61, 0x74, 0x63, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4a, 0x04,
0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e,
0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65,
0x79, 0x22, 0xd4, 0x02, 0x0a, 0x12, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65,
0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x72, 0x6f, 0x6d,
0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75,
0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6f, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74,
0x6f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x16,
0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 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, 0x52, 0x14, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x6f,
0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6f,
0x66, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69,
0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e,
0x70, 0x62, 0x2e, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f,
0x66, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x49, 0x0a,
0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x2d, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64,
0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73,
0x69, 0x6f, 0x6e, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x08,
0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x19, 0x53, 0x79, 0x6e,
0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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,
0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x43, 0x0a,
0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x27, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64,
0x65, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x64, 0x34, 0x34, 0x38, 0x53,
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0xaa, 0x02, 0x0a, 0x20, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72,
0x65, 0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x66, 0x6c,
0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x50, 0x72, 0x65, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x48, 0x00, 0x52, 0x09, 0x70, 0x72,
0x65, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x48, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x18, 0x02, 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, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x5c, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x71, 0x75, 0x69, 0x6c,
0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61,
0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41,
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52,
0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42,
0x0e, 0x0a, 0x0c, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
0xce, 0x01, 0x0a, 0x21, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73,
0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x66, 0x6c, 0x69, 0x67,
0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x50,
0x72, 0x65, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x48, 0x00, 0x52, 0x09, 0x70, 0x72, 0x65, 0x66,
0x6c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x49, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62,
0x52, 0x0c, 0x70, 0x61, 0x74, 0x63, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d,
0x0a, 0x14, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x72, 0x65, 0x61,
0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42,
0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x04, 0x08,
0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61,
0x74, 0x75, 0x72, 0x65, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79,
0x22, 0xd4, 0x02, 0x0a, 0x12, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73,
0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x72, 0x6f, 0x6d, 0x5f,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d,
0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6f, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x6f,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x16, 0x74,
0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x66,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 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, 0x52, 0x14, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x6f, 0x63,
0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62,
0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70,
0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64,
0x53, 0x79, 0x6e, 0x63, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x42, 0x0e, 0x0a, 0x0c, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x22, 0xa1, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x66,
0x72, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72,
0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66,
0x12, 0x52, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69,
0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e,
0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x22, 0x3e, 0x0a, 0x14, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f,
0x6e, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x12, 0x0a, 0x04,
0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68,
0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04,
0x64, 0x61, 0x74, 0x61, 0x22, 0x7b, 0x0a, 0x17, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f,
0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x12,
0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12,
0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65,
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0c, 0x52, 0x0d, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65,
0x73, 0x22, 0x51, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x70,
0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x65,
0x65, 0x72, 0x49, 0x64, 0x22, 0x70, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x63, 0x6c, 0x6f,
0x63, 0x6b, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
0x62, 0x2e, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66,
0x73, 0x4d, 0x61, 0x70, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x49, 0x0a, 0x08,
0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d,
0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65,
0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69,
0x6f, 0x6e, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x08, 0x73,
0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x19, 0x53, 0x79, 0x6e, 0x63,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x1c,
0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x43, 0x0a, 0x08,
0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27,
0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65,
0x2e, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x64, 0x34, 0x34, 0x38, 0x53, 0x69,
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0xaa, 0x02, 0x0a, 0x20, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65,
0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x66, 0x6c, 0x69,
0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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,
0x50, 0x72, 0x65, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x48, 0x00, 0x52, 0x09, 0x70, 0x72, 0x65,
0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x48, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x18, 0x02, 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, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x5c, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69,
0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e,
0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x75,
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0e,
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0e,
0x0a, 0x0c, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xce,
0x01, 0x0a, 0x21, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65,
0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x66, 0x6c, 0x69, 0x67, 0x68,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x50, 0x72,
0x65, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x48, 0x00, 0x52, 0x09, 0x70, 0x72, 0x65, 0x66, 0x6c,
0x69, 0x67, 0x68, 0x74, 0x12, 0x49, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72,
0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62,
0x2e, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x53,
0x79, 0x6e, 0x63, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
0x0e, 0x0a, 0x0c, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
0xa1, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f,
0x6f, 0x66, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x66, 0x72,
0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f,
0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12,
0x52, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75,
0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x49,
0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x22, 0x3e, 0x0a, 0x14, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e,
0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x68,
0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12,
0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64,
0x61, 0x74, 0x61, 0x22, 0x7b, 0x0a, 0x17, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e,
0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x1e,
0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x19,
0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x67,
0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0c, 0x52, 0x0d, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73,
0x22, 0x51, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66,
0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65,
0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x65, 0x65,
0x72, 0x49, 0x64, 0x22, 0x70, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x63, 0x6c, 0x6f, 0x63,
0x6b, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 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, 0x52, 0x0a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x51, 0x0a, 0x17, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e,
0x69, 0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e,
0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x69,
0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x34, 0x0a, 0x1c, 0x50, 0x72, 0x65, 0x4d,
0x69, 0x64, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65,
0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0x97,
0x01, 0x0a, 0x10, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63,
0x61, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20,
0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x47, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x63, 0x6b,
0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 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, 0x52, 0x0b, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x12, 0x16, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x22, 0xe6, 0x01, 0x0a, 0x15, 0x43, 0x68, 0x61,
0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 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, 0x12, 0x0a, 0x04, 0x63,
0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12,
0x45, 0x0a, 0x0b, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 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, 0x52, 0x0a, 0x63, 0x6c, 0x6f, 0x63,
0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x21,
0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74,
0x79, 0x22, 0x30, 0x0a, 0x16, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f,
0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74,
0x70, 0x75, 0x74, 0x32, 0xff, 0x05, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x76, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65,
0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 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, 0x52, 0x0a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x51, 0x0a, 0x17, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64,
0x6e, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69,
0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09,
0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x34, 0x0a, 0x1c, 0x50, 0x72, 0x65,
0x4d, 0x69, 0x64, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e,
0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22,
0x97, 0x01, 0x0a, 0x10, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x62, 0x72, 0x6f, 0x61, 0x64,
0x63, 0x61, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x47, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x63,
0x6b, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24,
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, 0x52, 0x0b, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x22, 0xe6, 0x01, 0x0a, 0x15, 0x43, 0x68,
0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75,
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, 0x12, 0x0a, 0x04,
0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65,
0x12, 0x45, 0x0a, 0x0b, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 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, 0x52, 0x0a, 0x63, 0x6c, 0x6f,
0x63, 0x6b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75,
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12,
0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62,
0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79,
0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c,
0x74, 0x79, 0x22, 0x30, 0x0a, 0x16, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50,
0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06,
0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75,
0x74, 0x70, 0x75, 0x74, 0x32, 0xff, 0x05, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x76, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x72,
0x65, 0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12,
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, 0x1a, 0x2b, 0x2e,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x71,
0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72,
0x65, 0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x30, 0x01, 0x12, 0x9a, 0x01, 0x0a, 0x1d,
0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73,
0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x39, 0x2e,
0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70,
0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x30, 0x01, 0x12, 0x9a, 0x01, 0x0a,
0x1d, 0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65,
0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x39,
0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x3a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69,
0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e,
0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65,
0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x76, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50,
0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x2e, 0x2e, 0x71,
0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x63,
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x32, 0x50, 0x43, 0x68, 0x61,
0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x1a, 0x2e, 0x2e, 0x71,
0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x63,
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x32, 0x50, 0x43, 0x68, 0x61,
0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x28, 0x01, 0x30, 0x01,
0x12, 0x68, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x12, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f,
0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x61,
0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65, 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, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d,
0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x3a, 0x2e, 0x71, 0x75, 0x69, 0x6c,
0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61,
0x2e, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73,
0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x76, 0x0a, 0x10, 0x47, 0x65, 0x74,
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x2e, 0x2e,
0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x32, 0x50, 0x43, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x1a, 0x2e, 0x2e,
0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x32, 0x50, 0x43, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x28, 0x01, 0x30,
0x01, 0x12, 0x68, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x12, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e,
0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x44,
0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65, 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, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x15, 0x48,
0x61, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69, 0x67, 0x68, 0x74,
0x4d, 0x69, 0x6e, 0x74, 0x12, 0x28, 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, 0x4d,
0x69, 0x6e, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65,
0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e,
0x69, 0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x83, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69,
0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x2e,
0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x15, 0x48, 0x61,
0x6e, 0x64, 0x6c, 0x65, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x4d,
0x69, 0x6e, 0x74, 0x12, 0x28, 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, 0x4d, 0x69,
0x6e, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e,
0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69,
0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75,
0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x50,
0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8c, 0x01, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x49,
0x50, 0x43, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x17, 0x43, 0x61, 0x6c,
0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50,
0x72, 0x6f, 0x6f, 0x66, 0x12, 0x2e, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75,
0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x43,
0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75,
0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x43,
0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 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,
0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x83, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69, 0x67,
0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x2e, 0x71,
0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69, 0x67,
0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d,
0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x72,
0x65, 0x4d, 0x69, 0x64, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8c, 0x01, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x49, 0x50,
0x43, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x17, 0x43, 0x61, 0x6c, 0x63,
0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x12, 0x2e, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d,
0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68,
0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d,
0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68,
0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 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 (
@ -1339,47 +1355,49 @@ var file_data_proto_goTypes = []interface{}{
(*FrameRebroadcast)(nil), // 13: quilibrium.node.data.pb.FrameRebroadcast
(*ChallengeProofRequest)(nil), // 14: quilibrium.node.data.pb.ChallengeProofRequest
(*ChallengeProofResponse)(nil), // 15: quilibrium.node.data.pb.ChallengeProofResponse
(*ClockFrame)(nil), // 16: quilibrium.node.clock.pb.ClockFrame
(*Ed448Signature)(nil), // 17: quilibrium.node.keys.pb.Ed448Signature
(*ClockFramesPreflight)(nil), // 18: quilibrium.node.clock.pb.ClockFramesPreflight
(*ClockFramesRequest)(nil), // 19: quilibrium.node.clock.pb.ClockFramesRequest
(*P2PChannelEnvelope)(nil), // 20: quilibrium.node.channel.pb.P2PChannelEnvelope
(*MintCoinRequest)(nil), // 21: quilibrium.node.node.pb.MintCoinRequest
(*wrapperspb.BoolValue)(nil), // 16: google.protobuf.BoolValue
(*ClockFrame)(nil), // 17: quilibrium.node.clock.pb.ClockFrame
(*Ed448Signature)(nil), // 18: quilibrium.node.keys.pb.Ed448Signature
(*ClockFramesPreflight)(nil), // 19: quilibrium.node.clock.pb.ClockFramesPreflight
(*ClockFramesRequest)(nil), // 20: quilibrium.node.clock.pb.ClockFramesRequest
(*P2PChannelEnvelope)(nil), // 21: quilibrium.node.channel.pb.P2PChannelEnvelope
(*MintCoinRequest)(nil), // 22: quilibrium.node.node.pb.MintCoinRequest
}
var file_data_proto_depIdxs = []int32{
1, // 0: quilibrium.node.data.pb.DataPeerListAnnounce.peer:type_name -> quilibrium.node.data.pb.DataPeer
16, // 1: quilibrium.node.data.pb.DataCompressedSync.truncated_clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame
6, // 2: quilibrium.node.data.pb.DataCompressedSync.proofs:type_name -> quilibrium.node.data.pb.InclusionProofsMap
7, // 3: quilibrium.node.data.pb.DataCompressedSync.segments:type_name -> quilibrium.node.data.pb.InclusionSegmentsMap
17, // 4: quilibrium.node.data.pb.SyncRequestAuthentication.response:type_name -> quilibrium.node.keys.pb.Ed448Signature
18, // 5: quilibrium.node.data.pb.DataCompressedSyncRequestMessage.preflight:type_name -> quilibrium.node.clock.pb.ClockFramesPreflight
19, // 6: quilibrium.node.data.pb.DataCompressedSyncRequestMessage.request:type_name -> quilibrium.node.clock.pb.ClockFramesRequest
3, // 7: quilibrium.node.data.pb.DataCompressedSyncRequestMessage.authentication:type_name -> quilibrium.node.data.pb.SyncRequestAuthentication
18, // 8: quilibrium.node.data.pb.DataCompressedSyncResponseMessage.preflight:type_name -> quilibrium.node.clock.pb.ClockFramesPreflight
2, // 9: quilibrium.node.data.pb.DataCompressedSyncResponseMessage.response:type_name -> quilibrium.node.data.pb.DataCompressedSync
8, // 10: quilibrium.node.data.pb.InclusionProofsMap.commitments:type_name -> quilibrium.node.data.pb.InclusionCommitmentsMap
16, // 11: quilibrium.node.data.pb.DataFrameResponse.clock_frame:type_name -> quilibrium.node.clock.pb.ClockFrame
16, // 12: quilibrium.node.data.pb.FrameRebroadcast.clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame
16, // 13: quilibrium.node.data.pb.ChallengeProofRequest.clock_frame:type_name -> quilibrium.node.clock.pb.ClockFrame
19, // 14: quilibrium.node.data.pb.DataService.GetCompressedSyncFrames:input_type -> quilibrium.node.clock.pb.ClockFramesRequest
4, // 15: quilibrium.node.data.pb.DataService.NegotiateCompressedSyncFrames:input_type -> quilibrium.node.data.pb.DataCompressedSyncRequestMessage
20, // 16: quilibrium.node.data.pb.DataService.GetPublicChannel:input_type -> quilibrium.node.channel.pb.P2PChannelEnvelope
9, // 17: quilibrium.node.data.pb.DataService.GetDataFrame:input_type -> quilibrium.node.data.pb.GetDataFrameRequest
21, // 18: quilibrium.node.data.pb.DataService.HandlePreMidnightMint:input_type -> quilibrium.node.node.pb.MintCoinRequest
12, // 19: quilibrium.node.data.pb.DataService.GetPreMidnightMintStatus:input_type -> quilibrium.node.data.pb.PreMidnightMintStatusRequest
14, // 20: quilibrium.node.data.pb.DataIPCService.CalculateChallengeProof:input_type -> quilibrium.node.data.pb.ChallengeProofRequest
2, // 21: quilibrium.node.data.pb.DataService.GetCompressedSyncFrames:output_type -> quilibrium.node.data.pb.DataCompressedSync
5, // 22: quilibrium.node.data.pb.DataService.NegotiateCompressedSyncFrames:output_type -> quilibrium.node.data.pb.DataCompressedSyncResponseMessage
20, // 23: quilibrium.node.data.pb.DataService.GetPublicChannel:output_type -> quilibrium.node.channel.pb.P2PChannelEnvelope
10, // 24: quilibrium.node.data.pb.DataService.GetDataFrame:output_type -> quilibrium.node.data.pb.DataFrameResponse
11, // 25: quilibrium.node.data.pb.DataService.HandlePreMidnightMint:output_type -> quilibrium.node.data.pb.PreMidnightMintResponse
11, // 26: quilibrium.node.data.pb.DataService.GetPreMidnightMintStatus:output_type -> quilibrium.node.data.pb.PreMidnightMintResponse
15, // 27: quilibrium.node.data.pb.DataIPCService.CalculateChallengeProof:output_type -> quilibrium.node.data.pb.ChallengeProofResponse
21, // [21:28] is the sub-list for method output_type
14, // [14:21] is the sub-list for method input_type
14, // [14:14] is the sub-list for extension type_name
14, // [14:14] is the sub-list for extension extendee
0, // [0:14] is the sub-list for field type_name
16, // 1: quilibrium.node.data.pb.DataPeer.externally_reachable:type_name -> google.protobuf.BoolValue
17, // 2: quilibrium.node.data.pb.DataCompressedSync.truncated_clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame
6, // 3: quilibrium.node.data.pb.DataCompressedSync.proofs:type_name -> quilibrium.node.data.pb.InclusionProofsMap
7, // 4: quilibrium.node.data.pb.DataCompressedSync.segments:type_name -> quilibrium.node.data.pb.InclusionSegmentsMap
18, // 5: quilibrium.node.data.pb.SyncRequestAuthentication.response:type_name -> quilibrium.node.keys.pb.Ed448Signature
19, // 6: quilibrium.node.data.pb.DataCompressedSyncRequestMessage.preflight:type_name -> quilibrium.node.clock.pb.ClockFramesPreflight
20, // 7: quilibrium.node.data.pb.DataCompressedSyncRequestMessage.request:type_name -> quilibrium.node.clock.pb.ClockFramesRequest
3, // 8: quilibrium.node.data.pb.DataCompressedSyncRequestMessage.authentication:type_name -> quilibrium.node.data.pb.SyncRequestAuthentication
19, // 9: quilibrium.node.data.pb.DataCompressedSyncResponseMessage.preflight:type_name -> quilibrium.node.clock.pb.ClockFramesPreflight
2, // 10: quilibrium.node.data.pb.DataCompressedSyncResponseMessage.response:type_name -> quilibrium.node.data.pb.DataCompressedSync
8, // 11: quilibrium.node.data.pb.InclusionProofsMap.commitments:type_name -> quilibrium.node.data.pb.InclusionCommitmentsMap
17, // 12: quilibrium.node.data.pb.DataFrameResponse.clock_frame:type_name -> quilibrium.node.clock.pb.ClockFrame
17, // 13: quilibrium.node.data.pb.FrameRebroadcast.clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame
17, // 14: quilibrium.node.data.pb.ChallengeProofRequest.clock_frame:type_name -> quilibrium.node.clock.pb.ClockFrame
20, // 15: quilibrium.node.data.pb.DataService.GetCompressedSyncFrames:input_type -> quilibrium.node.clock.pb.ClockFramesRequest
4, // 16: quilibrium.node.data.pb.DataService.NegotiateCompressedSyncFrames:input_type -> quilibrium.node.data.pb.DataCompressedSyncRequestMessage
21, // 17: quilibrium.node.data.pb.DataService.GetPublicChannel:input_type -> quilibrium.node.channel.pb.P2PChannelEnvelope
9, // 18: quilibrium.node.data.pb.DataService.GetDataFrame:input_type -> quilibrium.node.data.pb.GetDataFrameRequest
22, // 19: quilibrium.node.data.pb.DataService.HandlePreMidnightMint:input_type -> quilibrium.node.node.pb.MintCoinRequest
12, // 20: quilibrium.node.data.pb.DataService.GetPreMidnightMintStatus:input_type -> quilibrium.node.data.pb.PreMidnightMintStatusRequest
14, // 21: quilibrium.node.data.pb.DataIPCService.CalculateChallengeProof:input_type -> quilibrium.node.data.pb.ChallengeProofRequest
2, // 22: quilibrium.node.data.pb.DataService.GetCompressedSyncFrames:output_type -> quilibrium.node.data.pb.DataCompressedSync
5, // 23: quilibrium.node.data.pb.DataService.NegotiateCompressedSyncFrames:output_type -> quilibrium.node.data.pb.DataCompressedSyncResponseMessage
21, // 24: quilibrium.node.data.pb.DataService.GetPublicChannel:output_type -> quilibrium.node.channel.pb.P2PChannelEnvelope
10, // 25: quilibrium.node.data.pb.DataService.GetDataFrame:output_type -> quilibrium.node.data.pb.DataFrameResponse
11, // 26: quilibrium.node.data.pb.DataService.HandlePreMidnightMint:output_type -> quilibrium.node.data.pb.PreMidnightMintResponse
11, // 27: quilibrium.node.data.pb.DataService.GetPreMidnightMintStatus:output_type -> quilibrium.node.data.pb.PreMidnightMintResponse
15, // 28: quilibrium.node.data.pb.DataIPCService.CalculateChallengeProof:output_type -> quilibrium.node.data.pb.ChallengeProofResponse
22, // [22:29] is the sub-list for method output_type
15, // [15:22] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
}
func init() { file_data_proto_init() }

View File

@ -4,6 +4,8 @@ package quilibrium.node.data.pb;
option go_package = "source.quilibrium.com/quilibrium/monorepo/node/protobufs";
import "google/protobuf/wrappers.proto";
import "channel.proto";
import "clock.proto";
import "keys.proto";
@ -27,6 +29,7 @@ message DataPeer {
reserved "public_key";
bytes total_distance = 8;
bytes patch_version = 9;
google.protobuf.BoolValue externally_reachable = 10;
}
message DataCompressedSync {

View File

@ -37,6 +37,7 @@ const (
IdentityKeyType = ChannelPrefix + "IdentityKey"
SignedPreKeyType = ChannelPrefix + "SignedPreKey"
ClockFrameType = ClockPrefix + "ClockFrame"
ClockFrameFragmentType = ClockPrefix + "ClockFrameFragment"
ClockFramesRequestType = ClockPrefix + "ClockFramesRequest"
ClockFramesResponseType = ClockPrefix + "ClockFramesResponse"
Ed448PublicKeyType = KeysPrefix + "Ed448PublicKey"

View File

@ -1,6 +1,7 @@
package protobufs
import (
"crypto/sha256"
"encoding/binary"
"github.com/pkg/errors"
@ -10,6 +11,33 @@ type signatureMessage interface {
signatureMessage() []byte
}
var _ signatureMessage = (*ClockFrameFragment_ReedSolomonEncoding)(nil)
func (c *ClockFrameFragment_ReedSolomonEncoding) signatureMessage() []byte {
payload := []byte("reed-solomon-fragment")
payload = binary.BigEndian.AppendUint64(payload, c.FrameSize)
payload = binary.BigEndian.AppendUint64(payload, c.FragmentShard)
payload = binary.BigEndian.AppendUint64(payload, c.FragmentDataShardCount)
payload = binary.BigEndian.AppendUint64(payload, c.FragmentParityShardCount)
h := sha256.Sum256(c.FragmentData)
payload = append(payload, h[:]...)
return payload
}
var _ signatureMessage = (*ClockFrameFragment)(nil)
func (c *ClockFrameFragment) signatureMessage() []byte {
payload := []byte("fragment")
payload = binary.BigEndian.AppendUint64(payload, c.FrameNumber)
payload = append(payload, c.Filter...)
payload = binary.BigEndian.AppendUint64(payload, uint64(c.Timestamp))
payload = append(payload, c.FrameHash...)
if reedSolomon := c.GetReedSolomon(); reedSolomon != nil {
payload = append(payload, reedSolomon.signatureMessage()...)
}
return payload
}
var _ signatureMessage = (*TransferCoinRequest)(nil)
func (t *TransferCoinRequest) signatureMessage() []byte {
@ -99,6 +127,21 @@ type SignedMessage interface {
ValidateSignature() error
}
var _ SignedMessage = (*ClockFrameFragment)(nil)
// ValidateSignature checks the signature of the clock frame fragment.
func (c *ClockFrameFragment) ValidateSignature() error {
switch {
case c.GetPublicKeySignatureEd448() != nil:
if err := c.GetPublicKeySignatureEd448().verifyUnsafe(c.signatureMessage()); err != nil {
return errors.Wrap(err, "validate signature")
}
return nil
default:
return errors.New("invalid signature")
}
}
var _ SignedMessage = (*TransferCoinRequest)(nil)
// ValidateSignature checks the signature of the transfer coin request.
@ -204,6 +247,61 @@ type ValidatableMessage interface {
Validate() error
}
var _ ValidatableMessage = (*ClockFrameFragment_ReedSolomonEncoding)(nil)
// Validate checks the Reed-Solomon encoding.
func (c *ClockFrameFragment_ReedSolomonEncoding) Validate() error {
if c == nil {
return errors.New("nil Reed-Solomon encoding")
}
if c.FrameSize == 0 {
return errors.New("invalid frame size")
}
if c.FragmentDataShardCount == 0 {
return errors.New("invalid fragment data shard count")
}
if c.FragmentParityShardCount == 0 {
return errors.New("invalid fragment parity shard count")
}
if c.FragmentShard >= c.FragmentDataShardCount+c.FragmentParityShardCount {
return errors.New("invalid fragment shard")
}
if len(c.FragmentData) == 0 {
return errors.New("invalid fragment data")
}
return nil
}
var _ ValidatableMessage = (*ClockFrameFragment)(nil)
// Validate checks the clock frame fragment.
func (c *ClockFrameFragment) Validate() error {
if c == nil {
return errors.New("nil clock frame fragment")
}
if len(c.Filter) != 32 {
return errors.New("invalid filter")
}
if c.Timestamp == 0 {
return errors.New("invalid timestamp")
}
if n := len(c.FrameHash); n < 28 || n > 64 {
return errors.New("invalid frame hash")
}
switch {
case c.GetReedSolomon() != nil:
if err := c.GetReedSolomon().Validate(); err != nil {
return errors.Wrap(err, "reed-solomon encoding")
}
default:
return errors.New("missing encoding")
}
if err := c.ValidateSignature(); err != nil {
return errors.Wrap(err, "signature")
}
return nil
}
var _ ValidatableMessage = (*Ed448PublicKey)(nil)
// Validate checks the Ed448 public key.
@ -573,6 +671,20 @@ func newED448Signature(publicKey, signature []byte) *Ed448Signature {
}
}
var _ SignableED448Message = (*ClockFrameFragment)(nil)
// SignED448 signs the clock frame fragment with the given key.
func (c *ClockFrameFragment) SignED448(publicKey []byte, sign func([]byte) ([]byte, error)) error {
signature, err := sign(c.signatureMessage())
if err != nil {
return errors.Wrap(err, "sign")
}
c.PublicKeySignature = &ClockFrameFragment_PublicKeySignatureEd448{
PublicKeySignatureEd448: newED448Signature(publicKey, signature),
}
return nil
}
var _ SignableED448Message = (*TransferCoinRequest)(nil)
// SignED448 signs the transfer coin request with the given key.

View File

@ -41,6 +41,70 @@ func metaAppend[T any](bs ...[]T) []T {
return result
}
func TestClockFrameFragmentSignatureRoundtrip(t *testing.T) {
t.Parallel()
message := &protobufs.ClockFrameFragment{
Filter: bytes.Repeat([]byte{0x01}, 32),
FrameNumber: 1,
Timestamp: 2,
FrameHash: bytes.Repeat([]byte{0x03}, 28),
Encoding: &protobufs.ClockFrameFragment_ReedSolomon{
ReedSolomon: &protobufs.ClockFrameFragment_ReedSolomonEncoding{
FrameSize: 3,
FragmentShard: 4,
FragmentDataShardCount: 5,
FragmentParityShardCount: 6,
FragmentData: bytes.Repeat([]byte{0x02}, 6),
},
},
PublicKeySignature: &protobufs.ClockFrameFragment_PublicKeySignatureEd448{
PublicKeySignatureEd448: &protobufs.Ed448Signature{
Signature: bytes.Repeat([]byte{0x02}, 114),
PublicKey: &protobufs.Ed448PublicKey{
KeyValue: bytes.Repeat([]byte{0x03}, 57),
},
},
},
}
if !bytes.Equal(
protobufs.SignatureMessageOf(message),
metaAppend(
[]byte("fragment"),
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
bytes.Repeat([]byte{0x01}, 32),
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
bytes.Repeat([]byte{0x03}, 28),
metaAppend(
[]byte("reed-solomon-fragment"),
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04},
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05},
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06},
[]byte{
0x2e, 0xbd, 0x9a, 0x4e, 0x48, 0x8b, 0x47, 0x1c,
0xd7, 0x0a, 0x25, 0xae, 0xcc, 0xb2, 0xdb, 0x50,
0xaa, 0xbd, 0xa7, 0x3c, 0x92, 0xce, 0x8e, 0xe0,
0xe2, 0x15, 0xcd, 0x89, 0x32, 0x0f, 0x6b, 0x9a,
},
),
),
) {
t.Fatal("unexpected signature message")
}
if err := message.ValidateSignature(); err == nil {
t.Fatal("expected error")
}
if err := message.SignED448(primaryPublicKeyBytes, primaryPrivateKey.Sign); err != nil {
t.Fatal(err)
}
if !bytes.Equal(message.GetPublicKeySignatureEd448().PublicKey.KeyValue, primaryPublicKeyBytes) {
t.Fatal("unexpected public key")
}
if err := message.ValidateSignature(); err != nil {
t.Fatal(err)
}
}
func TestTransferCoinRequestSignatureRoundtrip(t *testing.T) {
t.Parallel()
message := &protobufs.TransferCoinRequest{
@ -422,6 +486,79 @@ func TestAnnounceProverResumeSignatureRoundtrip(t *testing.T) {
}
}
func TestClockFrameFragmentReedSolomonEncodingValidate(t *testing.T) {
t.Parallel()
if err := (*protobufs.ClockFrameFragment_ReedSolomonEncoding)(nil).Validate(); err == nil {
t.Fatal("expected error")
}
message := &protobufs.ClockFrameFragment_ReedSolomonEncoding{}
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.FrameSize = 1
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.FragmentShard = 2
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.FragmentDataShardCount = 3
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.FragmentParityShardCount = 4
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.FragmentData = bytes.Repeat([]byte{0x01}, 6)
if err := message.Validate(); err != nil {
t.Fatal(err)
}
}
func TestClockFrameFragmentValidate(t *testing.T) {
t.Parallel()
if err := (*protobufs.ClockFrameFragment)(nil).Validate(); err == nil {
t.Fatal("expected error")
}
message := &protobufs.ClockFrameFragment{}
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.Filter = bytes.Repeat([]byte{0x01}, 32)
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.FrameNumber = 1
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.Timestamp = 2
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.FrameHash = bytes.Repeat([]byte{0x03}, 28)
if err := message.Validate(); err == nil {
t.Fatal("expected error")
}
message.Encoding = &protobufs.ClockFrameFragment_ReedSolomon{
ReedSolomon: &protobufs.ClockFrameFragment_ReedSolomonEncoding{
FrameSize: 2,
FragmentShard: 3,
FragmentDataShardCount: 4,
FragmentParityShardCount: 5,
FragmentData: bytes.Repeat([]byte{0x02}, 6),
},
}
if err := message.SignED448(primaryPublicKeyBytes, primaryPrivateKey.Sign); err != nil {
t.Fatal(err)
}
if err := message.Validate(); err != nil {
t.Fatal(err)
}
}
func TestEd448PublicKeyValidate(t *testing.T) {
t.Parallel()
if err := (*protobufs.Ed448PublicKey)(nil).Validate(); err == nil {

View File

@ -1064,8 +1064,7 @@ func (p *PebbleClockStore) DeleteDataClockFrameRange(
for _, frame := range frames {
err = p.deleteAggregateProofs(txn, frame)
if err != nil {
txn.Abort()
return errors.Wrap(err, "delete data clock frame range")
continue
}
}
@ -1074,14 +1073,12 @@ func (p *PebbleClockStore) DeleteDataClockFrameRange(
clockDataParentIndexKey(filter, i, bytes.Repeat([]byte{0xff}, 32)),
)
if err != nil {
txn.Abort()
return errors.Wrap(err, "delete data clock frame range")
continue
}
err = txn.Delete(clockDataFrameKey(filter, i))
if err != nil {
txn.Abort()
return errors.Wrap(err, "delete data clock frame range")
continue
}
}