mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
Support frame fragmentation and dissemination (#396)
* Add clock frame fragment message * Add clock frame fragment validation * Add clock frame fragmentation utilities * Add clock frame fragmentation message handling * Report publication errors * Publish info list after frame * Add frame publish configuration * Publish clock frame fragments * Update BlossomSub dashboard * Publish clock frame fragments in parallel
This commit is contained in:
parent
f5f7eb243b
commit
d1e65c1c92
@ -85,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
|
||||
@ -164,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
|
||||
|
||||
@ -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=
|
||||
@ -664,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=
|
||||
|
||||
@ -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": ""
|
||||
}
|
||||
@ -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"`
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
@ -77,6 +96,95 @@ func (e *DataClockConsensusEngine) publishProof(
|
||||
),
|
||||
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,
|
||||
@ -91,13 +199,10 @@ func (e *DataClockConsensusEngine) publishProof(
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
"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"
|
||||
@ -113,6 +114,7 @@ type DataClockConsensusEngine struct {
|
||||
txFilter []byte
|
||||
infoFilter []byte
|
||||
frameFilter []byte
|
||||
frameFragmentFilter []byte
|
||||
input []byte
|
||||
parentSelector []byte
|
||||
syncingStatus SyncStatusType
|
||||
@ -131,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
|
||||
@ -140,6 +143,7 @@ type DataClockConsensusEngine struct {
|
||||
previousTree *mt.MerkleTree
|
||||
clientReconnectTest int
|
||||
requestSyncCh chan struct{}
|
||||
clockFrameFragmentBuffer fragmentation.ClockFrameFragmentBuffer
|
||||
}
|
||||
|
||||
var _ consensus.DataConsensusEngine = (*DataClockConsensusEngine)(nil)
|
||||
@ -229,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,
|
||||
@ -265,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,
|
||||
@ -275,6 +288,7 @@ func NewDataClockConsensusEngine(
|
||||
),
|
||||
requestSyncCh: make(chan struct{}, 1),
|
||||
validationFilter: map[string]struct{}{},
|
||||
clockFrameFragmentBuffer: clockFrameFragmentBuffer,
|
||||
}
|
||||
|
||||
logger.Info("constructing consensus engine")
|
||||
@ -287,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
|
||||
@ -319,16 +334,19 @@ 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() {
|
||||
@ -504,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 {
|
||||
@ -662,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))
|
||||
@ -684,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)
|
||||
|
||||
|
||||
371
node/consensus/data/fragmentation/clock_frame.go
Normal file
371
node/consensus/data/fragmentation/clock_frame.go
Normal 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
|
||||
}
|
||||
414
node/consensus/data/fragmentation/clock_frame_test.go
Normal file
414
node/consensus/data/fragmentation/clock_frame_test.go
Normal 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")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
10
node/consensus/data/fragmentation/hash.go
Normal file
10
node/consensus/data/fragmentation/hash.go
Normal 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[:]
|
||||
}
|
||||
100
node/consensus/data/fragmentation/hash_test.go
Normal file
100
node/consensus/data/fragmentation/hash_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -191,8 +191,8 @@ func (e *DataClockConsensusEngine) runLoop() {
|
||||
e.validationFilter = make(map[string]struct{}, len(e.validationFilter))
|
||||
e.validationFilterMx.Unlock()
|
||||
if e.FrameProverTrieContains(0, e.provingKeyAddress) {
|
||||
if err = e.publishProof(dataFrame); err != nil {
|
||||
e.logger.Error("could not publish", zap.Error(err))
|
||||
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
|
||||
@ -375,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(
|
||||
@ -412,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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -224,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")
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -140,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,
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@ -1437,10 +1439,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 {
|
||||
|
||||
@ -27,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
|
||||
@ -142,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
|
||||
@ -199,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
|
||||
|
||||
10
node/go.sum
10
node/go.sum
@ -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=
|
||||
@ -693,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=
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user