diff --git a/go.mod b/go.mod index eb7519162f..b329ca1863 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.8 require ( github.com/VictoriaMetrics/fastcache v1.12.1 github.com/antithesishq/antithesis-sdk-go v0.3.8 - github.com/ava-labs/avalanchego v1.11.13-0.20241029131257-e05aa37abaf9 + github.com/ava-labs/avalanchego v1.11.13-0.20241104091041-0b7a136fba6b github.com/cespare/cp v0.1.0 github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 github.com/davecgh/go-spew v1.1.1 @@ -76,17 +76,23 @@ require ( github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/google/renameio/v2 v2.0.0 // indirect github.com/gorilla/mux v1.8.0 // indirect @@ -96,17 +102,25 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/jackpal/gateway v1.0.6 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/moby/spdystream v0.2.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mr-tron/base58 v1.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect @@ -124,7 +138,7 @@ require ( github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect - github.com/supranational/blst v0.3.11 // indirect + github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect @@ -141,14 +155,25 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/net v0.28.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/term v0.23.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gonum.org/v1/gonum v0.11.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed // indirect google.golang.org/grpc v1.66.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.29.0 // indirect + k8s.io/apimachinery v0.29.0 // indirect + k8s.io/client-go v0.29.0 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect rsc.io/tmplfunc v0.0.3 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index c5d14ece7a..ca120b2521 100644 --- a/go.sum +++ b/go.sum @@ -58,10 +58,10 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax github.com/antithesishq/antithesis-sdk-go v0.3.8 h1:OvGoHxIcOXFJLyn9IJQ5DzByZ3YVAWNBc394ObzDRb8= github.com/antithesishq/antithesis-sdk-go v0.3.8/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanchego v1.11.13-0.20241026214739-acb3d7d102a0 h1:1T9OnvZP6XZ62EVWlfmrI8rrudyE6bM2Zt51pCHfS5o= -github.com/ava-labs/avalanchego v1.11.13-0.20241026214739-acb3d7d102a0/go.mod h1:gYlTU42Q4b29hzhUN22yclym5qwB3Si0jh4+LTn7DZM= -github.com/ava-labs/avalanchego v1.11.13-0.20241029131257-e05aa37abaf9 h1:rX5Xn5WBPppyvvZXp8wwx9dX+4fBY2/XeNIEm18ifzk= -github.com/ava-labs/avalanchego v1.11.13-0.20241029131257-e05aa37abaf9/go.mod h1:gYlTU42Q4b29hzhUN22yclym5qwB3Si0jh4+LTn7DZM= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/ava-labs/avalanchego v1.11.13-0.20241104091041-0b7a136fba6b h1:qvjqst/9X/c4tvI6nFzOwoTeRVIOMPAtEf1liDYrlhI= +github.com/ava-labs/avalanchego v1.11.13-0.20241104091041-0b7a136fba6b/go.mod h1:86tO6F1FT8emclUwdQ2WCwAtAerqjm5A4IbV6XxNUyM= github.com/ava-labs/coreth v0.13.8 h1:f14X3KgwHl9LwzfxlN6S4bbn5VA2rhEsNnHaRLSTo/8= github.com/ava-labs/coreth v0.13.8/go.mod h1:t3BSv/eQv0AlDPMfEDCMMoD/jq1RkUsbFzQAFg5qBcE= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -173,6 +173,8 @@ github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -214,6 +216,7 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -222,6 +225,12 @@ github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AE github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -280,6 +289,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -290,10 +301,13 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/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.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -326,6 +340,7 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk= github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -367,9 +382,13 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -406,6 +425,8 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -439,13 +460,22 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -548,6 +578,7 @@ github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobt github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -557,12 +588,13 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= +github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= @@ -742,6 +774,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1022,6 +1056,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1033,6 +1069,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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= @@ -1050,8 +1087,26 @@ 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= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A= +k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA= +k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o= +k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis= +k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8= +k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/plugin/evm/tx_gossip_test.go b/plugin/evm/tx_gossip_test.go index a87a7a3896..0eaaa63e6d 100644 --- a/plugin/evm/tx_gossip_test.go +++ b/plugin/evm/tx_gossip_test.go @@ -20,7 +20,6 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/enginetest" "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/snow/validators/validatorstest" agoUtils "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" @@ -155,14 +154,6 @@ func TestEthTxPushGossipOutbound(t *testing.T) { require := require.New(t) ctx := context.Background() snowCtx := utils.TestSnowContext() - snowCtx.ValidatorState = &validatorstest.State{ - GetCurrentHeightF: func(context.Context) (uint64, error) { - return 0, nil - }, - GetValidatorSetF: func(context.Context, uint64, ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { - return nil, nil - }, - } sender := &enginetest.SenderStub{ SentAppGossip: make(chan []byte, 1), } diff --git a/plugin/evm/uptime/pausable_manager.go b/plugin/evm/uptime/pausable_manager.go index 3976fcae6c..8b81c4264b 100644 --- a/plugin/evm/uptime/pausable_manager.go +++ b/plugin/evm/uptime/pausable_manager.go @@ -58,16 +58,10 @@ func (p *pausableManager) Disconnect(nodeID ids.NodeID) error { return nil } -// StartTracking starts tracking uptime for the nodes with the given IDs -// If a node is paused, it will not be tracked -func (p *pausableManager) StartTracking(nodeIDs []ids.NodeID) error { - activeNodeIDs := make([]ids.NodeID, 0, len(nodeIDs)) - for _, nodeID := range nodeIDs { - if !p.IsPaused(nodeID) { - activeNodeIDs = append(activeNodeIDs, nodeID) - } - } - return p.Manager.StartTracking(activeNodeIDs) +// IsConnected returns true if the node with the given ID is connected to the uptime.Manager +// Note: Inner manager may have a different view of the connection status due to pausing +func (p *pausableManager) IsConnected(nodeID ids.NodeID) bool { + return p.connectedVdrs.Contains(nodeID) } // OnValidatorAdded is called when a validator is added. diff --git a/plugin/evm/uptime/pausable_manager_test.go b/plugin/evm/uptime/pausable_manager_test.go index e1f4f4a6f8..73e84fb360 100644 --- a/plugin/evm/uptime/pausable_manager_test.go +++ b/plugin/evm/uptime/pausable_manager_test.go @@ -38,12 +38,14 @@ func TestPausableManager(t *testing.T) { // Elapse Time addTime(clk, time.Second) + // The node was paused before we started tracking + expectedUptime := 1 * time.Second // Start tracking require.NoError(up.StartTracking([]ids.NodeID{nodeID0})) currentTime := addTime(clk, time.Second) - // Uptime should not have increased since the node was paused - expectedUptime := 0 * time.Second + // Uptime should have increased since the node was paused before we started tracking + expectedUptime += 1 * time.Second checkUptime(t, up, nodeID0, expectedUptime, currentTime) // Disconnect @@ -118,11 +120,13 @@ func TestPausableManager(t *testing.T) { // Connect and check uptime addTime(clk, 1*time.Second) + // Uptime should be 1 since the node was paused before we started tracking + expectedUptime := 1 * time.Second + checkUptime(t, up, nodeID0, expectedUptime, clk.Time()) require.NoError(up.Connect(nodeID0)) currentTime := addTime(clk, 2*time.Second) - // Uptime should not have increased since the node was paused - expectedUptime := 0 * time.Second + // Uptime should not have increased since the node was paused after we started tracking checkUptime(t, up, nodeID0, expectedUptime, currentTime) // Disconnect and check uptime @@ -209,6 +213,81 @@ func TestPausableManager(t *testing.T) { checkUptime(t, up, nodeID0, expectedUptime, currentTime) }, }, + { + name: "Case 5: Node paused after we stop tracking", + testFunc: func(t *testing.T, up interfaces.PausableManager, clk *mockable.Clock, s uptime.State) { + require := require.New(t) + + // Start tracking and connect + require.NoError(up.StartTracking([]ids.NodeID{nodeID0})) + addTime(clk, time.Second) + require.NoError(up.Connect(nodeID0)) + + // Stop tracking + currentTime := addTime(clk, 2*time.Second) + expectedUptime := 2 * time.Second + checkUptime(t, up, nodeID0, expectedUptime, currentTime) + require.NoError(up.StopTracking([]ids.NodeID{nodeID0})) + + // Pause after a while + currentTime = addTime(clk, 3*time.Second) + // expectedUptime should increase since we stopped tracking + expectedUptime += 3 * time.Second + up.OnValidatorStatusUpdated(vID, nodeID0, false) + require.True(up.IsPaused(nodeID0)) + // expectedUptime should increase since we stopped tracking (even if the node was paused) + currentTime = addTime(clk, 4*time.Second) + expectedUptime += 4 * time.Second + + // Start tracking and check elapsed time + require.NoError(up.StartTracking([]ids.NodeID{nodeID0})) + // Uptime have increased since the node was paused before we started tracking + // We should be optimistic and assume the node was online and active until we start tracking + require.True(up.IsPaused(nodeID0)) + checkUptime(t, up, nodeID0, expectedUptime, currentTime) + }, + }, + { + name: "Case 6: Paused node got resumed after we stop tracking", + testFunc: func(t *testing.T, up interfaces.PausableManager, clk *mockable.Clock, s uptime.State) { + require := require.New(t) + + // Start tracking and connect + require.NoError(up.StartTracking([]ids.NodeID{nodeID0})) + addTime(clk, time.Second) + require.NoError(up.Connect(nodeID0)) + + // Pause after a while + currentTime := addTime(clk, 2*time.Second) + // expectedUptime should increase + expectedUptime := 2 * time.Second + up.OnValidatorStatusUpdated(vID, nodeID0, false) + require.True(up.IsPaused(nodeID0)) + checkUptime(t, up, nodeID0, expectedUptime, currentTime) + + // Stop tracking + currentTime = addTime(clk, 3*time.Second) + // expectedUptime should not increase since the node was paused + checkUptime(t, up, nodeID0, expectedUptime, currentTime) + require.NoError(up.StopTracking([]ids.NodeID{nodeID0})) + + // Resume after a while + currentTime = addTime(clk, 4*time.Second) + // expectedUptime should increase since we stopped tracking + expectedUptime += 4 * time.Second + up.OnValidatorStatusUpdated(vID, nodeID0, true) + require.False(up.IsPaused(nodeID0)) + // expectedUptime should increase since we stopped tracking + currentTime = addTime(clk, 5*time.Second) + expectedUptime += 5 * time.Second + + // Start tracking and check elapsed time + require.NoError(up.StartTracking([]ids.NodeID{nodeID0})) + // Uptime should have increased by 4 seconds since the node was resumed + // We should be optimistic and assume the node was online and active until we start tracking + checkUptime(t, up, nodeID0, expectedUptime, currentTime) + }, + }, } for _, test := range tests { diff --git a/plugin/evm/validators/interfaces/interface.go b/plugin/evm/validators/interfaces/interface.go index ab59b948c1..39b6b8c9e9 100644 --- a/plugin/evm/validators/interfaces/interface.go +++ b/plugin/evm/validators/interfaces/interface.go @@ -14,23 +14,20 @@ import ( type State interface { uptime.State // AddValidator adds a new validator to the state - AddValidator(vID ids.ID, nodeID ids.NodeID, startTimestamp uint64, isActive bool) error + AddValidator(vdr Validator) error + // UpdateValidator updates the validator in the state + UpdateValidator(vdr Validator) error + // GetValidator returns the validator data for the given validation ID + GetValidator(vID ids.ID) (Validator, error) // DeleteValidator deletes the validator from the state DeleteValidator(vID ids.ID) error // WriteState writes the validator state to the disk WriteState() error - // SetStatus sets the active status of the validator with the given vID - SetStatus(vID ids.ID, isActive bool) error - // GetStatus returns the active status of the validator with the given vID - GetStatus(vID ids.ID) (bool, error) - // GetValidationIDs returns the validation IDs in the state GetValidationIDs() set.Set[ids.ID] - // GetValidatorIDs returns the validator node IDs in the state - GetValidatorIDs() set.Set[ids.NodeID] - // GetValidator returns the validator data for the given nodeID - GetValidator(nodeID ids.NodeID) (*ValidatorOutput, error) + // GetNodeIDs returns the validator node IDs in the state + GetNodeIDs() set.Set[ids.NodeID] // RegisterListener registers a listener to the state RegisterListener(StateCallbackListener) @@ -46,9 +43,13 @@ type StateCallbackListener interface { OnValidatorStatusUpdated(vID ids.ID, nodeID ids.NodeID, isActive bool) } -type ValidatorOutput struct { - ValidationID ids.ID `json:"validationID"` - NodeID ids.NodeID `json:"nodeID"` - StartTime time.Time `json:"startTime"` - IsActive bool `json:"isActive"` +type Validator struct { + ValidationID ids.ID `json:"validationID"` + NodeID ids.NodeID `json:"nodeID"` + Weight uint64 `json:"weight"` + StartTimestamp uint64 `json:"startTimestamp"` + IsActive bool `json:"isActive"` + IsSoV bool `json:"isSoV"` } + +func (v *Validator) StartTime() time.Time { return time.Unix(int64(v.StartTimestamp), 0) } diff --git a/plugin/evm/validators/state.go b/plugin/evm/validators/state.go index 52edcd0710..8f8279785c 100644 --- a/plugin/evm/validators/state.go +++ b/plugin/evm/validators/state.go @@ -18,19 +18,24 @@ var _ uptime.State = &state{} type dbUpdateStatus bool -var ErrAlreadyExists = fmt.Errorf("validator already exists") +var ( + ErrAlreadyExists = fmt.Errorf("validator already exists") + ErrImmutableField = fmt.Errorf("immutable field cannot be updated") +) const ( - updated dbUpdateStatus = true - deleted dbUpdateStatus = false + updatedStatus dbUpdateStatus = true + deletedStatus dbUpdateStatus = false ) type validatorData struct { UpDuration time.Duration `serialize:"true"` LastUpdated uint64 `serialize:"true"` NodeID ids.NodeID `serialize:"true"` + Weight uint64 `serialize:"true"` StartTime uint64 `serialize:"true"` IsActive bool `serialize:"true"` + IsSoV bool `serialize:"true"` validationID ids.ID // database key } @@ -83,7 +88,7 @@ func (s *state) SetUptime( data.UpDuration = upDuration data.setLastUpdated(lastUpdated) - s.updatedData[data.validationID] = updated + s.updatedData[data.validationID] = updatedStatus return nil } @@ -98,23 +103,57 @@ func (s *state) GetStartTime(nodeID ids.NodeID) (time.Time, error) { // AddValidator adds a new validator to the state // the new validator is marked as updated and will be written to the disk when WriteState is called -func (s *state) AddValidator(vID ids.ID, nodeID ids.NodeID, startTimestamp uint64, isActive bool) error { +func (s *state) AddValidator(vdr interfaces.Validator) error { data := &validatorData{ - NodeID: nodeID, - validationID: vID, - IsActive: isActive, - StartTime: startTimestamp, + NodeID: vdr.NodeID, + validationID: vdr.ValidationID, + IsActive: vdr.IsActive, + StartTime: vdr.StartTimestamp, UpDuration: 0, - LastUpdated: startTimestamp, + LastUpdated: vdr.StartTimestamp, + IsSoV: vdr.IsSoV, + Weight: vdr.Weight, } - if err := s.addData(vID, data); err != nil { + if err := s.addData(vdr.ValidationID, data); err != nil { return err } - s.updatedData[vID] = updated + s.updatedData[vdr.ValidationID] = updatedStatus for _, listener := range s.listeners { - listener.OnValidatorAdded(vID, nodeID, startTimestamp, isActive) + listener.OnValidatorAdded(vdr.ValidationID, vdr.NodeID, vdr.StartTimestamp, vdr.IsActive) + } + return nil +} + +// UpdateValidator updates the validator in the state +// returns an error if the validator does not exist or if the immutable fields are modified +func (s *state) UpdateValidator(vdr interfaces.Validator) error { + data, exists := s.data[vdr.ValidationID] + if !exists { + return database.ErrNotFound + } + // check immutable fields + if !data.constantsAreUnmodified(vdr) { + return ErrImmutableField + } + // check if mutable fields have changed + updated := false + if data.IsActive != vdr.IsActive { + data.IsActive = vdr.IsActive + updated = true + for _, listener := range s.listeners { + listener.OnValidatorStatusUpdated(data.validationID, data.NodeID, data.IsActive) + } + } + + if data.Weight != vdr.Weight { + data.Weight = vdr.Weight + updated = true + } + + if updated { + s.updatedData[vdr.ValidationID] = updatedStatus } return nil } @@ -130,7 +169,7 @@ func (s *state) DeleteValidator(vID ids.ID) error { delete(s.index, data.NodeID) // mark as deleted for WriteValidator - s.updatedData[data.validationID] = deleted + s.updatedData[data.validationID] = deletedStatus for _, listener := range s.listeners { listener.OnValidatorRemoved(vID, data.NodeID) @@ -144,7 +183,7 @@ func (s *state) WriteState() error { batch := s.db.NewBatch() for vID, updateStatus := range s.updatedData { switch updateStatus { - case updated: + case updatedStatus: data := s.data[vID] dataBytes, err := vdrCodec.Marshal(codecVersion, data) @@ -154,7 +193,7 @@ func (s *state) WriteState() error { if err := batch.Put(vID[:], dataBytes); err != nil { return err } - case deleted: + case deletedStatus: if err := batch.Delete(vID[:]); err != nil { return err } @@ -174,7 +213,7 @@ func (s *state) SetStatus(vID ids.ID, isActive bool) error { return database.ErrNotFound } data.IsActive = isActive - s.updatedData[vID] = updated + s.updatedData[vID] = updatedStatus for _, listener := range s.listeners { listener.OnValidatorStatusUpdated(vID, data.NodeID, isActive) @@ -182,15 +221,6 @@ func (s *state) SetStatus(vID ids.ID, isActive bool) error { return nil } -// GetStatus returns the active status of the validator with the given vID -func (s *state) GetStatus(vID ids.ID) (bool, error) { - data, exists := s.data[vID] - if !exists { - return false, database.ErrNotFound - } - return data.IsActive, nil -} - // GetValidationIDs returns the validation IDs in the state func (s *state) GetValidationIDs() set.Set[ids.ID] { ids := set.NewSet[ids.ID](len(s.data)) @@ -200,8 +230,8 @@ func (s *state) GetValidationIDs() set.Set[ids.ID] { return ids } -// GetValidatorIDs returns the validator IDs in the state -func (s *state) GetValidatorIDs() set.Set[ids.NodeID] { +// GetNodeIDs returns the node IDs of validators in the state +func (s *state) GetNodeIDs() set.Set[ids.NodeID] { ids := set.NewSet[ids.NodeID](len(s.index)) for nodeID := range s.index { ids.Add(nodeID) @@ -209,17 +239,19 @@ func (s *state) GetValidatorIDs() set.Set[ids.NodeID] { return ids } -// GetValidator returns the validator data for the given nodeID -func (s *state) GetValidator(nodeID ids.NodeID) (*interfaces.ValidatorOutput, error) { - data, err := s.getData(nodeID) - if err != nil { - return nil, err +// GetValidator returns the validator data for the given validationID +func (s *state) GetValidator(vID ids.ID) (interfaces.Validator, error) { + data, ok := s.data[vID] + if !ok { + return interfaces.Validator{}, database.ErrNotFound } - return &interfaces.ValidatorOutput{ - ValidationID: data.validationID, - NodeID: data.NodeID, - StartTime: data.getStartTime(), - IsActive: data.IsActive, + return interfaces.Validator{ + ValidationID: data.validationID, + NodeID: data.NodeID, + StartTimestamp: data.StartTime, + IsActive: data.IsActive, + Weight: data.Weight, + IsSoV: data.IsSoV, }, nil } @@ -307,3 +339,14 @@ func (v *validatorData) getLastUpdated() time.Time { func (v *validatorData) getStartTime() time.Time { return time.Unix(int64(v.StartTime), 0) } + +// constantsAreUnmodified returns true if the constants of this validator have +// not been modified compared to the other validator. +func (v *validatorData) constantsAreUnmodified(o interfaces.Validator) bool { + if v.validationID != o.ValidationID { + return true + } + return v.NodeID == o.NodeID && + v.IsSoV == o.IsSoV && + v.StartTime == o.StartTimestamp +} diff --git a/plugin/evm/validators/state_test.go b/plugin/evm/validators/state_test.go index e5e8244027..2184a6fbbc 100644 --- a/plugin/evm/validators/state_test.go +++ b/plugin/evm/validators/state_test.go @@ -36,13 +36,23 @@ func TestState(t *testing.T) { require.ErrorIs(err, database.ErrNotFound) // add new validator - state.AddValidator(vID, nodeID, uint64(startTime.Unix()), true) + vdr := interfaces.Validator{ + ValidationID: vID, + NodeID: nodeID, + Weight: 1, + StartTimestamp: uint64(startTime.Unix()), + IsActive: true, + IsSoV: true, + } + state.AddValidator(vdr) // adding the same validator should fail - err = state.AddValidator(vID, ids.GenerateTestNodeID(), uint64(startTime.Unix()), true) + err = state.AddValidator(vdr) require.ErrorIs(err, ErrAlreadyExists) // adding the same nodeID should fail - err = state.AddValidator(ids.GenerateTestID(), nodeID, uint64(startTime.Unix()), true) + newVdr := vdr + newVdr.ValidationID = ids.GenerateTestID() + err = state.AddValidator(newVdr) require.ErrorIs(err, ErrAlreadyExists) // get uptime @@ -62,11 +72,26 @@ func TestState(t *testing.T) { require.Equal(newLastUpdated, lastUpdated) // set status - require.NoError(state.SetStatus(vID, false)) + vdr.IsActive = false + require.NoError(state.UpdateValidator(vdr)) // get status - status, err := state.GetStatus(vID) + data, err := state.GetValidator(vID) + require.NoError(err) + require.False(data.IsActive) + + // set weight + newWeight := uint64(2) + vdr.Weight = newWeight + require.NoError(state.UpdateValidator(vdr)) + // get weight + data, err = state.GetValidator(vID) require.NoError(err) - require.False(status) + require.Equal(newWeight, data.Weight) + + // set a different node ID should fail + newNodeID := ids.GenerateTestNodeID() + vdr.NodeID = newNodeID + require.ErrorIs(state.UpdateValidator(vdr), ErrImmutableField) // delete uptime require.NoError(state.DeleteValidator(vID)) @@ -88,7 +113,14 @@ func TestWriteValidator(t *testing.T) { nodeID := ids.GenerateTestNodeID() vID := ids.GenerateTestID() startTime := time.Now() - require.NoError(state.AddValidator(vID, nodeID, uint64(startTime.Unix()), true)) + require.NoError(state.AddValidator(interfaces.Validator{ + ValidationID: vID, + NodeID: nodeID, + Weight: 1, + StartTimestamp: uint64(startTime.Unix()), + IsActive: true, + IsSoV: true, + })) // write state, should reflect to DB require.NoError(state.WriteState()) @@ -132,8 +164,14 @@ func TestParseValidator(t *testing.T) { name: "nil", bytes: nil, expected: &validatorData{ - LastUpdated: 0, - StartTime: 0, + LastUpdated: 0, + StartTime: 0, + validationID: ids.Empty, + NodeID: ids.EmptyNodeID, + UpDuration: 0, + Weight: 0, + IsActive: false, + IsSoV: false, }, expectedErr: nil, }, @@ -141,8 +179,14 @@ func TestParseValidator(t *testing.T) { name: "empty", bytes: []byte{}, expected: &validatorData{ - LastUpdated: 0, - StartTime: 0, + LastUpdated: 0, + StartTime: 0, + validationID: ids.Empty, + NodeID: ids.EmptyNodeID, + UpDuration: 0, + Weight: 0, + IsActive: false, + IsSoV: false, }, expectedErr: nil, }, @@ -159,10 +203,14 @@ func TestParseValidator(t *testing.T) { 0x7e, 0xef, 0xe8, 0x8a, 0x45, 0xfb, 0x7a, 0xc4, 0xb0, 0x59, 0xc9, 0x33, 0x71, 0x0a, 0x57, 0x33, 0xff, 0x9f, 0x4b, 0xab, + // weight + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // start time 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x8D, 0x80, // status 0x01, + // is SoV + 0x01, }, expected: &validatorData{ UpDuration: time.Duration(6000000), @@ -170,6 +218,8 @@ func TestParseValidator(t *testing.T) { NodeID: testNodeID, StartTime: 6000000, IsActive: true, + Weight: 1, + IsSoV: true, }, }, { @@ -231,7 +281,14 @@ func TestStateListener(t *testing.T) { initialStartTime := time.Now() // add initial validator - require.NoError(state.AddValidator(initialvID, initialNodeID, uint64(initialStartTime.Unix()), true)) + require.NoError(state.AddValidator(interfaces.Validator{ + ValidationID: initialvID, + NodeID: initialNodeID, + Weight: 1, + StartTimestamp: uint64(initialStartTime.Unix()), + IsActive: true, + IsSoV: true, + })) // register listener mockListener.EXPECT().OnValidatorAdded(initialvID, initialNodeID, uint64(initialStartTime.Unix()), true) @@ -239,11 +296,23 @@ func TestStateListener(t *testing.T) { // add new validator mockListener.EXPECT().OnValidatorAdded(expectedvID, expectedNodeID, uint64(expectedStartTime.Unix()), true) - require.NoError(state.AddValidator(expectedvID, expectedNodeID, uint64(expectedStartTime.Unix()), true)) + vdr := interfaces.Validator{ + ValidationID: expectedvID, + NodeID: expectedNodeID, + Weight: 1, + StartTimestamp: uint64(expectedStartTime.Unix()), + IsActive: true, + IsSoV: true, + } + require.NoError(state.AddValidator(vdr)) // set status mockListener.EXPECT().OnValidatorStatusUpdated(expectedvID, expectedNodeID, false) - require.NoError(state.SetStatus(expectedvID, false)) + vdr.IsActive = false + require.NoError(state.UpdateValidator(vdr)) + + // set status twice should not trigger listener + require.NoError(state.UpdateValidator(vdr)) // remove validator mockListener.EXPECT().OnValidatorRemoved(expectedvID, expectedNodeID) diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 6d5937f546..7c2eec1d26 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -511,6 +511,7 @@ func (vm *VM) Initialize( return fmt.Errorf("failed to initialize validator state: %w", err) } + // Initialize uptime manager vm.uptimeManager = uptime.NewPausableManager(avalancheUptime.NewManager(vm.validatorState, &vm.clock)) vm.validatorState.RegisterListener(vm.uptimeManager) @@ -739,7 +740,7 @@ func (vm *VM) onNormalOperationsStarted() error { if err := vm.performValidatorUpdate(ctx); err != nil { return fmt.Errorf("failed to update validators: %w", err) } - vdrIDs := vm.validatorState.GetValidatorIDs().List() + vdrIDs := vm.validatorState.GetNodeIDs().List() // then start tracking with updated validators if err := vm.uptimeManager.StartTracking(vdrIDs); err != nil { return fmt.Errorf("failed to start tracking uptime: %w", err) @@ -880,7 +881,7 @@ func (vm *VM) Shutdown(context.Context) error { vm.cancel() } if vm.bootstrapped.Get() { - vdrIDs := vm.validatorState.GetValidatorIDs().List() + vdrIDs := vm.validatorState.GetNodeIDs().List() if err := vm.uptimeManager.StopTracking(vdrIDs); err != nil { return fmt.Errorf("failed to stop tracking uptime: %w", err) } @@ -1444,7 +1445,7 @@ func (vm *VM) performValidatorUpdate(ctx context.Context) error { now := time.Now() log.Debug("performing validator update") // get current validator set - currentValidatorSet, _, _, err := vm.ctx.ValidatorState.GetCurrentValidatorSet(ctx, vm.ctx.SubnetID) + currentValidatorSet, _, err := vm.ctx.ValidatorState.GetCurrentValidatorSet(ctx, vm.ctx.SubnetID) if err != nil { return fmt.Errorf("failed to get current validator set: %w", err) } @@ -1465,32 +1466,33 @@ func (vm *VM) performValidatorUpdate(ctx context.Context) error { } // loadValidators loads the [validators] into the validator state [validatorState] -func loadValidators(validatorState validatorsinterfaces.State, validators map[ids.ID]*avalancheValidators.GetCurrentValidatorOutput) error { +func loadValidators(validatorState validatorsinterfaces.State, newValidators map[ids.ID]*avalancheValidators.GetCurrentValidatorOutput) error { currentValidationIDs := validatorState.GetValidationIDs() // first check if we need to delete any existing validators for vID := range currentValidationIDs { // if the validator is not in the new set of validators // delete the validator - if _, exists := validators[vID]; !exists { + if _, exists := newValidators[vID]; !exists { validatorState.DeleteValidator(vID) } } // then load the new validators - for vID, vdr := range validators { - if currentValidationIDs.Contains(vID) { - // Check if IsActive has changed - isActive, err := validatorState.GetStatus(vID) - if err != nil { + for newVID, newVdr := range newValidators { + currentVdr := validatorsinterfaces.Validator{ + ValidationID: newVID, + NodeID: newVdr.NodeID, + Weight: newVdr.Weight, + StartTimestamp: newVdr.StartTime, + IsActive: newVdr.IsActive, + IsSoV: newVdr.IsSoV, + } + if currentValidationIDs.Contains(newVID) { + if err := validatorState.UpdateValidator(currentVdr); err != nil { return err } - if isActive != vdr.IsActive { - if err := validatorState.SetStatus(vID, vdr.IsActive); err != nil { - return err - } - } } else { - if err := validatorState.AddValidator(vID, vdr.NodeID, vdr.StartTime, vdr.IsActive); err != nil { + if err := validatorState.AddValidator(currentVdr); err != nil { return err } } diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index c3e251e9a4..42e525d656 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -33,11 +33,7 @@ import ( "github.com/ava-labs/avalanchego/snow/consensus/snowman" commonEng "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/enginetest" - "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/snow/validators/validatorstest" "github.com/ava-labs/avalanchego/upgrade" - avalancheConstants "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/components/chain" @@ -63,17 +59,14 @@ import ( "github.com/ava-labs/subnet-evm/vmerrs" avagoconstants "github.com/ava-labs/avalanchego/utils/constants" - avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" ) var ( - testNetworkID uint32 = avagoconstants.UnitTestID - testCChainID = ids.ID{'c', 'c', 'h', 'a', 'i', 'n', 't', 'e', 's', 't'} - testXChainID = ids.ID{'t', 'e', 's', 't', 'x'} - testMinGasPrice int64 = 225_000_000_000 + testNetworkID uint32 = avagoconstants.UnitTestID + + testMinGasPrice int64 = 225_000_000_000 testKeys []*ecdsa.PrivateKey testEthAddrs []common.Address // testEthAddrs[i] corresponds to testKeys[i] - testAvaxAssetID = ids.ID{1, 2, 3} username = "Johns" password = "CjasdjhiPeirbSenfeI13" // #nosec G101 @@ -139,44 +132,6 @@ func buildGenesisTest(t *testing.T, genesisJSON string) []byte { return genesisBytes } -func NewContext() *snow.Context { - ctx := utils.TestSnowContext() - ctx.NodeID = ids.GenerateTestNodeID() - ctx.NetworkID = testNetworkID - ctx.ChainID = testCChainID - ctx.AVAXAssetID = testAvaxAssetID - ctx.XChainID = testXChainID - aliaser := ctx.BCLookup.(ids.Aliaser) - _ = aliaser.Alias(testCChainID, "C") - _ = aliaser.Alias(testCChainID, testCChainID.String()) - _ = aliaser.Alias(testXChainID, "X") - _ = aliaser.Alias(testXChainID, testXChainID.String()) - ctx.ValidatorState = &validatorstest.State{ - GetCurrentHeightF: func(ctx context.Context) (uint64, error) { return 0, nil }, - GetValidatorSetF: func(ctx context.Context, height uint64, subnetID ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { - return map[ids.NodeID]*validators.GetValidatorOutput{}, nil - }, - GetSubnetIDF: func(_ context.Context, chainID ids.ID) (ids.ID, error) { - subnetID, ok := map[ids.ID]ids.ID{ - avalancheConstants.PlatformChainID: avalancheConstants.PrimaryNetworkID, - testXChainID: avalancheConstants.PrimaryNetworkID, - testCChainID: avalancheConstants.PrimaryNetworkID, - }[chainID] - if !ok { - return ids.Empty, errors.New("unknown chain") - } - return subnetID, nil - }, - } - blsSecretKey, err := bls.NewSecretKey() - if err != nil { - panic(err) - } - ctx.WarpSigner = avalancheWarp.NewSigner(blsSecretKey, ctx.NetworkID, ctx.ChainID) - ctx.PublicKey = bls.PublicFromSecretKey(blsSecretKey) - return ctx -} - // setupGenesis sets up the genesis // If [genesisJSON] is empty, defaults to using [genesisJSONLatest] func setupGenesis( @@ -192,7 +147,7 @@ func setupGenesis( genesisJSON = genesisJSONLatest } genesisBytes := buildGenesisTest(t, genesisJSON) - ctx := NewContext() + ctx := utils.TestSnowContext() baseDB := memdb.New() @@ -498,7 +453,7 @@ func TestBuildEthTxBlock(t *testing.T) { if err := restartedVM.Initialize( context.Background(), - NewContext(), + utils.TestSnowContext(), dbManager, genesisBytes, []byte(""), diff --git a/plugin/evm/vm_validators_state_test.go b/plugin/evm/vm_validators_state_test.go index cec73feeca..8bf8c3546f 100644 --- a/plugin/evm/vm_validators_state_test.go +++ b/plugin/evm/vm_validators_state_test.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/plugin/evm/validators" "github.com/ava-labs/subnet-evm/plugin/evm/validators/interfaces" + "github.com/ava-labs/subnet-evm/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -43,7 +44,7 @@ func TestValidatorState(t *testing.T) { ids.GenerateTestID(), } ctx.ValidatorState = &validatorstest.State{ - GetCurrentValidatorSetF: func(ctx context.Context, subnetID ids.ID) (map[ids.ID]*avagoValidators.GetCurrentValidatorOutput, uint64, bool, error) { + GetCurrentValidatorSetF: func(ctx context.Context, subnetID ids.ID) (map[ids.ID]*avagoValidators.GetCurrentValidatorOutput, uint64, error) { return map[ids.ID]*avagoValidators.GetCurrentValidatorOutput{ testValidationIDs[0]: { NodeID: testNodeIDs[0], @@ -60,7 +61,7 @@ func TestValidatorState(t *testing.T) { PublicKey: nil, Weight: 1, }, - }, 0, false, nil + }, 0, nil }, } appSender.SendAppGossipF = func(context.Context, commonEng.SendConfig, []byte) error { return nil } @@ -99,7 +100,7 @@ func TestValidatorState(t *testing.T) { vm = &VM{} err = vm.Initialize( context.Background(), - NewContext(), // this context does not have validators state, making VM to source it from the database + utils.TestSnowContext(), // this context does not have validators state, making VM to source it from the database dbManager, genesisBytes, []byte(""), @@ -118,7 +119,7 @@ func TestValidatorState(t *testing.T) { newValidationID := ids.GenerateTestID() newNodeID := ids.GenerateTestNodeID() testState := &validatorstest.State{ - GetCurrentValidatorSetF: func(ctx context.Context, subnetID ids.ID) (map[ids.ID]*avagoValidators.GetCurrentValidatorOutput, uint64, bool, error) { + GetCurrentValidatorSetF: func(ctx context.Context, subnetID ids.ID) (map[ids.ID]*avagoValidators.GetCurrentValidatorOutput, uint64, error) { return map[ids.ID]*avagoValidators.GetCurrentValidatorOutput{ testValidationIDs[0]: { NodeID: testNodeIDs[0], @@ -140,7 +141,7 @@ func TestValidatorState(t *testing.T) { PublicKey: nil, Weight: 1, }, - }, 0, false, nil + }, 0, nil }, } vm.ctx.ValidatorState = testState @@ -150,8 +151,8 @@ func TestValidatorState(t *testing.T) { // new validator should be added to the state eventually after validatorsLoadFrequency require.EventuallyWithT(func(c *assert.CollectT) { - assert.Len(c, vm.validatorState.GetValidatorIDs(), 4) - newValidator, err := vm.validatorState.GetValidator(newNodeID) + assert.Len(c, vm.validatorState.GetNodeIDs(), 4) + newValidator, err := vm.validatorState.GetValidator(newValidationID) assert.NoError(c, err) assert.Equal(c, newNodeID, newValidator.NodeID) }, loadValidatorsFrequency*2, 5*time.Second) @@ -173,6 +174,7 @@ func TestLoadNewValidators(t *testing.T) { initialValidators map[ids.ID]*avagoValidators.GetCurrentValidatorOutput newValidators map[ids.ID]*avagoValidators.GetCurrentValidatorOutput registerMockListenerCalls func(*interfaces.MockStateCallbackListener) + expectedLoadErr error }{ { name: "before empty/after empty", @@ -232,12 +234,13 @@ func TestLoadNewValidators(t *testing.T) { }, }, { - name: "status change and new one", + name: "status and weight change and new one", initialValidators: map[ids.ID]*avagoValidators.GetCurrentValidatorOutput{ testValidationIDs[0]: { NodeID: testNodeIDs[0], IsActive: true, StartTime: 0, + Weight: 1, }, }, newValidators: map[ids.ID]*avagoValidators.GetCurrentValidatorOutput{ @@ -245,6 +248,7 @@ func TestLoadNewValidators(t *testing.T) { NodeID: testNodeIDs[0], IsActive: false, StartTime: 0, + Weight: 2, }, testValidationIDs[1]: { NodeID: testNodeIDs[1], @@ -302,6 +306,7 @@ func TestLoadNewValidators(t *testing.T) { StartTime: 0, }, }, + expectedLoadErr: validators.ErrImmutableField, registerMockListenerCalls: func(mock *interfaces.MockStateCallbackListener) { // initial validator will trigger first mock.EXPECT().OnValidatorAdded(testValidationIDs[0], testNodeIDs[0], uint64(0), true).Times(1) @@ -319,7 +324,14 @@ func TestLoadNewValidators(t *testing.T) { // set initial validators for vID, validator := range test.initialValidators { - err := validatorState.AddValidator(vID, validator.NodeID, validator.StartTime, validator.IsActive) + err := validatorState.AddValidator(interfaces.Validator{ + ValidationID: vID, + NodeID: validator.NodeID, + Weight: validator.Weight, + StartTimestamp: validator.StartTime, + IsActive: validator.IsActive, + IsSoV: validator.IsSoV, + }) require.NoError(err) } // enable mock listener @@ -328,8 +340,24 @@ func TestLoadNewValidators(t *testing.T) { test.registerMockListenerCalls(mockListener) validatorState.RegisterListener(mockListener) - require.NoError(loadValidators(validatorState, test.newValidators)) - ctrl.Finish() + // load new validators + err = loadValidators(validatorState, test.newValidators) + if test.expectedLoadErr != nil { + require.Error(err) + return + } + require.NoError(err) + // check if the state is as expected + require.Equal(len(test.newValidators), validatorState.GetValidationIDs().Len()) + for vID, validator := range test.newValidators { + v, err := validatorState.GetValidator(vID) + require.NoError(err) + require.Equal(validator.NodeID, v.NodeID) + require.Equal(validator.Weight, v.Weight) + require.Equal(validator.StartTime, v.StartTimestamp) + require.Equal(validator.IsActive, v.IsActive) + require.Equal(validator.IsSoV, v.IsSoV) + } }) } } diff --git a/plugin/evm/vm_warp_test.go b/plugin/evm/vm_warp_test.go index b80af6fdd5..2131b79d94 100644 --- a/plugin/evm/vm_warp_test.go +++ b/plugin/evm/vm_warp_test.go @@ -481,7 +481,7 @@ func TestReceiveWarpMessage(t *testing.T) { }, { name: "C-Chain message should be signed by subnet without RequirePrimaryNetworkSigners", - sourceChainID: testCChainID, + sourceChainID: vm.ctx.CChainID, msgFrom: fromPrimary, useSigners: signersSubnet, blockTime: upgrade.InitiallyActiveTime.Add(2 * blockGap), @@ -504,7 +504,7 @@ func TestReceiveWarpMessage(t *testing.T) { }, { name: "C-Chain message should be signed by primary with RequirePrimaryNetworkSigners (impacted)", - sourceChainID: testCChainID, + sourceChainID: vm.ctx.CChainID, msgFrom: fromPrimary, useSigners: signersPrimary, blockTime: reEnableTime.Add(2 * blockGap), diff --git a/scripts/versions.sh b/scripts/versions.sh index fa04254c77..248a2002d8 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -4,7 +4,7 @@ # shellcheck disable=SC2034 # Don't export them as they're used in the context of other calls -AVALANCHE_VERSION=${AVALANCHE_VERSION:-'e05aa37a'} +AVALANCHE_VERSION=${AVALANCHE_VERSION:-'0b7a136f'} GINKGO_VERSION=${GINKGO_VERSION:-'v2.2.0'} # This won't be used, but it's here to make code syncs easier diff --git a/utils/snow.go b/utils/snow.go index 090d38102f..00901fbad5 100644 --- a/utils/snow.go +++ b/utils/snow.go @@ -5,6 +5,7 @@ package utils import ( "context" + "errors" "github.com/ava-labs/avalanchego/api/metrics" "github.com/ava-labs/avalanchego/ids" @@ -15,6 +16,13 @@ import ( "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/vms/platformvm/warp" +) + +var ( + testCChainID = ids.ID{'c', 'c', 'h', 'a', 'i', 'n', 't', 'e', 's', 't'} + testXChainID = ids.ID{'t', 'e', 's', 't', 'x'} + testChainID = ids.ID{'t', 'e', 's', 't', 'c', 'h', 'a', 'i', 'n'} ) func TestSnowContext() *snow.Context { @@ -23,19 +31,33 @@ func TestSnowContext() *snow.Context { panic(err) } pk := bls.PublicFromSecretKey(sk) - return &snow.Context{ - NetworkID: constants.UnitTestID, + networkID := constants.UnitTestID + chainID := testChainID + + ctx := &snow.Context{ + NetworkID: networkID, SubnetID: ids.Empty, - ChainID: ids.Empty, - NodeID: ids.EmptyNodeID, + ChainID: chainID, + NodeID: ids.GenerateTestNodeID(), + XChainID: testXChainID, + CChainID: testCChainID, NetworkUpgrades: upgradetest.GetConfig(upgradetest.Latest), PublicKey: pk, + WarpSigner: warp.NewSigner(sk, networkID, chainID), Log: logging.NoLog{}, BCLookup: ids.NewAliaser(), Metrics: metrics.NewPrefixGatherer(), ChainDataDir: "", ValidatorState: NewTestValidatorState(), } + + aliaser := ctx.BCLookup.(ids.Aliaser) + _ = aliaser.Alias(testCChainID, "C") + _ = aliaser.Alias(testCChainID, testCChainID.String()) + _ = aliaser.Alias(testXChainID, "X") + _ = aliaser.Alias(testXChainID, testXChainID.String()) + + return ctx } func NewTestValidatorState() *validatorstest.State { @@ -43,8 +65,22 @@ func NewTestValidatorState() *validatorstest.State { GetCurrentHeightF: func(context.Context) (uint64, error) { return 0, nil }, + GetSubnetIDF: func(_ context.Context, chainID ids.ID) (ids.ID, error) { + subnetID, ok := map[ids.ID]ids.ID{ + constants.PlatformChainID: constants.PrimaryNetworkID, + testXChainID: constants.PrimaryNetworkID, + testCChainID: constants.PrimaryNetworkID, + }[chainID] + if !ok { + return ids.Empty, errors.New("unknown chain") + } + return subnetID, nil + }, GetValidatorSetF: func(context.Context, uint64, ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { - return make(map[ids.NodeID]*validators.GetValidatorOutput), nil + return map[ids.NodeID]*validators.GetValidatorOutput{}, nil + }, + GetCurrentValidatorSetF: func(context.Context, ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + return map[ids.ID]*validators.GetCurrentValidatorOutput{}, 0, nil }, } }