diff --git a/docs/ibc/proto-docs.md b/docs/ibc/proto-docs.md index f1235bb252c..c52b01d3476 100644 --- a/docs/ibc/proto-docs.md +++ b/docs/ibc/proto-docs.md @@ -3307,7 +3307,7 @@ Commitment message signed by beefy validators | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `payload` | [bytes](#bytes) | | array of payload items signed by Beefy validators | +| `payload` | [PayloadItem](#ibc.lightclients.beefy.v1.PayloadItem) | repeated | array of payload items signed by Beefy validators | | `block_numer` | [uint32](#uint32) | | block number for this commitment | | `validator_set_id` | [uint64](#uint64) | | validator set that signed this commitment | diff --git a/go.mod b/go.mod index d05a1f0af55..f5dae4f86f0 100644 --- a/go.mod +++ b/go.mod @@ -33,9 +33,9 @@ require ( require ( github.com/ChainSafe/gossamer v0.6.1-0.20220114214423-e1f7f96cb8cb github.com/jhump/protoreflect v1.9.1-0.20210817181203-db1a327a393e // indirect - github.com/klauspost/compress v1.13.5 // indirect + github.com/klauspost/compress v1.14.2 // indirect golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed // indirect - golang.org/x/sys v0.0.0-20211210111614-af8b64212486 // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect ) @@ -69,7 +69,6 @@ require ( github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/disiqueira/gotree v1.0.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect github.com/felixge/httpsnoop v1.0.1 // indirect @@ -115,7 +114,7 @@ require ( github.com/mtibben/percent v0.2.1 // indirect github.com/multiformats/go-base32 v0.0.3 // indirect github.com/multiformats/go-base36 v0.1.0 // indirect - github.com/multiformats/go-multiaddr v0.4.1 // indirect + github.com/multiformats/go-multiaddr v0.5.0 // indirect github.com/multiformats/go-multibase v0.0.3 // indirect github.com/multiformats/go-multihash v0.0.15 // indirect github.com/multiformats/go-varint v0.0.6 // indirect @@ -123,10 +122,11 @@ require ( github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pierrec/xxHash v0.1.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.30.0 // indirect + github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/qdm12/gotree v0.2.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/rogpeppe/go-internal v1.8.0 // indirect github.com/rs/cors v1.8.2 // indirect @@ -152,6 +152,8 @@ require ( nhooyr.io/websocket v1.8.6 // indirect ) +replace github.com/ChainSafe/gossamer => ../../ChainSafe/gossamer + replace github.com/ComposableFi/go-substrate-rpc-client/v4 => ../go-substrate-rpc-client replace github.com/ChainSafe/go-schnorrkel v1.0.0 => github.com/ChainSafe/go-schnorrkel v0.0.0-20210222182958-bd440c890782 diff --git a/go.sum b/go.sum index ec4ba50534b..2970b3e555a 100644 --- a/go.sum +++ b/go.sum @@ -90,8 +90,6 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20201021020641-d3c6d3118d10/go.mod h1: github.com/ChainSafe/go-schnorrkel v0.0.0-20210222182958-bd440c890782 h1:lwmjzta2Xu+3rPVY/VeNQj2xfNkyih4CwyRxYg3cpRQ= github.com/ChainSafe/go-schnorrkel v0.0.0-20210222182958-bd440c890782/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/ChainSafe/go-schnorrkel v0.0.0-20210318173838-ccb5cd955283/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/ChainSafe/gossamer v0.6.1-0.20220114214423-e1f7f96cb8cb h1:MPPCOYwAsgjeIidv/aEmyKdLxvSKMJzkLst0HvPJ0J4= -github.com/ChainSafe/gossamer v0.6.1-0.20220114214423-e1f7f96cb8cb/go.mod h1:kNlZcWT/0yoCw6lT1Rx/rYba6guaj6qJd4kJQVCJkUU= github.com/ChainSafe/log15 v1.0.0 h1:vRDVtWtVwIH5uSCBvgTTZh6FA58UBJ6+QiiypaZfBf8= github.com/ChainSafe/log15 v1.0.0/go.mod h1:5v1+ALHtdW0NfAeeoYyKmzCAMcAeqkdhIg4uxXWIgOg= github.com/ComposableFi/go-merkle-trees v0.0.0-20220119155315-3ce250c9ec59 h1:+CUbcRmgeoeZGOW5uvk5lHbB7rhjsm7X7pnGtYLOPK0= @@ -323,7 +321,6 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/disiqueira/gotree v1.0.0 h1:en5wk87n7/Jyk6gVME3cx3xN9KmUCstJ1IjHr4Se4To= github.com/disiqueira/gotree v1.0.0/go.mod h1:7CwL+VWsWAU95DovkdRZAtA7YbtHwGk+tLV/kNi8niU= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= @@ -433,8 +430,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A= -github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -517,8 +514,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -779,8 +777,8 @@ github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4= -github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= +github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1126,8 +1124,8 @@ github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4 github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= -github.com/multiformats/go-multiaddr v0.4.1 h1:Pq37uLx3hsyNlTDir7FZyU8+cFCTqd5y1KiM2IzOutI= -github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= @@ -1287,8 +1285,9 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1310,8 +1309,9 @@ github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16 github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1326,6 +1326,8 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/qdm12/gotree v0.2.0 h1:+58ltxkNLUyHtATFereAcOjBVfY6ETqRex8XK90Fb/c= +github.com/qdm12/gotree v0.2.0/go.mod h1:1SdFaqKZuI46U1apbXIf25pDMNnrPuYLEqMF/qL4lY4= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -1880,8 +1882,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= diff --git a/modules/light-clients/11-beefy/types/beefy.pb.go b/modules/light-clients/11-beefy/types/beefy.pb.go index 9b45675a285..fb886cde6bd 100644 --- a/modules/light-clients/11-beefy/types/beefy.pb.go +++ b/modules/light-clients/11-beefy/types/beefy.pb.go @@ -77,7 +77,7 @@ func (*ClientState) XXX_MessageName() string { // Actual payload items type PayloadItem struct { // 2-byte payload id - PayloadId []byte `protobuf:"bytes,1,opt,name=payload_id,json=payloadId,proto3" json:"payload_id,omitempty"` + PayloadId *[2]byte `protobuf:"bytes,1,opt,name=payload_id,json=payloadId,proto3,customtype=[2]byte" json:"payload_id,omitempty"` // arbitrary length payload data., eg mmr_root_hash PayloadData []byte `protobuf:"bytes,2,opt,name=payload_data,json=payloadData,proto3" json:"payload_data,omitempty"` } @@ -113,7 +113,7 @@ func (*PayloadItem) XXX_MessageName() string { // Commitment message signed by beefy validators type Commitment struct { // array of payload items signed by Beefy validators - Payload *[32]byte `protobuf:"bytes,1,opt,name=payload,proto3,customtype=[32]byte" json:"payload,omitempty"` + Payload []*PayloadItem `protobuf:"bytes,1,rep,name=payload,proto3" json:"payload,omitempty"` // block number for this commitment BlockNumer uint32 `protobuf:"varint,2,opt,name=block_numer,json=blockNumer,proto3" json:"block_numer,omitempty"` // validator set that signed this commitment @@ -629,87 +629,88 @@ func init() { } var fileDescriptor_43205c4bfbe9a422 = []byte{ - // 1301 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x57, 0xcf, 0x6f, 0x1b, 0xc5, - 0x17, 0xf7, 0xda, 0xce, 0x0f, 0x3f, 0xff, 0x88, 0x33, 0x69, 0xbf, 0x5f, 0xb7, 0x14, 0x3b, 0x0d, - 0x94, 0xba, 0x2d, 0xb1, 0x65, 0x07, 0x24, 0xd4, 0x13, 0x75, 0xa8, 0xd4, 0x00, 0x8d, 0xa2, 0x4d, - 0x2b, 0x4a, 0x0b, 0xb2, 0xc6, 0xde, 0xb1, 0x3d, 0xea, 0xee, 0x8e, 0xb5, 0x33, 0x6b, 0x35, 0xbd, - 0x23, 0x71, 0xe0, 0xd0, 0x3f, 0xa1, 0x07, 0xee, 0x9c, 0xb8, 0x73, 0xac, 0xc4, 0xa5, 0x47, 0xd4, - 0x43, 0x40, 0xc9, 0x8d, 0x23, 0x67, 0x0e, 0x68, 0x7e, 0xec, 0x7a, 0xe3, 0x06, 0xd3, 0x70, 0xe5, - 0x36, 0xfb, 0x79, 0x6f, 0xde, 0xfb, 0xbc, 0xf7, 0xe6, 0xbd, 0x99, 0x85, 0x2b, 0xb4, 0xd7, 0x6f, - 0xba, 0x74, 0x38, 0x12, 0x7d, 0x97, 0x12, 0x5f, 0xf0, 0x66, 0x8f, 0x90, 0xc1, 0x41, 0x73, 0xd2, - 0xd2, 0x8b, 0xc6, 0x38, 0x60, 0x82, 0xa1, 0x0b, 0xb4, 0xd7, 0x6f, 0x24, 0xd5, 0x1a, 0x5a, 0x3a, - 0x69, 0x5d, 0xac, 0x0e, 0x19, 0x1b, 0xba, 0xa4, 0xa9, 0x14, 0x7b, 0xe1, 0xa0, 0xe9, 0x84, 0x01, - 0x16, 0x94, 0xf9, 0x7a, 0xeb, 0xc5, 0xda, 0xac, 0x5c, 0x50, 0x8f, 0x70, 0x81, 0xbd, 0xb1, 0x51, - 0x38, 0x37, 0x64, 0x43, 0xa6, 0x96, 0x4d, 0xb9, 0x32, 0x68, 0x61, 0x1c, 0x30, 0x36, 0xe0, 0xfa, - 0x6b, 0xe3, 0xf7, 0x34, 0xe4, 0xb7, 0x95, 0xe7, 0x7d, 0x81, 0x05, 0x41, 0x1b, 0x50, 0xf4, 0xbc, - 0xa0, 0x1b, 0x30, 0x26, 0xba, 0x23, 0xcc, 0x47, 0x15, 0x6b, 0xdd, 0xaa, 0x17, 0xec, 0xbc, 0xe7, - 0x05, 0x36, 0x63, 0xe2, 0x0e, 0xe6, 0x23, 0xd4, 0x80, 0x35, 0x17, 0x0b, 0xc2, 0x45, 0x57, 0x71, - 0xed, 0x8e, 0x88, 0xe4, 0x5f, 0x49, 0xaf, 0x5b, 0xf5, 0xa2, 0xbd, 0xaa, 0x45, 0x1d, 0x29, 0xb9, - 0xa3, 0x04, 0xe8, 0x1d, 0x28, 0x0e, 0x02, 0xf6, 0x94, 0xf8, 0x91, 0x66, 0x66, 0xdd, 0xaa, 0x67, - 0xed, 0x82, 0x06, 0x8d, 0xd2, 0x07, 0xf0, 0x3f, 0x6d, 0x0d, 0xf7, 0x05, 0x9d, 0xa8, 0x38, 0xbb, - 0x3d, 0x97, 0xf5, 0x1f, 0x57, 0xb2, 0xca, 0xee, 0x39, 0x25, 0xbd, 0x15, 0x0b, 0x3b, 0x52, 0x86, - 0x3e, 0x85, 0x1c, 0x0e, 0xc5, 0x88, 0x05, 0x54, 0x1c, 0x54, 0x16, 0xd6, 0xad, 0x7a, 0xbe, 0xfd, - 0x7e, 0xe3, 0x6f, 0x53, 0xda, 0x50, 0xac, 0x6e, 0x45, 0x1b, 0xf6, 0x89, 0xb0, 0xa7, 0xdb, 0xd1, - 0x43, 0x40, 0x3e, 0x79, 0x22, 0xba, 0x31, 0xd2, 0xe5, 0x44, 0x54, 0x16, 0xff, 0x85, 0xd1, 0xb2, - 0xb4, 0x93, 0x44, 0x6e, 0x66, 0xbf, 0x7d, 0x5e, 0x4b, 0x6d, 0xdc, 0x87, 0xfc, 0x1e, 0x3e, 0x70, - 0x19, 0x76, 0x76, 0x04, 0xf1, 0xd0, 0xdb, 0x00, 0x63, 0xfd, 0xd9, 0xa5, 0x8e, 0x49, 0x74, 0xce, - 0x20, 0x3b, 0x0e, 0xba, 0x0c, 0x85, 0x48, 0xec, 0x60, 0x81, 0x55, 0x7e, 0x0b, 0x76, 0xde, 0x60, - 0x9f, 0x60, 0x81, 0x8d, 0xd9, 0x6f, 0x2c, 0x80, 0x6d, 0xe6, 0x79, 0x54, 0x78, 0xc4, 0x17, 0xe8, - 0x3d, 0x58, 0x32, 0x3a, 0xda, 0x66, 0xa7, 0xf0, 0xea, 0xb0, 0xb6, 0xfc, 0x68, 0xab, 0xfd, 0x75, - 0xef, 0x40, 0x10, 0x3b, 0x12, 0xa2, 0x1a, 0xe4, 0x55, 0x82, 0xbb, 0x7e, 0xe8, 0x91, 0xc0, 0x94, - 0x0f, 0x14, 0xb4, 0x2b, 0x11, 0x54, 0x87, 0xf2, 0x04, 0xbb, 0xd4, 0xc1, 0x82, 0x05, 0x32, 0x17, - 0x92, 0xa5, 0x2e, 0x5d, 0x29, 0xc6, 0xf7, 0x89, 0xd8, 0x71, 0x0c, 0x8f, 0x1e, 0xac, 0x4d, 0x69, - 0xec, 0xd3, 0xa1, 0x8f, 0x45, 0x18, 0x10, 0x74, 0x09, 0x72, 0x3c, 0xfa, 0x88, 0xa2, 0x8c, 0x01, - 0x74, 0x15, 0x56, 0xa6, 0x09, 0xa7, 0xbe, 0x43, 0x9e, 0x18, 0x26, 0xa5, 0x18, 0xde, 0x91, 0xa8, - 0xf1, 0xf1, 0x83, 0x05, 0x65, 0x69, 0x9a, 0x38, 0x89, 0x88, 0x6f, 0x03, 0xf4, 0xe3, 0x2f, 0xe5, - 0x22, 0xdf, 0xbe, 0x32, 0xa7, 0x62, 0xd3, 0xad, 0x76, 0x62, 0x23, 0xda, 0x05, 0x88, 0x79, 0xf1, - 0x4a, 0x7a, 0x3d, 0x53, 0xcf, 0xb7, 0x1b, 0x6f, 0x64, 0x26, 0x0e, 0xd6, 0x4e, 0x58, 0x30, 0x8c, - 0xbf, 0x4f, 0x43, 0xe9, 0xae, 0x17, 0xdc, 0x1f, 0x3b, 0x58, 0x90, 0x3d, 0xd9, 0x7b, 0xa8, 0x03, - 0xcb, 0xb2, 0xc9, 0x5c, 0x82, 0x07, 0x86, 0xed, 0xd5, 0x7f, 0x3a, 0x5f, 0x77, 0xbd, 0xe0, 0x73, - 0x82, 0x07, 0xf6, 0x92, 0xa7, 0x17, 0xe8, 0x5d, 0x28, 0x45, 0x36, 0x12, 0x69, 0xcb, 0xda, 0x05, - 0xa3, 0xa0, 0x92, 0x86, 0xde, 0x82, 0x9c, 0xd4, 0x52, 0x2d, 0x5f, 0xc9, 0xac, 0x67, 0xea, 0x05, - 0x5b, 0xba, 0xd6, 0x34, 0x1e, 0xc0, 0x2a, 0x57, 0xa9, 0xec, 0x26, 0xb2, 0x97, 0x55, 0x7c, 0x6e, - 0xcc, 0xe1, 0x33, 0x9b, 0x7e, 0xbb, 0xcc, 0x67, 0x0b, 0x72, 0x03, 0x56, 0xa3, 0xea, 0x51, 0xc2, - 0x8d, 0xfb, 0x05, 0xe5, 0xbe, 0x9c, 0x10, 0x28, 0x1a, 0x26, 0x4d, 0x3f, 0x5b, 0x50, 0xda, 0x66, - 0x3e, 0x27, 0x3e, 0x0f, 0xb9, 0x9e, 0x45, 0x1d, 0xc8, 0xc5, 0x23, 0xcd, 0xe4, 0xe9, 0x62, 0x43, - 0x0f, 0xbd, 0x46, 0x34, 0xf4, 0x1a, 0xf7, 0x22, 0x8d, 0xce, 0xf2, 0x8b, 0xc3, 0x5a, 0xea, 0xd9, - 0xaf, 0x35, 0xcb, 0x9e, 0x6e, 0x43, 0x08, 0xb2, 0x72, 0x96, 0x99, 0xe6, 0x51, 0x6b, 0xf4, 0x08, - 0xca, 0x63, 0x1c, 0xe0, 0xfe, 0x08, 0x53, 0x39, 0x92, 0xb0, 0x43, 0x02, 0x13, 0xf6, 0xf5, 0x39, - 0x61, 0xef, 0x45, 0x5b, 0xee, 0xa8, 0x1d, 0x9d, 0xac, 0x74, 0x67, 0xaf, 0x8c, 0x4f, 0xc2, 0x26, - 0x9a, 0x97, 0x16, 0x14, 0xee, 0x52, 0xde, 0x23, 0x23, 0x3c, 0xa1, 0x2c, 0x0c, 0xd0, 0x57, 0xb0, - 0xac, 0x3d, 0x75, 0x5b, 0x8a, 0x4b, 0xbe, 0x7d, 0x79, 0x8e, 0x2f, 0xe3, 0xa2, 0x7a, 0x74, 0x58, - 0x5b, 0xd2, 0xeb, 0xd6, 0x1f, 0x87, 0xb5, 0x95, 0x03, 0xec, 0xb9, 0x37, 0x37, 0x22, 0x3b, 0x1b, - 0xf6, 0x92, 0x5e, 0xb6, 0x12, 0xd6, 0xdb, 0xaa, 0x43, 0xcf, 0x6a, 0xbd, 0xfd, 0x9a, 0xf5, 0x76, - 0x6c, 0xbd, 0x6d, 0x42, 0x7a, 0x04, 0x28, 0xce, 0xf5, 0xed, 0x27, 0x22, 0xa0, 0x3e, 0xa7, 0x7d, - 0xd9, 0xbe, 0x24, 0xfa, 0x30, 0x75, 0xb6, 0x54, 0x9d, 0x4b, 0x31, 0xac, 0x0f, 0xdb, 0x25, 0xc8, - 0xc5, 0x88, 0xa9, 0xc6, 0x14, 0xd8, 0xf8, 0xd3, 0x82, 0x45, 0x4d, 0x05, 0x7d, 0x01, 0xab, 0xb3, - 0xd5, 0xe1, 0xca, 0xe6, 0x99, 0xca, 0x63, 0x97, 0x67, 0x0a, 0xc3, 0xe5, 0xb8, 0x8d, 0x7b, 0x41, - 0xb7, 0x77, 0xc1, 0xce, 0x45, 0xcd, 0xc0, 0xd1, 0x05, 0xdd, 0x94, 0x9c, 0x3e, 0x25, 0x66, 0xca, - 0xc9, 0x5e, 0xdb, 0xa7, 0x4f, 0x09, 0xfa, 0x12, 0xca, 0x52, 0x14, 0xaa, 0x16, 0x36, 0x51, 0xea, - 0x03, 0x73, 0x6d, 0x0e, 0xa3, 0x93, 0x4d, 0xaf, 0xce, 0x8b, 0x65, 0xcb, 0xa6, 0x4d, 0xa0, 0x26, - 0xb7, 0xdf, 0x65, 0x60, 0x65, 0x26, 0x00, 0x74, 0xed, 0x94, 0x53, 0xaa, 0xa7, 0xe7, 0xec, 0x99, - 0x43, 0x0f, 0x34, 0x3f, 0x35, 0x0b, 0xc6, 0x38, 0x10, 0x14, 0xbb, 0xe6, 0x90, 0x35, 0xde, 0x70, - 0xae, 0xec, 0xe9, 0x5d, 0x8a, 0x5e, 0xe2, 0x1b, 0xfd, 0x5f, 0xde, 0x25, 0x01, 0x8e, 0x26, 0x7f, - 0xd1, 0x5e, 0x94, 0x9f, 0x3b, 0x0e, 0x6a, 0xc3, 0xf9, 0x93, 0xec, 0x78, 0x9c, 0x17, 0x99, 0xd7, - 0xb5, 0x13, 0x14, 0x75, 0xa3, 0xcb, 0xfb, 0x44, 0x6b, 0x26, 0x86, 0xd6, 0x82, 0x9e, 0xf5, 0x0a, - 0x9f, 0x8e, 0xad, 0xeb, 0xb0, 0xaa, 0x35, 0x05, 0x13, 0xd8, 0xed, 0xf6, 0x59, 0xe8, 0xeb, 0x9b, - 0xb8, 0x68, 0xaf, 0x28, 0xc1, 0x3d, 0x89, 0x6f, 0x4b, 0x18, 0x7d, 0x96, 0x9c, 0x12, 0x4b, 0x2a, - 0xea, 0xcd, 0x39, 0x51, 0xbf, 0x7e, 0x86, 0x13, 0xe3, 0x22, 0xba, 0x50, 0xd3, 0xb0, 0x76, 0x4a, - 0x76, 0xd0, 0x55, 0x58, 0x9a, 0x90, 0x80, 0x53, 0xe6, 0xab, 0x4a, 0x14, 0x3b, 0x45, 0x39, 0x03, - 0x5e, 0x1d, 0xd6, 0x16, 0x42, 0xea, 0x8b, 0x8f, 0xec, 0x48, 0x2a, 0x5f, 0x3c, 0x63, 0x1c, 0x10, - 0x5f, 0xc8, 0xbb, 0xb5, 0x17, 0x5f, 0xae, 0x05, 0x0d, 0xee, 0x2a, 0x0c, 0x6d, 0x42, 0xde, 0x28, - 0xa9, 0x87, 0x56, 0xe6, 0x94, 0xbb, 0x1a, 0xb4, 0x82, 0x7a, 0x75, 0x3d, 0x86, 0x8a, 0x7e, 0x20, - 0x9d, 0xf2, 0x48, 0xc9, 0x9e, 0xfd, 0x91, 0x62, 0xe6, 0xd7, 0x79, 0xa5, 0xb1, 0x7b, 0xfa, 0x7b, - 0x65, 0x0c, 0xab, 0xaf, 0xed, 0x43, 0x25, 0x48, 0x9b, 0xd7, 0x4a, 0xd6, 0x4e, 0x53, 0x07, 0x95, - 0x21, 0xe3, 0x12, 0xdf, 0x44, 0x28, 0x97, 0x68, 0x0b, 0xa6, 0x77, 0xb7, 0x7a, 0x49, 0x9e, 0x1a, - 0x5b, 0x31, 0xd6, 0x91, 0x0f, 0x4b, 0xe3, 0xf1, 0xc7, 0x34, 0x14, 0x92, 0x99, 0xff, 0xef, 0xa4, - 0x1c, 0x7d, 0x08, 0x2b, 0x33, 0x1d, 0xa5, 0x9a, 0x63, 0x96, 0x5f, 0xe9, 0x64, 0x67, 0xe9, 0xbc, - 0x75, 0x06, 0x2f, 0x8e, 0xaa, 0xa9, 0x97, 0x47, 0xd5, 0xd4, 0x6f, 0x47, 0xd5, 0xd4, 0xb3, 0xe3, - 0x6a, 0xea, 0xf9, 0x71, 0x35, 0xf5, 0xd3, 0x71, 0xd5, 0x7a, 0x71, 0x5c, 0xb5, 0x5e, 0x1e, 0x57, - 0x53, 0xbf, 0x1c, 0x57, 0x53, 0x0f, 0x3f, 0x1e, 0x52, 0x31, 0x0a, 0x7b, 0x8d, 0x3e, 0xf3, 0x9a, - 0x7d, 0xc6, 0x3d, 0xc6, 0x9b, 0xb4, 0xd7, 0xdf, 0x1c, 0xb2, 0xe6, 0x64, 0xab, 0xe9, 0x31, 0x27, - 0x74, 0x09, 0xd7, 0xff, 0x2c, 0x9b, 0xd1, 0x4f, 0x4b, 0xab, 0xb5, 0xa9, 0xff, 0x5b, 0xc4, 0xc1, - 0x98, 0xf0, 0xde, 0xa2, 0xba, 0x77, 0xb7, 0xfe, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x6c, 0x00, 0x37, - 0xa1, 0xde, 0x0c, 0x00, 0x00, + // 1313 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x57, 0xcd, 0x6f, 0x1b, 0x45, + 0x14, 0xf7, 0xda, 0x4e, 0x1c, 0x3f, 0x7f, 0xc4, 0x99, 0xb4, 0xe0, 0x96, 0x62, 0xa7, 0x81, 0x52, + 0xb7, 0x25, 0xb6, 0xec, 0x80, 0x84, 0x7a, 0x6a, 0x1d, 0x2a, 0x35, 0x40, 0xa3, 0x6a, 0x53, 0x44, + 0x69, 0x40, 0xd6, 0xd8, 0x3b, 0xb6, 0x47, 0xdd, 0xdd, 0xb1, 0x76, 0xc6, 0x56, 0xd3, 0x3b, 0x12, + 0x07, 0x0e, 0xfd, 0x0f, 0xe8, 0x81, 0x3b, 0x27, 0xee, 0x1c, 0x2b, 0x71, 0xe9, 0x11, 0xf5, 0x10, + 0x50, 0x7c, 0xe3, 0xc8, 0x99, 0x03, 0x9a, 0x8f, 0x5d, 0x6f, 0xdc, 0x60, 0x5a, 0xae, 0xdc, 0x66, + 0xdf, 0xf7, 0xfb, 0xbd, 0x79, 0x6f, 0xde, 0xc2, 0x25, 0xda, 0xed, 0x35, 0x5c, 0x3a, 0x18, 0x8a, + 0x9e, 0x4b, 0x89, 0x2f, 0x78, 0xa3, 0x4b, 0x48, 0xff, 0xb0, 0x31, 0x69, 0xea, 0x43, 0x7d, 0x14, + 0x30, 0xc1, 0xd0, 0x39, 0xda, 0xed, 0xd5, 0xe3, 0x62, 0x75, 0xcd, 0x9d, 0x34, 0xcf, 0x57, 0x06, + 0x8c, 0x0d, 0x5c, 0xd2, 0x50, 0x82, 0xdd, 0x71, 0xbf, 0xe1, 0x8c, 0x03, 0x2c, 0x28, 0xf3, 0xb5, + 0xea, 0xf9, 0xea, 0x3c, 0x5f, 0x50, 0x8f, 0x70, 0x81, 0xbd, 0x91, 0x11, 0x38, 0x33, 0x60, 0x03, + 0xa6, 0x8e, 0x0d, 0x79, 0x32, 0xd4, 0xfc, 0x28, 0x60, 0xac, 0xcf, 0xf5, 0xd7, 0xe6, 0x1f, 0x49, + 0xc8, 0xed, 0x28, 0xcf, 0xfb, 0x02, 0x0b, 0x82, 0x36, 0xa1, 0xe0, 0x79, 0x41, 0x27, 0x60, 0x4c, + 0x74, 0x86, 0x98, 0x0f, 0xcb, 0xd6, 0x86, 0x55, 0xcb, 0xdb, 0x39, 0xcf, 0x0b, 0x6c, 0xc6, 0xc4, + 0x6d, 0xcc, 0x87, 0xa8, 0x0e, 0xeb, 0x2e, 0x16, 0x84, 0x8b, 0x8e, 0x8a, 0xb5, 0x33, 0x24, 0x32, + 0xfe, 0x72, 0x72, 0xc3, 0xaa, 0x15, 0xec, 0x35, 0xcd, 0x6a, 0x4b, 0xce, 0x6d, 0xc5, 0x40, 0xef, + 0x40, 0xa1, 0x1f, 0xb0, 0xc7, 0xc4, 0x0f, 0x25, 0x53, 0x1b, 0x56, 0x2d, 0x6d, 0xe7, 0x35, 0xd1, + 0x08, 0x7d, 0x00, 0x6f, 0x68, 0x6b, 0xb8, 0x27, 0xe8, 0x44, 0xe5, 0xd9, 0xe9, 0xba, 0xac, 0xf7, + 0xb0, 0x9c, 0x56, 0x76, 0xcf, 0x28, 0xee, 0xcd, 0x88, 0xd9, 0x96, 0x3c, 0xf4, 0x09, 0x64, 0xf1, + 0x58, 0x0c, 0x59, 0x40, 0xc5, 0x61, 0x79, 0x69, 0xc3, 0xaa, 0xe5, 0x5a, 0xef, 0xd7, 0xff, 0x11, + 0xd2, 0xba, 0x8a, 0xea, 0x66, 0xa8, 0xb0, 0x4f, 0x84, 0x3d, 0x53, 0x47, 0x0f, 0x00, 0xf9, 0xe4, + 0x91, 0xe8, 0x44, 0x94, 0x0e, 0x27, 0xa2, 0xbc, 0xfc, 0x1f, 0x8c, 0x96, 0xa4, 0x9d, 0x38, 0xe5, + 0x7a, 0xfa, 0xdb, 0xa7, 0xd5, 0xc4, 0x66, 0x17, 0x72, 0x77, 0xf1, 0xa1, 0xcb, 0xb0, 0xb3, 0x2b, + 0x88, 0x87, 0xae, 0x02, 0x8c, 0xf4, 0x67, 0x87, 0x3a, 0x1a, 0xe8, 0x76, 0xee, 0xc5, 0x51, 0x35, + 0x73, 0xd0, 0xfa, 0xba, 0x7b, 0x28, 0x88, 0x9d, 0x35, 0xec, 0x5d, 0x07, 0x5d, 0x84, 0x7c, 0x28, + 0xeb, 0x60, 0x81, 0x15, 0xd8, 0x79, 0x3b, 0x67, 0x68, 0x1f, 0x63, 0x81, 0x8d, 0x8f, 0xef, 0x2d, + 0x80, 0x1d, 0xe6, 0x79, 0x54, 0x78, 0xc4, 0x17, 0xe8, 0x06, 0x64, 0x8c, 0x4c, 0xd9, 0xda, 0x48, + 0xd5, 0x72, 0xad, 0xf7, 0x16, 0x64, 0x12, 0x0b, 0xce, 0x0e, 0xd5, 0x50, 0x15, 0x72, 0xaa, 0x0e, + 0x1d, 0x7f, 0xec, 0x91, 0xc0, 0x54, 0x19, 0x14, 0x69, 0x4f, 0x52, 0x50, 0x0d, 0x4a, 0x13, 0xec, + 0x52, 0x07, 0x0b, 0x16, 0x48, 0xc8, 0x64, 0x32, 0xba, 0xc2, 0xc5, 0x88, 0xbe, 0x4f, 0xc4, 0xae, + 0x13, 0xa1, 0xb0, 0x3e, 0x0b, 0x70, 0x9f, 0x0e, 0x7c, 0x2c, 0xc6, 0x01, 0x41, 0x17, 0x20, 0xcb, + 0xc3, 0x0f, 0x73, 0xeb, 0x66, 0x04, 0x74, 0x19, 0x56, 0x67, 0x75, 0xa1, 0xbe, 0x43, 0x1e, 0x99, + 0x48, 0x8a, 0x11, 0x79, 0x57, 0x52, 0x8d, 0x8f, 0x1f, 0x2d, 0x28, 0x49, 0xd3, 0xc4, 0x89, 0x61, + 0x71, 0x0b, 0xa0, 0x17, 0x7d, 0x29, 0x17, 0xb9, 0xd6, 0xa5, 0x05, 0x70, 0xcc, 0x54, 0xed, 0x98, + 0x22, 0xda, 0x03, 0x88, 0xe2, 0xe2, 0xe5, 0xa4, 0x42, 0xb5, 0xfe, 0x4a, 0x66, 0xa2, 0x64, 0xed, + 0x98, 0x05, 0x13, 0xf1, 0x0f, 0x49, 0x28, 0xde, 0xf1, 0x82, 0xcf, 0x47, 0x0e, 0x16, 0xe4, 0xae, + 0x6c, 0x51, 0xd4, 0x86, 0x15, 0xd9, 0x8b, 0x2e, 0xc1, 0x7d, 0x13, 0xed, 0xe5, 0x7f, 0xbb, 0x86, + 0x77, 0xbc, 0xe0, 0x33, 0x82, 0xfb, 0x76, 0xc6, 0xd3, 0x07, 0xf4, 0x2e, 0x14, 0x43, 0x1b, 0x31, + 0xd8, 0xd2, 0x76, 0xde, 0x08, 0x28, 0xd0, 0xd0, 0x5b, 0x90, 0x95, 0x52, 0x6a, 0x32, 0x94, 0x53, + 0x1b, 0xa9, 0x5a, 0xde, 0x96, 0xae, 0x75, 0x18, 0xf7, 0x61, 0x8d, 0x2b, 0x28, 0x3b, 0x31, 0xf4, + 0xd2, 0x2a, 0x9e, 0x6b, 0x0b, 0xe2, 0x99, 0x87, 0xdf, 0x2e, 0xf1, 0xf9, 0x82, 0x5c, 0x83, 0xb5, + 0xb0, 0x7a, 0x94, 0x70, 0xe3, 0x7e, 0x49, 0xb9, 0x2f, 0xc5, 0x18, 0x2a, 0x0c, 0x03, 0xd3, 0x2f, + 0x16, 0x14, 0x77, 0x98, 0xcf, 0x89, 0xcf, 0xc7, 0x5c, 0x8f, 0xac, 0x36, 0x64, 0xa3, 0xc9, 0x67, + 0x70, 0x3a, 0x5f, 0xd7, 0xb3, 0xb1, 0x1e, 0xce, 0xc6, 0xfa, 0xbd, 0x50, 0xa2, 0xbd, 0xf2, 0xec, + 0xa8, 0x9a, 0x78, 0xf2, 0x5b, 0xd5, 0xb2, 0x67, 0x6a, 0x08, 0x41, 0x5a, 0x8e, 0x3c, 0xd3, 0x56, + 0xea, 0x8c, 0x0e, 0xa0, 0x34, 0xc2, 0x01, 0xee, 0x0d, 0x31, 0x95, 0x93, 0x0b, 0x3b, 0x24, 0x30, + 0x69, 0x5f, 0x5d, 0xd8, 0x43, 0x46, 0xe5, 0xb6, 0xd2, 0x68, 0xa7, 0xa5, 0x3b, 0x7b, 0x75, 0x74, + 0x92, 0x6c, 0xb2, 0x79, 0x6e, 0x41, 0xfe, 0x0e, 0xe5, 0x5d, 0x32, 0xc4, 0x13, 0xca, 0xc6, 0x01, + 0xfa, 0x0a, 0x56, 0xb4, 0xa7, 0x4e, 0x53, 0xc5, 0x92, 0x6b, 0x5d, 0x5c, 0xe0, 0xcb, 0xb8, 0xa8, + 0x1c, 0x1f, 0x55, 0x33, 0xfa, 0xdc, 0xfc, 0xf3, 0xa8, 0xba, 0x7a, 0x88, 0x3d, 0xf7, 0xfa, 0x66, + 0x68, 0x67, 0xd3, 0xce, 0xe8, 0x63, 0x33, 0x66, 0xbd, 0xa5, 0x3a, 0xf4, 0x75, 0xad, 0xb7, 0x5e, + 0xb2, 0xde, 0x8a, 0xac, 0xb7, 0x4c, 0x4a, 0x07, 0x80, 0x22, 0xac, 0x6f, 0x3d, 0x12, 0x01, 0xf5, + 0x39, 0xed, 0xc9, 0xf6, 0x25, 0xe1, 0x87, 0xa9, 0xb3, 0xa5, 0xea, 0x5c, 0x8c, 0xc8, 0xfa, 0xb2, + 0x5d, 0x80, 0x6c, 0x44, 0x31, 0xd5, 0x98, 0x11, 0x36, 0xff, 0xb2, 0x60, 0x59, 0x87, 0x82, 0xbe, + 0x80, 0xb5, 0xf9, 0xea, 0x70, 0x33, 0xe2, 0x5e, 0xa3, 0x3c, 0x76, 0x69, 0xae, 0x30, 0x1c, 0xbd, + 0x0d, 0x10, 0xf5, 0x82, 0x6e, 0xef, 0xbc, 0x9d, 0x0d, 0x9b, 0x81, 0xa3, 0x73, 0xba, 0x29, 0x39, + 0x7d, 0x4c, 0xcc, 0x94, 0x93, 0xbd, 0xb6, 0x4f, 0x1f, 0x13, 0xf4, 0x25, 0x94, 0x24, 0x6b, 0xac, + 0x5a, 0xd8, 0x64, 0xa9, 0x2f, 0xcc, 0x95, 0x05, 0x11, 0x9d, 0x6c, 0x7a, 0x75, 0x5f, 0x2c, 0x5b, + 0x36, 0x6d, 0x8c, 0x6a, 0xb0, 0xfd, 0x2e, 0x05, 0xab, 0x73, 0x09, 0xa0, 0x2b, 0xa7, 0xdc, 0x52, + 0x3d, 0x3d, 0xe7, 0xef, 0x1c, 0xba, 0xaf, 0xe3, 0x53, 0xb3, 0x60, 0x84, 0x03, 0x41, 0xb1, 0x6b, + 0x2e, 0x59, 0xfd, 0x15, 0xe7, 0xca, 0x5d, 0xad, 0xa5, 0xc2, 0x8b, 0x7d, 0xa3, 0x37, 0xe5, 0x2b, + 0x13, 0xe0, 0x70, 0xf2, 0x17, 0xec, 0x65, 0xf9, 0xb9, 0xeb, 0xa0, 0x16, 0x9c, 0x3d, 0x19, 0x1d, + 0x8f, 0x70, 0x91, 0xb8, 0xae, 0x9f, 0x08, 0x51, 0x37, 0xba, 0x7c, 0x4f, 0xb4, 0x64, 0x6c, 0x68, + 0x2d, 0xe9, 0x59, 0xaf, 0xe8, 0xb3, 0xb1, 0x75, 0x15, 0xd6, 0xb4, 0xa4, 0x60, 0x02, 0xbb, 0x9d, + 0x1e, 0x1b, 0xfb, 0xfa, 0xc1, 0x2e, 0xd8, 0xab, 0x8a, 0x71, 0x4f, 0xd2, 0x77, 0x24, 0x19, 0x7d, + 0x1a, 0x9f, 0x12, 0x19, 0x95, 0xf5, 0xd6, 0x82, 0xac, 0x5f, 0xbe, 0xc3, 0xb1, 0x71, 0x61, 0xca, + 0xf1, 0x4d, 0x12, 0xd6, 0x4f, 0x41, 0x07, 0x5d, 0x86, 0xcc, 0x84, 0x04, 0x9c, 0x32, 0x5f, 0x55, + 0xa2, 0xd0, 0x2e, 0xc8, 0x19, 0xf0, 0xe2, 0xa8, 0xba, 0x34, 0xa6, 0xbe, 0xf8, 0xc8, 0x0e, 0xb9, + 0x72, 0x31, 0x1a, 0xe1, 0x80, 0xf8, 0x42, 0xbe, 0xad, 0xdd, 0xe8, 0x71, 0xcd, 0x6b, 0xe2, 0x9e, + 0xa2, 0xa1, 0x2d, 0xc8, 0x19, 0x21, 0xb5, 0x8f, 0xa5, 0xd4, 0x9a, 0x90, 0x7f, 0x71, 0x54, 0x5d, + 0x39, 0xd8, 0x36, 0x7b, 0x02, 0x68, 0x01, 0xb5, 0x9c, 0x3d, 0x84, 0xb2, 0xde, 0xa3, 0x4e, 0xd9, + 0x65, 0xd2, 0xaf, 0xbf, 0xcb, 0x98, 0xf9, 0x75, 0x56, 0x49, 0xec, 0x9d, 0xbe, 0xd6, 0x8c, 0x60, + 0xed, 0x25, 0x3d, 0x54, 0x84, 0xa4, 0x59, 0x6a, 0xd2, 0x76, 0x92, 0x3a, 0xa8, 0x04, 0x29, 0x97, + 0xf8, 0x26, 0x43, 0x79, 0x44, 0xdb, 0x30, 0x7b, 0xbb, 0xd5, 0xc2, 0x79, 0x6a, 0x6e, 0x85, 0x48, + 0x46, 0xee, 0x9f, 0xc6, 0xe3, 0x4f, 0x49, 0xc8, 0xc7, 0x91, 0xff, 0xff, 0x40, 0x8e, 0x3e, 0x84, + 0xd5, 0xb9, 0x8e, 0x52, 0xcd, 0x31, 0x1f, 0x5f, 0xf1, 0x64, 0x67, 0x69, 0xdc, 0xda, 0xfd, 0x67, + 0xc7, 0x95, 0xc4, 0xf3, 0xe3, 0x4a, 0xe2, 0xf7, 0xe3, 0x4a, 0xe2, 0xc9, 0xb4, 0x92, 0x78, 0x3a, + 0xad, 0x24, 0x7e, 0x9e, 0x56, 0xac, 0x67, 0xd3, 0x8a, 0xf5, 0x7c, 0x5a, 0x49, 0xfc, 0x3a, 0xad, + 0x24, 0x1e, 0xdc, 0x18, 0x50, 0x31, 0x1c, 0x77, 0xeb, 0x3d, 0xe6, 0x35, 0x7a, 0x8c, 0x7b, 0x8c, + 0x37, 0x68, 0xb7, 0xb7, 0x35, 0x60, 0x8d, 0xc9, 0x76, 0xc3, 0x63, 0xce, 0xd8, 0x25, 0x5c, 0xff, + 0xda, 0x6c, 0x85, 0xff, 0x36, 0xcd, 0xe6, 0x96, 0xfe, 0xbd, 0x11, 0x87, 0x23, 0xc2, 0xbb, 0xcb, + 0xea, 0xdd, 0xdd, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xb5, 0xb5, 0x7d, 0x2c, 0x05, 0x0d, 0x00, + 0x00, } diff --git a/modules/light-clients/11-beefy/types/mmr_test.go b/modules/light-clients/11-beefy/types/mmr_test.go new file mode 100644 index 00000000000..c214b754377 --- /dev/null +++ b/modules/light-clients/11-beefy/types/mmr_test.go @@ -0,0 +1,96 @@ +package types_test + +import ( + "bytes" + "encoding/hex" + "fmt" + "testing" + + "github.com/ChainSafe/gossamer/lib/trie" + "github.com/ComposableFi/go-merkle-trees/mmr" + substrate "github.com/ComposableFi/go-substrate-rpc-client/v4/types" + "github.com/cosmos/ibc-go/v3/modules/light-clients/11-beefy/types" + "github.com/ethereum/go-ethereum/crypto" +) + +func TestTrieProof(t *testing.T) { + key, err := hex.DecodeString("f0c365c3cf59d671eb72da0e7a4113c4bbd108c4899964f707fdaffb82636065") + if err != nil { + panic(err) + } + root, err := hex.DecodeString("5e1eb8e577ea88deaa94b456da24ab0c9f4c0c6d9372af1568edd7aeef3b4c4e") + if err != nil { + panic(err) + } + bytes1, err := hex.DecodeString("80fffd8028b54b9a0a90d41b7941c43e6a0597d5914e3b62bdcb244851b9fc806c28ea2480e2f0847174b6f8ea15133a8d70de58d1a6174b7542e8e12028154c611bc3ee5280ddd81bdda149a8bc6990d3548a719d4a90ddbe5ea4a598211aacf6afd0b23bf58038fe7e08c8e684bd600f25631f32e6510ed7d37f43fce0d5aa974009857aeb5b80aafc60caa3519d4b861e6b8da226266a15060e2071bba4184e194da61dfb208e80b34a4ee6e2f949f58b7cb7f4a7fb1aaea8cdc2a5cb27557d32da7096fdf157c58024a760a8f6c27928ae9e2fed9968bc5f6e17c3ae647398d8a615e5b2bb4b425f8085a0da830399f25fca4b653de654ffd3c92be39f3ae4f54e7c504961b5bd00cf80c2d44d371e5fc1f50227d7491ad65ad049630361cefb4ab1844831237609f08380c8ae6a1e8df858b43e050a3959a25b90d711413ee1a863622c3914d45250738980b5955ff982ab818fcba39b2d507a6723504cef4969fc7c722ee175df95a33ae280509bb016f2887d12137e73d26d7ddcd7f9c8ff458147cb9d309494655fe68de180009f8697d760fbe020564b07f407e6aad58ba9451b3d2d88b3ee03e12db7c47480952dcc0804e1120508a1753f1de4aa5b7481026a3320df8b48e918f0cecbaed380fff4f175da5ff30200fabfdc2bbdd45f864d84f339ec2432f80b5749ac35bbfc") + if err != nil { + panic(err) + } + bytes2, err := hex.DecodeString("9ec365c3cf59d671eb72da0e7a4113c41002505f0e7b9012096b41c4eb3aaf947f6ea429080000685f0f1f0515f462cdcf84e0f1d6045dfcbb2056145f077f010000") + if err != nil { + panic(err) + } + bytes3, err := hex.DecodeString("80050880149156720805d0ad098ae52fcffae34ff637b1d1f1a0fa8e7f94201b8615695580c1638f702aaa71e4b78cc8538ecae03e827bb494cc54279606b201ec071a5e24806d2a1e6d5236e1e13c5a5c84831f5f5383f97eba32df6f9faf80e32cf2f129bc") + if err != nil { + panic(err) + } + var proof = [][]byte{ + bytes1, bytes2, bytes3, + } + trie := trie.NewEmptyTrie() + errd := trie.LoadFromProof(proof, root) + if errd != nil { + panic(err) + } + value := trie.Get(key) + fmt.Printf("value: %s\n", value) +} + +func TestMultiLeafMmrProofs(t *testing.T) { + var opaqueLeaves []substrate.OpaqueLeafWithIndex + err := types.DecodeFromHexString( + "10c50100bd020000dbd670705fddee2d22d0d3cdced8734aa8c8374197eaf1493f9fb86e7fbeba0f010000000000000005000000baa93c7834125ee3120bac6e3342bd3f28611110ad21ab6075367abdffefeb0975e8469015638c96e3d9942cb35297b28d0cca7add9932c5a7354fa302d6f2e3bd02000000000000c50100be020000a76a43d5b7bf9bfa6c7562ebd35019f7709910a3f76464688f62717b13b20fe8010000000000000005000000baa93c7834125ee3120bac6e3342bd3f28611110ad21ab6075367abdffefeb0975e8469015638c96e3d9942cb35297b28d0cca7add9932c5a7354fa302d6f2e3be02000000000000c50100bf0200006d0ab0459bf2a9305e048805fbc9bc58b7e9454906c2e94b6d981f0e8ceb3180010000000000000005000000baa93c7834125ee3120bac6e3342bd3f28611110ad21ab6075367abdffefeb091b8751c2c1962bde4b57548c1bdef9ef2efcf93730e130036feee3f944bec9edbf02000000000000c50100c0020000d6aaaaa38e330ac1500a22d0fe382ffe2ca9f95161f479dca2e56038696ee343010000000000000005000000baa93c7834125ee3120bac6e3342bd3f28611110ad21ab6075367abdffefeb091b8751c2c1962bde4b57548c1bdef9ef2efcf93730e130036feee3f944bec9edc002000000000000", + &opaqueLeaves, + ) + if err != nil { + panic(err) + } + var leaves []mmr.Leaf + + for _, leaf := range opaqueLeaves { + leaves = append(leaves, mmr.Leaf{ + Index: leaf.Index, + Hash: crypto.Keccak256(leaf.Leaf), + }) + } + + var batchProof substrate.MmrBatchProof + + derr := types.DecodeFromHexString( + "10bd02000000000000be02000000000000bf02000000000000c002000000000000e903000000000000380b69447305465f8796365fe6035c938e8307482a7eb81d312c74e3bdd4d06e6f861ff8ff2a2c35ba80caf31bbb1d5042133a61b8371af548477d7cf2fc7456ba2c831a65e8ca11b67a84f4b36a9cacb86a27b30e0cc0f10b7a4d406bbcf331e881ae35265781aa57e7619352caad12c681d6c07157f337f5b57a52491475289823ebb41b1af8e1213ae3159bd422d8b421d2813435d89c2dde3b3e201940a49eb282a3bda4a8cf9bef677ae1b49dc211cf25473e02fbf4aca9257552d91bb9763dca3cf547d4d15d53e4c9ee730e3acc8b3705359cbc2857eceea31121ed6706a0c991631e945495269afa5b3759915e77b62add69c1849ac742917e62922819b5c14bffd531d4ff99ef95b9f2e897d64e0e027439334d63cdb7d3ec0c988fa1aed09fb5b47b41a2e27946eecead11062188fb0353b813c1e74c23943a0497f9a5a92a54b9292f657ce45b9bcc699d4eac12a587f19878c51bb338c3c9d84f4481e964f7f7480b0ab9da1e691359b03c003cb3c2f5dc4a29ba9610167f0d782caad6b08a2ec0e74a66afea72837b5e070d18c5e79f0c1fc35fc9c5f0645811bcdaf53cb132d461ea60f4fe62f5a3fc1aa723f4854c067d84a3b1e26c93398bf9", + &batchProof, + ) + + if derr != nil { + panic(derr) + } + + size := mmr.LeafIndexToMMRSize(uint64(batchProof.LeafCount - 1)) + + var proofItems = make([][]byte, len(batchProof.Items)) + for i := range batchProof.Items { + proofItems[i] = batchProof.Items[i][:] + } + + expectedRoot := []byte{ + 72, 183, 40, 135, 139, 221, 74, 166, 201, 0, 52, 167, 117, 108, 17, 181, 114, 52, 217, + 146, 200, 40, 236, 116, 241, 209, 1, 223, 30, 128, 62, 112, + } + + root, cerr := mmr.NewProof(size, proofItems, leaves, types.Keccak256{}).CalculateRoot() + if cerr != nil { + panic(cerr) + } + + fmt.Printf("Are they equal?: %t\n\n", bytes.Equal(expectedRoot, root)) +} diff --git a/modules/light-clients/11-beefy/types/update.go b/modules/light-clients/11-beefy/types/update.go index 0c2046f0337..ac548082ae6 100644 --- a/modules/light-clients/11-beefy/types/update.go +++ b/modules/light-clients/11-beefy/types/update.go @@ -1,6 +1,10 @@ package types import ( + "bytes" + "encoding/binary" + "fmt" + "github.com/ComposableFi/go-merkle-trees/merkle" "github.com/ComposableFi/go-merkle-trees/mmr" "github.com/cosmos/cosmos-sdk/codec" @@ -13,6 +17,11 @@ import ( type Keccak256 struct{} +type ParaIdAndHead struct { + ParaId uint32 + Header []byte +} + func (b Keccak256) Merge(left, right interface{}) interface{} { l := left.([]byte) r := right.([]byte) @@ -88,7 +97,7 @@ func (cs *ClientState) CheckHeaderAndUpdateState( } // beefy authorities are signing the hash of the scale-encoded Commitment - commitmentBytes, err := Encode(signedCommitment.Commitment) + commitmentBytes, err := Encode(&signedCommitment.Commitment) if err != nil { // todo: proper errors return nil, nil, err @@ -100,7 +109,8 @@ func (cs *ClientState) CheckHeaderAndUpdateState( // array of leaves in the authority merkle root. var authorityLeaves []merkle.Leaf - for _, signature := range signedCommitment.Signatures { + for i := 0; i < len(signedCommitment.Signatures); i++ { + signature := signedCommitment.Signatures[i] // recover uncompressed public key from signature pubkey, err := crypto.SigToPub(commitmentHash, signature.Signature) @@ -147,64 +157,58 @@ func (cs *ClientState) CheckHeaderAndUpdateState( // only update if we have a higher block number. if signedCommitment.Commitment.BlockNumer > cs.LatestBeefyHeight { - payload := signedCommitment.Commitment.Payload - // for _, payload := range signedCommitment.Commitment.Payload { - // checks for the right payloadId - // if reflect.DeepEqual(payload.PayloadId, []byte("mh")) { - // the next authorities are in the latest BeefyMmrLeaf - - // scale encode the mmr leaf - mmrLeafBytes, err := Encode(mmrUpdateProof.MmrLeaf) - if err != nil { - return nil, nil, err - } - // we treat this leaf as the latest leaf in the mmr - mmrSize := mmr.LeafIndexToMMRSize(mmrUpdateProof.MmrLeafIndex) - mmrLeaves := []mmr.Leaf{ - { - Hash: crypto.Keccak256(mmrLeafBytes), - Index: mmrUpdateProof.MmrLeafIndex, - }, - } - mmrProof := mmr.NewProof(mmrSize, mmrUpdateProof.MmrProof, mmrLeaves, Keccak256{}) - // verify that the leaf is valid, for the signed mmr-root-hash - if !mmrProof.Verify(payload[:]) { - return nil, nil, err // error!, mmr proof is invalid - } - // update the block_number - cs.LatestBeefyHeight = signedCommitment.Commitment.BlockNumer - // updates the mmr_root_hash - cs.MmrRootHash = payload[:] - // authority set has changed, rotate our view of the authorities - if updatedAuthority { - cs.Authority = cs.NextAuthoritySet - // mmr leaf has been verified, use it to update our view of the next authority set - cs.NextAuthoritySet = &mmrUpdateProof.MmrLeaf.BeefyNextAuthoritySet - // } - // break - // } + for _, payload := range signedCommitment.Commitment.Payload { + mmrRootId := []byte("mh") + // checks for the right payloadId + if bytes.Equal(payload.PayloadId[:], mmrRootId) { + // the next authorities are in the latest BeefyMmrLeaf + + // scale encode the mmr leaf + mmrLeafBytes, err := Encode(mmrUpdateProof.MmrLeaf) + if err != nil { + return nil, nil, err + } + // we treat this leaf as the latest leaf in the mmr + mmrSize := mmr.LeafIndexToMMRSize(mmrUpdateProof.MmrLeafIndex) + mmrLeaves := []mmr.Leaf{ + { + Hash: crypto.Keccak256(mmrLeafBytes), + Index: mmrUpdateProof.MmrLeafIndex, + }, + } + mmrProof := mmr.NewProof(mmrSize, mmrUpdateProof.MmrProof, mmrLeaves, Keccak256{}) + // verify that the leaf is valid, for the signed mmr-root-hash + if !mmrProof.Verify(payload.PayloadData[:]) { + return nil, nil, err // error!, mmr proof is invalid + } + // update the block_number + cs.LatestBeefyHeight = signedCommitment.Commitment.BlockNumer + // updates the mmr_root_hash + cs.MmrRootHash = payload.PayloadData[:] + // authority set has changed, rotate our view of the authorities + if updatedAuthority { + cs.Authority = cs.NextAuthoritySet + // mmr leaf has been verified, use it to update our view of the next authority set + cs.NextAuthoritySet = &mmrUpdateProof.MmrLeaf.BeefyNextAuthoritySet + } + break + } } } } - var mmrLeaves []mmr.Leaf + var mmrLeaves = make([]mmr.Leaf, len(beefyHeader.ParachainHeaders)) + var paraHeads = make([][]byte, len(beefyHeader.ParachainHeaders)) // verify parachain headers - for _, parachainHeader := range beefyHeader.ParachainHeaders { - type ParaIdAndHead struct { - ParaId uint32 - Header []byte - } - paraIdAndHead := ParaIdAndHead{ - ParaId: parachainHeader.ParaId, - Header: parachainHeader.ParachainHeader, - } + for i := 0; i < len(beefyHeader.ParachainHeaders); i++ { + // first we need to reconstruct the mmr leaf for this header + parachainHeader := beefyHeader.ParachainHeaders[i] + paraIdScale := make([]byte, 4) + // scale encode para_id + binary.LittleEndian.PutUint32(paraIdScale[:], parachainHeader.ParaId) // scale encode to get parachain heads leaf bytes - headsLeafBytes, err := Encode(paraIdAndHead) - if err != nil { - // todo: failed to encode para id - return nil, nil, err - } + headsLeafBytes := append(paraIdScale, parachainHeader.ParachainHeader...) headsLeaf := []merkle.Leaf{ { Hash: crypto.Keccak256(headsLeafBytes), @@ -224,39 +228,46 @@ func (cs *ClientState) CheckHeaderAndUpdateState( } mmrLeaf := BeefyMmrLeaf{ - Version: parachainHeader.MmrLeafPartial.Version, - ParentNumber: parachainHeader.MmrLeafPartial.ParentNumber, - ParentHash: parachainHeader.MmrLeafPartial.ParentHash, - ParachainHeads: &ParachainHeads, + Version: parachainHeader.MmrLeafPartial.Version, + ParentNumber: parachainHeader.MmrLeafPartial.ParentNumber, + ParentHash: parachainHeader.MmrLeafPartial.ParentHash, BeefyNextAuthoritySet: BeefyAuthoritySet{ Id: cs.NextAuthoritySet.Id, AuthorityRoot: cs.NextAuthoritySet.AuthorityRoot, Len: cs.NextAuthoritySet.Len, }, + ParachainHeads: &ParachainHeads, } + paraHeads[i] = ParachainHeadsRoot - // the mmr leafs are a scale-encoded + // the mmr leafs are a scale-encoded mmrLeafBytes, err := Encode(mmrLeaf) if err != nil { // todo: error failed to encode MmrLeaf return nil, nil, err } - leafIndex := cs.GetLeafIndexFor(parachainHeader.MmrLeafPartial.ParentNumber) - - mmrData := mmr.Leaf{ - Hash: crypto.Keccak256(mmrLeafBytes), - Index: uint64(leafIndex), + mmrLeaves[i] = mmr.Leaf{ + Hash: crypto.Keccak256(mmrLeafBytes), + // based on our knowledge of the beefy protocol, and the structure of mmrs + // we are be able to reconstruct the leaf index of this mmr leaf + // given the parent_number of this leaf, the beefy activation block + Index: uint64(cs.GetLeafIndexForBlockNumber(parachainHeader.MmrLeafPartial.ParentNumber + 1)), } - - mmrLeaves = append(mmrLeaves, mmrData) } mmrProof := mmr.NewProof(beefyHeader.MmrSize, beefyHeader.MmrProofs, mmrLeaves, Keccak256{}) - // Given the proofs and the leaves, we should be able to verify that each parachain header was - // indeed included in the leaves of our mmr root hash. + // Given the leaves, we should be able to verify that each parachain header was + // indeed included in the leaves of our mmr. if !mmrProof.Verify(cs.MmrRootHash) { + root, err := mmrProof.CalculateRoot() + if err != nil { + // todo: error failed to encode MmrLeaf + panic(err) + + } + fmt.Printf("failed to verify mmr leaf %v", root) return nil, nil, nil // error!, mmr proof is invalid } @@ -345,17 +356,32 @@ func (cs *ClientState) CheckHeaderAndUpdateState( return nil, nil, nil } +func (cs ClientState) GetBlockNumberForLeaf(leafIndex uint32) uint32 { + var blockNumber uint32 + + // calculate the leafIndex for this leaf. + if cs.BeefyActivationBlock == 0 { + // in this case the leaf index is the same as the block number - 1 (leaf index starts at 0) + blockNumber = leafIndex + 1 + } else { + // in this case the leaf index is activation block - current block number. + blockNumber = cs.BeefyActivationBlock + leafIndex + } + + return blockNumber +} + // given the MmrLeafPartial.ParentNumber & BeefyActivationBlock, -func (cs ClientState) GetLeafIndexFor(parentBlockNumber uint32) uint32 { +func (cs ClientState) GetLeafIndexForBlockNumber(blockNumber uint32) uint32 { var leafIndex uint32 // calculate the leafIndex for this leaf. if cs.BeefyActivationBlock == 0 { // in this case the leaf index is the same as the block number - 1 (leaf index starts at 0) - leafIndex = parentBlockNumber + leafIndex = blockNumber - 1 } else { // in this case the leaf index is activation block - current block number. - leafIndex = cs.BeefyActivationBlock - (parentBlockNumber + 1) + leafIndex = cs.BeefyActivationBlock - (blockNumber + 1) } return leafIndex diff --git a/modules/light-clients/11-beefy/types/update_test.go b/modules/light-clients/11-beefy/types/update_test.go index 321a425d995..bb42f703b4f 100644 --- a/modules/light-clients/11-beefy/types/update_test.go +++ b/modules/light-clients/11-beefy/types/update_test.go @@ -16,6 +16,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/ibc-go/v3/modules/light-clients/11-beefy/types" "github.com/ethereum/go-ethereum/crypto" + + // for creating storage keys + "github.com/ComposableFi/go-substrate-rpc-client/v4/xxhash" ) func bytes32(bytes []byte) [32]byte { @@ -24,6 +27,8 @@ func bytes32(bytes []byte) [32]byte { return buffer } +const PARA_ID = 2000 + func TestCheckHeaderAndUpdateState(t *testing.T) { relayApi, err := client.NewSubstrateAPI("ws://127.0.0.1:65353") @@ -37,6 +42,7 @@ func TestCheckHeaderAndUpdateState(t *testing.T) { // panic(err) // } + // channel to recieve new SignedCommitments ch := make(chan interface{}) sub, err := relayApi.Client.Subscribe( @@ -61,67 +67,66 @@ func TestCheckHeaderAndUpdateState(t *testing.T) { panic("error reading channel") } - signedCommitment := &clientTypes.SignedCommitment{} + compactCommitment := clientTypes.CompactSignedCommitment{} - err := types.DecodeFromHexString(msg.(string), signedCommitment) + // attempt to decode the SignedCommitments + err := types.DecodeFromHexString(msg.(string), &compactCommitment) if err != nil { panic(err.Error()) } + signedCommitment := compactCommitment.Unpack() + + // latest finalized block number blockNumber := uint32(signedCommitment.Commitment.BlockNumber) + // initialize our client state if clientState != nil && clientState.LatestBeefyHeight >= blockNumber { fmt.Printf("Skipping stale Commitment for block: %d", signedCommitment.Commitment.BlockNumber) continue } + // convert to the blockhash blockHash, err := relayApi.RPC.Chain.GetBlockHash(uint64(blockNumber)) if err != nil { panic(err) } - authorities, err := getBeefyAuthorities(blockNumber, relayApi, "Authorities") + authorities, err := BeefyAuthorities(blockNumber, relayApi, "Authorities") if err != nil { panic(err) } - paraHeads, err := fetchParaHeads(relayApi, blockHash) - if err != nil { - panic("Failed to decode BEEFY commitment messages") - } - - nextAuthorities, err := getBeefyAuthorities(blockNumber, relayApi, "NextAuthorities") + nextAuthorities, err := BeefyAuthorities(blockNumber, relayApi, "NextAuthorities") if err != nil { panic(err) } var authorityLeaves [][]byte for _, v := range authorities { - hash := crypto.Keccak256(v) - authorityLeaves = append(authorityLeaves, hash) + authorityLeaves = append(authorityLeaves, crypto.Keccak256(v)) + } + authorityTree, err := merkle.NewTree(types.Keccak256{}).FromLeaves(authorityLeaves) + if err != nil { + panic(err) } var nextAuthorityLeaves [][]byte - for _, v := range authorities { + for _, v := range nextAuthorities { nextAuthorityLeaves = append(nextAuthorityLeaves, crypto.Keccak256(v)) } - authorityTree, err := merkle.NewTree(types.Keccak256{}).FromLeaves(authorityLeaves) - if err != nil { - panic(err) - } nextAuthorityTree, err := merkle.NewTree(types.Keccak256{}).FromLeaves(nextAuthorityLeaves) if err != nil { panic(err) } if clientState == nil { - var authorityTreeRoot [32]byte - copy(authorityTreeRoot[:], authorityTree.Root()) - var nextAuthorityTreeRoot [32]byte - copy(nextAuthorityTreeRoot[:], nextAuthorityTree.Root()) + var authorityTreeRoot = bytes32(authorityTree.Root()) + var nextAuthorityTreeRoot = bytes32(nextAuthorityTree.Root()) + clientState = &types.ClientState{ - MmrRootHash: signedCommitment.Commitment.Payload[:], + MmrRootHash: signedCommitment.Commitment.Payload[0].Value, LatestBeefyHeight: blockNumber, BeefyActivationBlock: 0, Authority: &types.BeefyAuthoritySet{ @@ -139,71 +144,172 @@ func TestCheckHeaderAndUpdateState(t *testing.T) { continue } - var paraHeadsLeaves [][]byte - var index uint32 - var paraHeader []byte - count := 0 + // first get all paraIds - sortedParaHeadKeys := func() []uint32 { - var keys []uint32 - for k, _ := range paraHeads { - keys = append(keys, k) + // fetch all registered parachainIds, this method doesn't account for + // if the parachains whose header was included in the batch of finalized blocks have now + // lost their parachain slot at this height + paraIds, err := fetchParaIds(relayApi, blockHash) + if err != nil { + panic(err) + } + + var paraHeaderKeys []clientTypes.StorageKey + + // create full storage key for each known paraId. + keyPrefix := clientTypes.CreateStorageKeyPrefix("Paras", "Heads") + // so we can query all blocks from lastfinalized to latestBeefyHeight + for _, paraId := range paraIds { + encodedParaId, err := types.Encode(paraId) + if err != nil { + panic(err) } - sort.SliceStable(keys, func(i, j int) bool { - return keys[i] < keys[j] - }) - return keys + twoxhash := xxhash.New64(encodedParaId).Sum(nil) + // full key path in the storage source: https://www.shawntabrizi.com/assets/presentations/substrate-storage-deep-dive.pdf + // xx128("Paras") + xx128("Heads") + xx64(Encode(paraId)) + Encode(paraId) + fullKey := append(append(keyPrefix, twoxhash[:]...), encodedParaId...) + paraHeaderKeys = append(paraHeaderKeys, fullKey) } + previousFinalizedHash, err := relayApi.RPC.Chain.GetBlockHash(uint64(clientState.LatestBeefyHeight + 1)) + if err != nil { + panic(err) + } + changeSet, err := relayApi.RPC.State.QueryStorage(paraHeaderKeys, previousFinalizedHash, blockHash) + if err != nil { + panic(err) + } + + // double map that holds block numbers, for which our parachain header + // was included in the mmr leaf, seeing as our parachain headers might not make it into + // every relay chain block. + // Map> + var finalizedBlocks = make(map[uint32]map[uint32][]byte) + + // request for batch mmr proof of those leaves + var leafIndeces []uint64 + + for _, changes := range changeSet { + header, err := relayApi.RPC.Chain.GetHeader(changes.Block) + if err != nil { + panic(err) + } + var heads = make(map[uint32][]byte) + + for _, keyValue := range changes.Changes { + if keyValue.HasStorageData { + var paraId uint32 + err := types.DecodeFromBytes(keyValue.StorageKey[40:], ¶Id) + if err != nil { + panic(err) + } + + heads[paraId] = keyValue.StorageData + } + } - for _, v := range sortedParaHeadKeys() { - paraIdScale := make([]byte, 4) - // scale encode para_id - binary.LittleEndian.PutUint32(paraIdScale[:], v) - leaf := append(paraIdScale, paraHeads[v]...) - paraHeadsLeaves = append(paraHeadsLeaves, crypto.Keccak256(leaf)) - if v == 2000 { - paraHeader = paraHeads[v] - index = uint32(count) + // check if heads has target id, else skip + if heads[PARA_ID] == nil { + continue } - count++ + + finalizedBlocks[uint32(header.Number)] = heads + + leafIndeces = append(leafIndeces, uint64(clientState.GetLeafIndexForBlockNumber(uint32(header.Number)))) } - tree, err := merkle.NewTree(types.Keccak256{}).FromLeaves(paraHeadsLeaves) + // fetch mmr proofs for leaves containing our target paraId + mmrBatchProof, err := relayApi.RPC.MMR.GenerateBatchProof(leafIndeces, blockHash) if err != nil { panic(err) } - // todo: convert block number to leafIndex - mmrProofs, err := relayApi.RPC.MMR.GenerateProof(uint64(blockNumber)-1, blockHash) + var parachainHeaders []*types.ParachainHeader + + var paraHeads = make([][]byte, len(mmrBatchProof.Leaves)) + + for i := 0; i < len(mmrBatchProof.Leaves); i++ { + v := mmrBatchProof.Leaves[i] + paraHeads[i] = v.Leaf.ParachainHeads[:] + var leafBlockNumber = clientState.GetBlockNumberForLeaf(uint32(v.Index)) + paraHeaders := finalizedBlocks[leafBlockNumber] + + var paraHeadsLeaves [][]byte + // index of our parachain header in the + // parachain heads merkle root + var index uint32 + + count := 0 + + // sort by paraId + var sortedParaIds []uint32 + for paraId, _ := range paraHeaders { + sortedParaIds = append(sortedParaIds, paraId) + } + sort.SliceStable(sortedParaIds, func(i, j int) bool { + return sortedParaIds[i] < sortedParaIds[j] + }) + + for _, paraId := range sortedParaIds { + paraIdScale := make([]byte, 4) + // scale encode para_id + binary.LittleEndian.PutUint32(paraIdScale[:], paraId) + leaf := append(paraIdScale, paraHeaders[paraId]...) + paraHeadsLeaves = append(paraHeadsLeaves, crypto.Keccak256(leaf)) + if paraId == PARA_ID { + // note index of paraId + index = uint32(count) + } + count++ + } + + tree, err := merkle.NewTree(types.Keccak256{}).FromLeaves(paraHeadsLeaves) + if err != nil { + panic(err) + } + paraHeadsProof := tree.Proof([]uint32{index}) + authorityRoot := bytes32(v.Leaf.BeefyNextAuthoritySet.Root[:]) + parentHash := bytes32(v.Leaf.ParentNumberAndHash.Hash[:]) + + header := types.ParachainHeader{ + ParachainHeader: paraHeaders[PARA_ID], + MmrLeafPartial: &types.BeefyMmrLeafPartial{ + Version: uint8(v.Leaf.Version), + ParentNumber: uint32(v.Leaf.ParentNumberAndHash.ParentNumber), + ParentHash: &parentHash, + BeefyNextAuthoritySet: types.BeefyAuthoritySet{ + Id: uint64(v.Leaf.BeefyNextAuthoritySet.ID), + Len: uint32(v.Leaf.BeefyNextAuthoritySet.Len), + AuthorityRoot: &authorityRoot, + }, + }, + ParachainHeadsProof: paraHeadsProof.ProofHashes(), + ParaId: PARA_ID, + HeadsLeafIndex: index, + HeadsTotalCount: uint32(len(paraHeadsLeaves)), + } + + parachainHeaders = append(parachainHeaders, &header) + } + + mmrProof, err := relayApi.RPC.MMR.GenerateProof( + uint64(clientState.GetLeafIndexForBlockNumber(blockNumber)), + blockHash, + ) if err != nil { panic(err) } + latestLeaf := mmrProof.Leaf - paraHeadsProof := tree.Proof([]uint32{index}) - BeefyNextAuthoritySetRoot := bytes32(mmrProofs.Leaf.BeefyNextAuthoritySet.Root[:]) - parentHash := bytes32(mmrProofs.Leaf.ParentNumberAndHash.Hash[:]) + BeefyNextAuthoritySetRoot := bytes32(latestLeaf.BeefyNextAuthoritySet.Root[:]) + parentHash := bytes32(latestLeaf.ParentNumberAndHash.Hash[:]) - parachainHeader := []*types.ParachainHeader{{ - ParachainHeader: paraHeader, - MmrLeafPartial: &types.BeefyMmrLeafPartial{ - Version: uint8(mmrProofs.Leaf.Version), - ParentNumber: uint32(mmrProofs.Leaf.ParentNumberAndHash.ParentNumber), - ParentHash: &parentHash, - BeefyNextAuthoritySet: types.BeefyAuthoritySet{ - Id: uint64(mmrProofs.Leaf.BeefyNextAuthoritySet.ID), - Len: uint32(mmrProofs.Leaf.BeefyNextAuthoritySet.Len), - AuthorityRoot: &BeefyNextAuthoritySetRoot, - }, - }, - ParachainHeadsProof: paraHeadsProof.ProofHashes(), - ParaId: 2000, - HeadsLeafIndex: index, - HeadsTotalCount: uint32(len(paraHeadsLeaves)), - }} - - var proofItems [][]byte - for i := 0; i < len(mmrProofs.Proof.Items); i++ { - proofItems = append(proofItems, mmrProofs.Proof.Items[i][:]) + var latestLeafMmrProof = make([][]byte, len(mmrProof.Proof.Items)) + for i := 0; i < len(mmrProof.Proof.Items); i++ { + latestLeafMmrProof[i] = mmrProof.Proof.Items[i][:] + } + var mmrBatchProofItems = make([][]byte, len(mmrBatchProof.Proof.Items)) + for i := 0; i < len(mmrBatchProof.Proof.Items); i++ { + mmrBatchProofItems[i] = mmrBatchProof.Proof.Items[i][:] } var signatures []*types.CommitmentSignature var authorityIndeces []uint32 @@ -219,37 +325,40 @@ func TestCheckHeaderAndUpdateState(t *testing.T) { } } - CommitmentPayload := bytes32(signedCommitment.Commitment.Payload[:]) - ParachainHeads := bytes32(mmrProofs.Leaf.ParachainHeads[:]) - header := types.Header{ - ParachainHeaders: parachainHeader, - MmrProofs: proofItems, - MmrSize: mmr.LeafIndexToMMRSize(uint64(mmrProofs.Proof.LeafIndex)), - MmrUpdateProof: &types.MmrUpdateProof{ - MmrLeaf: &types.BeefyMmrLeaf{ - Version: uint8(mmrProofs.Leaf.Version), - ParentNumber: uint32(mmrProofs.Leaf.ParentNumberAndHash.ParentNumber), - ParentHash: &parentHash, - ParachainHeads: &ParachainHeads, - BeefyNextAuthoritySet: types.BeefyAuthoritySet{ - Id: uint64(mmrProofs.Leaf.BeefyNextAuthoritySet.ID), - Len: uint32(mmrProofs.Leaf.BeefyNextAuthoritySet.Len), - AuthorityRoot: &BeefyNextAuthoritySetRoot, - }, + CommitmentPayload := signedCommitment.Commitment.Payload[0] + ParachainHeads := bytes32(latestLeaf.ParachainHeads[:]) + leafIndex := clientState.GetLeafIndexForBlockNumber(blockNumber) + + mmrUpdateProof := types.MmrUpdateProof{ + MmrLeaf: &types.BeefyMmrLeaf{ + Version: uint8(latestLeaf.Version), + ParentNumber: uint32(latestLeaf.ParentNumberAndHash.ParentNumber), + ParentHash: &parentHash, + ParachainHeads: &ParachainHeads, + BeefyNextAuthoritySet: types.BeefyAuthoritySet{ + Id: uint64(latestLeaf.BeefyNextAuthoritySet.ID), + Len: uint32(latestLeaf.BeefyNextAuthoritySet.Len), + AuthorityRoot: &BeefyNextAuthoritySetRoot, }, - MmrLeafIndex: uint64(mmrProofs.Proof.LeafIndex), - MmrProof: proofItems, - SignedCommitment: &types.SignedCommitment{ - Commitment: &types.Commitment{ - Payload: &CommitmentPayload, - // Payload: []*types.PayloadItem{{PayloadId: []byte("mh"), PayloadData: signedCommitment.Commitment.Payload[:]}}, - BlockNumer: uint32(signedCommitment.Commitment.BlockNumber), - ValidatorSetId: uint64(signedCommitment.Commitment.ValidatorSetID), - }, - Signatures: signatures, + }, + MmrLeafIndex: uint64(leafIndex), + MmrProof: latestLeafMmrProof, + SignedCommitment: &types.SignedCommitment{ + Commitment: &types.Commitment{ + Payload: []*types.PayloadItem{{PayloadId: &CommitmentPayload.Id, PayloadData: CommitmentPayload.Value}}, + BlockNumer: uint32(signedCommitment.Commitment.BlockNumber), + ValidatorSetId: uint64(signedCommitment.Commitment.ValidatorSetID), }, - AuthoritiesProof: authorityTree.Proof(authorityIndeces).ProofHashes(), + Signatures: signatures, }, + AuthoritiesProof: authorityTree.Proof(authorityIndeces).ProofHashes(), + } + + header := types.Header{ + ParachainHeaders: parachainHeaders, + MmrProofs: mmrBatchProofItems, + MmrSize: mmr.LeafIndexToMMRSize(uint64(leafIndex)), + MmrUpdateProof: &mmrUpdateProof, } _, _, errs := clientState.CheckHeaderAndUpdateState(sdk.Context{}, nil, nil, &header) @@ -264,13 +373,15 @@ func TestCheckHeaderAndUpdateState(t *testing.T) { } fmt.Printf("====== successfully processed justification! ======\n") + // TODO: assert that the consensus states were actually persisted + // TODO: tests against invalid proofs and consensus states } } } type Authorities = [][33]uint8 -func getBeefyAuthorities(blockNumber uint32, conn *client.SubstrateAPI, method string) ([][]byte, error) { +func BeefyAuthorities(blockNumber uint32, conn *client.SubstrateAPI, method string) ([][]byte, error) { blockHash, err := conn.RPC.Chain.GetBlockHash(uint64(blockNumber)) if err != nil { return nil, err @@ -315,45 +426,28 @@ func getBeefyAuthorities(blockNumber uint32, conn *client.SubstrateAPI, method s return authorityEthereumAddresses, nil } -func fetchParaHeads(conn *client.SubstrateAPI, blockHash clientTypes.Hash) (map[uint32][]byte, error) { - - keyPrefix := clientTypes.CreateStorageKeyPrefix("Paras", "Heads") - - keys, err := conn.RPC.State.GetKeys(keyPrefix, blockHash) +func fetchParaIds(conn *client.SubstrateAPI, blockHash clientTypes.Hash) ([]uint32, error) { + // Fetch metadata + meta, err := conn.RPC.State.GetMetadataLatest() if err != nil { - fmt.Errorf("Failed to get all parachain keys %v \n", err) return nil, err } - changeSets, err := conn.RPC.State.QueryStorageAt(keys, blockHash) + storageKey, err := clientTypes.CreateStorageKey(meta, "Paras", "Parachains", nil, nil) if err != nil { - fmt.Errorf("Failed to get all parachain headers %v \n", err) return nil, err } - heads := make(map[uint32][]byte) - - for _, changeSet := range changeSets { - for _, change := range changeSet.Changes { - - var paraID uint32 + var paraIds []uint32 - if err := types.DecodeFromBytes(change.StorageKey[40:], ¶ID); err != nil { - fmt.Errorf("Failed to decode parachain ID %v \n", err) - return nil, err - } - - headDataWrapped := change.StorageData - - var headData clientTypes.Bytes - if err := types.DecodeFromBytes(headDataWrapped, &headData); err != nil { - fmt.Errorf("Failed to decode HeadData wrapper %v \n", err) - return nil, err - } + ok, err := conn.RPC.State.GetStorage(storageKey, ¶Ids, blockHash) + if err != nil { + return nil, err + } - heads[paraID] = headData - } + if !ok { + return nil, fmt.Errorf("Beefy authorities not found") } - return heads, nil + return paraIds, nil } diff --git a/proto/ibc/lightclients/beefy/v1/beefy.proto b/proto/ibc/lightclients/beefy/v1/beefy.proto index 244c86ec465..40c5716e5b1 100644 --- a/proto/ibc/lightclients/beefy/v1/beefy.proto +++ b/proto/ibc/lightclients/beefy/v1/beefy.proto @@ -46,7 +46,7 @@ message PayloadItem { option (gogoproto.goproto_getters) = false; // 2-byte payload id - bytes payload_id = 1; + bytes payload_id = 1 [(gogoproto.customtype) = "[2]byte"]; // arbitrary length payload data., eg mmr_root_hash bytes payload_data = 2; @@ -57,7 +57,7 @@ message Commitment { option (gogoproto.goproto_getters) = false; // array of payload items signed by Beefy validators - bytes payload = 1 [(gogoproto.customtype) = "[32]byte"]; + repeated PayloadItem payload = 1; // block number for this commitment uint32 block_numer = 2;