From b468bb96bc4474ba777b9bf4ed36022af65a3523 Mon Sep 17 00:00:00 2001 From: Robert Pirtle Date: Mon, 4 Mar 2024 13:42:17 -0800 Subject: [PATCH] make shards inclusive of end block --- config/intervalmap.go | 10 +++++----- config/intervalmap_test.go | 11 +++++----- docker-compose.yml | 4 ++-- service/shard_test.go | 41 ++++++++++++++++++++++++++++++++++---- 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/config/intervalmap.go b/config/intervalmap.go index 09a73e5..07dc531 100644 --- a/config/intervalmap.go +++ b/config/intervalmap.go @@ -7,15 +7,15 @@ import ( // IntervalURLMap stores URLs associated with a range of numbers. // The intervals are defined by their endpoints and must not overlap. -// The intervals are exclusive of the endpoints. +// The intervals are inclusive of the endpoints. type IntervalURLMap struct { UrlByEndHeight map[uint64]*url.URL endpoints []uint64 } // NewIntervalURLMap creates a new IntervalMap from a map of interval endpoint => url. -// The intervals are exclusive of their endpoint. -// ie. if the lowest value endpoint in the map is 10, the interval is for all numbers 1 through 9. +// The intervals are inclusive of their endpoint. +// ie. if the lowest value endpoint in the map is 10, the interval is for all numbers 1 through 10. func NewIntervalURLMap(urlByEndHeight map[uint64]*url.URL) IntervalURLMap { endpoints := make([]uint64, 0, len(urlByEndHeight)) for e := range urlByEndHeight { @@ -31,9 +31,9 @@ func NewIntervalURLMap(urlByEndHeight map[uint64]*url.URL) IntervalURLMap { // Lookup finds the value associated with the interval containing the number, if it exists. func (im *IntervalURLMap) Lookup(num uint64) (*url.URL, uint64, bool) { - i := sort.Search(len(im.endpoints), func(i int) bool { return im.endpoints[i] > num }) + i := sort.Search(len(im.endpoints), func(i int) bool { return im.endpoints[i] >= num }) - if i < len(im.endpoints) && num < im.endpoints[i] { + if i < len(im.endpoints) && num <= im.endpoints[i] { return im.UrlByEndHeight[im.endpoints[i]], im.endpoints[i], true } diff --git a/config/intervalmap_test.go b/config/intervalmap_test.go index 7e9cae0..6a9b24c 100644 --- a/config/intervalmap_test.go +++ b/config/intervalmap_test.go @@ -33,19 +33,20 @@ func TestUnitTestIntervalMap(t *testing.T) { }{ {1, true, 10, "A"}, {9, true, 10, "A"}, - {10, true, 20, "B"}, + {10, true, 10, "A"}, {15, true, 20, "B"}, - {20, true, 100, "C"}, + {20, true, 20, "B"}, {75, true, 100, "C"}, - {100, false, 0, ""}, + {100, true, 100, "C"}, + {101, false, 0, ""}, {300, false, 0, ""}, } for _, tc := range testCases { t.Run(fmt.Sprintf("Lookup(%d)", tc.value), func(t *testing.T) { result, endHeight, found := intervalmap.Lookup(tc.value) - require.Equal(t, tc.expectFound, found) - require.Equal(t, tc.expectEndHeight, endHeight) + require.Equal(t, tc.expectFound, found, "unexpected found value") + require.Equal(t, tc.expectEndHeight, endHeight, "unexpected end height found") if tc.expectResult == "" { require.Nil(t, result) } else { diff --git a/docker-compose.yml b/docker-compose.yml index 020984c..178fba2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,7 +52,7 @@ services: - "${KAVA_CONTAINER_EVM_RPC_PORT}" # shards are in name only. they are standard peer nodes, but will only recieve traffic - # for a specific block range. kava-shard-10 receives requests for heights 1-9 + # for a specific block range. kava-shard-10 receives requests for heights 1-10 kava-shard-10: image: kava/kava:${KAVA_CONTAINER_TAG} entrypoint: /docker/shared/kava-entrypoint.sh @@ -66,7 +66,7 @@ services: - "${KAVA_CONTAINER_EVM_RPC_PORT}" # shards are in name only. they are standard peer nodes, but will only recieve traffic - # for a specific block range. kava-shard-20 receives requests for heights 10-19 + # for a specific block range. kava-shard-20 receives requests for heights 11-20 kava-shard-20: image: kava/kava:${KAVA_CONTAINER_TAG} entrypoint: /docker/shared/kava-entrypoint.sh diff --git a/service/shard_test.go b/service/shard_test.go index 1f9c06a..9927940 100644 --- a/service/shard_test.go +++ b/service/shard_test.go @@ -156,8 +156,8 @@ func TestUnitTest_PruningOrDefaultProxies(t *testing.T) { } require.True(t, found, "expected proxy to be found") require.NotNil(t, proxy) - require.Equal(t, metadata.BackendName, tc.expectBackend) - require.Equal(t, metadata.BackendRoute.String(), tc.expectRoute) + require.Equal(t, tc.expectBackend, metadata.BackendName) + require.Equal(t, tc.expectRoute, metadata.BackendRoute.String()) requireProxyRoutesToUrl(t, proxy, req, tc.expectRoute) }) } @@ -315,6 +315,28 @@ func TestUnitTest_ShardProxies(t *testing.T) { expectBackend: service.ResponseBackendShard, expectRoute: shard1Backend, }, + { + name: "end block of shard 1 routes to shard 1", + url: "//archive.kava.io", + req: &decode.EVMRPCRequestEnvelope{ + Method: "eth_getBlockByNumber", + Params: []interface{}{"0xA", false}, // block 10 + }, + expectFound: true, + expectBackend: service.ResponseBackendShard, + expectRoute: shard1Backend, + }, + { + name: "first block of shard 2 routes to shard 2", + url: "//archive.kava.io", + req: &decode.EVMRPCRequestEnvelope{ + Method: "eth_getBlockByNumber", + Params: []interface{}{"0xB", false}, // block 11 + }, + expectFound: true, + expectBackend: service.ResponseBackendShard, + expectRoute: shard2Backend, + }, { name: "routes to shard 2 for specific height in shard 2", url: "//archive.kava.io", @@ -326,6 +348,17 @@ func TestUnitTest_ShardProxies(t *testing.T) { expectBackend: service.ResponseBackendShard, expectRoute: shard2Backend, }, + { + name: "end block of shard 2 routes to shard 2", + url: "//archive.kava.io", + req: &decode.EVMRPCRequestEnvelope{ + Method: "eth_getBlockByNumber", + Params: []interface{}{"0x14", false}, // block 20 + }, + expectFound: true, + expectBackend: service.ResponseBackendShard, + expectRoute: shard2Backend, + }, } for _, tc := range testCases { @@ -338,8 +371,8 @@ func TestUnitTest_ShardProxies(t *testing.T) { } require.True(t, found, "expected proxy to be found") require.NotNil(t, proxy) - require.Equal(t, metadata.BackendName, tc.expectBackend) - require.Equal(t, metadata.BackendRoute.String(), tc.expectRoute) + require.Equal(t, tc.expectBackend, metadata.BackendName) + require.Equal(t, tc.expectRoute, metadata.BackendRoute.String()) requireProxyRoutesToUrl(t, proxy, req, tc.expectRoute) }) }