From 384d664a6e315e398a4da02a4baba431f18cacde Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Tue, 13 Jun 2023 10:58:36 -0400 Subject: [PATCH 01/14] Add p2p msgs for votes and timeouts --- .gitignore | 1 + go.mod | 5 +- go.sum | 23 +--- lib/constants.go | 3 + lib/network.go | 10 +- lib/network_pos.go | 263 ++++++++++++++++++++++++++++++++++++++++ lib/network_pos_test.go | 51 ++++++++ 7 files changed, 332 insertions(+), 24 deletions(-) create mode 100644 lib/network_pos.go create mode 100644 lib/network_pos_test.go diff --git a/.gitignore b/.gitignore index dc0267338..608a45416 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ backend core .idea +.vscode local_scripts/* lib/mem.log diff --git a/go.mod b/go.mod index 1e34c1732..7db2ed102 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/holiman/uint256 v1.1.1 github.com/mitchellh/go-homedir v1.1.0 github.com/oleiade/lane v1.0.1 + github.com/onflow/flow-go/crypto v0.24.7 github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 github.com/robinjoseph08/go-pg-migrations/v3 v3.0.0 @@ -45,9 +46,7 @@ require ( ) require ( - github.com/DataDog/zstd v1.4.8 // indirect github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/NVIDIA/cstruct v0.0.0-20210817223100-441a06a021c8 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/bwesterb/go-ristretto v1.2.0 // indirect @@ -79,7 +78,6 @@ require ( github.com/mattn/goveralls v0.0.6 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/mapstructure v1.1.2 // indirect - github.com/onflow/flow-go/crypto v0.24.7 // indirect github.com/onsi/ginkgo v1.15.0 // indirect github.com/onsi/gomega v1.10.5 // indirect github.com/pelletier/go-toml v1.7.0 // indirect @@ -100,7 +98,6 @@ require ( github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.opencensus.io v0.23.0 // indirect - golang.org/x/mod v0.4.2 // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect golang.org/x/text v0.3.6 // indirect diff --git a/go.sum b/go.sum index c2e35d0c6..f0f9a57dc 100644 --- a/go.sum +++ b/go.sum @@ -30,12 +30,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.5.0+incompatible h1:MyyuIz5LVAI3Im+0F/tfo64ETyH4sNVynZ29yOiHm50= github.com/DataDog/datadog-go v4.5.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/DataDog/zstd v1.4.8 h1:Rpmta4xZ/MgZnriKNd24iZMhGpP5dvUcs/uqfBapKZY= -github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/NVIDIA/cstruct v0.0.0-20210817223100-441a06a021c8/go.mod h1:GPbuJvLD4QWiHPS6vivLzh+XMAx6va0Aucm6ipa5S0I= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -125,13 +121,8 @@ github.com/deso-protocol/go-deadlock v1.0.0 h1:mw0pHy/19zgC+JFBStuQt1+1Ehv5OKA5N github.com/deso-protocol/go-deadlock v1.0.0/go.mod h1:K0Wd2OV2x7ck7SMYDraWerpKjFKUeBqaFcwz21tmkb8= github.com/deso-protocol/go-merkle-tree v1.0.0 h1:9zkI5dQsITYy77s4kbTGPQmZnhQ+LsH/kRdL5l/Yzvg= github.com/deso-protocol/go-merkle-tree v1.0.0/go.mod h1:V/vbg/maaNv6G7zf9VVs645nLFx/jsO2L/awFB/S/ZU= -github.com/dgraph-io/badger/v3 v3.2103.0 h1:abkD2EnP3+6Tj8h5LI1y00dJ9ICKTIAzvG9WmZ8S2c4= -github.com/dgraph-io/badger/v3 v3.2103.0/go.mod h1:GHMCYxuDWyzbHkh4k3yyg4PM61tJPFfEGSMbE3Vd5QE= github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= -github.com/dgraph-io/ristretto v0.0.4-0.20210309073149-3836124cdc5a/go.mod h1:MIonLggsKgZLUSt414ExgwNtlOL5MuEoAJP514mwGe8= -github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= -github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -215,7 +206,6 @@ github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI= github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= @@ -309,6 +299,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -434,6 +425,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= @@ -462,7 +454,6 @@ github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZL github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -472,13 +463,13 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/supranational/blst v0.3.10 h1:CMciDZ/h4pXDDXQASe8ZGTNKUiVNxVVA5hpci2Uuhuk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= @@ -546,7 +537,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -606,8 +596,6 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -655,13 +643,11 @@ golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -779,8 +765,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= @@ -791,4 +775,5 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w= mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ= +pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/lib/constants.go b/lib/constants.go index 52c651669..99a03ecac 100644 --- a/lib/constants.go +++ b/lib/constants.go @@ -105,6 +105,9 @@ const ( CurrentHeaderVersion = HeaderVersion1 ) +const ValidatorVoteVersion0 = uint8(0) +const ValidatorTimeoutVersion0 = uint8(0) + var ( MaxUint256, _ = uint256.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") diff --git a/lib/network.go b/lib/network.go index 0ce83d3e4..ef385bdbb 100644 --- a/lib/network.go +++ b/lib/network.go @@ -93,7 +93,11 @@ const ( // MsgTypeTransactionBundleV2 contains transactions after the balance model block height from a peer. MsgTypeTransactionBundleV2 MsgType = 19 - // NEXT_TAG = 20 + // Proof of stake vote and timeout messages + MsgTypeValidatorVote MsgType = 20 + MsgTypeValidatorTimeout MsgType = 21 + + // NEXT_TAG = 22 // Below are control messages used to signal to the Server from other parts of // the code but not actually sent among peers. @@ -151,6 +155,10 @@ func (msgType MsgType) String() string { return "TRANSACTION_BUNDLE" case MsgTypeTransactionBundleV2: return "TRANSACTION_BUNDLE_V2" + case MsgTypeValidatorVote: + return "VALIDATOR_VOTE" + case MsgTypeValidatorTimeout: + return "VALIDATOR_TIMEOUT" case MsgTypeMempool: return "MEMPOOL" case MsgTypeAddr: diff --git a/lib/network_pos.go b/lib/network_pos.go new file mode 100644 index 000000000..f630cd07e --- /dev/null +++ b/lib/network_pos.go @@ -0,0 +1,263 @@ +package lib + +import ( + "bytes" + "fmt" + + "github.com/deso-protocol/core/bls" + "github.com/pkg/errors" +) + +// ================================================================== +// Proof of Stake Vote Message +// ================================================================== + +type MsgDeSoValidatorVote struct { + MsgVersion uint8 + + // BLS public key of the validator voting for this block. This can be + // mapped directly to the validator's ECDSA public key to verify their + // stale. We include the BLS public key here so that it's easy to verify + // the signature on the block without having to look up the validator's + // ECDSA public key. + ValidatorVotingPublicKey *bls.PublicKey + + // The block hash corresponding to the block that this vote is for. + BlockHash *BlockHash + + // TODO: Do we want to add BlockHeight and ProposedInView here too? They're + // not strictly necessary because they can be looked up based on BlockHash, + // but they are convenient to have on-hand here for debugging. + + // The validator's partial BLS signature of the block hash, representing + // the validator's vote for this block. The block hash captures the block + // height and view. + VotePartialSignature *bls.Signature +} + +func (msg *MsgDeSoValidatorVote) GetMsgType() MsgType { + return MsgTypeValidatorVote +} + +func (msg *MsgDeSoValidatorVote) ToBytes(bool) ([]byte, error) { + if msg.MsgVersion != ValidatorVoteVersion0 { + return nil, fmt.Errorf("MsgDeSoValidatorVote.ToBytes: Invalid MsgVersion %d", msg.MsgVersion) + } + + retBytes := []byte{} + + // MsgVersion + retBytes = append(retBytes, msg.MsgVersion) + + // ValidatorVotingPublicKey + if msg.ValidatorVotingPublicKey == nil { + return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: HighQC must not be nil") + } + encodedValidatorVotingPublicKey := msg.ValidatorVotingPublicKey.ToBytes() + retBytes = append(retBytes, UintToBuf(uint64(len(encodedValidatorVotingPublicKey)))...) + retBytes = append(retBytes, msg.ValidatorVotingPublicKey.ToBytes()...) + + // BlockHash + if msg.BlockHash == nil { + return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: BlockHash must not be nil") + } + retBytes = append(retBytes, msg.BlockHash.ToBytes()...) + + // VotePartialSignature + if msg.VotePartialSignature == nil { + return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: VotePartialSignature must not be nil") + } + retBytes = append(retBytes, msg.VotePartialSignature.ToBytes()...) + + return retBytes, nil +} + +func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { + rr := bytes.NewReader(data) + + // MsgVersion + msgVersion, err := rr.ReadByte() + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading MsgVersion") + } + if msgVersion != ValidatorVoteVersion0 { + return fmt.Errorf("MsgDeSoValidatorVote.FromBytes: Invalid MsgVersion %d", msgVersion) + } + msg.MsgVersion = msgVersion + + // ValidatorVotingPublicKey + validatorVotingPublicKeyLen, err := ReadUvarint(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading length for ValidatorVotingPublicKey") + } + validatorVotingPublicKeyBytes := make([]byte, validatorVotingPublicKeyLen) + _, err = rr.Read(validatorVotingPublicKeyBytes) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading ValidatorVotingPublicKey") + } + validatorVotingPublicKey, err := (&bls.PublicKey{}).FromBytes(validatorVotingPublicKeyBytes) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem decoding ValidatorVotingPublicKey") + } + msg.ValidatorVotingPublicKey = validatorVotingPublicKey + + // BlockHash + blockHashBytes := make([]byte, HashSizeBytes) + _, err = rr.Read(blockHashBytes) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading BlockHash") + } + + // VotePartialSignature + // TODO + + return nil +} + +// ================================================================== +// Proof of Stake Timeout Message +// ================================================================== + +type MsgDeSoValidatorTimeout struct { + MsgVersion uint8 + + // BLS public key of the validator that's timed out for this block. This + // public key can be mapped directly to the validator's ECDSA public key + // to verify their stale. We include the BLS public key here so that it's + // easy to verify the signature on the block without having to look up the + // validator's ECDSA public key. + ValidatorVotingPublicKey *bls.PublicKey + + // The view that the validator has timed out on and to skip over because + // they haven't received a valid block for it and they timed out. + TimedOutView uint64 + + // This BlockQuorumCertificate has the highest view that the validator is aware + // of. This QC allows the leader to link back to the most recent block that + // 2/3rds of validators are aware of when constructing the next block. + HighQC *BlockQuorumCertificate + + // A signature of (TimeoutView, HighQC.View) that indicates this validator + // wants to timeout. Notice that we include the HighQC.View in the signature + // payload rather than signing the full serialized HighQC itself. This allows + // the leader to better aggregate validator signatures without compromising the + // integrity of the protocol. + TimeoutPartialSignature *bls.Signature +} + +func (msg *MsgDeSoValidatorTimeout) GetMsgType() MsgType { + return MsgTypeValidatorTimeout +} + +func (msg *MsgDeSoValidatorTimeout) ToBytes(bool) ([]byte, error) { + if msg.MsgVersion != ValidatorTimeoutVersion0 { + return nil, fmt.Errorf("MsgDeSoValidatorTimeout.ToBytes: Invalid MsgVersion %d", msg.MsgVersion) + } + + retBytes := []byte{} + + // MsgVersion + retBytes = append(retBytes, msg.MsgVersion) + + // ValidatorVotingPublicKey + if msg.ValidatorVotingPublicKey == nil { + return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: ValidatorVotingPublicKey must not be nil") + } + retBytes = append(retBytes, msg.ValidatorVotingPublicKey.ToBytes()...) + + // TimeoutView + retBytes = append(retBytes, UintToBuf(msg.TimedOutView)...) + + // HighQC + if msg.HighQC == nil { + return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: HighQC must not be nil") + } + encodedHighQC, err := msg.HighQC.ToBytes() + if err != nil { + return nil, errors.Wrapf(err, "MsgDeSoValidatorTimeout.ToBytes: Problem encoding HighQC") + } + retBytes = append(retBytes, encodedHighQC...) + + // TimeoutPartialSignature + if msg.TimeoutPartialSignature == nil { + return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: TimeoutPartialSignature must not be nil") + } + retBytes = append(retBytes, msg.TimeoutPartialSignature.ToBytes()...) + + return retBytes, nil +} + +func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { + rr := bytes.NewReader(data) + + // MsgVersion + msgVersion, err := rr.ReadByte() + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading MsgVersion") + } + if msgVersion != ValidatorVoteVersion0 { + return fmt.Errorf("MsgDeSoValidatorVote.FromBytes: Invalid MsgVersion %d", msgVersion) + } + msg.MsgVersion = msgVersion + + // ValidatorVotingPublicKey + // TODO + + // TimedOutView + // TODO + + // HighQC + // TODO + + // TimeoutPartialSignature + // TODO + + return nil +} + +// A QuorumCertificate contains an aggregated signature from 2/3rds of the validators +// on the network, weighted by stake. The signatures are associated with a block hash +// and view both of which are identified in the certificate. +type BlockQuorumCertificate struct { + // No versioning field is needed for this type since it is a member field + // for other top-level P2P messages, which will be versioned themselves. + + // The block hash corresponding to the block that this QC authorizes. + BlockHash *BlockHash + + // The view number when the the block was proposed. + ProposedInView uint64 + + // This BLS signature is aggregated from all of the partial BLS signatures for vote + // messages that have been aggregated by the leader. The partial signatures sign the + // block hash for the block this QC authorizes. + // + // Based on the block hash, we can determine the view number, block height, and ordering + // of validators in this signature. + AggregatedVoteSignature *bls.Signature +} + +func (qc *BlockQuorumCertificate) ToBytes() ([]byte, error) { + retBytes := []byte{} + + // BlockHash + if qc.BlockHash == nil { + return nil, errors.New("QuorumCertificate.ToBytes: BlockHash must not be nil") + } + retBytes = append(retBytes, qc.BlockHash.ToBytes()...) + + // ProposedInView + retBytes = append(retBytes, UintToBuf(qc.ProposedInView)...) + + // AggregatedVoteSignature + if qc.AggregatedVoteSignature == nil { + return nil, errors.New("QuorumCertificate.ToBytes: AggregatedVoteSignature must not be nil") + } + retBytes = append(retBytes, qc.AggregatedVoteSignature.ToBytes()...) + + return retBytes, nil +} + +func (qc *BlockQuorumCertificate) Read(rr *bytes.Reader) error { + return nil +} diff --git a/lib/network_pos_test.go b/lib/network_pos_test.go new file mode 100644 index 000000000..9df6a9f95 --- /dev/null +++ b/lib/network_pos_test.go @@ -0,0 +1,51 @@ +//go:build relic + +package lib + +import ( + "testing" + + "github.com/deso-protocol/core/bls" + "github.com/stretchr/testify/require" +) + +func TestValidatorVoteEncodeDecode(t *testing.T) { + blsPublicKey, blsSignature := _generateValidatorVotingPublicKeyAndSignature(t) + + originalMsg := MsgDeSoValidatorVote{ + MsgVersion: ValidatorVoteVersion0, + ValidatorVotingPublicKey: blsPublicKey, + BlockHash: &BlockHash{}, + VotePartialSignature: blsSignature, + } + + // Encode the message and verify the length is correct. + encodedMsgBytes, err := originalMsg.ToBytes(false) + require.NoError(t, err) + require.Equal(t, 178, len(encodedMsgBytes)) + + // Decode the message. + decodedMsg := &MsgDeSoValidatorVote{} + err = decodedMsg.FromBytes(encodedMsgBytes) + require.NoError(t, err) + + // Check that the message versions are the same. + require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) + require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) + require.Equal(t, originalMsg.BlockHash, decodedMsg.BlockHash) + require.True(t, originalMsg.VotePartialSignature.Eq(decodedMsg.VotePartialSignature)) +} + +func TestValidatorTimeoutEncodeDecode(t *testing.T) { + // TODO +} + +// Creates an arbitrary BLS public key and signature for testing. +func _generateValidatorVotingPublicKeyAndSignature(t *testing.T) (*bls.PublicKey, *bls.Signature) { + blsPrivateKey, err := bls.NewPrivateKey() + require.NoError(t, err) + blsPublicKey := blsPrivateKey.PublicKey() + blsSignature, err := blsPrivateKey.Sign([]byte{0x01, 0x02, 0x03}) + require.NoError(t, err) + return blsPublicKey, blsSignature +} From 9a7ecb35c72f2b7389bc9300c23e40a8f660e66a Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 13:56:17 -0400 Subject: [PATCH 02/14] Implement remaining tests --- lib/network_pos.go | 92 +++++++++++++++++++++++++---------------- lib/network_pos_test.go | 48 ++++++++++++++++++--- 2 files changed, 99 insertions(+), 41 deletions(-) diff --git a/lib/network_pos.go b/lib/network_pos.go index f630cd07e..60e1cf847 100644 --- a/lib/network_pos.go +++ b/lib/network_pos.go @@ -51,23 +51,21 @@ func (msg *MsgDeSoValidatorVote) ToBytes(bool) ([]byte, error) { // ValidatorVotingPublicKey if msg.ValidatorVotingPublicKey == nil { - return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: HighQC must not be nil") + return nil, errors.New("MsgDeSoValidatorVote.ToBytes: ValidatorVotingPublicKey must not be nil") } - encodedValidatorVotingPublicKey := msg.ValidatorVotingPublicKey.ToBytes() - retBytes = append(retBytes, UintToBuf(uint64(len(encodedValidatorVotingPublicKey)))...) - retBytes = append(retBytes, msg.ValidatorVotingPublicKey.ToBytes()...) + retBytes = append(retBytes, EncodeBLSPublicKey(msg.ValidatorVotingPublicKey)...) // BlockHash if msg.BlockHash == nil { - return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: BlockHash must not be nil") + return nil, errors.New("MsgDeSoValidatorVote.ToBytes: BlockHash must not be nil") } retBytes = append(retBytes, msg.BlockHash.ToBytes()...) // VotePartialSignature if msg.VotePartialSignature == nil { - return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: VotePartialSignature must not be nil") + return nil, errors.New("MsgDeSoValidatorVote.ToBytes: VotePartialSignature must not be nil") } - retBytes = append(retBytes, msg.VotePartialSignature.ToBytes()...) + retBytes = append(retBytes, EncodeBLSSignature(msg.VotePartialSignature)...) return retBytes, nil } @@ -86,30 +84,22 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { msg.MsgVersion = msgVersion // ValidatorVotingPublicKey - validatorVotingPublicKeyLen, err := ReadUvarint(rr) - if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading length for ValidatorVotingPublicKey") - } - validatorVotingPublicKeyBytes := make([]byte, validatorVotingPublicKeyLen) - _, err = rr.Read(validatorVotingPublicKeyBytes) - if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading ValidatorVotingPublicKey") - } - validatorVotingPublicKey, err := (&bls.PublicKey{}).FromBytes(validatorVotingPublicKeyBytes) + msg.ValidatorVotingPublicKey, err = DecodeBLSPublicKey(rr) if err != nil { return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem decoding ValidatorVotingPublicKey") } - msg.ValidatorVotingPublicKey = validatorVotingPublicKey // BlockHash - blockHashBytes := make([]byte, HashSizeBytes) - _, err = rr.Read(blockHashBytes) + msg.BlockHash, err = ReadBlockHash(rr) if err != nil { return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading BlockHash") } // VotePartialSignature - // TODO + msg.VotePartialSignature, err = DecodeBLSSignature(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem decoding VotePartialSignature") + } return nil } @@ -132,10 +122,10 @@ type MsgDeSoValidatorTimeout struct { // they haven't received a valid block for it and they timed out. TimedOutView uint64 - // This BlockQuorumCertificate has the highest view that the validator is aware + // This VoteQuorumCertificate has the highest view that the validator is aware // of. This QC allows the leader to link back to the most recent block that // 2/3rds of validators are aware of when constructing the next block. - HighQC *BlockQuorumCertificate + HighQC *VoteQuorumCertificate // A signature of (TimeoutView, HighQC.View) that indicates this validator // wants to timeout. Notice that we include the HighQC.View in the signature @@ -163,7 +153,7 @@ func (msg *MsgDeSoValidatorTimeout) ToBytes(bool) ([]byte, error) { if msg.ValidatorVotingPublicKey == nil { return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: ValidatorVotingPublicKey must not be nil") } - retBytes = append(retBytes, msg.ValidatorVotingPublicKey.ToBytes()...) + retBytes = append(retBytes, EncodeBLSPublicKey(msg.ValidatorVotingPublicKey)...) // TimeoutView retBytes = append(retBytes, UintToBuf(msg.TimedOutView)...) @@ -182,7 +172,7 @@ func (msg *MsgDeSoValidatorTimeout) ToBytes(bool) ([]byte, error) { if msg.TimeoutPartialSignature == nil { return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: TimeoutPartialSignature must not be nil") } - retBytes = append(retBytes, msg.TimeoutPartialSignature.ToBytes()...) + retBytes = append(retBytes, EncodeBLSSignature(msg.TimeoutPartialSignature)...) return retBytes, nil } @@ -193,24 +183,36 @@ func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { // MsgVersion msgVersion, err := rr.ReadByte() if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading MsgVersion") + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem reading MsgVersion") } if msgVersion != ValidatorVoteVersion0 { - return fmt.Errorf("MsgDeSoValidatorVote.FromBytes: Invalid MsgVersion %d", msgVersion) + return fmt.Errorf("MsgDeSoValidatorTimeout.FromBytes: Invalid MsgVersion %d", msgVersion) } msg.MsgVersion = msgVersion // ValidatorVotingPublicKey - // TODO + msg.ValidatorVotingPublicKey, err = DecodeBLSPublicKey(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem decoding ValidatorVotingPublicKey") + } // TimedOutView - // TODO + msg.TimedOutView, err = ReadUvarint(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem reading TimedOutView") + } // HighQC - // TODO + msg.HighQC, err = DecodeQuorumCertificate(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem reading HighQC") + } // TimeoutPartialSignature - // TODO + msg.TimeoutPartialSignature, err = DecodeBLSSignature(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem decoding TimeoutPartialSignature") + } return nil } @@ -218,7 +220,7 @@ func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { // A QuorumCertificate contains an aggregated signature from 2/3rds of the validators // on the network, weighted by stake. The signatures are associated with a block hash // and view both of which are identified in the certificate. -type BlockQuorumCertificate struct { +type VoteQuorumCertificate struct { // No versioning field is needed for this type since it is a member field // for other top-level P2P messages, which will be versioned themselves. @@ -237,7 +239,7 @@ type BlockQuorumCertificate struct { AggregatedVoteSignature *bls.Signature } -func (qc *BlockQuorumCertificate) ToBytes() ([]byte, error) { +func (qc *VoteQuorumCertificate) ToBytes() ([]byte, error) { retBytes := []byte{} // BlockHash @@ -253,11 +255,29 @@ func (qc *BlockQuorumCertificate) ToBytes() ([]byte, error) { if qc.AggregatedVoteSignature == nil { return nil, errors.New("QuorumCertificate.ToBytes: AggregatedVoteSignature must not be nil") } - retBytes = append(retBytes, qc.AggregatedVoteSignature.ToBytes()...) + retBytes = append(retBytes, EncodeBLSSignature(qc.AggregatedVoteSignature)...) return retBytes, nil } -func (qc *BlockQuorumCertificate) Read(rr *bytes.Reader) error { - return nil +func DecodeQuorumCertificate(rr *bytes.Reader) (*VoteQuorumCertificate, error) { + var qc VoteQuorumCertificate + var err error + + qc.BlockHash, err = ReadBlockHash(rr) + if err != nil { + return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Problem reading BlockHash") + } + + qc.ProposedInView, err = ReadUvarint(rr) + if err != nil { + return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Problem reading ProposedInView") + } + + qc.AggregatedVoteSignature, err = DecodeBLSSignature(rr) + if err != nil { + return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Problem reading AggregatedVoteSignature") + } + + return &qc, nil } diff --git a/lib/network_pos_test.go b/lib/network_pos_test.go index 9df6a9f95..dbeb08b56 100644 --- a/lib/network_pos_test.go +++ b/lib/network_pos_test.go @@ -10,19 +10,19 @@ import ( ) func TestValidatorVoteEncodeDecode(t *testing.T) { - blsPublicKey, blsSignature := _generateValidatorVotingPublicKeyAndSignature(t) + validatorVotingPublicKey, votePartialSignature := _generateValidatorVotingPublicKeyAndSignature(t) originalMsg := MsgDeSoValidatorVote{ MsgVersion: ValidatorVoteVersion0, - ValidatorVotingPublicKey: blsPublicKey, + ValidatorVotingPublicKey: validatorVotingPublicKey, BlockHash: &BlockHash{}, - VotePartialSignature: blsSignature, + VotePartialSignature: votePartialSignature, } // Encode the message and verify the length is correct. encodedMsgBytes, err := originalMsg.ToBytes(false) require.NoError(t, err) - require.Equal(t, 178, len(encodedMsgBytes)) + require.Equal(t, 179, len(encodedMsgBytes)) // Decode the message. decodedMsg := &MsgDeSoValidatorVote{} @@ -37,7 +37,45 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { } func TestValidatorTimeoutEncodeDecode(t *testing.T) { - // TODO + validatorVotingPublicKey, timeoutPartialSignature := _generateValidatorVotingPublicKeyAndSignature(t) + + _, partialSignature1 := _generateValidatorVotingPublicKeyAndSignature(t) + _, partialSignature2 := _generateValidatorVotingPublicKeyAndSignature(t) + + aggregateSignature, err := bls.AggregateSignatures([]*bls.Signature{partialSignature1, partialSignature2}) + require.NoError(t, err) + + originalMsg := MsgDeSoValidatorTimeout{ + MsgVersion: ValidatorTimeoutVersion0, + ValidatorVotingPublicKey: validatorVotingPublicKey, + TimedOutView: 999912, + HighQC: &VoteQuorumCertificate{ + BlockHash: &BlockHash{}, + ProposedInView: 999910, + AggregatedVoteSignature: aggregateSignature, + }, + TimeoutPartialSignature: timeoutPartialSignature, + } + + // Encode the message and verify the length is correct. + encodedMsgBytes, err := originalMsg.ToBytes(false) + require.NoError(t, err) + require.Equal(t, 234, len(encodedMsgBytes)) + + // Decode the message. + decodedMsg := &MsgDeSoValidatorTimeout{} + err = decodedMsg.FromBytes(encodedMsgBytes) + require.NoError(t, err) + + // Check that the message versions are the same. + require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) + require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) + require.Equal(t, originalMsg.TimedOutView, decodedMsg.TimedOutView) + require.NotNil(t, decodedMsg.HighQC) + require.Equal(t, originalMsg.HighQC.BlockHash, decodedMsg.HighQC.BlockHash) + require.Equal(t, originalMsg.HighQC.ProposedInView, decodedMsg.HighQC.ProposedInView) + require.True(t, originalMsg.HighQC.AggregatedVoteSignature.Eq(decodedMsg.HighQC.AggregatedVoteSignature)) + require.True(t, originalMsg.TimeoutPartialSignature.Eq(decodedMsg.TimeoutPartialSignature)) } // Creates an arbitrary BLS public key and signature for testing. From 18de02428a02ccd867d3cf12cc54bf744e3f63fe Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 14:19:11 -0400 Subject: [PATCH 03/14] Add ProposedInView field to vote message --- lib/network_pos.go | 73 ++++++++++++++++++++++++----------------- lib/network_pos_test.go | 4 ++- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/lib/network_pos.go b/lib/network_pos.go index 60e1cf847..2f108d7a1 100644 --- a/lib/network_pos.go +++ b/lib/network_pos.go @@ -15,23 +15,29 @@ import ( type MsgDeSoValidatorVote struct { MsgVersion uint8 - // BLS public key of the validator voting for this block. This can be - // mapped directly to the validator's ECDSA public key to verify their - // stale. We include the BLS public key here so that it's easy to verify - // the signature on the block without having to look up the validator's - // ECDSA public key. + // BLS voting public key of the validator who constructed this vote. This public + // key can be mapped directly to the validator's ECDSA public key to verify + // their stake. We use the BLS public key here instead of the ECDSA so that + // so that it's trivial to verify the signature in this message without + // having to look up anything for the validator in consensus. ValidatorVotingPublicKey *bls.PublicKey // The block hash corresponding to the block that this vote is for. BlockHash *BlockHash - // TODO: Do we want to add BlockHeight and ProposedInView here too? They're - // not strictly necessary because they can be looked up based on BlockHash, - // but they are convenient to have on-hand here for debugging. + // The view number when the the block was proposed. + ProposedInView uint64 + + // TODO: Do we want to add BlockHeight here too? It's not strictly necessary + // because it can be derived based on BlockHash alone, but it is convenient + // to have on-hand here for debugging. The trade-off of including it is that + // it results in a larger size message. In general, we should try to keep the + // size of vote messages as small as possible as there will be O(n) votes per block + // where n is the number of validators. - // The validator's partial BLS signature of the block hash, representing - // the validator's vote for this block. The block hash captures the block - // height and view. + // The validator's partial BLS signature of the (ProposedInView, BlockHash) pair + // This represents the validator's vote for this block. The block height is implicitly + // captured in the block hash. VotePartialSignature *bls.Signature } @@ -61,6 +67,9 @@ func (msg *MsgDeSoValidatorVote) ToBytes(bool) ([]byte, error) { } retBytes = append(retBytes, msg.BlockHash.ToBytes()...) + // ProposedInView + retBytes = append(retBytes, UintToBuf(msg.ProposedInView)...) + // VotePartialSignature if msg.VotePartialSignature == nil { return nil, errors.New("MsgDeSoValidatorVote.ToBytes: VotePartialSignature must not be nil") @@ -95,6 +104,12 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading BlockHash") } + // ProposedInView + msg.ProposedInView, err = ReadUvarint(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading ProposedInView") + } + // VotePartialSignature msg.VotePartialSignature, err = DecodeBLSSignature(rr) if err != nil { @@ -111,27 +126,25 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { type MsgDeSoValidatorTimeout struct { MsgVersion uint8 - // BLS public key of the validator that's timed out for this block. This - // public key can be mapped directly to the validator's ECDSA public key - // to verify their stale. We include the BLS public key here so that it's - // easy to verify the signature on the block without having to look up the - // validator's ECDSA public key. + // BLS voting public key of the validator who constructed this timeout message. + // The public key can be mapped directly to the validator's ECDSA public key + // to verify their stake. We use the BLS public key here instead of the ECDSA + // so that so that it's trivial to verify the signature in this message without + // having to look up anything for the validator in consensus. ValidatorVotingPublicKey *bls.PublicKey - // The view that the validator has timed out on and to skip over because - // they haven't received a valid block for it and they timed out. + // The view that the validator has timed out on. TimedOutView uint64 - // This VoteQuorumCertificate has the highest view that the validator is aware - // of. This QC allows the leader to link back to the most recent block that - // 2/3rds of validators are aware of when constructing the next block. + // This QC has the highest view that the validator is aware of. This QC allows + // the leader to link back to the most recent block that 2/3rds of validators + // are aware of when constructing the next block. HighQC *VoteQuorumCertificate - // A signature of (TimeoutView, HighQC.View) that indicates this validator - // wants to timeout. Notice that we include the HighQC.View in the signature - // payload rather than signing the full serialized HighQC itself. This allows - // the leader to better aggregate validator signatures without compromising the - // integrity of the protocol. + // The validator's BLS signature on (TimedOutView, HighQC.View). Notice that we + // include the HighQC.View in the signature payload rather than signing the full + // serialized HighQC itself. This allows the leader to better aggregate validator + // signatures without compromising the integrity of the protocol. TimeoutPartialSignature *bls.Signature } @@ -219,7 +232,7 @@ func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { // A QuorumCertificate contains an aggregated signature from 2/3rds of the validators // on the network, weighted by stake. The signatures are associated with a block hash -// and view both of which are identified in the certificate. +// and a view, both of which are identified in the certificate. type VoteQuorumCertificate struct { // No versioning field is needed for this type since it is a member field // for other top-level P2P messages, which will be versioned themselves. @@ -232,10 +245,10 @@ type VoteQuorumCertificate struct { // This BLS signature is aggregated from all of the partial BLS signatures for vote // messages that have been aggregated by the leader. The partial signatures sign the - // block hash for the block this QC authorizes. + // (ProposedInView, BlockHash) for the block. // - // Based on the block hash, we can determine the view number, block height, and ordering - // of validators in this signature. + // Based on the block hash, block height, and ordering of validator BLS public keys in + // the aggregated signature. AggregatedVoteSignature *bls.Signature } diff --git a/lib/network_pos_test.go b/lib/network_pos_test.go index dbeb08b56..8e5bcd0bf 100644 --- a/lib/network_pos_test.go +++ b/lib/network_pos_test.go @@ -16,13 +16,14 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { MsgVersion: ValidatorVoteVersion0, ValidatorVotingPublicKey: validatorVotingPublicKey, BlockHash: &BlockHash{}, + ProposedInView: 9910, VotePartialSignature: votePartialSignature, } // Encode the message and verify the length is correct. encodedMsgBytes, err := originalMsg.ToBytes(false) require.NoError(t, err) - require.Equal(t, 179, len(encodedMsgBytes)) + require.Equal(t, 181, len(encodedMsgBytes)) // Decode the message. decodedMsg := &MsgDeSoValidatorVote{} @@ -33,6 +34,7 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) require.Equal(t, originalMsg.BlockHash, decodedMsg.BlockHash) + require.Equal(t, originalMsg.ProposedInView, decodedMsg.ProposedInView) require.True(t, originalMsg.VotePartialSignature.Eq(decodedMsg.VotePartialSignature)) } From 178480a22fc21f27fcbf65f38673216f8102e35f Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 14:35:33 -0400 Subject: [PATCH 04/14] Cleanup --- lib/constants.go | 4 ++-- lib/network_pos.go | 47 +++++++++++++++++++++-------------------- lib/network_pos_test.go | 4 ++-- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/lib/constants.go b/lib/constants.go index 99a03ecac..fd190c163 100644 --- a/lib/constants.go +++ b/lib/constants.go @@ -105,8 +105,8 @@ const ( CurrentHeaderVersion = HeaderVersion1 ) -const ValidatorVoteVersion0 = uint8(0) -const ValidatorTimeoutVersion0 = uint8(0) +const MsgValidatorVoteVersion0 = uint8(0) +const MsgValidatorTimeoutVersion0 = uint8(0) var ( MaxUint256, _ = uint256.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") diff --git a/lib/network_pos.go b/lib/network_pos.go index 2f108d7a1..7518333a1 100644 --- a/lib/network_pos.go +++ b/lib/network_pos.go @@ -46,7 +46,7 @@ func (msg *MsgDeSoValidatorVote) GetMsgType() MsgType { } func (msg *MsgDeSoValidatorVote) ToBytes(bool) ([]byte, error) { - if msg.MsgVersion != ValidatorVoteVersion0 { + if msg.MsgVersion != MsgValidatorVoteVersion0 { return nil, fmt.Errorf("MsgDeSoValidatorVote.ToBytes: Invalid MsgVersion %d", msg.MsgVersion) } @@ -85,9 +85,9 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { // MsgVersion msgVersion, err := rr.ReadByte() if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading MsgVersion") + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Error decoding MsgVersion") } - if msgVersion != ValidatorVoteVersion0 { + if msgVersion != MsgValidatorVoteVersion0 { return fmt.Errorf("MsgDeSoValidatorVote.FromBytes: Invalid MsgVersion %d", msgVersion) } msg.MsgVersion = msgVersion @@ -95,25 +95,25 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { // ValidatorVotingPublicKey msg.ValidatorVotingPublicKey, err = DecodeBLSPublicKey(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem decoding ValidatorVotingPublicKey") + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Error decoding ValidatorVotingPublicKey") } // BlockHash msg.BlockHash, err = ReadBlockHash(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading BlockHash") + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Error decoding BlockHash") } // ProposedInView msg.ProposedInView, err = ReadUvarint(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem reading ProposedInView") + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Error decoding ProposedInView") } // VotePartialSignature msg.VotePartialSignature, err = DecodeBLSSignature(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Problem decoding VotePartialSignature") + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Error decoding VotePartialSignature") } return nil @@ -153,7 +153,7 @@ func (msg *MsgDeSoValidatorTimeout) GetMsgType() MsgType { } func (msg *MsgDeSoValidatorTimeout) ToBytes(bool) ([]byte, error) { - if msg.MsgVersion != ValidatorTimeoutVersion0 { + if msg.MsgVersion != MsgValidatorTimeoutVersion0 { return nil, fmt.Errorf("MsgDeSoValidatorTimeout.ToBytes: Invalid MsgVersion %d", msg.MsgVersion) } @@ -177,7 +177,7 @@ func (msg *MsgDeSoValidatorTimeout) ToBytes(bool) ([]byte, error) { } encodedHighQC, err := msg.HighQC.ToBytes() if err != nil { - return nil, errors.Wrapf(err, "MsgDeSoValidatorTimeout.ToBytes: Problem encoding HighQC") + return nil, errors.Wrapf(err, "MsgDeSoValidatorTimeout.ToBytes: Error encoding HighQC") } retBytes = append(retBytes, encodedHighQC...) @@ -196,9 +196,9 @@ func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { // MsgVersion msgVersion, err := rr.ReadByte() if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem reading MsgVersion") + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Error decoding MsgVersion") } - if msgVersion != ValidatorVoteVersion0 { + if msgVersion != MsgValidatorVoteVersion0 { return fmt.Errorf("MsgDeSoValidatorTimeout.FromBytes: Invalid MsgVersion %d", msgVersion) } msg.MsgVersion = msgVersion @@ -206,25 +206,25 @@ func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { // ValidatorVotingPublicKey msg.ValidatorVotingPublicKey, err = DecodeBLSPublicKey(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem decoding ValidatorVotingPublicKey") + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Error decoding ValidatorVotingPublicKey") } // TimedOutView msg.TimedOutView, err = ReadUvarint(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem reading TimedOutView") + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Error decoding TimedOutView") } // HighQC msg.HighQC, err = DecodeQuorumCertificate(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem reading HighQC") + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Error decoding HighQC") } // TimeoutPartialSignature msg.TimeoutPartialSignature, err = DecodeBLSSignature(rr) if err != nil { - return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Problem decoding TimeoutPartialSignature") + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Error decoding TimeoutPartialSignature") } return nil @@ -243,12 +243,13 @@ type VoteQuorumCertificate struct { // The view number when the the block was proposed. ProposedInView uint64 - // This BLS signature is aggregated from all of the partial BLS signatures for vote - // messages that have been aggregated by the leader. The partial signatures sign the - // (ProposedInView, BlockHash) for the block. + // This BLS signature is aggregated from all of the partial BLS signatures for + // vote messages that have been aggregated by the leader. The partial signatures + // sign the (ProposedInView, BlockHash) pair for the block. // - // Based on the block hash, block height, and ordering of validator BLS public keys in - // the aggregated signature. + // From the block hash, we can look up the block height and ordering of validator + // BLS public keys at that block height which determines the ordering of BLS public + // keys in the aggregated signature. AggregatedVoteSignature *bls.Signature } @@ -279,17 +280,17 @@ func DecodeQuorumCertificate(rr *bytes.Reader) (*VoteQuorumCertificate, error) { qc.BlockHash, err = ReadBlockHash(rr) if err != nil { - return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Problem reading BlockHash") + return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Error decoding BlockHash") } qc.ProposedInView, err = ReadUvarint(rr) if err != nil { - return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Problem reading ProposedInView") + return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Error decoding ProposedInView") } qc.AggregatedVoteSignature, err = DecodeBLSSignature(rr) if err != nil { - return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Problem reading AggregatedVoteSignature") + return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Error decoding AggregatedVoteSignature") } return &qc, nil diff --git a/lib/network_pos_test.go b/lib/network_pos_test.go index 8e5bcd0bf..1f4457b6d 100644 --- a/lib/network_pos_test.go +++ b/lib/network_pos_test.go @@ -13,7 +13,7 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { validatorVotingPublicKey, votePartialSignature := _generateValidatorVotingPublicKeyAndSignature(t) originalMsg := MsgDeSoValidatorVote{ - MsgVersion: ValidatorVoteVersion0, + MsgVersion: MsgValidatorVoteVersion0, ValidatorVotingPublicKey: validatorVotingPublicKey, BlockHash: &BlockHash{}, ProposedInView: 9910, @@ -48,7 +48,7 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { require.NoError(t, err) originalMsg := MsgDeSoValidatorTimeout{ - MsgVersion: ValidatorTimeoutVersion0, + MsgVersion: MsgValidatorTimeoutVersion0, ValidatorVotingPublicKey: validatorVotingPublicKey, TimedOutView: 999912, HighQC: &VoteQuorumCertificate{ From 43d7f2b6a8196ccdacb229759efa6c0d31f9c9d8 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 14:38:37 -0400 Subject: [PATCH 05/14] Fix failing TestEnumExtras unit test --- lib/network.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/network.go b/lib/network.go index ef385bdbb..099c7b2f8 100644 --- a/lib/network.go +++ b/lib/network.go @@ -753,6 +753,10 @@ func NewMessage(msgType MsgType) DeSoMessage { return &MsgDeSoTransactionBundle{} case MsgTypeTransactionBundleV2: return &MsgDeSoTransactionBundleV2{} + case MsgTypeValidatorVote: + return &MsgDeSoValidatorVote{} + case MsgTypeValidatorTimeout: + return &MsgDeSoValidatorTimeout{} case MsgTypeMempool: return &MsgDeSoMempool{} case MsgTypeGetHeaders: From edab49648800851e2942165e426cf218c6885911 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 18:00:36 -0400 Subject: [PATCH 06/14] Comments --- lib/network_pos.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/network_pos.go b/lib/network_pos.go index 7518333a1..6ffcc07e2 100644 --- a/lib/network_pos.go +++ b/lib/network_pos.go @@ -247,9 +247,8 @@ type VoteQuorumCertificate struct { // vote messages that have been aggregated by the leader. The partial signatures // sign the (ProposedInView, BlockHash) pair for the block. // - // From the block hash, we can look up the block height and ordering of validator - // BLS public keys at that block height which determines the ordering of BLS public - // keys in the aggregated signature. + // From the block hash, we can look up the block height, the validator set at that + // block height, and measure if the QC has 2/3rds of the total stake. AggregatedVoteSignature *bls.Signature } From 2cc1f3fca0e9d31a9329f3b27e5746ede327c748 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 20:00:05 -0400 Subject: [PATCH 07/14] Add validators list to aggregated signature --- lib/network_pos.go | 66 ++++++++++++++++++++++++++++++++++++----- lib/network_pos_test.go | 24 +++++++++++---- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/lib/network_pos.go b/lib/network_pos.go index 6ffcc07e2..44a7d1157 100644 --- a/lib/network_pos.go +++ b/lib/network_pos.go @@ -248,8 +248,10 @@ type VoteQuorumCertificate struct { // sign the (ProposedInView, BlockHash) pair for the block. // // From the block hash, we can look up the block height, the validator set at that - // block height, and measure if the QC has 2/3rds of the total stake. - AggregatedVoteSignature *bls.Signature + // block height, and the ordering of validators in consensus which identifies the + // present signers in the provided signers list. We can then use this to determine + // if the QC has 2/3rds of the total stake. + ValidatorsVoteAggregatedSignature *AggregatedBLSSignature } func (qc *VoteQuorumCertificate) ToBytes() ([]byte, error) { @@ -264,11 +266,15 @@ func (qc *VoteQuorumCertificate) ToBytes() ([]byte, error) { // ProposedInView retBytes = append(retBytes, UintToBuf(qc.ProposedInView)...) - // AggregatedVoteSignature - if qc.AggregatedVoteSignature == nil { - return nil, errors.New("QuorumCertificate.ToBytes: AggregatedVoteSignature must not be nil") + // ValidatorsVoteAggregatedSignature + if qc.ValidatorsVoteAggregatedSignature == nil { + return nil, errors.New("QuorumCertificate.ToBytes: ValidatorsVoteAggregatedSignature must not be nil") } - retBytes = append(retBytes, EncodeBLSSignature(qc.AggregatedVoteSignature)...) + encodedValidatorsVoteAggregatedSignature, err := qc.ValidatorsVoteAggregatedSignature.ToBytes() + if err != nil { + return nil, errors.Wrapf(err, "QuorumCertificate.ToBytes: Error encoding ValidatorsVoteAggregatedSignature") + } + retBytes = append(retBytes, encodedValidatorsVoteAggregatedSignature...) return retBytes, nil } @@ -287,10 +293,54 @@ func DecodeQuorumCertificate(rr *bytes.Reader) (*VoteQuorumCertificate, error) { return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Error decoding ProposedInView") } - qc.AggregatedVoteSignature, err = DecodeBLSSignature(rr) + qc.ValidatorsVoteAggregatedSignature, err = DecodeAggregatedBLSSignature(rr) if err != nil { - return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Error decoding AggregatedVoteSignature") + return nil, errors.Wrapf(err, "DecodeQuorumCertificate: Error decoding ValidatorsVoteAggregatedSignature") } return &qc, nil } + +// This is an aggregated BLS signature from a set of validators. Each validator's +// presence in the signature is denoted in the provided signers list. I.e. if the +// list's value at index 0 is 1, then the validator identified by that index is +// present in the aggregated signature. The indices of all validators are expected +// to be known by the caller. +type AggregatedBLSSignature struct { + // TODO: Switch this to a bitlist, which will result in ~8x reduction in total + // size of this construct. + SignersList []byte + Signature *bls.Signature +} + +func (sig *AggregatedBLSSignature) ToBytes() ([]byte, error) { + retBytes := []byte{} + + // SignersList + retBytes = append(retBytes, EncodeByteArray(sig.SignersList)...) + + // Signature + if sig.Signature == nil { + return nil, errors.New("AggregatedBLSSignature.ToBytes: Signature must not be nil") + } + retBytes = append(retBytes, EncodeBLSSignature(sig.Signature)...) + + return retBytes, nil +} + +func DecodeAggregatedBLSSignature(rr *bytes.Reader) (*AggregatedBLSSignature, error) { + var sig AggregatedBLSSignature + var err error + + sig.SignersList, err = DecodeByteArray(rr) + if err != nil { + return nil, errors.Wrapf(err, "DecodeAggregatedBLSSignature: Error decoding SignersList") + } + + sig.Signature, err = DecodeBLSSignature(rr) + if err != nil { + return nil, errors.Wrapf(err, "DecodeAggregatedBLSSignature: Error decoding Signature") + } + + return &sig, nil +} diff --git a/lib/network_pos_test.go b/lib/network_pos_test.go index 1f4457b6d..ea81240b7 100644 --- a/lib/network_pos_test.go +++ b/lib/network_pos_test.go @@ -52,9 +52,12 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { ValidatorVotingPublicKey: validatorVotingPublicKey, TimedOutView: 999912, HighQC: &VoteQuorumCertificate{ - BlockHash: &BlockHash{}, - ProposedInView: 999910, - AggregatedVoteSignature: aggregateSignature, + BlockHash: &BlockHash{}, + ProposedInView: 999910, + ValidatorsVoteAggregatedSignature: &AggregatedBLSSignature{ + SignersList: []byte{1, 2}, + Signature: aggregateSignature, + }, }, TimeoutPartialSignature: timeoutPartialSignature, } @@ -62,7 +65,7 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { // Encode the message and verify the length is correct. encodedMsgBytes, err := originalMsg.ToBytes(false) require.NoError(t, err) - require.Equal(t, 234, len(encodedMsgBytes)) + require.Equal(t, 237, len(encodedMsgBytes)) // Decode the message. decodedMsg := &MsgDeSoValidatorTimeout{} @@ -73,11 +76,20 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) require.Equal(t, originalMsg.TimedOutView, decodedMsg.TimedOutView) - require.NotNil(t, decodedMsg.HighQC) require.Equal(t, originalMsg.HighQC.BlockHash, decodedMsg.HighQC.BlockHash) require.Equal(t, originalMsg.HighQC.ProposedInView, decodedMsg.HighQC.ProposedInView) - require.True(t, originalMsg.HighQC.AggregatedVoteSignature.Eq(decodedMsg.HighQC.AggregatedVoteSignature)) require.True(t, originalMsg.TimeoutPartialSignature.Eq(decodedMsg.TimeoutPartialSignature)) + + // Check the aggregated signature. + require.True(t, + originalMsg.HighQC.ValidatorsVoteAggregatedSignature.Signature.Eq( + decodedMsg.HighQC.ValidatorsVoteAggregatedSignature.Signature, + ), + ) + require.Equal(t, + originalMsg.HighQC.ValidatorsVoteAggregatedSignature.SignersList, + decodedMsg.HighQC.ValidatorsVoteAggregatedSignature.SignersList, + ) } // Creates an arbitrary BLS public key and signature for testing. From cd49d760ebe2591e1a4b5f3946d3ee25bec6f591 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 20:07:25 -0400 Subject: [PATCH 08/14] Fix naming for QC type --- lib/network_pos.go | 10 +++++----- lib/network_pos_test.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/network_pos.go b/lib/network_pos.go index 44a7d1157..f29654b3f 100644 --- a/lib/network_pos.go +++ b/lib/network_pos.go @@ -139,7 +139,7 @@ type MsgDeSoValidatorTimeout struct { // This QC has the highest view that the validator is aware of. This QC allows // the leader to link back to the most recent block that 2/3rds of validators // are aware of when constructing the next block. - HighQC *VoteQuorumCertificate + HighQC *QuorumCertificate // The validator's BLS signature on (TimedOutView, HighQC.View). Notice that we // include the HighQC.View in the signature payload rather than signing the full @@ -233,7 +233,7 @@ func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { // A QuorumCertificate contains an aggregated signature from 2/3rds of the validators // on the network, weighted by stake. The signatures are associated with a block hash // and a view, both of which are identified in the certificate. -type VoteQuorumCertificate struct { +type QuorumCertificate struct { // No versioning field is needed for this type since it is a member field // for other top-level P2P messages, which will be versioned themselves. @@ -254,7 +254,7 @@ type VoteQuorumCertificate struct { ValidatorsVoteAggregatedSignature *AggregatedBLSSignature } -func (qc *VoteQuorumCertificate) ToBytes() ([]byte, error) { +func (qc *QuorumCertificate) ToBytes() ([]byte, error) { retBytes := []byte{} // BlockHash @@ -279,8 +279,8 @@ func (qc *VoteQuorumCertificate) ToBytes() ([]byte, error) { return retBytes, nil } -func DecodeQuorumCertificate(rr *bytes.Reader) (*VoteQuorumCertificate, error) { - var qc VoteQuorumCertificate +func DecodeQuorumCertificate(rr *bytes.Reader) (*QuorumCertificate, error) { + var qc QuorumCertificate var err error qc.BlockHash, err = ReadBlockHash(rr) diff --git a/lib/network_pos_test.go b/lib/network_pos_test.go index ea81240b7..bc7e4e647 100644 --- a/lib/network_pos_test.go +++ b/lib/network_pos_test.go @@ -51,7 +51,7 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { MsgVersion: MsgValidatorTimeoutVersion0, ValidatorVotingPublicKey: validatorVotingPublicKey, TimedOutView: 999912, - HighQC: &VoteQuorumCertificate{ + HighQC: &QuorumCertificate{ BlockHash: &BlockHash{}, ProposedInView: 999910, ValidatorsVoteAggregatedSignature: &AggregatedBLSSignature{ From bab6fded771430670e1124019eb84512aa9ec9dd Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 14 Jun 2023 20:48:46 -0400 Subject: [PATCH 09/14] Use io.reader --- lib/network_pos.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/network_pos.go b/lib/network_pos.go index f29654b3f..5eb0577af 100644 --- a/lib/network_pos.go +++ b/lib/network_pos.go @@ -3,6 +3,7 @@ package lib import ( "bytes" "fmt" + "io" "github.com/deso-protocol/core/bls" "github.com/pkg/errors" @@ -279,7 +280,7 @@ func (qc *QuorumCertificate) ToBytes() ([]byte, error) { return retBytes, nil } -func DecodeQuorumCertificate(rr *bytes.Reader) (*QuorumCertificate, error) { +func DecodeQuorumCertificate(rr io.Reader) (*QuorumCertificate, error) { var qc QuorumCertificate var err error @@ -328,7 +329,7 @@ func (sig *AggregatedBLSSignature) ToBytes() ([]byte, error) { return retBytes, nil } -func DecodeAggregatedBLSSignature(rr *bytes.Reader) (*AggregatedBLSSignature, error) { +func DecodeAggregatedBLSSignature(rr io.Reader) (*AggregatedBLSSignature, error) { var sig AggregatedBLSSignature var err error From 9aa28230ac6ad4497e667ed68de02f21be511f11 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Mon, 19 Jun 2023 10:17:32 -0400 Subject: [PATCH 10/14] Prefix new file names with 'pos_' --- lib/{network_pos.go => pos_network.go} | 0 lib/{network_pos_test.go => pos_network_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename lib/{network_pos.go => pos_network.go} (100%) rename lib/{network_pos_test.go => pos_network_test.go} (100%) diff --git a/lib/network_pos.go b/lib/pos_network.go similarity index 100% rename from lib/network_pos.go rename to lib/pos_network.go diff --git a/lib/network_pos_test.go b/lib/pos_network_test.go similarity index 100% rename from lib/network_pos_test.go rename to lib/pos_network_test.go From d89000fb7b8ca8d827fb5f93ccf0925fcf868907 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 21 Jun 2023 06:31:49 -0600 Subject: [PATCH 11/14] Add deep equality check functions to new types --- lib/pos_network.go | 29 +++++++++++++++++++++++++++++ lib/pos_network_test.go | 16 +++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/pos_network.go b/lib/pos_network.go index 5eb0577af..8a362b58b 100644 --- a/lib/pos_network.go +++ b/lib/pos_network.go @@ -255,6 +255,22 @@ type QuorumCertificate struct { ValidatorsVoteAggregatedSignature *AggregatedBLSSignature } +// Performs a deep equality check between two QuorumCertificates, and returns +// true if the values of the two are identical. +func (qc *QuorumCertificate) Eq(other *QuorumCertificate) bool { + if qc == nil && other == nil { + return true + } + + if (qc == nil) != (other == nil) { + return false + } + + return bytes.Equal(qc.BlockHash.ToBytes(), other.BlockHash.ToBytes()) && + qc.ProposedInView == other.ProposedInView && + qc.ValidatorsVoteAggregatedSignature.Eq(other.ValidatorsVoteAggregatedSignature) +} + func (qc *QuorumCertificate) ToBytes() ([]byte, error) { retBytes := []byte{} @@ -314,6 +330,19 @@ type AggregatedBLSSignature struct { Signature *bls.Signature } +func (sig *AggregatedBLSSignature) Eq(other *AggregatedBLSSignature) bool { + if sig == nil && other == nil { + return true + } + + if (sig == nil) != (other == nil) { + return false + } + + return bytes.Equal(sig.SignersList, other.SignersList) && + sig.Signature.Eq(other.Signature) +} + func (sig *AggregatedBLSSignature) ToBytes() ([]byte, error) { retBytes := []byte{} diff --git a/lib/pos_network_test.go b/lib/pos_network_test.go index bc7e4e647..ae67ac151 100644 --- a/lib/pos_network_test.go +++ b/lib/pos_network_test.go @@ -30,7 +30,7 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { err = decodedMsg.FromBytes(encodedMsgBytes) require.NoError(t, err) - // Check that the message versions are the same. + // Check that the message bodies are the same. require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) require.Equal(t, originalMsg.BlockHash, decodedMsg.BlockHash) @@ -72,24 +72,18 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { err = decodedMsg.FromBytes(encodedMsgBytes) require.NoError(t, err) - // Check that the message versions are the same. + // Check that the message bodies are the same. require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) require.Equal(t, originalMsg.TimedOutView, decodedMsg.TimedOutView) - require.Equal(t, originalMsg.HighQC.BlockHash, decodedMsg.HighQC.BlockHash) - require.Equal(t, originalMsg.HighQC.ProposedInView, decodedMsg.HighQC.ProposedInView) require.True(t, originalMsg.TimeoutPartialSignature.Eq(decodedMsg.TimeoutPartialSignature)) - // Check the aggregated signature. + // Check the high QC is the same. require.True(t, - originalMsg.HighQC.ValidatorsVoteAggregatedSignature.Signature.Eq( - decodedMsg.HighQC.ValidatorsVoteAggregatedSignature.Signature, + originalMsg.HighQC.ValidatorsVoteAggregatedSignature.Eq( + decodedMsg.HighQC.ValidatorsVoteAggregatedSignature, ), ) - require.Equal(t, - originalMsg.HighQC.ValidatorsVoteAggregatedSignature.SignersList, - decodedMsg.HighQC.ValidatorsVoteAggregatedSignature.SignersList, - ) } // Creates an arbitrary BLS public key and signature for testing. From 52db5c1f9a1607e0c433528ee08eaeaf2e71ea5a Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Wed, 21 Jun 2023 06:47:11 -0600 Subject: [PATCH 12/14] Add ECDSA public key to new message types --- lib/pos_network.go | 50 ++++++++++++++++++++++++++++++++--------- lib/pos_network_test.go | 10 ++++++--- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/lib/pos_network.go b/lib/pos_network.go index 8a362b58b..a7d0470e0 100644 --- a/lib/pos_network.go +++ b/lib/pos_network.go @@ -16,11 +16,14 @@ import ( type MsgDeSoValidatorVote struct { MsgVersion uint8 - // BLS voting public key of the validator who constructed this vote. This public - // key can be mapped directly to the validator's ECDSA public key to verify - // their stake. We use the BLS public key here instead of the ECDSA so that - // so that it's trivial to verify the signature in this message without - // having to look up anything for the validator in consensus. + // The ECDSA and BLS voting public key of the validator who constructed this + // vote. We include both keys here: + // - the ECDSA key is used to perform a lookup of the validator's stake in consensus, + // and fetch the validator's registered BLS public key for the block height + // - the BLS public key is used to cheaply verify the integrity of the signature + // as soon as we receive this message, before having to perform any lookups in + // on this message before performing any lookups in consensus. + ValidatorPublicKey *PublicKey ValidatorVotingPublicKey *bls.PublicKey // The block hash corresponding to the block that this vote is for. @@ -56,6 +59,12 @@ func (msg *MsgDeSoValidatorVote) ToBytes(bool) ([]byte, error) { // MsgVersion retBytes = append(retBytes, msg.MsgVersion) + // ValidatorPublicKey + if msg.ValidatorPublicKey == nil { + return nil, errors.New("MsgDeSoValidatorVote.ToBytes: ValidatorPublicKey must not be nil") + } + retBytes = append(retBytes, msg.ValidatorPublicKey.ToBytes()...) + // ValidatorVotingPublicKey if msg.ValidatorVotingPublicKey == nil { return nil, errors.New("MsgDeSoValidatorVote.ToBytes: ValidatorVotingPublicKey must not be nil") @@ -93,6 +102,12 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { } msg.MsgVersion = msgVersion + // ValidatorPublicKey + msg.ValidatorPublicKey, err = ReadPublicKey(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorVote.FromBytes: Error decoding ValidatorPublicKey") + } + // ValidatorVotingPublicKey msg.ValidatorVotingPublicKey, err = DecodeBLSPublicKey(rr) if err != nil { @@ -127,11 +142,14 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { type MsgDeSoValidatorTimeout struct { MsgVersion uint8 - // BLS voting public key of the validator who constructed this timeout message. - // The public key can be mapped directly to the validator's ECDSA public key - // to verify their stake. We use the BLS public key here instead of the ECDSA - // so that so that it's trivial to verify the signature in this message without - // having to look up anything for the validator in consensus. + // The ECDSA and BLS voting public key of the validator who constructed this + // vote. We include both keys here: + // - the ECDSA key is used to perform a lookup of the validator's stake in consensus, + // and fetch the validator's registered BLS public key for the block height + // - the BLS public key is used to cheaply verify the integrity of the signature + // as soon as we receive this message, before having to perform any lookups in + // on this message before performing any lookups in consensus. + ValidatorPublicKey *PublicKey ValidatorVotingPublicKey *bls.PublicKey // The view that the validator has timed out on. @@ -163,6 +181,12 @@ func (msg *MsgDeSoValidatorTimeout) ToBytes(bool) ([]byte, error) { // MsgVersion retBytes = append(retBytes, msg.MsgVersion) + // ValidatorPublicKey + if msg.ValidatorPublicKey == nil { + return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: ValidatorPublicKey must not be nil") + } + retBytes = append(retBytes, msg.ValidatorPublicKey.ToBytes()...) + // ValidatorVotingPublicKey if msg.ValidatorVotingPublicKey == nil { return nil, errors.New("MsgDeSoValidatorTimeout.ToBytes: ValidatorVotingPublicKey must not be nil") @@ -204,6 +228,12 @@ func (msg *MsgDeSoValidatorTimeout) FromBytes(data []byte) error { } msg.MsgVersion = msgVersion + // ValidatorPublicKey + msg.ValidatorPublicKey, err = ReadPublicKey(rr) + if err != nil { + return errors.Wrapf(err, "MsgDeSoValidatorTimeout.FromBytes: Error decoding ValidatorPublicKey") + } + // ValidatorVotingPublicKey msg.ValidatorVotingPublicKey, err = DecodeBLSPublicKey(rr) if err != nil { diff --git a/lib/pos_network_test.go b/lib/pos_network_test.go index ae67ac151..76514eabc 100644 --- a/lib/pos_network_test.go +++ b/lib/pos_network_test.go @@ -14,6 +14,7 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { originalMsg := MsgDeSoValidatorVote{ MsgVersion: MsgValidatorVoteVersion0, + ValidatorPublicKey: &PublicKey{}, ValidatorVotingPublicKey: validatorVotingPublicKey, BlockHash: &BlockHash{}, ProposedInView: 9910, @@ -23,7 +24,7 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { // Encode the message and verify the length is correct. encodedMsgBytes, err := originalMsg.ToBytes(false) require.NoError(t, err) - require.Equal(t, 181, len(encodedMsgBytes)) + require.Equal(t, 214, len(encodedMsgBytes)) // Decode the message. decodedMsg := &MsgDeSoValidatorVote{} @@ -32,6 +33,7 @@ func TestValidatorVoteEncodeDecode(t *testing.T) { // Check that the message bodies are the same. require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) + require.True(t, originalMsg.ValidatorPublicKey.Equal(*decodedMsg.ValidatorPublicKey)) require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) require.Equal(t, originalMsg.BlockHash, decodedMsg.BlockHash) require.Equal(t, originalMsg.ProposedInView, decodedMsg.ProposedInView) @@ -49,6 +51,7 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { originalMsg := MsgDeSoValidatorTimeout{ MsgVersion: MsgValidatorTimeoutVersion0, + ValidatorPublicKey: &PublicKey{}, ValidatorVotingPublicKey: validatorVotingPublicKey, TimedOutView: 999912, HighQC: &QuorumCertificate{ @@ -65,7 +68,7 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { // Encode the message and verify the length is correct. encodedMsgBytes, err := originalMsg.ToBytes(false) require.NoError(t, err) - require.Equal(t, 237, len(encodedMsgBytes)) + require.Equal(t, 270, len(encodedMsgBytes)) // Decode the message. decodedMsg := &MsgDeSoValidatorTimeout{} @@ -74,11 +77,12 @@ func TestValidatorTimeoutEncodeDecode(t *testing.T) { // Check that the message bodies are the same. require.Equal(t, originalMsg.MsgVersion, decodedMsg.MsgVersion) + require.True(t, originalMsg.ValidatorPublicKey.Equal(*decodedMsg.ValidatorPublicKey)) require.True(t, originalMsg.ValidatorVotingPublicKey.Eq(decodedMsg.ValidatorVotingPublicKey)) require.Equal(t, originalMsg.TimedOutView, decodedMsg.TimedOutView) require.True(t, originalMsg.TimeoutPartialSignature.Eq(decodedMsg.TimeoutPartialSignature)) - // Check the high QC is the same. + // Check that the high QCs are the same. require.True(t, originalMsg.HighQC.ValidatorsVoteAggregatedSignature.Eq( decodedMsg.HighQC.ValidatorsVoteAggregatedSignature, From 044509b39cd2981b3e5c98b5d5cf78eeeebb7687 Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Fri, 23 Jun 2023 00:08:50 -0600 Subject: [PATCH 13/14] Address Nina's comments --- lib/constants.go | 17 ++++++++++++++-- lib/pos_network.go | 50 +++++++++++++++++++++------------------------- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/lib/constants.go b/lib/constants.go index fd190c163..0920238cb 100644 --- a/lib/constants.go +++ b/lib/constants.go @@ -105,8 +105,21 @@ const ( CurrentHeaderVersion = HeaderVersion1 ) -const MsgValidatorVoteVersion0 = uint8(0) -const MsgValidatorTimeoutVersion0 = uint8(0) +// Versioning for the MsgValidatorVote message type. This type alias is equivalent +// to a uint8, and supports the same byte encoders/decoders. +type MsgValidatorVoteVersion = byte + +const ( + MsgValidatorVoteVersion0 MsgValidatorVoteVersion = 0 +) + +// Versioning for the MsgValidatorTimeout message type. This type alias is equivalent +// to a uint8, and supports the same byte encoders/decoders. +type MsgValidatorTimeoutVersion = byte + +const ( + MsgValidatorTimeoutVersion0 MsgValidatorTimeoutVersion = 0 +) var ( MaxUint256, _ = uint256.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") diff --git a/lib/pos_network.go b/lib/pos_network.go index a7d0470e0..cceef4301 100644 --- a/lib/pos_network.go +++ b/lib/pos_network.go @@ -14,16 +14,18 @@ import ( // ================================================================== type MsgDeSoValidatorVote struct { - MsgVersion uint8 - - // The ECDSA and BLS voting public key of the validator who constructed this - // vote. We include both keys here: - // - the ECDSA key is used to perform a lookup of the validator's stake in consensus, - // and fetch the validator's registered BLS public key for the block height - // - the BLS public key is used to cheaply verify the integrity of the signature - // as soon as we receive this message, before having to perform any lookups in - // on this message before performing any lookups in consensus. - ValidatorPublicKey *PublicKey + MsgVersion MsgValidatorVoteVersion + + // The ECDSA public key for the validator who constructed this vote message. + // Given the validator's ECDSA public key, we can look up their Validator PKID + // and their stake in consensus. This allows us to verify that the vote message + // was sent by a registered validator. + ValidatorPublicKey *PublicKey + // The BLS voting public key for the validator who constructed this vote message. + // The BLS public key is included in the vote message for because it allows us to + // easily verify if the BLS VotePartialSignature is correctly formed, without having + // to first look up the validator's BLS public key in consensus. It helps optimize + // vote validation. ValidatorVotingPublicKey *bls.PublicKey // The block hash corresponding to the block that this vote is for. @@ -32,13 +34,6 @@ type MsgDeSoValidatorVote struct { // The view number when the the block was proposed. ProposedInView uint64 - // TODO: Do we want to add BlockHeight here too? It's not strictly necessary - // because it can be derived based on BlockHash alone, but it is convenient - // to have on-hand here for debugging. The trade-off of including it is that - // it results in a larger size message. In general, we should try to keep the - // size of vote messages as small as possible as there will be O(n) votes per block - // where n is the number of validators. - // The validator's partial BLS signature of the (ProposedInView, BlockHash) pair // This represents the validator's vote for this block. The block height is implicitly // captured in the block hash. @@ -140,16 +135,17 @@ func (msg *MsgDeSoValidatorVote) FromBytes(data []byte) error { // ================================================================== type MsgDeSoValidatorTimeout struct { - MsgVersion uint8 - - // The ECDSA and BLS voting public key of the validator who constructed this - // vote. We include both keys here: - // - the ECDSA key is used to perform a lookup of the validator's stake in consensus, - // and fetch the validator's registered BLS public key for the block height - // - the BLS public key is used to cheaply verify the integrity of the signature - // as soon as we receive this message, before having to perform any lookups in - // on this message before performing any lookups in consensus. - ValidatorPublicKey *PublicKey + MsgVersion MsgValidatorTimeoutVersion + + // The ECDSA public key for the validator who constructed this timeout message. + // Given the validator's ECDSA public key, we can look up their Validator PKID. + // This allows us to verify that the timeout originated from a registered validator. + ValidatorPublicKey *PublicKey + // The BLS voting public key for the validator who constructed this timeout. The BLS + // public key is included in the timeout message reasons because it allows us to easily + // verify that the BLS TimeoutPartialSignature is correctly formed, without having to + // first look up the validator's BLS public key in consensus. It helps optimize timeout + // message validation. ValidatorVotingPublicKey *bls.PublicKey // The view that the validator has timed out on. From 9daf864ccfe6c28b5c05fb0a71aa46c076993cfd Mon Sep 17 00:00:00 2001 From: iamsofonias Date: Sun, 25 Jun 2023 14:44:47 -0600 Subject: [PATCH 14/14] Address nits --- lib/pos_network.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pos_network.go b/lib/pos_network.go index cceef4301..f2db4117d 100644 --- a/lib/pos_network.go +++ b/lib/pos_network.go @@ -22,7 +22,7 @@ type MsgDeSoValidatorVote struct { // was sent by a registered validator. ValidatorPublicKey *PublicKey // The BLS voting public key for the validator who constructed this vote message. - // The BLS public key is included in the vote message for because it allows us to + // The BLS public key is included in the vote message because it allows us to // easily verify if the BLS VotePartialSignature is correctly formed, without having // to first look up the validator's BLS public key in consensus. It helps optimize // vote validation. @@ -142,7 +142,7 @@ type MsgDeSoValidatorTimeout struct { // This allows us to verify that the timeout originated from a registered validator. ValidatorPublicKey *PublicKey // The BLS voting public key for the validator who constructed this timeout. The BLS - // public key is included in the timeout message reasons because it allows us to easily + // public key is included in the timeout message because it allows us to easily // verify that the BLS TimeoutPartialSignature is correctly formed, without having to // first look up the validator's BLS public key in consensus. It helps optimize timeout // message validation.