From 16bf45a6504f3a1210b23eb5249a54eb07b97ca9 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 31 Jan 2024 18:18:03 -0500 Subject: [PATCH 01/85] Cleanup ID initialization --- ids/id.go | 9 +++++++++ version/constants.go | 36 ++++++++++++------------------------ vms/proposervm/vm.go | 17 ++--------------- 3 files changed, 23 insertions(+), 39 deletions(-) diff --git a/ids/id.go b/ids/id.go index 6cda4b6ec854..91eacfdbd08f 100644 --- a/ids/id.go +++ b/ids/id.go @@ -46,6 +46,15 @@ func FromString(idStr string) (ID, error) { return ToID(bytes) } +// FromStringOrPanic is the same as FromString, but will panic on error +func FromStringOrPanic(idStr string) ID { + id, err := FromString(idStr) + if err != nil { + panic(err) + } + return id +} + func (id ID) MarshalJSON() ([]byte, error) { str, err := cb58.Encode(id[:]) if err != nil { diff --git a/version/constants.go b/version/constants.go index f0b28ab8ac0b..238ae5d8c98b 100644 --- a/version/constants.go +++ b/version/constants.go @@ -123,7 +123,18 @@ var ( constants.MainnetID: time.Date(2023, time.April, 25, 15, 0, 0, 0, time.UTC), constants.FujiID: time.Date(2023, time.April, 6, 15, 0, 0, 0, time.UTC), } - CortinaXChainStopVertexID map[uint32]ids.ID + CortinaXChainStopVertexID = map[uint32]ids.ID{ + // The mainnet stop vertex is well known. It can be verified on any + // fully synced node by looking at the parentID of the genesis block. + // + // Ref: https://subnets.avax.network/x-chain/block/0 + constants.MainnetID: ids.FromStringOrPanic("jrGWDh5Po9FMj54depyunNixpia5PN4aAYxfmNzU8n752Rjga"), + // The fuji stop vertex is well known. It can be verified on any fully + // synced node by looking at the parentID of the genesis block. + // + // Ref: https://subnets-test.avax.network/x-chain/block/0 + constants.FujiID: ids.FromStringOrPanic("2D1cmbiG36BqQMRyHt4kFhWarmatA1ighSpND3FeFgz3vFVtCZ"), + } // TODO: update this before release DurangoTimes = map[uint32]time.Time{ @@ -151,29 +162,6 @@ func init() { } RPCChainVMProtocolCompatibility[rpcChainVMProtocol] = versions } - - // The mainnet stop vertex is well known. It can be verified on any fully - // synced node by looking at the parentID of the genesis block. - // - // Ref: https://subnets.avax.network/x-chain/block/0 - mainnetXChainStopVertexID, err := ids.FromString("jrGWDh5Po9FMj54depyunNixpia5PN4aAYxfmNzU8n752Rjga") - if err != nil { - panic(err) - } - - // The fuji stop vertex is well known. It can be verified on any fully - // synced node by looking at the parentID of the genesis block. - // - // Ref: https://subnets-test.avax.network/x-chain/block/0 - fujiXChainStopVertexID, err := ids.FromString("2D1cmbiG36BqQMRyHt4kFhWarmatA1ighSpND3FeFgz3vFVtCZ") - if err != nil { - panic(err) - } - - CortinaXChainStopVertexID = map[uint32]ids.ID{ - constants.MainnetID: mainnetXChainStopVertexID, - constants.FujiID: fujiXChainStopVertexID, - } } func GetApricotPhase1Time(networkID uint32) time.Time { diff --git a/vms/proposervm/vm.go b/vms/proposervm/vm.go index 9f77a658b55d..111c0922104c 100644 --- a/vms/proposervm/vm.go +++ b/vms/proposervm/vm.go @@ -57,27 +57,14 @@ var ( _ block.StateSyncableVM = (*VM)(nil) // TODO: remove after the X-chain supports height indexing. - mainnetXChainID ids.ID - fujiXChainID ids.ID + mainnetXChainID = ids.FromStringOrPanic("2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM") + fujiXChainID = ids.FromStringOrPanic("2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm") dbPrefix = []byte("proposervm") errHeightIndexInvalidWhilePruning = errors.New("height index invalid while pruning old blocks") ) -func init() { - var err error - mainnetXChainID, err = ids.FromString("2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM") - if err != nil { - panic(err) - } - - fujiXChainID, err = ids.FromString("2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm") - if err != nil { - panic(err) - } -} - func cachedBlockSize(_ ids.ID, blk snowman.Block) int { return ids.IDLen + len(blk.Bytes()) + constants.PointerOverhead } From e8724d1bb62f79ab763cc2756e67494d46406d3b Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 31 Jan 2024 19:04:39 -0500 Subject: [PATCH 02/85] wip --- snow/engine/snowman/bootstrap/bootstrapper.go | 58 +++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 29754a24d734..a96935680521 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -22,6 +22,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/utils/bimap" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer" "github.com/ava-labs/avalanchego/version" @@ -385,19 +386,68 @@ func (b *Bootstrapper) GetAcceptedFailed(ctx context.Context, nodeID ids.NodeID, return b.sendBootstrappingMessagesOrFinish(ctx) } +var knownAcceptedContainerIDs = map[uint32]map[ids.ID][]ids.ID{ + constants.FujiID: { + constants.PlatformChainID: { + ids.FromStringOrPanic("FtwibNbLTvczaCyEH3FqRqTqQ4bTm2ZUKg6RjdttTFCFmxXBr"), // https://subnets-test.avax.network/p-chain/block/130000 + ids.FromStringOrPanic("WvqDHkdLFS8LqtZrsmred5nxPYMRU3mN6pQpEp5kw1FVzV54d"), // https://subnets-test.avax.network/p-chain/block/120000 + ids.FromStringOrPanic("8khC8p1qYwWB5QoEXyQM4p8pRpirYMfb8HiM8k7nSbFHthRej"), // https://subnets-test.avax.network/p-chain/block/110000 + ids.FromStringOrPanic("2sDGZLbsjRRfLQHnsjp2fZ7bZNGihV5TJsxTAKXxna9tjQDLc"), // https://subnets-test.avax.network/p-chain/block/100000 + ids.FromStringOrPanic("uMvcoswATF22hc4YLNHTaEFqEz2bZdCM9q5HjVZEnhrnhRpTa"), // https://subnets-test.avax.network/p-chain/block/090000 + ids.FromStringOrPanic("VPV9gaqfhvggdWe8bEvPxmS5ZmsWe7Y8iFBd9mrzhdYn3GAYG"), // https://subnets-test.avax.network/p-chain/block/080000 + ids.FromStringOrPanic("2VmRST6sy1E9wandsgod7DH2ToenvmUaoDw54EnR2uGj6yzoY3"), // https://subnets-test.avax.network/p-chain/block/070000 + ids.FromStringOrPanic("C6TbmVqoFhKZPB5aqqScRRvL6f3W4zKagAA7vfVdARxpJfMkU"), // https://subnets-test.avax.network/p-chain/block/060000 + ids.FromStringOrPanic("euNKcrcf1EeDEiRrQtdEL7kj9a6CDjZXWMys7SLNYmu6eLhyj"), // https://subnets-test.avax.network/p-chain/block/050000 + ids.FromStringOrPanic("27UyZ7cK8Z4hieP9v7vt8nVzUWWG8dTevG4KG8bD1tdcW1WyLg"), // https://subnets-test.avax.network/p-chain/block/040000 + ids.FromStringOrPanic("L472PqnP7C3n6ChqhuUePDWVsspx7J1Akbywuqub22qMqkV4r"), // https://subnets-test.avax.network/p-chain/block/030000 + ids.FromStringOrPanic("2atCgGVNqVEPFxeXkPx5efYbzPMRHnj4oaiNJmYgTMx2sRH1S1"), // https://subnets-test.avax.network/p-chain/block/020000 + ids.FromStringOrPanic("2JSAgjJYve7X8DGVfffpK3BcaToQhMoJZ99XjM4E2t7ddDuA9Q"), // https://subnets-test.avax.network/p-chain/block/010000 + }, + }, + constants.MainnetID: { + constants.PlatformChainID: { + ids.FromStringOrPanic("eZpu3i8otKKBEt1DRcM2cwJ1b6NeZV7QRsHbG17rjmjYjERwU"), // https://subnets.avax.network/p-chain/block/11000000 + ids.FromStringOrPanic("2u1ccTx2BD8mrTf5dcLifCxGhUm82GD7qvW786V76S3dqe4Q9q"), // https://subnets.avax.network/p-chain/block/10500000 + ids.FromStringOrPanic("BP6HSddREevAhZ1axVWS33kAJvz3gk1pjL2zkY548xRBvEpAg"), // https://subnets.avax.network/p-chain/block/10000000 + ids.FromStringOrPanic("AZz8jyYj3pfTT7TsTPBKiKB5ByxfUZu2ZsNFUYobAKyN5eFQ5"), // https://subnets.avax.network/p-chain/block/09500000 + ids.FromStringOrPanic("nTXX6XCNeRA7RqAY658a91tf5NjwsgZyhDshvWsjDooik6w3o"), // https://subnets.avax.network/p-chain/block/09000000 + ids.FromStringOrPanic("s8u9dvLEXQSjvhvo5Lp5qgDH8CiMnfimVEkjjKrLiiLgDBNB4"), // https://subnets.avax.network/p-chain/block/08500000 + ids.FromStringOrPanic("2pE1vB9HxPVhxgR2WS98jvcGygQzg9kaTkxyZ5E9BiTG9a5FG4"), // https://subnets.avax.network/p-chain/block/08000000 + ids.FromStringOrPanic("7HzrVujhGqLG8tJANXtNr8brT6ByyEutN6d1eTN3ixrC7jRcS"), // https://subnets.avax.network/p-chain/block/07500000 + ids.FromStringOrPanic("2kLaFPNUZBcgxv7Agff2VaxwEmCeZwf1Zr99rVPU7BXc4mLzbZ"), // https://subnets.avax.network/p-chain/block/07000000 + ids.FromStringOrPanic("tEPEYtZkM4A47xxyZRNDRAQrHN4a2Y5j65rfzDTTKdW2ovnjw"), // https://subnets.avax.network/p-chain/block/06500000 + ids.FromStringOrPanic("2o5CQWZY1uViNW3ejoTc6bhtoacDhH2TcEZdk1k3gqew7qtAq8"), // https://subnets.avax.network/p-chain/block/06000000 + ids.FromStringOrPanic("2TpCtdtrMdQQSeUxbSoS7jp8EbmRhwDPuR71jLYkc6y7r5LPN"), // https://subnets.avax.network/p-chain/block/05500000 + ids.FromStringOrPanic("X9X4kPTriRrNb1Hui9nT7XnQAN5RdMjoBVwaWsKdM2mLpjqmk"), // https://subnets.avax.network/p-chain/block/05000000 + ids.FromStringOrPanic("2GF21ZWpvqaC1u1REKeDeaRHopLRiHvNN7nGrFzZwAyXVMnQtt"), // https://subnets.avax.network/p-chain/block/04500000 + ids.FromStringOrPanic("2ute95hYkTBrcNRQW7oVbhTP8t3HqqbRfrxAt7BT8Thf48c2RD"), // https://subnets.avax.network/p-chain/block/04000000 + ids.FromStringOrPanic("XBeyojZENqRmjWbWiMYRZJmpeZdCEryL6iLPDzs9Bp3jaQ6g6"), // https://subnets.avax.network/p-chain/block/03500000 + ids.FromStringOrPanic("JAykub6SHtfsAxpeCsQfkujLYwVsAm1N6wnKeMn8Dxykys7dP"), // https://subnets.avax.network/p-chain/block/03000000 + ids.FromStringOrPanic("2dR4yFxErqppuhWGfZD1SHjryN6A8ajR7B8DJ2b26X7Z4qTHyY"), // https://subnets.avax.network/p-chain/block/02500000 + ids.FromStringOrPanic("2oTyxikDac4xpCdzmSBHZAgfxRhYt98NENpUqriQKJPHek6pdv"), // https://subnets.avax.network/p-chain/block/02000000 + ids.FromStringOrPanic("9bhZfjd4jo2pgJS3sVtvwRiQzx7k4gFiabskD1Gka1Z6F4huh"), // https://subnets.avax.network/p-chain/block/01500000 + ids.FromStringOrPanic("2PdY2BgLwvSk8jpuyVn2j1rwDqKbUATQGDpqxuwgdpziHUPPdt"), // https://subnets.avax.network/p-chain/block/01000000 + ids.FromStringOrPanic("vKBoQUUGnbQoHtHqxg7RVwBZxbBkPrQqrSamSevcsZKRif3Ad"), // https://subnets.avax.network/p-chain/block/00500000 + }, + }, +} + func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs []ids.ID) error { // Initialize the fetch from set to the currently preferred peers b.fetchFrom = b.StartupTracker.PreferredPeers() + knownContainerIDs := knownAcceptedContainerIDs[b.Ctx.NetworkID][b.Ctx.ChainID] pendingContainerIDs := b.Blocked.MissingIDs() - // Append the list of accepted container IDs to pendingContainerIDs to ensure - // we iterate over every container that must be traversed. - pendingContainerIDs = append(pendingContainerIDs, acceptedContainerIDs...) - b.Ctx.Log.Debug("starting bootstrapping", + b.Ctx.Log.Warn("starting bootstrapping", + zap.Int("numKnownBlocks", len(knownContainerIDs)), zap.Int("numPendingBlocks", len(pendingContainerIDs)), zap.Int("numAcceptedBlocks", len(acceptedContainerIDs)), ) + pendingContainerIDs = append(pendingContainerIDs, acceptedContainerIDs...) + pendingContainerIDs = append(pendingContainerIDs, knownContainerIDs...) + // Append the list of accepted container IDs to pendingContainerIDs to ensure + // we iterate over every container that must be traversed. toProcess := make([]snowman.Block, 0, len(pendingContainerIDs)) for _, blkID := range pendingContainerIDs { b.Blocked.AddMissingID(blkID) From 5f18895967f7e9fb6a2d1435b515f13dfc0872c7 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Sat, 10 Feb 2024 19:30:32 -0500 Subject: [PATCH 03/85] wip --- chains/manager.go | 24 ++++-- .../snowman/bootstrap/bootstrapper_test.go | 80 ++++++++++++++----- snow/engine/snowman/bootstrap/config.go | 3 + vms/platformvm/vm_test.go | 24 ++++-- 4 files changed, 99 insertions(+), 32 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index 8d63db69f9cb..444bfc177b96 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -28,7 +28,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" "github.com/ava-labs/avalanchego/network" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/avalanche/state" "github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex" @@ -63,6 +63,7 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/vms/tracedvm" + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" smcon "github.com/ava-labs/avalanchego/snow/consensus/snowman" aveng "github.com/ava-labs/avalanchego/snow/engine/avalanche" avbootstrap "github.com/ava-labs/avalanchego/snow/engine/avalanche/bootstrap" @@ -583,7 +584,7 @@ func (m *manager) createAvalancheChain( defer ctx.Lock.Unlock() ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + Type: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, State: snow.Initializing, }) @@ -618,7 +619,7 @@ func (m *manager) createAvalancheChain( m.Net, m.ManagerConfig.Router, m.TimeoutManager, - p2p.EngineType_ENGINE_TYPE_AVALANCHE, + p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, sb, ) if err != nil { @@ -646,7 +647,7 @@ func (m *manager) createAvalancheChain( m.Net, m.ManagerConfig.Router, m.TimeoutManager, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, sb, ) if err != nil { @@ -814,6 +815,17 @@ func (m *manager) createAvalancheChain( } vdrs.RegisterCallbackListener(ctx.SubnetID, connectedValidators) + peerTracker, err := p2p.NewPeerTracker( + ctx.Log, + "peer_tracker", + ctx.Registerer, + set.Of(ctx.NodeID), + nil, + ) + if err != nil { + return nil, fmt.Errorf("error creating peer tracker: %w", err) + } + // Asynchronously passes messages from the network to the consensus engine h, err := handler.New( ctx, @@ -986,7 +998,7 @@ func (m *manager) createSnowmanChain( defer ctx.Lock.Unlock() ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Initializing, }) @@ -1010,7 +1022,7 @@ func (m *manager) createSnowmanChain( m.Net, m.ManagerConfig.Router, m.TimeoutManager, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, sb, ) if err != nil { diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index d5cb9cc763fc..7f3de46213c0 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -16,7 +16,7 @@ import ( "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" @@ -31,6 +31,8 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/version" + + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" ) var errUnknownBlock = errors.New("unknown block") @@ -68,10 +70,9 @@ func newConfig(t *testing.T) (Config, ids.NodeID, *common.SenderTest, *block.Tes peer := ids.GenerateTestNodeID() require.NoError(vdrs.AddStaker(ctx.SubnetID, peer, nil, ids.Empty, 1)) - peerTracker := tracker.NewPeers() totalWeight, err := vdrs.TotalWeight(ctx.SubnetID) require.NoError(err) - startupTracker := tracker.NewStartup(peerTracker, totalWeight/2+1) + startupTracker := tracker.NewStartup(tracker.NewPeers(), totalWeight/2+1) vdrs.RegisterCallbackListener(ctx.SubnetID, startupTracker) require.NoError(startupTracker.Connected(context.Background(), peer, version.CurrentApp)) @@ -79,13 +80,27 @@ func newConfig(t *testing.T) (Config, ids.NodeID, *common.SenderTest, *block.Tes snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) require.NoError(err) - blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) + blocker, err := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) + require.NoError(err) + + peerTracker, err := p2p.NewPeerTracker( + ctx.Log, + "", + prometheus.NewRegistry(), + nil, + nil, + ) + require.NoError(err) + + peerTracker.Connected(peer, version.CurrentApp) + return Config{ AllGetsServer: snowGetHandler, Ctx: ctx, Beacons: vdrs, SampleK: vdrs.Count(ctx.SubnetID), StartupTracker: startupTracker, + PeerTracker: peerTracker, Sender: sender, BootstrapTracker: bootstrapTracker, Timer: &common.TimerTest{}, @@ -113,19 +128,29 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { alpha := uint64(10) startupAlpha := alpha - peerTracker := tracker.NewPeers() - startupTracker := tracker.NewStartup(peerTracker, startupAlpha) + startupTracker := tracker.NewStartup(tracker.NewPeers(), startupAlpha) peers.RegisterCallbackListener(ctx.SubnetID, startupTracker) blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) require.NoError(err) + + peerTracker, err := p2p.NewPeerTracker( + ctx.Log, + "", + prometheus.NewRegistry(), + nil, + nil, + ) + require.NoError(err) + cfg := Config{ AllGetsServer: snowGetHandler, Ctx: ctx, Beacons: peers, SampleK: sampleK, StartupTracker: startupTracker, + PeerTracker: peerTracker, Sender: sender, BootstrapTracker: &common.BootstrapTrackerTest{}, Timer: &common.TimerTest{}, @@ -156,7 +181,7 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { // create bootstrapper dummyCallback := func(context.Context, uint32) error { cfg.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -183,6 +208,8 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { // attempt starting bootstrapper with not enough stake connected. Bootstrapper should stall. vdr0 := ids.GenerateTestNodeID() require.NoError(peers.AddStaker(ctx.SubnetID, vdr0, nil, ids.Empty, startupAlpha/2)) + + peerTracker.Connected(vdr0, version.CurrentApp) require.NoError(bs.Connected(context.Background(), vdr0, version.CurrentApp)) require.NoError(bs.Start(context.Background(), 0)) @@ -191,6 +218,8 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { // finally attempt starting bootstrapper with enough stake connected. Frontiers should be requested. vdr := ids.GenerateTestNodeID() require.NoError(peers.AddStaker(ctx.SubnetID, vdr, nil, ids.Empty, startupAlpha)) + + peerTracker.Connected(vdr, version.CurrentApp) require.NoError(bs.Connected(context.Background(), vdr, version.CurrentApp)) require.True(frontierRequested) } @@ -238,7 +267,7 @@ func TestBootstrapperSingleFrontier(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -336,7 +365,7 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -468,7 +497,7 @@ func TestBootstrapperPartialFetch(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -615,7 +644,7 @@ func TestBootstrapperEmptyResponse(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -778,7 +807,7 @@ func TestBootstrapperAncestors(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -906,7 +935,7 @@ func TestBootstrapperFinalized(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -1105,7 +1134,7 @@ func TestRestartBootstrapping(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -1213,7 +1242,7 @@ func TestBootstrapOldBlockAfterStateSync(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -1282,7 +1311,7 @@ func TestBootstrapContinueAfterHalt(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -1345,10 +1374,9 @@ func TestBootstrapNoParseOnNew(t *testing.T) { peer := ids.GenerateTestNodeID() require.NoError(peers.AddStaker(ctx.SubnetID, peer, nil, ids.Empty, 1)) - peerTracker := tracker.NewPeers() totalWeight, err := peers.TotalWeight(ctx.SubnetID) require.NoError(err) - startupTracker := tracker.NewStartup(peerTracker, totalWeight/2+1) + startupTracker := tracker.NewStartup(tracker.NewPeers(), totalWeight/2+1) peers.RegisterCallbackListener(ctx.SubnetID, startupTracker) require.NoError(startupTracker.Connected(context.Background(), peer, version.CurrentApp)) @@ -1400,12 +1428,24 @@ func TestBootstrapNoParseOnNew(t *testing.T) { blocker, err = queue.NewWithMissing(queueDB, "", prometheus.NewRegistry()) require.NoError(err) + peerTracker, err := p2p.NewPeerTracker( + ctx.Log, + "", + prometheus.NewRegistry(), + nil, + nil, + ) + require.NoError(err) + + peerTracker.Connected(peer, version.CurrentApp) + config := Config{ AllGetsServer: snowGetHandler, Ctx: ctx, Beacons: peers, SampleK: peers.Count(ctx.SubnetID), StartupTracker: startupTracker, + PeerTracker: peerTracker, Sender: sender, BootstrapTracker: bootstrapTracker, Timer: &common.TimerTest{}, @@ -1418,7 +1458,7 @@ func TestBootstrapNoParseOnNew(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil @@ -1480,7 +1520,7 @@ func TestBootstrapperReceiveStaleAncestorsMessage(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) return nil diff --git a/snow/engine/snowman/bootstrap/config.go b/snow/engine/snowman/bootstrap/config.go index 6fb8894db96f..708a2f5a0f6e 100644 --- a/snow/engine/snowman/bootstrap/config.go +++ b/snow/engine/snowman/bootstrap/config.go @@ -4,6 +4,7 @@ package bootstrap import ( + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/common/queue" @@ -24,6 +25,8 @@ type Config struct { BootstrapTracker common.BootstrapTracker Timer common.Timer + PeerTracker *p2p.PeerTracker + // This node will only consider the first [AncestorsMaxContainersReceived] // containers in an ancestors message it receives. AncestorsMaxContainersReceived int diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index ac4926a4160a..5f4e89ceb0bf 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -20,7 +20,7 @@ import ( "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowball" @@ -61,6 +61,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" smcon "github.com/ava-labs/avalanchego/snow/consensus/snowman" smeng "github.com/ava-labs/avalanchego/snow/engine/snowman" snowgetter "github.com/ava-labs/avalanchego/snow/engine/snowman/getter" @@ -1375,7 +1376,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { externalSender, chainRouter, timeoutManager, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, subnets.New(consensusCtx.NodeID, subnets.Config{GossipConfig: gossipConfig}), ) require.NoError(err) @@ -1408,12 +1409,22 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { ) require.NoError(err) + peerTracker, err := p2p.NewPeerTracker( + consensusCtx.Log, + "", + prometheus.NewRegistry(), + nil, + nil, + ) + require.NoError(err) + bootstrapConfig := bootstrap.Config{ AllGetsServer: snowGetHandler, Ctx: consensusCtx, Beacons: beacons, SampleK: beacons.Count(ctx.SubnetID), StartupTracker: startup, + PeerTracker: peerTracker, Sender: sender, BootstrapTracker: bootstrapTracker, AncestorsMaxContainersReceived: 2000, @@ -1485,7 +1496,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { }) consensusCtx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, }) @@ -1509,13 +1520,14 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { return nodeIDs } + peerTracker.Connected(peerID, version.CurrentApp) require.NoError(bootstrapper.Connected(context.Background(), peerID, version.CurrentApp)) externalSender.SendF = func(msg message.OutboundMessage, nodeIDs set.Set[ids.NodeID], _ ids.ID, _ subnets.Allower) set.Set[ids.NodeID] { inMsgIntf, err := mc.Parse(msg.Bytes(), ctx.NodeID, func() {}) require.NoError(err) require.Equal(message.GetAcceptedOp, inMsgIntf.Op()) - inMsg := inMsgIntf.Message().(*p2p.GetAccepted) + inMsg := inMsgIntf.Message().(*p2ppb.GetAccepted) reqID = inMsg.RequestId return nodeIDs @@ -1527,7 +1539,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { inMsgIntf, err := mc.Parse(msg.Bytes(), ctx.NodeID, func() {}) require.NoError(err) require.Equal(message.GetAncestorsOp, inMsgIntf.Op()) - inMsg := inMsgIntf.Message().(*p2p.GetAncestors) + inMsg := inMsgIntf.Message().(*p2ppb.GetAncestors) reqID = inMsg.RequestId @@ -1558,7 +1570,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { inMsgIntf, err := mc.Parse(msg.Bytes(), ctx.NodeID, func() {}) require.NoError(err) require.Equal(message.GetAcceptedOp, inMsgIntf.Op()) - inMsg := inMsgIntf.Message().(*p2p.GetAccepted) + inMsg := inMsgIntf.Message().(*p2ppb.GetAccepted) reqID = inMsg.RequestId return nodeIDs From d016bae0714939803b16d443c79cf06f45fa2e34 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 19 Feb 2024 17:13:03 -0500 Subject: [PATCH 04/85] Add checkpoints and validators --- genesis/checkpoints.go | 35 + genesis/checkpoints.json | 120 ++ genesis/generate/checkpoints/main.go | 111 ++ genesis/generate/validators/main.go | 64 + genesis/validators.go | 34 + genesis/validators.json | 2459 ++++++++++++++++++++++++++ 6 files changed, 2823 insertions(+) create mode 100644 genesis/checkpoints.go create mode 100644 genesis/checkpoints.json create mode 100644 genesis/generate/checkpoints/main.go create mode 100644 genesis/generate/validators/main.go create mode 100644 genesis/validators.go create mode 100644 genesis/validators.json diff --git a/genesis/checkpoints.go b/genesis/checkpoints.go new file mode 100644 index 000000000000..f2e39a282860 --- /dev/null +++ b/genesis/checkpoints.go @@ -0,0 +1,35 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package genesis + +import ( + "encoding/json" + "fmt" + + _ "embed" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/set" +) + +var ( + //go:embed checkpoints.json + checkpointsPerNetworkJSON []byte + + checkpointsPerNetwork map[string]map[ids.ID]set.Set[ids.ID] +) + +func init() { + if err := json.Unmarshal(checkpointsPerNetworkJSON, &checkpointsPerNetwork); err != nil { + panic(fmt.Sprintf("failed to decode checkpoints.json %v", err)) + } +} + +// GetCheckpoints returns all specified checkpoints for the chain on the +// requested network. +func GetCheckpoints(networkID uint32, chainID ids.ID) set.Set[ids.ID] { + networkName := constants.NetworkIDToNetworkName[networkID] + return checkpointsPerNetwork[networkName][chainID] +} diff --git a/genesis/checkpoints.json b/genesis/checkpoints.json new file mode 100644 index 000000000000..df8dae2577fa --- /dev/null +++ b/genesis/checkpoints.json @@ -0,0 +1,120 @@ +{ + "fuji": { + "11111111111111111111111111111111LpoYY": [ + "27UyZ7cK8Z4hieP9v7vt8nVzUWWG8dTevG4KG8bD1tdcW1WyLg", + "2JSAgjJYve7X8DGVfffpK3BcaToQhMoJZ99XjM4E2t7ddDuA9Q", + "2VmRST6sy1E9wandsgod7DH2ToenvmUaoDw54EnR2uGj6yzoY3", + "2atCgGVNqVEPFxeXkPx5efYbzPMRHnj4oaiNJmYgTMx2sRH1S1", + "2sDGZLbsjRRfLQHnsjp2fZ7bZNGihV5TJsxTAKXxna9tjQDLc", + "8khC8p1qYwWB5QoEXyQM4p8pRpirYMfb8HiM8k7nSbFHthRej", + "C6TbmVqoFhKZPB5aqqScRRvL6f3W4zKagAA7vfVdARxpJfMkU", + "FtwibNbLTvczaCyEH3FqRqTqQ4bTm2ZUKg6RjdttTFCFmxXBr", + "L472PqnP7C3n6ChqhuUePDWVsspx7J1Akbywuqub22qMqkV4r", + "VPV9gaqfhvggdWe8bEvPxmS5ZmsWe7Y8iFBd9mrzhdYn3GAYG", + "WvqDHkdLFS8LqtZrsmred5nxPYMRU3mN6pQpEp5kw1FVzV54d", + "euNKcrcf1EeDEiRrQtdEL7kj9a6CDjZXWMys7SLNYmu6eLhyj", + "uMvcoswATF22hc4YLNHTaEFqEz2bZdCM9q5HjVZEnhrnhRpTa" + ], + "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm": [ + "2pCJ9gCnbCFC8e1xQNYgu63XQzCLqp9uupk7ePgDX3vWvwoPGb", + "3oxSU7pEZzr7MMSBLeWprp1e851JtwHT4YCvEzs4vzamAVCfj" + ], + "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp": [ + "21JL6NSfcwJWCtKqAV5fEzvcjXiDFbPJBqtNgWVmRphHQmp3K2", + "26ARTBTnBpALjtK4VcWbqE8GDwasYuHaCrpa4RBjrnxxurjaks", + "29yzKYLoKaDDbhTa4ugM91Q8fN2FWFXHwjFC4XhgFfPunc7xfA", + "2CTwkS8TRfNK91mRDV2Mtdm3vpCYWMSuTG6M6rS55M3MKrL3x", + "2Dm1gkhRHzc4VFDDFnPPc7SmbUngx9wEuDzrnx9nTXjB61oeDY", + "2KpmUTDDnrC7CS3dBZcD93gjrESwBiGQNw8ghgi6dQpcZvL7gX", + "2KwiBuGqgTpp5WFbYZgmEQsj37i8eEEyMNdrcwQCNzdWN34iUY", + "2QuQiJETyN82sicpwNVzoRNvs3eX7sQCiFE4XPHUCm5oVHoYYt", + "2Ts7VC5VUyJ6ug6KkzB7UdS5bPofkJAwscJNsH1KkiZzhdRXhm", + "2VD38bY9Mv17HhpbSGmvuXBCMuS85Fio4bk9uE5dktPtCjomJa", + "2cTVk64L5Ewbmz2xEjd2Yu9UznptZ3MW9EhELJvZYYi5XxCCgc", + "2jagCcJ1AtDZ3ksqbEs6F9TEXRn3YfSNNeGQsZwb8Wdzn24V81", + "2osF1mZCzHBn4kwfSi4hgDvcSDoB5X2yLFs7Cs3nikXQzd11un", + "2rnF1eYbGkFtm188NAqmAjGFS5Chn7wfDW4cmSerotZ3v7xhv6", + "59PZZ1DKTgCJza1xjgvKekfx3P61eypedPwWSsLTUmifppVZk", + "5EvUT2oCwMq33k1owWySBRbEWEXMbiKugZgNXUTgQUsjxyTPu", + "63JVNPfXguA6998RSH43eMdo6TrCLCd99ds8v5Ujmwp9pUacP", + "Esd2dUPSeKZvbFkJpeYxuDwL21HmWVtZ2bQc2d1XdpWVcmkuT", + "FpNdqmJfv3Lrct7UhieXaXYpAKyVmVuSbchJxUeBtpWaCqtm4", + "HJGuD27nX4RQnddgEMfpLtoiWEwjGYTqNMVcmrciZFTTCsDyj", + "JEde81vDS4Rvj9wbyDsAnRQ7N8YnxbXQojJaHTJk2i4dZqsbw", + "KmkaqscUQAZaWwvsawoMcHerGYZCJeE73wWSGhPV3GfsyYPMZ", + "NpeZvNuau3tgZY6b8qtsX8PFqbnFMesmHEy2GCAEq2k9KtWtV", + "ahtk5oCozDQDq9mkrJXDEtrSnc8gtCnEnqKb3aRKaVBcN58rK", + "hUqmvoNFTtArkS5n3PWeXUFoYdAFbMyxo545KE6uPtbQZ5H6F", + "jJwCiWtk3e3MxwjE4J5APR86Fgxkct9QDG38tBpvMc6LSk2dS", + "kB61R92fKJUxxSQPj5nMH5SMrHFBSbs7WgCVSF5Ha4WR69DhB", + "mka4V1BeCAUmLVki5YGLXSqXFZH5kzL2xGcueN64yVP8wmFB3", + "vad1jee6EYvjDKPgdQGW8dQ8C4CMqaefUPEbyE1yxfrjbQa2z", + "xD43ndAQFfo1RmRi3cHH6TDfGNPkR6bZR716NgB9mQx5eBXg9" + ] + }, + "mainnet": { + "11111111111111111111111111111111LpoYY": [ + "2GF21ZWpvqaC1u1REKeDeaRHopLRiHvNN7nGrFzZwAyXVMnQtt", + "2PdY2BgLwvSk8jpuyVn2j1rwDqKbUATQGDpqxuwgdpziHUPPdt", + "2TpCtdtrMdQQSeUxbSoS7jp8EbmRhwDPuR71jLYkc6y7r5LPN", + "2dR4yFxErqppuhWGfZD1SHjryN6A8ajR7B8DJ2b26X7Z4qTHyY", + "2kLaFPNUZBcgxv7Agff2VaxwEmCeZwf1Zr99rVPU7BXc4mLzbZ", + "2o5CQWZY1uViNW3ejoTc6bhtoacDhH2TcEZdk1k3gqew7qtAq8", + "2oTyxikDac4xpCdzmSBHZAgfxRhYt98NENpUqriQKJPHek6pdv", + "2pE1vB9HxPVhxgR2WS98jvcGygQzg9kaTkxyZ5E9BiTG9a5FG4", + "2u1ccTx2BD8mrTf5dcLifCxGhUm82GD7qvW786V76S3dqe4Q9q", + "2ute95hYkTBrcNRQW7oVbhTP8t3HqqbRfrxAt7BT8Thf48c2RD", + "7HzrVujhGqLG8tJANXtNr8brT6ByyEutN6d1eTN3ixrC7jRcS", + "9HTMRKfXuzq3KVrKF7EEzXouDcB1M3asCexNqtJDg8CCGdMd4", + "9bhZfjd4jo2pgJS3sVtvwRiQzx7k4gFiabskD1Gka1Z6F4huh", + "AZz8jyYj3pfTT7TsTPBKiKB5ByxfUZu2ZsNFUYobAKyN5eFQ5", + "BP6HSddREevAhZ1axVWS33kAJvz3gk1pjL2zkY548xRBvEpAg", + "JAykub6SHtfsAxpeCsQfkujLYwVsAm1N6wnKeMn8Dxykys7dP", + "X9X4kPTriRrNb1Hui9nT7XnQAN5RdMjoBVwaWsKdM2mLpjqmk", + "XBeyojZENqRmjWbWiMYRZJmpeZdCEryL6iLPDzs9Bp3jaQ6g6", + "eZpu3i8otKKBEt1DRcM2cwJ1b6NeZV7QRsHbG17rjmjYjERwU", + "nTXX6XCNeRA7RqAY658a91tf5NjwsgZyhDshvWsjDooik6w3o", + "s8u9dvLEXQSjvhvo5Lp5qgDH8CiMnfimVEkjjKrLiiLgDBNB4", + "tEPEYtZkM4A47xxyZRNDRAQrHN4a2Y5j65rfzDTTKdW2ovnjw", + "vKBoQUUGnbQoHtHqxg7RVwBZxbBkPrQqrSamSevcsZKRif3Ad" + ], + "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM": [ + "25V23ZbFXr6qmZkmGaNGppRpRHqsUc5NXd7ack8aBPLiV7tRNF", + "25g4kcd6N7sv3NNkgrkujCAf2riouW4JA8LpjUg6qvzxDL9Tsd", + "2Mrm9TNbJhrMUzxwDtitH8LGTSfhjZVbVNsFMugddtAdAsaqFe", + "2Qny7y4zUEaEPghMg9axqfiFjWfEGx9ok4FzCumRGzN3eTrb33", + "2RioJaHRz883cJP87uaBQtnXMLesJorUP3yBw3AnDXBEy9jkSF", + "2d7hQSDVrMXEWwM65g4g7vC7SFYEhiRU8DRVcwR79Rdyy4LWJA", + "2umyLtWu9HKcKLFfHvPJ4Cw6Fh2P7ngbPMkqVK6EdAKa6JN9b6", + "7anFSrdJvD3dkRwJciEZXiuzjUtpt5NpRaAM6RuHEyQxJh7TU", + "DVXavgfkgeQpKh7BgGazfiiYC9frsdx7mipc2DJ8yy7cwhEPV", + "KzkUEjrBkGHgCgPqNv43dFWZBHN8J6cLTfvoAbPy97zHcdLyj", + "eNisZEUqAyeeNLXVUn1wfLqFf1D5a3AELz8KnoR3tj1kcrMTr", + "k54VutZaDA35VeCi9yAegWcfU9qVcnABJeax3BQM7bCrSQUD2", + "qkcnLHCgtJkFLcANQNRE7gdzG1UzBGhhek8ZJrVbAQDGuYMGt", + "tQHZwERneSsvkrgx3d8b22991SaSamxdARCcQzd2mZMbr2KrJ" + ], + "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5": [ + "25XhJmnidUnsWFGhrsgPhnwVV74vYNsRmPtr65xg7Spy6bqU6e", + "26nQJbkaALi5wZF6fKgcUbip5rK6DqKkuDu2rprUWAzGATP3mo", + "2HTKTdMGHTyUacDfzmEDs2fKVdzuumBkTFY2Rgkjt1yZPJhoCp", + "2JS1SKHSFNZnfVcyRCRXYmAsL4WMUc4TskwzY9w3r2t5GapDoN", + "2LZzxHPxKAkauVPf7Pn43SBQT46xDrbPTUBwnDwicaVSy1WgzL", + "2NpqFckbrnbZgGzw8sh1a9F1EAB6VLjFhPcnjTLoPdR26wWoq9", + "2XojhYy1mNkdmFZoCNvycB9QgXDHmFK53Qvc5iGk6e11kQbY6Q", + "2dwqBWd3P1h5Bzm3dhhqUiNizmHfYekAQK8qNVgpNooArjhfhG", + "2fXeVYeAFqSrBnKjQ2ubVvdxSTePDNpUbURjKwvHP4gs9RtoUu", + "2jupSbpuugeUd3Q9BAp7G7inHqBtjhh4mY7hi491bGXcp6V4fY", + "2suYWABBH4yE4UjMc1TzrZcgsNrQMy1rJcG6p7ckSQLk6e1ubq", + "2v45JaLJXdA1t2WPDYFxiieuX5cQ8oKF7pn9TqHJpoaBRkRNPG", + "A2bq6adFZmnizLXFS6yvLRXA74RfhrqJWAXZAJ4CzA8YtS5ot", + "NcaZhSi2DF9nhXsmaHRmHZQp7DaNdk54gLsa1w39bfZGUCkNN", + "NtbdHLdfQWeWqSdM1ZYQNfeFy39RoEzyfDZcdFTQpTYtf2S2o", + "PgHyVD222KcxHkBeoc41PH64dHRykyUo9fLT171VGMBh6xJy3", + "YW7BB7uo9wQwfC6kJ6JgGzarbtYm9s9a4mgUy9qrmwUCjq1KU", + "gTjiLnQCWjK4jWMbY2Do2VBoAERc2QuCqoghAVfhPceaKCysa", + "hLikKEdcco5VdxGpLyHW7PWw2X2rc7QBVpivuKtnDzLid73X4", + "hMkwsrAepCYKMc54s9b2pbGEf9wMQMND8Ek1dANNLEEwQAaQb" + ] + } +} \ No newline at end of file diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go new file mode 100644 index 000000000000..22878482c783 --- /dev/null +++ b/genesis/generate/checkpoints/main.go @@ -0,0 +1,111 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/indexer" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/perms" + "github.com/ava-labs/avalanchego/utils/set" +) + +const ( + fujiURI = "http://localhost:9650" + mainnetURI = "http://localhost:9660" +) + +var ( + fujiXChainID = ids.FromStringOrPanic("2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm") + fujiCChainID = ids.FromStringOrPanic("yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp") + mainnetXChainID = ids.FromStringOrPanic("2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM") + mainnetCChainID = ids.FromStringOrPanic("2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5") +) + +// This example program continuously polls for the next X-Chain block +// and prints the ID of the block and its transactions. +func main() { + ctx := context.Background() + + fujiPChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "P", 10_000) + if err != nil { + log.Fatalf("failed to fetch Fuji P-chain checkpoints: %v", err) + } + fujiXChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "X", 10_000) + if err != nil { + log.Fatalf("failed to fetch Fuji X-chain checkpoints: %v", err) + } + fujiCChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "C", 1_000_000) + if err != nil { + log.Fatalf("failed to fetch Fuji C-chain checkpoints: %v", err) + } + + mainnetPChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "P", 500_000) + if err != nil { + log.Fatalf("failed to fetch Mainnet P-chain checkpoints: %v", err) + } + mainnetXChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "X", 20_000) + if err != nil { + log.Fatalf("failed to fetch Mainnet X-chain checkpoints: %v", err) + } + mainnetCChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "C", 2_000_000) + if err != nil { + log.Fatalf("failed to fetch Mainnet C-chain checkpoints: %v", err) + } + + checkpoints := map[string]map[ids.ID]set.Set[ids.ID]{ + constants.FujiName: { + constants.PlatformChainID: fujiPChainCheckpoints, + fujiXChainID: fujiXChainCheckpoints, + fujiCChainID: fujiCChainCheckpoints, + }, + constants.MainnetName: { + constants.PlatformChainID: mainnetPChainCheckpoints, + mainnetXChainID: mainnetXChainCheckpoints, + mainnetCChainID: mainnetCChainCheckpoints, + }, + } + checkpointsJSON, err := json.MarshalIndent(checkpoints, "", " ") + if err != nil { + log.Fatalf("failed to marshal checkpoints: %v", err) + } + + err = perms.WriteFile("checkpoints.json", checkpointsJSON, perms.ReadWrite) + if err != nil { + log.Fatalf("failed to write checkpoints: %v", err) + } +} + +func getCheckpoints( + ctx context.Context, + uri string, + chainAlias string, + interval uint64, +) (set.Set[ids.ID], error) { + var ( + chainURI = fmt.Sprintf("%s/ext/index/%s/block", uri, chainAlias) + client = indexer.NewClient(chainURI) + ) + + _, lastIndex, err := client.GetLastAccepted(ctx) + if err != nil { + return nil, err + } + + var checkpoints set.Set[ids.ID] + for index := interval - 1; index <= lastIndex; index += interval { + container, err := client.GetContainerByIndex(ctx, index) + if err != nil { + return nil, err + } + + checkpoints.Add(container.ID) + } + return checkpoints, nil +} diff --git a/genesis/generate/validators/main.go b/genesis/generate/validators/main.go new file mode 100644 index 000000000000..6a7adde12065 --- /dev/null +++ b/genesis/generate/validators/main.go @@ -0,0 +1,64 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package main + +import ( + "context" + "encoding/json" + "log" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/perms" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/platformvm" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) + +// This fetches the current validator set of both Fuji and Mainnet. +func main() { + ctx := context.Background() + + fujiValidators, err := getCurrentValidators(ctx, primary.FujiAPIURI) + if err != nil { + log.Fatalf("failed to fetch Fuji validators: %v", err) + } + + mainnetValidators, err := getCurrentValidators(ctx, primary.MainnetAPIURI) + if err != nil { + log.Fatalf("failed to fetch Mainnet validators: %v", err) + } + + validators := map[string]set.Set[ids.NodeID]{ + constants.FujiName: fujiValidators, + constants.MainnetName: mainnetValidators, + } + validatorsJSON, err := json.MarshalIndent(validators, "", " ") + if err != nil { + log.Fatalf("failed to marshal validators: %v", err) + } + + err = perms.WriteFile("validators.json", validatorsJSON, perms.ReadWrite) + if err != nil { + log.Fatalf("failed to write validators: %v", err) + } +} + +func getCurrentValidators(ctx context.Context, uri string) (set.Set[ids.NodeID], error) { + client := platformvm.NewClient(uri) + currentValidators, err := client.GetCurrentValidators( + ctx, + constants.PrimaryNetworkID, + nil, // fetch all validators + ) + if err != nil { + return nil, err + } + + var nodeIDs set.Set[ids.NodeID] + for _, validator := range currentValidators { + nodeIDs.Add(validator.NodeID) + } + return nodeIDs, nil +} diff --git a/genesis/validators.go b/genesis/validators.go new file mode 100644 index 000000000000..adb876cf6fc0 --- /dev/null +++ b/genesis/validators.go @@ -0,0 +1,34 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package genesis + +import ( + "encoding/json" + "fmt" + + _ "embed" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/set" +) + +var ( + //go:embed validators.json + validatorsPerNetworkJSON []byte + + validatorsPerNetwork map[string]set.Set[ids.NodeID] +) + +func init() { + if err := json.Unmarshal(validatorsPerNetworkJSON, &validatorsPerNetwork); err != nil { + panic(fmt.Sprintf("failed to decode validators.json %v", err)) + } +} + +// GetValidators returns recent validators for the requested network. +func GetValidators(networkID uint32) set.Set[ids.NodeID] { + networkName := constants.NetworkIDToNetworkName[networkID] + return validatorsPerNetwork[networkName] +} diff --git a/genesis/validators.json b/genesis/validators.json new file mode 100644 index 000000000000..a6a79e2a2b7d --- /dev/null +++ b/genesis/validators.json @@ -0,0 +1,2459 @@ +{ + "fuji": [ + "NodeID-11114JmSuQh3uKVcgTTSfTDw1FkPQhg3", + "NodeID-11114UC8HucRiRbUuV4dq1VL5WQmM2fk", + "NodeID-1111SJCR5o7pRK817ZBY4tEeYRZEbhq", + "NodeID-1111ZgWnsrSvMjwG1DppPRFvcdQgwbk", + "NodeID-12BFLTEPWCwrWuK8PNf2Pui9N1MVXDwGw", + "NodeID-13yohiYMSFxpqnXiTDGRjGyhEPds8rLJr", + "NodeID-15uUYVJH5xM396PKH5d9GTjGErkciLdBx", + "NodeID-1REAt4C9SQUo17pseGmHL2oNUdpkBkrB", + "NodeID-23GCcht221hDaKdtH8BhSLpUrugsfRAY6", + "NodeID-24WK7qiKXAumya1kKEktwj2ubBbRyq5UW", + "NodeID-24nupT8dLucgRn2HuYGzqUZEbkfKRaUnX", + "NodeID-26yNpVkHNGxboUshTXtFAy76yYLmWa7bU", + "NodeID-29tGiEe2rxuoHJgjEZ4sDytQAivwjJmaC", + "NodeID-2Bxm4MQUKqq7yMtHLWsfYpKqRAfSterR2", + "NodeID-2CDAbZAYzHv4imG3sC9hBx9WGMzJdAJeX", + "NodeID-2CVgPTjtmaxSSjKuZXUwrgG4cPapmEgmD", + "NodeID-2GKxWMGx19NvTSorxibapih9DcuRx6WzV", + "NodeID-2GXYggxghp56hz5zkdSvtVXEQ3AZB1gGM", + "NodeID-2Gp8ZuzK92tZDzLknZxmsm48RvppFYSqc", + "NodeID-2JGdGihFqGFcKEZEUswXDSWwaBJcU797P", + "NodeID-2PfNAhAG7nypsyDRHzPwZaZsDcj1jA6rU", + "NodeID-2Pvoq8Stniirtie17djAh3ys7rUxn21F5", + "NodeID-2TXd5wd2Bf6pFG9C13fAtC65G7pnzo33x", + "NodeID-2Ty5YxnuVTUkPX8SPMcS1b1qfE3sMbcRV", + "NodeID-2bRcmz6BF39s7bMoG7wWPWST73LWcaAUp", + "NodeID-2cU7F76JcCHXcsY6L8pMeHQBxwXqMumNC", + "NodeID-2cu2JVaQDucg81tff1W4PBeZ5oMUG3vj6", + "NodeID-2ebMFnGycbMsnxJ3VV2WLhJSQPLQUSJgk", + "NodeID-2j78EmuBiyV9CBfVHgA1juLJHZZp9qu98", + "NodeID-2kwc3kKwtfgTQ7aPahndbHAer236maSBH", + "NodeID-2m38qc95mhHXtrhjyGbe7r2NhniqHHJRB", + "NodeID-2mcgvk2tEnhaXseBy6BPyXivsVvSvSg8n", + "NodeID-2n8rK9kL8N7y1P6hyKu5ZwrMFUX1NEXG8", + "NodeID-2wQ6p4vgDiKFkeCR2MzZQ5aWQ3dCq6QfD", + "NodeID-2x51r8aE1QxG2Vs4vGXKeB1hi7bvTERPg", + "NodeID-2z5K9uUhQdVfAQjqfQSWAgCrjt2f1sFtm", + "NodeID-31NFpxN7VniDZbDDNkvvZaFuuNhDJyYro", + "NodeID-33PdW8ge5VAHD98Bmxy6kYhm992Mhnu8x", + "NodeID-34qTBTrvhsF3MQDuwdNUDHBvj982Wm6NV", + "NodeID-34sJYzSaqAD8GSoK1WVguqLgdg9uVotGH", + "NodeID-36ktMvm5GFTkfTAd5pPw7zpAXZG174Fvo", + "NodeID-37fc7hgUGsXKxPx3rMYyBdHatNpKRb8z2", + "NodeID-3932bao9oUnjfwGwWgsBk96M8rBhgQdeG", + "NodeID-39V1962v35f5Rs1NsaCskg84uaMqyxeAs", + "NodeID-39w4saojjUihKVNHJiQuSwugYbiGraXGU", + "NodeID-3DgkJ24cK9scEWQnoa7BwgP6YpB9ibccJ", + "NodeID-3FQZUAfKMJVzV5opV1DC3EpEYiZ5aYJQm", + "NodeID-3FYxUrCrACjqdBYFc8SnTzJ7Xq9fY3i2G", + "NodeID-3FaY3uSPkatMS3HUWXDeq6WuYyFPrHoj1", + "NodeID-3HNtqQ9HQftuHD8gApoDTLMH78z33P4Ze", + "NodeID-3KSEXMHijPpZbUHHgpqubFvjA2N4GJ6MC", + "NodeID-3KixTZkLBUqrDDeaaEpXaTTiU4Qan9xdC", + "NodeID-3M7L6w9a1G7o6ywAuY47HTnuGaMPZKQWx", + "NodeID-3PjPmpuCghoVT7AJRb8qTjyZ6DtCPuURp", + "NodeID-3QKhsmp2cj4eJ1hYecqQ6UAPYGTfZhWfr", + "NodeID-3U18hPBaGyELh3ZFEBPsvidFv5gP2Pv38", + "NodeID-3UhYTVhNbwBBALPyvwhRiGmgJts3obFvr", + "NodeID-3VWnZNViBP2b56QBY7pNJSLzN2rkTyqnK", + "NodeID-3VteqBi7XCUxezhkqgoJ5ZejfRKWaLcvR", + "NodeID-3XynFeRRXjz7gKPWWdyfi7ymxFWi8LEyc", + "NodeID-3ZCAFhahev1RL1t1pt7cmL13mjCykhMLr", + "NodeID-3d2VDPUTpXd97ukrx9Faepmb79wzFicQZ", + "NodeID-3dahoBAqDyB1vskabnMHPy47zg8gJ9tD4", + "NodeID-3e9afsN2qNVzgz7mCac8mcjDXgxpjMiWi", + "NodeID-3jFnB85bDiJ8f1G8EgptsZMENJfGCeBVD", + "NodeID-3jbJ1eh1i8iqQKsrMjcG5WzAmPhkFU1Ds", + "NodeID-3kuuAaJKZWFYp4dy8rcrBWVkV4LDb86hE", + "NodeID-3nhpqPqAz8og2A2DBeVjb4fmFK1d2rRvQ", + "NodeID-3oFxfDPzWo4YhvYzswCMzLrcJwx2UKkwV", + "NodeID-3ry1arUtntKBQ4shFYgF9VB6AbGRHnPwe", + "NodeID-3uK65P4yQGns5wVB9Bv955dHP2rRiXzFF", + "NodeID-3uRhwbfSajPyvWGaNSJyjhDKGPACGqHz4", + "NodeID-3vtMDZ9Eqs3AzwNbqudMoxuUXyi97MKut", + "NodeID-41cr9VeX852rtHrELWnHthUV4Bbm75WBY", + "NodeID-468yx2KFJV9M7uNiTXJrbqyFGeQxgiBfh", + "NodeID-4B4rc5vdD1758JSBYL1xyvE5NHGzz6xzH", + "NodeID-4CWTbdvgXHY1CLXqQNAp22nJDo5nAmts6", + "NodeID-4DDjS32CM5oK7tbba8iNnXv7VWJsrynDu", + "NodeID-4FB6KKULLKMss9cAdfgabKqpEfDtaGPXd", + "NodeID-4JwxRwRY8LgeSdDLNargL9NBEBUuvTk9v", + "NodeID-4KKUrWvuKKEwNQWvZj7x6NDhUEan1m44C", + "NodeID-4P3c2QGazSpTXeb1WoPaD55hCiGUkKxSD", + "NodeID-4QBwET5o8kUhvt9xArhir4d3R25CtmZho", + "NodeID-4RApHGzbpwtrUEbL9BpkV8AfdCzr1ciCj", + "NodeID-4SdtN4zCP8h3ZEymEfGxJRocAu5hrwphC", + "NodeID-4TJyt2f7zGuusjc1yXcBJnkNvDMAJ9py4", + "NodeID-4WP36nX46eS27wcRsW1agg7bzpNDonEf6", + "NodeID-4ZrTre1sS8qxndZvsMNzBGm3MxxWBpbJb", + "NodeID-4bPd6dgavJ9sggrbTMou3jkjcJ6Ng9L43", + "NodeID-4cJyBoufFfiMShtRhcd6WGTYdvUCE3Ai4", + "NodeID-4eruhJFiLfkgmeKrG9udZthPCvGpyyw9d", + "NodeID-4kMv27g3A6x2RMkiJjiK73zmAxvPDmbct", + "NodeID-4kSPhc76z8Nxfta8gjxHDCHcNx7TrNSLX", + "NodeID-4syxSZ2LPcCeE96VL1HsY3fx3AYnnGfsi", + "NodeID-4t94JpNNhRT9v6uoUWFY5G4jKmNqV6BQh", + "NodeID-4tsmKt9tHvMocmyHe9oKD1PkAa67iHn4k", + "NodeID-4wL6VGogpJKy7EB69BxaRi1R7sg4npMxV", + "NodeID-4wnwAREi6cY2vYccTktFC1gCEJfxwMJrU", + "NodeID-4xKQvNdSepnCAUZ5JMvqNxanaUQ4Qn22k", + "NodeID-4xpmwNTMoAxA4XGPyrBzas5Vnu1Beykmw", + "NodeID-4xyPSDPrx6wecMnPu754XG6hnb2HYCYLz", + "NodeID-52UrdjqkYxmkasCeLaH2jkHMXEYayFn61", + "NodeID-53BzXzD64f4CrJQZJmn5VWhwwys1cpzGU", + "NodeID-53QuyRVXP99F83s85cp7Fe8Aax8KAFQct", + "NodeID-54RagM4VF5VNeKWoVV5UNHJfM6ccHtBob", + "NodeID-54WkEbocc1ACvV6N6Qu4NVDGHGfpFhBzr", + "NodeID-59HRzrFCmhEmUJAncPdXZ5H1NrreBQR6e", + "NodeID-5Duaym34R1PzdVKEeQNtqVKmoEvP8dfL8", + "NodeID-5RHueEiTPCFb2T8YuDid94rJtr31UvnYW", + "NodeID-5TcM4MkRoE7Vhnv9kcawSwpVSiTPDDBKw", + "NodeID-5UVT7fNKF22XkWXMxCDvGHZW2auLgxprr", + "NodeID-5Vd1XuN87ZgjBzpGL5NDhVPbmaqzd4YfU", + "NodeID-5Vpuk2sJiHhYjELfcRzYEws1iN64isPbD", + "NodeID-5aqkYoNRpwJ3EhBvc8uF3626mzfiUsxdG", + "NodeID-5bGeKYsDjDfMwPAipVDPk5rYX5b8vc1aN", + "NodeID-5dCr6Szbv9p1RpUQWatYgNJb9wEBmhgAi", + "NodeID-5ewkSj3RxqMG7shRumy4USF5ibHMaFAJY", + "NodeID-5fvPxB3edzXX3Eb5x5r7tbknoxqKyELtf", + "NodeID-5ivzLGz96pAJWd3o83x4JWHTpWZoHJvc9", + "NodeID-5kJjV8Xa6RrkiwascxHUrpFQnPLcav3NS", + "NodeID-5mb46qkSBj81k9g9e4VFjGGSbaaSLFRzD", + "NodeID-5naAivQLhjbpVw35YGaD4HJwXTwuDufXA", + "NodeID-5oRZWHEqipzXDnScB5UgPP5cUqfgPa9GR", + "NodeID-5q6drRMuNYp3hfZokxgB2m5NxBoFZXc6X", + "NodeID-5rLsXFYvpZqjWfXkPouCUAmXc3Xcvebvn", + "NodeID-5rZ6LbEm6o3baUxVyV4GV21sPD4QqjPk1", + "NodeID-5tqDUvtVzpChaPgXcrXjuRRS5EJU648en", + "NodeID-5vCs6XJWRNTLpAkQP2HK8fwprGb1v86Q9", + "NodeID-5wgChqKt5SksEAZtUDYcaUG41Y1v7KbDv", + "NodeID-5xyc9328PKgo98C2DvveTZ4Zqp237kN8h", + "NodeID-653BnnF1HfEQY9APtAu7V23FNEmRMBGDW", + "NodeID-67tGW3yXGqnDVnEwEAwVv84yZtm1AiZPA", + "NodeID-6DjE25mD9X5AXWf8xpfgJ5tK94SFq11Vw", + "NodeID-6DxE723urFNy3H7SyMMs76ZLRYx6bDJdz", + "NodeID-6FgfGS3McpD27X8hdC7ZgQVhs6DoKvBzq", + "NodeID-6J3LY7ojkK7WCZzmArvxEozaESDMb42hX", + "NodeID-6Kgqv9SV42oRBk2KNSRwFfJwsLBia49De", + "NodeID-6LZ6k2VRSdaF4qLHgfjER6gjVjrjDEAmm", + "NodeID-6MnjianNNDMpLNhCnirZsw47aGGkkfCZd", + "NodeID-6Powgn3qZ8HZGmHUeQ7b1acypxzXhA9Lq", + "NodeID-6TrmPJiRneiG2ztDxBPWQAxAqv976ZJmU", + "NodeID-6Uh985Lx96QQZ6LmbqJF1j4CxLu4ZCcd7", + "NodeID-6YPFxT3358wbWFW6zHTnVtUYYedASEnVu", + "NodeID-6ZmBHXTqjknJoZtXbnJ6x7af863rXDTwx", + "NodeID-6dfJg4Ttv3nEPJTakzmYwqv4Qny6fUjgA", + "NodeID-6f4T9BgmXJVJBNTwAj2giidTU7WiomG8G", + "NodeID-6gVjCexoCvwXqApW3YVLnQSjsCUjbSDYx", + "NodeID-6jRufzNELpUH7jeTz71PhiKJvyjzWNjuf", + "NodeID-6pMsJc16h9YF2mMY5VkZu8rDS5Qco23fC", + "NodeID-6tWHHU9uVWAf46qTYTsnTnVZJeL65hwgR", + "NodeID-6uRAYA8LDmiD4se1Ve9fBSRrjNi5TZjw7", + "NodeID-6uicgS3fAizqshZgZPrNqm66YieUeZkbj", + "NodeID-6xEvEA7hcEAnqaXW7R9RFZSkdsAniHPad", + "NodeID-6xFbRUP8AZCCGDMYtu1P3g6zK9weKbQKT", + "NodeID-77ebv49H9yRLLiUC46Hm9H371wXYNZNjL", + "NodeID-79idCdyu498QoEFzvqKBbWFsXECKSYbpb", + "NodeID-79u7mCRHvc9q5piSciiTphM8H1TDEq4Ab", + "NodeID-7A8w1M4GpWHy8UMwQkARRoB9a67Rod7yR", + "NodeID-7BPqDUFt9F5Vs9eqZiBYXmnaeC5UtZ2U", + "NodeID-7DYhQRawvQ3hoDTfytAa5KHeMTUM7buBN", + "NodeID-7EP7QhMfQsBYa7CgwzCb82Fq4D39FvsjY", + "NodeID-7FXaqpRJgAPGWAUPs1UunagASkxPZps2D", + "NodeID-7GM3ww9CL3uXtZuK6nSpdKJmEbiiyYgu2", + "NodeID-7GvViHLjftpvgZLD7RNo1YHZzt5iUihCf", + "NodeID-7H5yeX5kkfdUBFCHLbDfDRxqWCDoFrCcL", + "NodeID-7HvCZsgMXsCTjddz7cYNpKrGxK1i1SxMr", + "NodeID-7L9oKJx6AsgGfG2GR8qQ7ndbKBVxqV9At", + "NodeID-7NenT29nACMVLj8K685mBLodfp6GehVy7", + "NodeID-7QTLwAtcwhLPNFkmwyaXmC2tUW5CsgaS8", + "NodeID-7QjQJHgVxMFBZzNG6n7ULTeaa7dAbd1U9", + "NodeID-7TwAjiRpTbNcqUx6F9EoyXRBLAfeoQXRq", + "NodeID-7XRaRs6shZG5VVVoaKeUxdJfbPmuVU4CB", + "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", + "NodeID-7Z2Ca8HDwrD2QxWqGSR4F76xRp5Po4dhP", + "NodeID-7cukmtqdCLDWG6N8BJswwKidxe5iGyVvm", + "NodeID-7dCZydYmPM846KqjhL9b4gRT1C7MDFFxG", + "NodeID-7dZ86Yv4Md2dwhHPpJNyuh83LjKNKvw44", + "NodeID-7eR9d4bjMsTgpwCbvXz4ynETmbXiQrJ1X", + "NodeID-7hwpMxuv6Q3yB4F19zXuk9n7n4oioiKZo", + "NodeID-7kVsskXDhAQ2grucq8sUwJARmtqsTmw9a", + "NodeID-7kfKeW5gRRVj7XgsssdWaKNU4AvC8dLiG", + "NodeID-7peBGoPt8rGfPUEeH1VCqnKyMFJg9y6z", + "NodeID-7q4hAGaEeRrzWdCDQADFBdpXnJzv3bWuf", + "NodeID-7rWB8y7nQQSmSmmEBeaAWQKKZYG6SXpQv", + "NodeID-7smHERiKttWGYmBwxnpGJ8QBHA92eNtvC", + "NodeID-7uXxUx1VAs3NUs2J472MdQ4V9xVNKZHxN", + "NodeID-7yTMMzMTd1Fuct5tTeCB34HoZ9kLdKCpF", + "NodeID-7zbpDafC5Rxm6ZMXqSrz9D28ZdC4WV7Hp", + "NodeID-84KbQHSDnojrmyuZjWM6hrM2vgPtMWt3", + "NodeID-84KbQHSDnojroCVY7vQ7u9Tx7pUonPaS", + "NodeID-89GQ3qi4bif58ovQnQAehtccU8Jbynozk", + "NodeID-89UCR1CsPzzEHuknxhJHKxuFPNCyPz7Bu", + "NodeID-8DLjsnc2R3mm64NJ5puhrgisrLXHXihKc", + "NodeID-8F62HdqXVhqGTySVZ7HyQbEyFDMo33iKd", + "NodeID-8JC2wNQkExELqhtzoGnyBcC7b5Su1C9ju", + "NodeID-8JtmUUx6NHGVACFTReQbFxx1mWMJTdsWb", + "NodeID-8JvHG2u3R6DLSBpv55rHhNvj7MCbeWRGL", + "NodeID-8LjNUkzYVge7UvJkrJmaCYyWvmRb4oxoA", + "NodeID-8PvUVsNyrXj2SpTyrfxM7AcgjWU4xCufs", + "NodeID-8WJr4wGhcXChCXKXQpSidvTW5RiCQzX64", + "NodeID-8XhZkWckQGKgzhv3XSmUeM3NSrskD4bew", + "NodeID-8YHqGprPt4vva7TqVbzTtVFRv38BmpDUD", + "NodeID-8ZD8eAZmNvwtfuRC7uLj7PLqWgTK962iX", + "NodeID-8ZFQww8ESvtRDufva6uRbHpKW4D3ARvhU", + "NodeID-8Zf1gnqD7KuNhL5Ho13KB4QT5r86q3c19", + "NodeID-8bVFU3U2PpHCwavsvzfMTE54cir79cmPr", + "NodeID-8eH3T4H9fwcgn1o4oNCxULXiiFHwiqy6W", + "NodeID-8eZ8eW3Q2Kf6YV1wEVCaFpEsRMm2vfmqy", + "NodeID-8hqGf72EsTsRTWpP1kxGJkbzeJjnosiDM", + "NodeID-8i9eqbVxzf2KtQkBPiX2BvZujYza6fDe9", + "NodeID-8nCutCx3GgDYrNL1ancH4ZsE5tXHRYj2Z", + "NodeID-8nXdZLTjc3FLaPGbS41WXt3Qwa3JvKaHF", + "NodeID-8pDV7WK6kEp4mw2kupK1bSXTsShiZamE4", + "NodeID-8qNPJ4cmRiqaM7LA9v9tishQvkqqHLCeY", + "NodeID-8qTXyZZtMFdVqfEvr1nhnCJgh1i4ZGqqz", + "NodeID-8rLtFc9Ds7Liw6mF9vz51fmHfxFqDuCvF", + "NodeID-8rcfydaHitUhBWcUuDxf5p24p4qwfvucw", + "NodeID-8tpPNhuBrXw8KKqJjrsxUwVqsgdgbuoc5", + "NodeID-8vGhAbGtfHhi1nNg8A1Jof4ivgLCRdU8M", + "NodeID-93n7QZ5J8s1hej9LEVKX8g8yV8g9FvqCY", + "NodeID-96B6wPgw4HKySZk2C65c33YzzNx5VGmE4", + "NodeID-96ugvCFSQ4Df84uPhPwqHQNRCxVvkpxep", + "NodeID-97jPS9hQkuWC7DhEchgwC2aUN75oto4XL", + "NodeID-989RjLGtpnUjDHGD9mqxgyHLcXfnsaw4H", + "NodeID-9B3HLkYWERnM5daHNb6XaX8on8WP3XiGE", + "NodeID-9DQ6UMDYYWZccC5MRmT2xqE5TaMZUDbLN", + "NodeID-9DnRjykQ4ZdyebJ3FeoqKBBjJcbMC4nsV", + "NodeID-9ENGXxXDAEdGcRNZ7UU4Cu1FSZssJQto3", + "NodeID-9HUatTvqyEsDD4bUaocsDGpVeePh7KEdE", + "NodeID-9KhiEguiCdK9KGCsfwkWY7M4VLvM5dbuo", + "NodeID-9NsPTteByFVHbn26rvU9NjjLjRKKCR84g", + "NodeID-9PsQNVrDQB8PvyRKjCiK1x4pkGSNHnDtK", + "NodeID-9QhM9oKKXbAV5xtfARnyKXM97L7nwvGSu", + "NodeID-9TCq8np31pHjjhGaHtLjs6ptYYPEt3LGb", + "NodeID-9TrHs373qdrNrt1axAFCL4YX976pgfBUk", + "NodeID-9X4SMAESCQz8H32PMq4wrSafx6sAUv6oN", + "NodeID-9Xp5yzoLDUuCzUdaU6uFxXTjUYjwoCvPp", + "NodeID-9Y2jEfz3E452jT6QGSpJ5Kd7NLPbVPinz", + "NodeID-9YzkgDFxmnRQxV4M8E7cuWPd5HukCaQkt", + "NodeID-9aqgQwSS5HsfP52YvvVKoB3E5ZTfQZxqj", + "NodeID-9bk3GQD8qBvHfFTFaBCBURupAKLQEYg6", + "NodeID-9c5whzpb1QstunxbQ9PGqKQLanAU32Wnu", + "NodeID-9cQwDnPkD4Km3rQFvyJuWD5GUCMYrPHkk", + "NodeID-9hW5Lb3t5JMgP945DB8wHUJP73uLuDLAZ", + "NodeID-9j9p75hBtn6rMES3TuWrGc7Q7tQZrfWf5", + "NodeID-9nP42bsqJ3HkqLUwNnnCtTgDQ51QfPDgG", + "NodeID-9quZArokFFqk7EPAMJFYxa6KCcGWsbqj5", + "NodeID-9yrLEmUoyFvZ6MVwrtsXr82LpFExgsfim", + "NodeID-A1SAHmXVC3D7dn67LPmWgd8bMvoNKgqTj", + "NodeID-A1YeC21gHYrEf4HBdRvxFheviXct4MUQ", + "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", + "NodeID-A2Z8m7egVLhKf1Qj14uvXadhExM5zrB7p", + "NodeID-A7az7ffBywSGhgSGvwC2WbUgNxcQSiJD8", + "NodeID-A8VrzZuMjMGkFce5zqSQ4nbSwUMwNmnHt", + "NodeID-AAvXsy99V6dtcjwvweVC6FRWRk4fxwhjZ", + "NodeID-ABCBD3w6GosyujRHjEAXfbRkU14YxX1Af", + "NodeID-AByPv1JZTACocLTLXzpqeWgDKkCkKqZvM", + "NodeID-AGxsF8rtNeZgsEFkK4urDff5PE2odBT5c", + "NodeID-AHnXYg7f19R1MMmtt8D2yNejuBwha5i8Y", + "NodeID-ALEsCNXhMUCtphtQcxFQB6Q1bg6wXtXDX", + "NodeID-APKTqeD7UsfjYqfYBtDGaDCwLpr3ECVBN", + "NodeID-APhFyzYExri3n5GtDz7ytXCgbt8x5NAud", + "NodeID-AQYxySZDaBzqEojxps2crnAf79UJYcCbU", + "NodeID-AUFGUsjF8DR9cPfh4kLWCjtwdKyop1Y6H", + "NodeID-AZsVs7FHdKmNfjDDesfRY5w9J3bJd2e9j", + "NodeID-AcDXsx3uYnVkZs5BJy496WfHe1NC3uaXk", + "NodeID-Ahtb1pwX6ugZfmb8ioJrBRWkPqg762Ed4", + "NodeID-AnJkYoj9mvGqv1A7WBujia17Hq1rDZp4Y", + "NodeID-AnZdc4zkKTSkYUDUByvX6u3HJP2MU53Pq", + "NodeID-AohNLSFbhRMHRdF9CPe72epbRtYPeZwjB", + "NodeID-AqXr2RXWtX9FcPndqPZmEDHqfd8Rm5cxq", + "NodeID-AveomWdS99JgszXcmvcUn62EzoWGbu1We", + "NodeID-B1SoG2eCceT7YhdRq8EdcuVZgcXeWB5VD", + "NodeID-B1jRRwEACvv92YJWyZrWwQn8DaAhEQA8K", + "NodeID-B3KbeQXjwDat2ySJrVppBxRrTxb7RwRjy", + "NodeID-B3si8iQ5MxJDRnwMBJyVt6puzici5tufY", + "NodeID-B4t2yBUNfc3fUg1639NSLoy39ui2aYtC2", + "NodeID-B6GaYh7RRopBAkQJGiMeMZAsAbHXyYi6e", + "NodeID-B8SLANqFYZnUqfnWMuJjsjfzcN8Fxs9rp", + "NodeID-BBt17ZXGPvov135835zT6BBAa6uTwriQi", + "NodeID-BFa1padLXBj7VHa2JYvYGzcTBPQGjPhUy", + "NodeID-BGrjjjfPCWR6pGWNTN7YcW1XtUKofMQsL", + "NodeID-BJjQb2PFLPiHsvejL2Q3yX28nqRxGxEqA", + "NodeID-BSE4qod6VYM7Xxeausg2UzgxZqMmTTWnU", + "NodeID-BSa2KH8iHJPibpJvNKEkswp8FDNub5v1f", + "NodeID-BTATPxEmZ5HoetuSpGDnPMzs6J6KuTEA1", + "NodeID-BVXicWEU3ULP9aBsmRT82PLJMCXfdXDMp", + "NodeID-BWNtQCsbVKauhUwXik3iKZ5ibTCXQGPp4", + "NodeID-BXTBUqX8gitUDtVam4fhRWGD1SfeHGoBx", + "NodeID-BZq3oJcE1Unw1rYTB86B1q56x2VYQ7PwD", + "NodeID-BbDHoP1Th9LSr8iEuoHktCF38MQ6Wx5Ws", + "NodeID-Bd7EUL6WhVm1wF5bVNefWxHYsg8q2ttuh", + "NodeID-BdhYSwf3LW3bBqt3235WS6Cw7P5GYDFSV", + "NodeID-BdpT6z1FRz6vjEQp7Cb7nRFUgvcquBXT2", + "NodeID-BemmZ7Y5HLGHSz2kUjmPUDD7bbJDebVd4", + "NodeID-Bevezp7VTbNs4wGiiB115f8NrBwuRa79F", + "NodeID-BffXkmzM8EwrBZgpqFp9pwgE9DbDgYKG2", + "NodeID-Bfg5ZtbEdFYJx8iVFGMxtS5YQoCZRCo87", + "NodeID-Bgskmf8PocRPgtHgnAYKUgyifo9qD3Y5g", + "NodeID-Bh1NKhN5t6MBcHvY7XuGhLK14q7FwQjmf", + "NodeID-BhmBgAcV8WiNyrVUdDYJ9CVi7TvjPfJV", + "NodeID-BiRB38NNFxPXDbYbBp3oFJffJvDfC3fzr", + "NodeID-Bk8Etvn1q5cEbZcn4y9QjbXoEAPwsHxB", + "NodeID-BmkswdTypyATT3xP9as8BeUCyq2sGScBD", + "NodeID-Bqqf3VLNgeaFCRHevXVzZriYB3hLdW72A", + "NodeID-BrYXghQSu6KKGjuzhs3nrkcB46Wc2yYHy", + "NodeID-BroSWTprybJuNtDcJ2hjHbsGzrvLkKAo3", + "NodeID-C2Yoi9vTGPppDhpFMx8J1XvKJv3CY2x8n", + "NodeID-CA74JxFwV5BeRMCesYQruxjiKw4ofkEKQ", + "NodeID-CBy6ZLEwBBuYFtVDDvz8Wra2AfeAd96fs", + "NodeID-CET8PwdAu6Q2Cx7iqHrfdSyo4WEnkoxFr", + "NodeID-CEzYD3rFjsGtKFu7JLGpD7rMcGRNJFLGB", + "NodeID-CMSgVPNXC5R1kL19KHCNgbbRTeStUWPJA", + "NodeID-CNK8vDPGbKfS3YSptRPPN4VYUEpoNH4Vz", + "NodeID-CT2Fqk6d8eYAx627aYB8HAr7VjWHZYPQc", + "NodeID-CTL3MEW1JDE4iNayXgMjaoamy7i7TEyCq", + "NodeID-CTtkcXvVdhpNp6f97LEUXPwsRD3A2ZHqP", + "NodeID-CZP8JG4BKdDyiktxg3D2ZYgREHtFhqzjH", + "NodeID-CZmZ9xpCzkWqjAyS7L4htzh5Lg6kf1k18", + "NodeID-CafHoeCqCjg8fWufaorRqFe3iX8s7z6A8", + "NodeID-CcS3n2j4CEaQCEnY39qaBDZajeZaXkRGU", + "NodeID-Cdm8CPSJiHkZdWWZsPQ9iycBrCZ5CaGtN", + "NodeID-CduWdu3Gv7bsqAxnsdTCWuuMEyLYQqchX", + "NodeID-CehvZ1zrpo5HAb7K2sDiQcrks1Cn4d5Ew", + "NodeID-CkS5zL9rUsJkYHgSMtoYF7yBwBCV6Gn3X", + "NodeID-CoKgGkWBUGouNZTqKCYLBNJ9dw4yJXUEW", + "NodeID-CpLDjTHrAuB8p3G42uRtGhnGKJ5YzGkFa", + "NodeID-Cq8kbEVqteYEqfNNW1CJSkrG7S16GiZ3u", + "NodeID-CqDq4nGVYJoSgKVpZpyutzkZPfcugTdjG", + "NodeID-CqGy1ZUkq4ZTznvsvzwwXtQiu8gBT3eYW", + "NodeID-CvFCEpXymDz9A2EftqnJmCNi8qVHxwKXq", + "NodeID-CyQc7xjJ2gJtCQNL6RVMEJf1KysJXG6QF", + "NodeID-CyS27tGGmcmxeKhCuCwhT4GwiZGBE8QEb", + "NodeID-CzBZTXGcxZqfB7UiN9ALzssfyHMWbMKH6", + "NodeID-D3BkKn3N6chukRSZN3yr6zQvu4DgCSvp2", + "NodeID-D7WZhpVMpyCMtSenB5peUHuaQkokXZST7", + "NodeID-D7jdvPnW8XX3Yz1k4YYKCZxaY1FF7x6at", + "NodeID-D8bHw3BUjyGycV3dDTknNp1p6w8LHkNhh", + "NodeID-DDSorcx8EXWLLV5kECjjo9nFMUTA3kEUy", + "NodeID-DFzso5PTUHWDPe4qL64Ec5mnhGQ6LFhhp", + "NodeID-DJHKfhFKe4QjX6AY7tyj2VTjZrpxUWUyQ", + "NodeID-DMbbEVaCyas1EXR5ubg2naKgEBmVerPne", + "NodeID-DQEFtYhQ3WUKQoVSTi6fH3MXhuBAPjKv1", + "NodeID-DUNsbAcHScpFE2uwBQ2o3SPZ46C2svMqq", + "NodeID-DVZ7ffBkVkXDbpjGPEqwyYQgvcHhuTynj", + "NodeID-DdhG9cNQmDpPwWSpEW9u6T7PNCc9GKv2S", + "NodeID-DeeVioFXeoXx718FkbAk2unyikBN8iLJo", + "NodeID-DfWyvyBF7XF33B9kkSiXYcJyzxRBATXN", + "NodeID-Dh1JnVoEMU5zEQtvR6LHPVsyw6AGqbLuG", + "NodeID-DhQSUszPR4zHoxF2Cicx3pCUnjrfsewnp", + "NodeID-DjUwAHNXgKWFRLJPN9LiMEGLtnFromVnb", + "NodeID-DnyNinbTZWYSyoekJ1xMmh8TxQCw9kHdz", + "NodeID-DonmTGabi4TZjWH1ue6W9GnHB9ZSjTrqG", + "NodeID-DqogihFFxTyKaUTqmjDt1Fh82hWwkeq9v", + "NodeID-Dr3k3Xb2uFHqztcbVtAbbfhtrwYjsRysu", + "NodeID-Drb1UM6uo69KiAy8tyD2QXv3JUGU9exaz", + "NodeID-Ds4BPVEDoEPu9wHT5rk7ry8vWaHoY4cDo", + "NodeID-DuXPSVSZUeEJA8QP9QV4Vt2G3y3WbPvRx", + "NodeID-DxV8FsH9amd8cjQhEboKZerAPsBR94maA", + "NodeID-Dyd6GY1EnBTGi9WEMvFo7kkjsZBWWRDo7", + "NodeID-DzyJouyxaQRYYyfYEvTaWrB4uaPTTKn2V", + "NodeID-E1tni7wFcu9CizXdckfgxo9dhUwR3243v", + "NodeID-E6CBZzykpEJSqKyNjDdFeLvDN1AmZccWY", + "NodeID-E7Cm2d6wVhaA4Q7AnuRg2S3sD6noReX91", + "NodeID-E7e5wZQb8QYEKYd1BrRrszjPxUaAQNaY7", + "NodeID-E8dfbZCzX8VXgXYmjnA58GorajNrNcpFL", + "NodeID-ECmPviPvgqFc4iXFi3soN1xpXnUUDHjoG", + "NodeID-EDESh4DfZFC15i613pMtWniQ9arbBZRnL", + "NodeID-EGzKzc9RU6HGCzBe8nK2qY6mVs6WqroBg", + "NodeID-EHV8d1ezFyoA8DMzTU3WZXfVR95R7v1cv", + "NodeID-EJ8BPX5xG4WDPAtcpTWWKVL9PCNJErsa8", + "NodeID-ENMu41b1avXe4yRxmF1uzymNJP9Xf4jcy", + "NodeID-EXuaP8HAE4anxXGR4QJX2em2nfEiTR9tz", + "NodeID-EYEsr6Srmjn4XM8DijPFLFT3Hf7fsDMHA", + "NodeID-EZ38CcWHoSyoEfAkDN9zaieJ5Yq64YePY", + "NodeID-EdSG1Dy4kqqaDJRn3kSAdM7RVSdW5eyyz", + "NodeID-EfGKSr1JxRXofvpSo1kABnyjuyJWLr19K", + "NodeID-Ej578hCdtGtaSQUMQFkPkoXVHHByJJzZM", + "NodeID-EjvGBJ65yHcJMwV5RhDJBEcKb1QP4Du1L", + "NodeID-Enfkqb6z3yyuL9c9FGhWUmzMYp4kFE2np", + "NodeID-EqJ1JGnx7zPAEvGy9JRgytDDTrsPtZUet", + "NodeID-Et4ic8Ew2HhDqKzb4Zx68SMbC8mCLUWzi", + "NodeID-EtBgBdH22chVR1fzZZPky3jzUZDTigCbV", + "NodeID-EtUZs6wf6j5kZMUuABEzUY7Z16Ja9DtoM", + "NodeID-EuQ17UhJAMCCPKo6qhEkeiEgeyNQk3vLt", + "NodeID-EzGaipqomyK9UKx9DBHV6Ky3y68hoknrF", + "NodeID-EzN4q9mU6TVFkND6oghbdLAUqDacE9Czp", + "NodeID-Ezs3eF4YftR5XQKvyN8NzRs5bzQC1QVm8", + "NodeID-F19vhTXhznYNp6pAvaUmUpj4VWq7qjUyP", + "NodeID-F3c4DfFS8crrJUyExRhgaMiXtZrn3TuP", + "NodeID-F6AdvbZj7E2JZDfG9WhafyQeFAqiU3geT", + "NodeID-F9kHeXw8eoxEMpKVCi7yCUwYGry5zPURy", + "NodeID-FDXS1jxwngimMxWwdysC5N1dNZVPZ9GQ2", + "NodeID-FKxCgNYHFdfrwJUTyEvZx6vknoiywzcvL", + "NodeID-FMjQwTYbygN4dMc5csXuHkttP73SqFn5S", + "NodeID-FPZ87ZH95TeFm1su82QJRX8PCJi4oBAoJ", + "NodeID-FPwz77ux26d2dyQji9ZrcLieVGUS7KFay", + "NodeID-FT1FE1i1J2t8QnnvbaxMqdyGy31N7MnfS", + "NodeID-FT27zhjAL6HYVkfBHoWk8FQ3pCt4xyVsA", + "NodeID-FTtpSNGEGH4HiQbi99qcgwGsgHthwMUGZ", + "NodeID-FYD28utCsypYL6THXnyT8bTW9syP4WQrm", + "NodeID-FaADDvJH51EAP4vhJEKCEfCtgpUUnTNX6", + "NodeID-Fc8JvkNuUmo9oSy8jXiNXUczUM2q3jWrS", + "NodeID-Fcz43yNkFRu3jL97vjLi3ZkpmeAcVR8La", + "NodeID-FdcqnJ1bwv976Ft4RibXmD5DTeWSnMzS5", + "NodeID-FehvGhfc73qH6s4zTdiKrNA4WmSMbCW4X", + "NodeID-FesGqwKq7z5nPFHa5iwZctHE5EZV9Lpdq", + "NodeID-FfiosnkKYLrMKoUpNTuFZz6gY5kb9cPb2", + "NodeID-Ffr1YgeWw3h2Ct9dY7V3u79ScrAbhSUUz", + "NodeID-FfxNCp6tZxTpj1JxA8GGVTtJWowqKDmvY", + "NodeID-FgvaeMrL2GqxSBV9R2hkLL7jH29vhBeao", + "NodeID-FkbkPTVMLbZZJKFHYUKZTt1Z3quNUurV", + "NodeID-FnWP36cM3Sgw351JmpbzJSScnDoaANehz", + "NodeID-FnaPiXmmbc79HUCCuzN7FF86vsJizdfa", + "NodeID-FnsrF37UrgFtzoEKNxyAV7wN516SwqFVN", + "NodeID-FqAXbqQUVaXS6z6jTaLPZGivbLnHf3G7q", + "NodeID-FsBU6yEVf9ZVEhuFy5sRixYwio3LRN9Ey", + "NodeID-FxHNunDVymBHtATSVZc9BusCtFL2B4Gcv", + "NodeID-FxgVB4Wwgg4dZ5WTkkBp9EbwJhAgwZgWd", + "NodeID-G1MJv3mVMjo2SueWzr6rvn1gWyAvgTXrQ", + "NodeID-G46UpgR7qUjbM8U52MStLHuQonVAHQ7ui", + "NodeID-G4Za1ZuLLinkM5skf1LZqAWqKs3P5xs7F", + "NodeID-G7fjDTJ9DH2P3ckC4VqKvH9q9Zqsv9b6b", + "NodeID-GDZpG8cVCndUcnoHiub4XPM5WR2hF7tmk", + "NodeID-GEC1zVazREQmLUpj1fF2qvuATpRvMgf62", + "NodeID-GK8GSuLrw6jk9CVZ7ryAjSTm3pFEmeVF8", + "NodeID-GPc1Si7SQ6oAEfP8MzQ3cFN3fsAtkwC6i", + "NodeID-GR5Hc9oEi2AvNBAoUaQDZtWEYz73jP6jq", + "NodeID-GRG3yvkpJJ1zAxxjpHYuvXaNSgPoWwiaW", + "NodeID-GRTQxKr1NMbxPZTBWkHKUg72jCgtwd37y", + "NodeID-GTgPUiVqjBX1UAFmdDmBoyHuiRhTPrZen", + "NodeID-GTx2HdjpdzYuQEpjrKnuuvXDzd8XPBxBG", + "NodeID-GUUNt9rB66P2HE2Nmke3Bq6Hw7K2pe2Uy", + "NodeID-GUkLRudNfaCjrKSbmAgG4TDVanAixyrG1", + "NodeID-GWRSuAdKF4LjKSgEYFXR1crtjov8vnW4a", + "NodeID-GXtJyspnxHxzLWWyUqJ3xgXNidoxwAtdw", + "NodeID-GYXpBJh1SYjG9heFSV51NVhJHh5LindGx", + "NodeID-GgDJXjd35ewugJyG9tonbjBEKVZambFAb", + "NodeID-GhLyXd9aVH4xujx9SzC9oy2JcQQ5amXuC", + "NodeID-GhsAAVi8nXhvLS1Xv4ast3EbcL4BDU8NK", + "NodeID-GiAS7J8Aiuj2iBAnKT2wmnxWWqp1QLd2v", + "NodeID-GiQ2h9z9qok5FKJV49hitcyWiu7RLwR67", + "NodeID-GkiKRa6ww4zJqXKQUcqHXnGaRKD6JNoYx", + "NodeID-GmQXASjUEx7pRPkJEMeYD23PsxTrStRGw", + "NodeID-GoVFrxwF41mzpVyt6Pb8K83ynj3q2U1CV", + "NodeID-Gohrw1ApuWhwFwUbCLKjS6hbijukerjuo", + "NodeID-GqqRC1EFp63nGjHHuwNZu6NqqqyyihS5Q", + "NodeID-GrL2hD5CdKU4CE8fbN97kVH5DpztHMLPX", + "NodeID-GsGzZFRypbZdhosjortCTbGCHiMGAifhw", + "NodeID-GsoJqaJe9SBrouxVCtSriYE64e2cQB4NP", + "NodeID-GsufzM4GKTutEFEAkDunS2wkhjdUPUvCu", + "NodeID-GtJaZR21ZmzB8CcPYXVA2Ks6Qgb26upj5", + "NodeID-GxKwZRuXEtYMgd2JbXZS1iCeh18NhGnaK", + "NodeID-H4UuVAHhJGARXDJc11NP6Rdejh5chhACW", + "NodeID-H5Kcdpnye7iumF8ad4EHEFxvYzPAg4o89", + "NodeID-H7Wq3A1RJsb5skBd9iy8zY37yW72zrNLy", + "NodeID-HBkBmNgoiab6dDBZ3d7Atiq8ja9achxwV", + "NodeID-HDcjsGMHLaLgJFoQYmi4CBsbjMKPacuP6", + "NodeID-HFEef35BkgqRBYiQ2ou5JhsyB8LHRtyuo", + "NodeID-HGZ8ae74J3odT8ESreAdCtdnvWG1J4X5n", + "NodeID-HHXxANboEXufRMuSFBHgc5dbpk67L7XPV", + "NodeID-HM73QztvPuGikaADwnjpaJ1iKWAABuQon", + "NodeID-HPpKmAyrXsouQTaxMJR2YFgSDVV8BA5xP", + "NodeID-HQ4mk1kjeNvfsan5qrmynaMhQLCsQ4pYv", + "NodeID-HThbCMfRbs6nVRR1ySihYtWLraLZw8x16", + "NodeID-HTkPf7hwzrLyDDjAZAqMNQh9oF4B9iebY", + "NodeID-HTkhG7jLgNvjmLv7uaLzihgofmfKdEsS", + "NodeID-HVYnT9MUfcK8sFV9tRirmkppWiNmFWQya", + "NodeID-HYDf2HUkHFDiUKYmort7tjUFLq3253dHc", + "NodeID-HeWWhU8g5KQBNFaVdwnj2TZLvBVuke7kB", + "NodeID-Hfm8gpD4DpCz4KTzt2osJPfFvu7az3qiD", + "NodeID-HkyME9tYN3G6DR9bvrha6XWNB3kYaDJbq", + "NodeID-Hu4Ap79XGvJrRtLcWikAN7fqorC5cjwzb", + "NodeID-HwYioQttyXRmGzdGAfNcZ8cAkrhfCqSuj", + "NodeID-HyWNPsQZyve88fbwmxgUzq8FnNfE6wR9E", + "NodeID-J3s61uikXhXGVxC8ffsgbctVLV1Mbvxz6", + "NodeID-J7EzGdbSy8EFrQM9bBJXdLfwCoRHtXok3", + "NodeID-J7yqAsDbJ9jXTg3dbszqUoJMgUwDgnmyn", + "NodeID-JAyKNPqtqsmjizdEWgTy8C8dM1tgZ7XNz", + "NodeID-JBWVRVMqqTR9sYFQqESA1V9YQNoi8oa1b", + "NodeID-JBiRdFNc9he8ivyGkdAzH9WaL4GKHoQG4", + "NodeID-JDR81pYzZNZ9Dm4EfFVQsRoopBCi8YRSL", + "NodeID-JHQyndxosLrdixA6TjB6bexisQxCuQkgR", + "NodeID-JHVmPLfE3YrKdBozJM5MEn1BzgMJzUyPz", + "NodeID-JNRTA7Q6t5azWZrT3qaVeeXnT4vH73zDF", + "NodeID-JQGMqAo4i7uXuS49vgaZDeJedDRp6oyuH", + "NodeID-JYJRG5ZYgd6kuQ6RvqHMs9CGh8RkyEpvv", + "NodeID-JbeonHKqomERomXgCiXr9oC9vfynkBupj", + "NodeID-JeAa13owysmBVL3CU4qToAP4qbvnQ1kGq", + "NodeID-JgQWdp2K5yq7Bj2Z3TfGDP8GYAmeqtUQX", + "NodeID-JhWkuVZGeJ42FLktoMVoiGuoaepWjxyqx", + "NodeID-JjvzhxnLHLUQ5HjVRkvG827ivbLXPwA9u", + "NodeID-JkadBNex6QYkFN6MRMjrRq8LHn6jp6qKk", + "NodeID-Jni7c9DhGu4aMvU4axvH8jfnKLmi5iaCo", + "NodeID-Jov5q3HSj2somCAaZkhj3m8VfxpW9TZeg", + "NodeID-JqPCvrvnKgNEKdsKfCnhVcaP9KJ3GWPq8", + "NodeID-JrKGcbdnCzXUijeLiwzJZQNX48Cyrs9Yx", + "NodeID-JvyHfY99GqXXWUsSaoeEEZZ64LQpMCUMU", + "NodeID-Jx97Z1v4Zz6DDG8JKuxfEPvjhfVG18yB4", + "NodeID-JyE4P8f4cTryNV8DCz2M81bMtGhFFHexG", + "NodeID-JyRud4d7Sp77cjoXiuaThBsUVrSFEHgMQ", + "NodeID-JyhVgztS2ZmF3dcYiG62J1owhVLkUU5W8", + "NodeID-K2tnczAaPNak4WDoHs7thRxztKDc3LgoH", + "NodeID-K7X83JX64HEzj4xSLF8MZWNNtUbQmwnn7", + "NodeID-KEkeqcndUcaWVXNjNCXUUbX3gUepXqvCm", + "NodeID-KFmFFLE7HCvT4MjaDxLV2ZsNeF5XZcgTH", + "NodeID-KGfpnGi2LiRyTFfeq866B4skCpo5xuwFp", + "NodeID-KHU8AsLkZweFTA6vMie7E159rbDrWdvUN", + "NodeID-KHbuVifm5BFUNaaSKnqbFHw1npqegLMY4", + "NodeID-KKMxwJXjz4iB6G1VopYYst5W9VJ7dE5RH", + "NodeID-KRibmCkicP8FkeGM5Xm9yykNcrED2sjaK", + "NodeID-KRvfLaiAUDLBEixkmdTDf43nNppas96Mg", + "NodeID-KTnhPkucgchw74sGCrkpuCUmv5y2Nwnnz", + "NodeID-KVTtBgVLRs8umzWJS9gLQX6L4hgvEPUew", + "NodeID-KYr2Ldd1YHibJx38nkQ1vfqzRmsc41Gzu", + "NodeID-KcC4UA5WXJtgRBdhtEnECqxyNcxh6bsno", + "NodeID-KerQSdj93DReMZFcDxqCVqs37jwEQb1Ji", + "NodeID-KiYKTPc1Kz9tCGSy8tYceHs8zLZs8rUEJ", + "NodeID-KjKVvgJ71tiwHGwqBmhQLKGqrNeQBpqeR", + "NodeID-KmzXj1CfPzG2WoTJiXr2DACTksgeQARJp", + "NodeID-Kn1JzoTMNzKS67fuEtcLU73dUTCdjoomR", + "NodeID-KnV3Bcb8A6Yrbhwwzj9XUGpqJRN4ygnk7", + "NodeID-KpdyakxPD8mdLHV7XDYjrtUZ6BG4rXRKu", + "NodeID-KrZPkFHQnZWqdSC76pXRvnPVXBC7PyWWZ", + "NodeID-KvSUP1BJ6rUh32FNrXZdXfJBjiYz3n1A8", + "NodeID-KxPfHCXWXAe9LiP13K5fkKKSoHAzG8z2j", + "NodeID-L2kZ947yAuzugQaduZPJdysWRqxxsT2Ak", + "NodeID-L3eNEFiZPrdiToXvDvcR2Yepk9p23NK7X", + "NodeID-L5ABr7mT84CLoKUePv19PyZBa3d3Xp2GA", + "NodeID-L5SLiTDbpJAgt4VFJ7CtVscaYcLk4L8jT", + "NodeID-LADSSEtszTR1nvUXc87ZaRrNLzhCTbykS", + "NodeID-LCXfgTWLmmxazX8C3JuRbvpzmzqjzT3xe", + "NodeID-LDKGrAwCoz5Tdhu4tVDjqFFQsR7nKqNHz", + "NodeID-LE9q4y22nKHCv1gHSJfUyYY1qXcziLkFx", + "NodeID-LF6k1axP5xwxhBenLMHb7hwSokxRsFiCh", + "NodeID-LGGrrgqBdzT3smcojPh7nTKiPRu4Q8G9g", + "NodeID-LJH9JffagSPthZ4adGRjHByXFytPdrmmc", + "NodeID-LRZMF1NjDo4neYWtbA1vRD6P7rmLKu3RL", + "NodeID-LSsApoxv5refjrydswTevcdtddK4LU392", + "NodeID-LUMxSYFmov1nDn7KZE1Z4RmT1EYgTCu3v", + "NodeID-LUTHJ9cdMxmsTbN6kztgbhSv3U9iGmq4", + "NodeID-LVSzcr2TXAjTTNbEi8Nxfjwk3GQyZo2s9", + "NodeID-LX75T9BwhW85T9Vz9mxvUEQhFqR1688Qn", + "NodeID-LZMzeFFuZvg2fL3JYoAGd8sChmBncgPA2", + "NodeID-La8YHdyQZHuaaoEb6ww2BznRa1N4c54J3", + "NodeID-LaidvDiaEiYSxKhqPsJx3ST2PQKFidmY8", + "NodeID-Lb7Ez9LWTXUeKRUMgHX4JJtg4WNh31JUS", + "NodeID-LbijL9cqXkmq2Q8oQYYGs8LmcSRhnrDWJ", + "NodeID-Le4BWsZM3dAuMXTDL4rkcRZBTyHpC9zzq", + "NodeID-LegbVf6qaMKcsXPnLStkdc1JVktmmiDxy", + "NodeID-Lf75GiFUq2psqfd3e6GkMNuVEYx9BUuuT", + "NodeID-LkER3oCznkUE1mTaRsugitboTtBSxNF7o", + "NodeID-LkdxkfYhg6nSw1EEUxDUSYPXPwmr2cUet", + "NodeID-LsgAS4nCNrjL4gxPmTSDmNu2ywWrPwvVK", + "NodeID-LtUqKXZBqZj37HCNQGqjaor6TZVBVF51x", + "NodeID-LyaNgPqgHTrKSiLdEpp1JPF3Qkv1k6n1B", + "NodeID-M1745j4YUixszHoRfPq52DpyQ4TSiM8pL", + "NodeID-M97sgMKR1gLqZxy83MXhjusNB2rS3YLet", + "NodeID-MEe8K9JFZHtovv515bNciv3YGC3jci3yN", + "NodeID-MGkAX1DhKPPUudKPgP9qu2bCh3h2KY2ea", + "NodeID-MKXBMesCpDp9u2GCPXLhBWXaCKr5LifqM", + "NodeID-MPw5DtJq8yeFFuEj9LrhiM6p6hhdTXBsd", + "NodeID-MS5HLVJTZt1qW3BHmymnFhRaDoMMrD2g", + "NodeID-MSF7z6rWEhimnDUJwwaGTiuWxkQEjT1Di", + "NodeID-MT8bs75x9ZZYTCC2G3FdBfSiSPmW5nste", + "NodeID-MViNUVT7MHKe7jS91EtfJixZG1nDowv9y", + "NodeID-MVsWL9MCUvzXMe17w9d3cdeWJwj6yzvrK", + "NodeID-MZxyHcXmSRh6uLruUmgBEhXRxYge4rooz", + "NodeID-McsVE9skuHHM3ebcFwWLhzXvhpT2Dc8Z8", + "NodeID-MeDZKLP7y9ydHRVixZ54yxZQzWqS8YvG", + "NodeID-MeZyN4H2yUfvu3KuiTFDh7KLctHWni9tF", + "NodeID-Mj7LRrnqPK2UPrAKYHY3aNSDpshsM9tXP", + "NodeID-Mn5pQf8vkLQtic9W6beXzE592Gyctr4qo", + "NodeID-MnAL4QmHAqYihdL8Ad61AY5NuKAtYjz9j", + "NodeID-MnBVormBXdmpzuFUVFX7XVdwoMHEbH2bV", + "NodeID-MnNiFH3NJLWYsH1MU7C4U6fXdzhqtZW6a", + "NodeID-MoW5hERQWaaaZDvy2g3LDHqUNqkf7Bjo6", + "NodeID-MtR3HLYP88Xmsd8whwWHRvijdAuWsPsBA", + "NodeID-MvxNcbGGUifjjh41nnrm7RRsTqmU75mH1", + "NodeID-Mw9wURaGBAXkgbpX5fkipsmoqnWXXxzdF", + "NodeID-MwBo6z1rpGZqbD9xuo3ByvcKTw55D4393", + "NodeID-MxsyPb1TKJzaTxyVvEvYqmkYfAH2NKED4", + "NodeID-MySLmc7236dztdt3jA5znemeaSHWGCg8x", + "NodeID-MzpGqPgcjmT5ALuCnZXbociRiWJTQyncW", + "NodeID-MzqqzQwU5BGCTTTj7FTEG8eGK35Sp4jrB", + "NodeID-N1dQ3zWTgcpnxDqejNYLevSQQPGNZSgvg", + "NodeID-N2vaQwWF6MeLWTT8Y9pBKV2oGjKVxZ6K2", + "NodeID-N59JVgQCpF5cRt4e6zKQUBgDkgyNH5GAa", + "NodeID-N5gc5soT3Gpr98NKpqvQQG2SgGrVPL64w", + "NodeID-NEeaczgsLrh5DKparo914eAz4SHCNrCSn", + "NodeID-NF3dhwiiGHc1MoT85T7MwWk2xLF9zpgeh", + "NodeID-NHv8CEWXzT8z8A4xDU9qDVp9yGfM9SZVo", + "NodeID-NK38Y3Y1gg3duKmwEmPURY5ngYLYb1yAq", + "NodeID-NL8ivcdpDokN2c2XB36iBbqTP2dmtDN2z", + "NodeID-NMqMW67zt1QwWhyJhxa7nqtir6n6hqze", + "NodeID-NQxiZFkiHvPMdFnVQer5K3mPJPxctBefD", + "NodeID-NRhg5SrvPn8CvtisAdgFXA1QkLoPsqRdp", + "NodeID-NTELjonQCqJzT1QFvRdvMSDtJ2qwnqXGR", + "NodeID-NTvmKq2wmTvqoccqpxW7fQd1iGCiGhAsj", + "NodeID-NZeTWb3Ri5eR3tim5hAntmiwEWoLVdkDE", + "NodeID-NhqNSzgKY5HahcosTxbcB887htZgzcrjS", + "NodeID-NjPTsac32vTLnYBmz95TLBmMZZyy68Y8t", + "NodeID-NmGx6qD19PwiQRPwJq5fxfoKc4QUaSYPc", + "NodeID-NmUiTVDryDrut41qnwaNrBref4FMfn9Wg", + "NodeID-NnvANHHBKof7x3k5JFY1qhDiwfkqixzh5", + "NodeID-NtyTVeUSdkNrAEQo3vPLzrqhQfrYg8f7Q", + "NodeID-P8uDYREb61uhJV316geKEMZuUYvkrDBxy", + "NodeID-PA9LANCKQbk9Un8Wv4SbBXoDCW4bP9yLk", + "NodeID-PB6nGgZqX8ccEvyEutDiasS8ndhnrakdf", + "NodeID-PBDjgkEC6S7Y4mRB6j7ffWFmkjCv1S4iq", + "NodeID-PCuSoYTWTcZwQUZW41HpW3VaU5ogsAGER", + "NodeID-PEdsT2FKxpXiemSctvHry8gbZJC6bJrF7", + "NodeID-PGhVwQYM5eidnACK7jQ5ZkL1CnFpKTAm3", + "NodeID-PHiFH2SQRhBFnaNsLVZX179np4y8gjmk5", + "NodeID-PKSwUUGdADabw5br1MosKrSPyyeYdRKAu", + "NodeID-PMYYkxDpE7RPrtmACDaHi6RESLwhoHcYw", + "NodeID-PNXWeCUduveVZYuHRf9Mi6b4suVMJsxSK", + "NodeID-PPCdQBpQ5THZzWrbKAHTdwj5fcx2x3wBs", + "NodeID-PPhqhyAvf9a6XukC5wSTTBQ2VmXoDHamN", + "NodeID-PPoRxaftnXBv7Egx2f4ts7GFNRv4J1vwQ", + "NodeID-PQRNvZxSZi598GNxbH6joNaUPgxaD5Yaa", + "NodeID-PUNwng1LNJ22Fp93S8WHt7MjmeZKbHBxB", + "NodeID-PVrXwPVn24111jS3rS69ufseedz5uvoZ5", + "NodeID-PWko2VpWPb748ARPENzdAfak6NZ6pYG1D", + "NodeID-PWnPrE1Sckzuoj4Di5zBwrRc5q8UYGm7j", + "NodeID-PWxEYBRBbKai9U3t8jgfb2SA8uAECKvju", + "NodeID-PYXgapX8Yi28W2Xib9oNDxuaaLkZ1gZ42", + "NodeID-PgBvqpbMQzJk61yoN346xxrnrHad8y8LB", + "NodeID-Pn9jFroHyLVfDmsEruHABa73mpbnSU5RN", + "NodeID-PoyWPaU4f25ev8h5KQYWrnTdGMiN9scHK", + "NodeID-PpR5kKTZTpF2VstAXn4BwNKHeNEvo3LiA", + "NodeID-PqKQwU5B1hzz11kW9BE4G642BMB6xrdnz", + "NodeID-PqZJgjNLDbeqmSg7hMWU8R1a5HCEjbBP9", + "NodeID-Pr6ZsMxfFr6uyMyZeN95ZJ1yHqGrDhqRP", + "NodeID-PrZZEFnhrsgdbWr7hZYBw1vTpLpkntFLv", + "NodeID-PtHsgZydMzwYNT3GcUXmaKptmScFwJkZY", + "NodeID-PwWYr47hP18fedky9LpuN4iNsjWxHHjdP", + "NodeID-Py6qdStyPBTqcLxpiLVWAz4CmJ3oHZLHd", + "NodeID-PzPoTUQaErAzPd5EBdRzJeNSFr1kVMX3h", + "NodeID-Q2J1vGj5FvVz5rDST2nC2saG1BeDofUbY", + "NodeID-Q5Jk89SmFTSnxonorozufMhqnyY1RiUQx", + "NodeID-Q5XuPs5dhsQRuGJebnzStvyF7GKWt9JVp", + "NodeID-QAnYYbuWU1PfEqVFgZQz9EHKEWd8fky9z", + "NodeID-QE8ipEQ1Sc56Fa15G6HdCfUFk9SpFRBjM", + "NodeID-QFG9ZiXr7boyFonB2D5B4MLfPHRgQDwLd", + "NodeID-QGGJXjdsv7EKVKy1EG5Hq9GzeFcNFMbMh", + "NodeID-QKHoaJm3tfMjTcknMuCtx4HheAYHpQ1iP", + "NodeID-QKheyKgFVkDyMxLcnoUHregsKHFuzuR6h", + "NodeID-SCtrKtb5k75f8KUnTPj2gBsq6yrxpmk3", + "NodeID-SvkCVFNKhd5VEo8Hgdky2TyxZ4J18NpV", + "NodeID-TJvKKLYAycYi23bnFiSFpq9pZBNktyer", + "NodeID-UCaJK1qXng91C24jExSCkRhqE8hSCXWW", + "NodeID-UujvYYJGbxFXh357EMppUFsXzPKvU3sN", + "NodeID-WqHQbG5MYQAYBRzjJV3qqy263mbz6iko", + "NodeID-XHq85YsvM6SKvSQJiBsEZuZ9Zcg1NHqn", + "NodeID-a4kVGB6zfhfHgz3JpoLY7Yqr6aXM9BRv", + "NodeID-bQd33gr3fvRae95TLYkF6LcuyqrJeKK2", + "NodeID-bpSs3H78Q6kdMPHyy1WAYGdVXhVMmuWg", + "NodeID-c6NmA1sCyFvKV6NeKBndEykD3a5Y3Svc", + "NodeID-cCZxQ6nBdNcPMpKdKHHxm5kjwfR3caTk", + "NodeID-ei9CM9pS3ePsg2UYUrdRRALKr61jyJav", + "NodeID-fJcYnNFYcnf9Tn4sLVPSyKnpFr7yivMH", + "NodeID-ftRqiSfcMstsADKTtMnHGX8svv95tPXn", + "NodeID-fwEVgpiS2sV9LjEou9N9dd86Ud1x2Qyq", + "NodeID-hArafGhY2HFTbwaaVh1CSCUCUCiJ2Vfb", + "NodeID-jRBYRTWyowM2FUvfyZkg8cmhtKwqRYb3", + "NodeID-kCqLujZC9JuZp7sqe3vhffxgMgVwq7bu", + "NodeID-mce4CCkKp1Vx9ck6FwtjQVbTyUSvKe1V", + "NodeID-oRUBcQ7Lsrxi2S5bmWGD5CF69e2x8mct", + "NodeID-sd3N4YhnSr74bwpzbBU6ADqRAt3XxiPw", + "NodeID-tFgE4qqgLiivtexeoojvJgSk7eHv1HRU", + "NodeID-tVTPo39FS8aTyQ7DYrzFpCNdWjMNegwh", + "NodeID-tkLPZudEk3RpVG2DLq5jfZS4KHLJf27E", + "NodeID-uoYEe3FynohdxKEaHpvPeQbLajgNGery", + "NodeID-wvLAxGEDoLcPaTWzEkmV1n7ipXFiWAA1", + "NodeID-xkyMHEuJMHTSngLzm5GQY7r7GmoDoFRr", + "NodeID-z7b2btT1NfrouM5xCJPescQW1QxWLq2v" + ], + "mainnet": [ + "NodeID-12dyQ7nhRzsNSiFzEoW1RWK819Zkssf5g", + "NodeID-13XrVPjS5dVxBKaweeG94SjY1Q6yeM4EJ", + "NodeID-15AuPME9h4AS8CAEDsokNE5KMjLovnphr", + "NodeID-15ngGTze32Rsr3WgHyLHVgcdqnY2eyFo", + "NodeID-168kTGVaSDD9CsPQzbqMpQg6zUvKatqr6", + "NodeID-1A1GTyMcDcassSiTBZFVuoXs7AS5HcHu", + "NodeID-1Z67stQzn6v2hi1wD1Zd7nooPoqJE4es", + "NodeID-1aA7BtLfTX4SRXaWR8HttP4z2UapE1R9", + "NodeID-22jB4hF45iUrVhqiHvbDETRgpHKJdirY3", + "NodeID-22k7HZj3D9DSAD7ujyvvuYn8XzWuwA1Hi", + "NodeID-22wjev1roSt8jieZ4SW8rJLG3YiWyvbV3", + "NodeID-23Xaok4Hr7SgTcCjjMnVsYJaN5cSZLR3Z", + "NodeID-23jyZenUu8Fm26ebdyXEEVH6PDoEXJ9j2", + "NodeID-24gzuDUUhGEsAGbxhMZNJJ2x5G1wDVHEo", + "NodeID-25GWqcvqc8m2ZT5ULNWfan5SEJNFBZMcw", + "NodeID-26VN5FUvCmFWEhHm2k85hHn4rDqyKsV3W", + "NodeID-26jY6nu8uyVyQLQpi3SMdvSTbMTZeajHD", + "NodeID-28wbL4a2ozWTgYXt7NekGT12h5wp6UyKg", + "NodeID-2BSvxuZFVVSpjrezuABMPvC6cLMwH8TT8", + "NodeID-2Bq98e7Q94vVWipc5tv9jCL4aMxL7pjxr", + "NodeID-2EH9c6NwjHLZLWC2Ah3vekv3XUwcup62L", + "NodeID-2F2gRAyyVkaNC7jtPzJ4zgcQh64QyMkvx", + "NodeID-2FNBUKXo8ShvqRgGhEUF1FxYC95Rk5qtY", + "NodeID-2HvkjoRiMzEcZgpWKNAruLKNv9r7Lb2pv", + "NodeID-2HwdM25EpGSt2M2BDaYREmGJrbYNudMma", + "NodeID-2KSietvSEq4mX2C8p1DAT83RTJPykxUqN", + "NodeID-2KfgS6P7vf9L55fMRTbHPgS4ugVSDW3nj", + "NodeID-2L2wFDTAv9Ti1wpqbFzqLbTa87dMw7QQM", + "NodeID-2PZiqgTALZcdU1TUvQeypFARYEgjkQZPg", + "NodeID-2Q8DS1hgPgsaMB1y8VqmxeworYJ2h2Ubt", + "NodeID-2QKRkQ1A9DTdXPAuwVC2DYWPBNmBpgZaS", + "NodeID-2THa3uLP7oEvBj19k4E4jm1tCpT4muhYi", + "NodeID-2UXMFjdXTw96iQHNL23PxH2hcLJUxnWic", + "NodeID-2VJfSPqaevBmiJKSVDnw7GBwsdfgA1XuM", + "NodeID-2WfvcQumS36rdyubDSioc8B5YinToKAaf", + "NodeID-2ZtHY1RPNrq1y5YuJLaCShK617g6CjRsU", + "NodeID-2aCXkeemxpBXiFui8BX1tVpyVsvhoZCU8", + "NodeID-2bRK9nCjngVig5fMFjLhVgqf18L7dbTj6", + "NodeID-2cH1ggEZ8Z6CoKoQsEeZudUy5kEihW4T2", + "NodeID-2d3ZJcLUXLyZE11hw7FUi2YM3nUkMvvdP", + "NodeID-2eBu8RjbvCFTZMcxu1oh2oKtfHT7V4zyM", + "NodeID-2eJ2XJDpUagguhE9wKFR9JUxYNaBk49Ko", + "NodeID-2eraCsE3WijaEnkcFX77hbK494TneHXkY", + "NodeID-2ff3RLJaMK5VdQ4jnXELc9yas4iKoKuLG", + "NodeID-2hoNSdthtVU9RE6g4VJ7Y6tGdWm3s1PKN", + "NodeID-2iVvryG4GyPR5XBQebYMMVTFYfsNKy9oB", + "NodeID-2iWqUM3VWvrcTLyXi2KgBLVhunMvFW7vY", + "NodeID-2iY9tRvYLGjeGtjnUGyGbMz7uoaBdZR58", + "NodeID-2jnJ9jJrW2EULmCCNnZz88HHCAQYo1Bja", + "NodeID-2mWa8ytKEtviCNwmHfSPmDvkTGPLH3kf7", + "NodeID-2nfH8Mmj5ZY6Tx5oD8ebst7prrEmbS4Ex", + "NodeID-2pC9PZWbWLdaxTuXX3zvh4xZ4WobwiExr", + "NodeID-2pN3EtqAUKWvJedQvYfPSgKeonNmFn8bA", + "NodeID-2pNQqfaBqMqwWgeJiqPbmHZk1cUtWcjqb", + "NodeID-2rpzBQ931ezzMPY8EKKivdZWfkiWtAyvZ", + "NodeID-2sNYafYrpqSjsGspW2emjd6TqNTtWz74S", + "NodeID-2sspVTzGYqTkeiQeBsdFKv57gWpLg6Efg", + "NodeID-2uA1cSeJhPtYgGtMUcnGgjesqAK7LzpQw", + "NodeID-2vbdREFyZitz6LvSBca5gCe3eCPHZGq3b", + "NodeID-2ves7JhkWUcLfPWWtKVgh7uvJogz8HLnR", + "NodeID-2wWroHMggzJvKh6t3tdPtJTTP9DNmdc4K", + "NodeID-2xWeMjBPrnJejBo1vFiyNZzy2FcquZnae", + "NodeID-2yC7fWX23kGjCd7ytqGzQQcRJf7xaj1N1", + "NodeID-2yZivvmC5XD2M6CwcVVBdPGGgU3MNta1o", + "NodeID-2yrtwg1pRGi9jB6ayaXgpNbMTeGHUyofw", + "NodeID-2zzp8nVwqw7ssQsMXniESwjwpZYMzeFsa", + "NodeID-313g6SGRoJXgCh4wVo8YpXyhDqkKVG2hs", + "NodeID-31xXC3YuXN5S9Bv9d63kH7ev1vuQKG3wR", + "NodeID-32EFwYSrpMmuxwDsgGf29ouKrcPquTQ5e", + "NodeID-32JAXT6PVdHqpvDuXXHfWrFLXg8oZGqiv", + "NodeID-32aVnE9HYv1FesKKbvvUh1ZvFU3ARNtR2", + "NodeID-32dhPQyEQArm4ybXTxAvAAWAap7DkZAPh", + "NodeID-33Ztk39cwheRHZbWLMyrNFUea7y7VoaWW", + "NodeID-33miCHPn9eN8H9Yi4bCzEaL9Sc5BLeKMg", + "NodeID-33sja4uJHmJ3fpDDu5byuG6V8icdSAke7", + "NodeID-34HkMQ1oU1vf7wNpzY9xWCiazE2tGhyJs", + "NodeID-34QP8d17f1XjB778dCTCsBfjL3T4PeMAf", + "NodeID-35rq6ZWsLWs3coxC38LACEayLh99jxMav", + "NodeID-36Vywf4J2tu9gA8xJCxZjwi2JABWSF7qo", + "NodeID-36i6jQQTfB6Z8NXFPQJsY3FVukaSGKTDp", + "NodeID-37Aec6FfbDxVtjLNUv3bTsaXWaw5EGUrM", + "NodeID-37ZMQ9ZZ4e7ZD1kmRg1WSTpRrEPSQ5LGT", + "NodeID-3A2diR9QLdWU77zW1sS39tAb1rSYexhSG", + "NodeID-3AMVspPXZimHQ3yqWizDf1bcW3GjL2B2e", + "NodeID-3AUVAzMqQ66svzG1H7JVgURhUQHU8Y3r7", + "NodeID-3BVt7MvqaJ5jpoGecuNzzdz7cqGTKUjLb", + "NodeID-3BmiiYjMNvspTqKKo4fXJWbjDbaaWRNXE", + "NodeID-3CHc7PuHw5sGxtSVjujpHRxgiFDSFfucK", + "NodeID-3Cbz64Z4cvF1ykJ2vP1h2VmUFwgZHRDgj", + "NodeID-3DwhPYMEQABuocceWDAZEpi8GMcLyvTYy", + "NodeID-3DyUWkRptB3CRUVHk39Ni6Dpr6QvGWXwA", + "NodeID-3FhRFK6UxSfMED5EkK7jZT84pFZy9f17D", + "NodeID-3HLAgdaA61zPrTx5yQ7Cc6waKWidsiqMT", + "NodeID-3HvUXQy1siDNUBGWMYxwMfjufh8mxLtQY", + "NodeID-3K3PUAqo3cKxRoQyYto1EsXtuTHoDZ2B6", + "NodeID-3KAxYX7JeLQgm1fwzVqbzjow6eNzSS9Aa", + "NodeID-3KX9tgCEQcTHbC8W9yY4zY32Cj3ET9MNQ", + "NodeID-3KyemFW2jou47TCfoJG4YQhtCDd6Si64q", + "NodeID-3M5i35f5u99QbBn6fP1FzeAto7NA4TFKt", + "NodeID-3MFu1eLpGRrRcWksHJLBuk516Vk5PoYgC", + "NodeID-3NJgvio7B47MB7BZWm31LHzbPWVdkEiEP", + "NodeID-3NXS6ZAzHeqV7w4saG4vXxAd4tcbpmxfk", + "NodeID-3PJY4Rpb5BRR3xSUvuU5Dj3cyHcAmzfjD", + "NodeID-3QvnmD9KrJt7BcoYytWfCsCD83TmKo16d", + "NodeID-3ShFK7JbJ2LN2gFT2W4iXp4N2NVuP4vZC", + "NodeID-3TWEGuLyjvyKYLQqXNvQ7GQqSNoSQrviN", + "NodeID-3U6UcmBu6WVCgodXYsH72VwVKpgE4XomQ", + "NodeID-3U945Ju6EUzVaiA25ea2BvaapV111iqcW", + "NodeID-3V8B3h9bS1cQerQMF47sw8Tr9jmJz4uHG", + "NodeID-3ViTS5vVn4uLoQQ5d7Qs8mF5eYvgQcLQe", + "NodeID-3W61mLt8G9fVa3VNnNiStsbqmkeeSPQ5U", + "NodeID-3WH62agC9m63q5SmAyPvhhLygsUjboQe3", + "NodeID-3YkLrm1D9MqZ6K4YTwaQkt1NBb6wP9Ldx", + "NodeID-3Zbddv2qkn6gWAfd12ysNN7N9EsDTjc9v", + "NodeID-3aBrvkLR4sqBEdeRoj1WsWDeWLuoiZzZw", + "NodeID-3b2dLL4mSiGK2gx9pmML5n2Za4T9pLHe3", + "NodeID-3bciNCJdZcW5k8jMtHujT6msFbGMotkSF", + "NodeID-3cqFtBUEe4LgkL94wHotgwtEMhboQqxr5", + "NodeID-3dan8fxgCWWJZpNUkrBBEw1vhL8E85h4i", + "NodeID-3douD9GDP69zSq1eMzRAYfKCUVtjEEUCt", + "NodeID-3fntmpjeW5JhEgbVfKT9fy8xeaMg4tquo", + "NodeID-3hcHkkARQk8K3voT2NBHf79NFYonQkvPf", + "NodeID-3iXKmHPAMgJa7z7pGcPpMC6pAmx8fjM1q", + "NodeID-3iknBWGJowmNu2d63Qv7mRM52xoQ3mCoB", + "NodeID-3izZtcg2iecpF5rEkQF7Mwofd4puVGZwz", + "NodeID-3jYdfpPubNVyDqKkVrkLfDyy8RtZr4wBg", + "NodeID-3kGMSCRnasr5CjsgNm1D8FbZnY4C5iNRE", + "NodeID-3kTMjX1jJvdH2S94GHLi6Qxy1DKyLhuc3", + "NodeID-3kUUeZB7umtaENekUfWxa1bxrAU2eq1AD", + "NodeID-3mvtMQ554k7VbrbYFUaNZR4JmeCoggD5P", + "NodeID-3oJ5XYknQTmDrwTkBxLx4DCuFgFKFP2h6", + "NodeID-3oaegcGaKyncpiWQCzEVd7vN1Vcsue3Wc", + "NodeID-3p3GjN8gxjGNpFCEKyErnWoXJGENDdj7W", + "NodeID-3p3zJHazEyiVrhRXKL6jJds5esWnwzbW4", + "NodeID-3pSYSkZy99npP3NS1UfES7beUM1y84EjP", + "NodeID-3pfvvxwJWQb1w7KrtGfGhd9ZtLZhrBrBc", + "NodeID-3qUq9jKXL43HwdMEov6KBsnCjcvWXmAoF", + "NodeID-3rw6bDxFFNVoRnZmBAnTV4ZEXnkjooVq4", + "NodeID-3tTQWaeudKziFWpbmzbawLJTunDsQnjnu", + "NodeID-3tjM63VDvTaHkhzxWxV3zrnJjAfHFAgfC", + "NodeID-3txc7u47G8EyCyD5aSZdTxeVdhAWSbpoa", + "NodeID-3vkjzH23PgBPmHixW9xpdUD9vndf6ffBZ", + "NodeID-3wd8cyGCDmhuoZYWmNDab2FhAVpnKYKJE", + "NodeID-3xtitFQ6k29E476KCq7a6CoZtDmUgKqmQ", + "NodeID-3yiw3g5Rer7repmzoJaATJpkf7GnWD5j9", + "NodeID-41CFoAtQx8Bqivuq3tkg5oqnj6WpBz32S", + "NodeID-41G32TrnmUaVZUbWBSA6oyUZLCJoz3m2V", + "NodeID-41mvUJUdqhRjP7pX9BB7R89PXkDhC7f7i", + "NodeID-42kmqmMDkmMyw2q6gS1uLi4wiXdC2NLwW", + "NodeID-43AKDBv1R4hvnt9bjDFA4SEcwFMzZqpXX", + "NodeID-43LKNkQ9avhKgVj7KrHXjq1bYi6mvxQ2C", + "NodeID-45hNv286MEyVSjGrtiYLt3qqnj8G7FecS", + "NodeID-45kFbHHYtgXEXEy53LCaLMBE8CA5XEdKL", + "NodeID-45p6WjZk3E9Je9Sw4q4SvEaagbYF7Jsud", + "NodeID-47pbycgGRRWtAB4FZ5fJZApoeG4nzv41U", + "NodeID-48tcs7C6Q7sBPrCMJbhWNAMj7bEnnDVNE", + "NodeID-49LTjmBTcdjMyD33u7gKkfREPqEhhfPaj", + "NodeID-49tGSAiEbwhRcTvnu2EaskxZPiPb9Lv2T", + "NodeID-4AW19ZAJMCyr64UKfFAUhZXuZDtVshQ36", + "NodeID-4AWHc6b817tKesbKJ22EAEsJa4GkrDuNE", + "NodeID-4BQYSFMqtFcjNgwS1bQgLnzvoKqqMx18E", + "NodeID-4CJDfSDWT9X3hTosPsgui1ZRkBNRhX6jV", + "NodeID-4CL8XnuYqfVVLxRre5C5A1dpRv3cZN2Zs", + "NodeID-4DHwFAw2xZ8HuSu3jFzMU9cXvNhUHCkZ9", + "NodeID-4GFFG65jrNUU3X6vsZKgUhmz5iCG21nyS", + "NodeID-4GcMxoKhvXDebqgeZq2zKWPgQZF5aDPm4", + "NodeID-4GkgAWZzSWHi3hZZLjLGes5HwuJ5FXDuj", + "NodeID-4JcnzK8FQKGHGMt5EQHRWgBVxxdA4sFy7", + "NodeID-4K6rXew2J41T5LTWmTi8AjMbUFsidXGpE", + "NodeID-4MqtiVkCYGD4TmoBhH3b6a6UTGNrPhvvW", + "NodeID-4PKUhJMxeL5C7A5epar2X5TAAzXLqH44r", + "NodeID-4PTYheMTMhPZvYhJJ1Hj2FwCZSR6rSWsr", + "NodeID-4Q7EdeK1p9JkHULo5nZ9KVwgWYjDjDf9F", + "NodeID-4Q97SD75d14ikayvi4C21CkbdoaboGonV", + "NodeID-4R4zmBEWqY3dCtKHmvDd56Dupq97UAwtP", + "NodeID-4RV8eRbw9andBLK2og4rtt3W7txBmSuxA", + "NodeID-4RVd14QquiKdEXitdrnTuZiYpaBY1W6QM", + "NodeID-4S2uvFvPmHh2Q4f2To1XznG2HMsyohuA1", + "NodeID-4S5sLovGppHvP9uv4v6jZHV7JtASRpUUk", + "NodeID-4SvFyvJPHPYvkMnJqBaNcwr5yuU8sCsem", + "NodeID-4TSV8FnyRHrVAmPALXfvLnGaHGspS5W2R", + "NodeID-4TaEnGcWM77nvEityjYDxB4zYdLQ6LiZ1", + "NodeID-4Ubqsj2vfwdGUUYNg1jtYpkYNNLugNBQ9", + "NodeID-4V2KBeNd58jdBXej3ohL8E5d1bNTTp4tT", + "NodeID-4VpJH4PkkQmg7KrJ9z3czh2Uipg16PRYt", + "NodeID-4Vs1rw4jmL5QersqfLr3qB9HmyNtfeVeK", + "NodeID-4WGNJ4vv6bH3FLCJgovqn3D7RCJ8rKBDR", + "NodeID-4Wt44Y2AAuuD8iRvFfh1va5K7p7v697my", + "NodeID-4Xw1ekhVqhHqzZ4pLTPtofbTZxpkvcQNi", + "NodeID-4YYQc96D2kyeXh2z5Eb9U2owhPXKPJgS5", + "NodeID-4Zw4yFm9gJwULZHsgYuG7AbFKUJ7wuKMh", + "NodeID-4abzhcVga2Mc1BJYEfypmRVtVctYwsvpx", + "NodeID-4bKCgF7VcG9ZtcfMwAVFfBJoh2xDgvz1j", + "NodeID-4bajtcpjERHRChiaYpovKU8XE5qAE4usY", + "NodeID-4btZGj8TmrycK22kwgBK5wJEFighAFWiZ", + "NodeID-4c9S7HLgYom8eoa8So5ZrfmzZVvGQpLNX", + "NodeID-4cJyBoufFfiMShtRhcd6WGTYdvUCE3Ai4", + "NodeID-4cuTK1XYjm1VMTitd4MPBcwZ7LYyiqjfd", + "NodeID-4cw926TqMXDNo7QyraCShjWMXNSCDZqMQ", + "NodeID-4cwQT5hvhnhgYM7kJia4MK5kT8XLVZSNz", + "NodeID-4dJTYbWkF82oeT3gYAjoVNNbaga2zXsy4", + "NodeID-4e1C32U5TBUFuQpykL6rSw46RijbjdwRz", + "NodeID-4eaj7e8pXaR1TSuCF5n7tKDCHPPemZGky", + "NodeID-4edDKb3xKovZjTSuFbhNzJZ3Y9KTAzDaQ", + "NodeID-4fK92LkTyEUzPoDW44Bo9b5YvL5kJ7369", + "NodeID-4gTwepTF5fcacXB7gdYZLTtfSFsYh4faj", + "NodeID-4givb8yw6262YETrNnm4hTSRPeK4qEBfk", + "NodeID-4k9FLLYj63sJNrrGycj6MTRm6JqyacEav", + "NodeID-4kCLS16Wy73nt1Zm54jFZsL7Msrv3UCeJ", + "NodeID-4m1TLqY9ob5u23YrJx9zWDj11dz6DmV19", + "NodeID-4nc9Pi32BZwWxcM21U95mVHsbExbPSmkq", + "NodeID-4ngWFEcMdBhXKj38YwJA29WS3mczGNrNd", + "NodeID-4oA58fddyvuKuRtqanZtp8V1Sz9mbr6sS", + "NodeID-4ofBXitDMQ6QZi83yvPjCYn5LG6HBwqSn", + "NodeID-4pZqGB9JdyanFMVQEeq5VZ6YG9yZNsCF8", + "NodeID-4ppYtgngzEnrgBZ7JUVw8bTbaBD76efcR", + "NodeID-4qzj4sLxsLnmhhktyTyR3BWXu8nXTABnY", + "NodeID-4soc4KzELnfnTLLw4FTgpEefZpE6aSQbw", + "NodeID-4ttQXnMSk443JHiMCRaoHBjjLArwEWbya", + "NodeID-4uHXbHesQbAzcDBRqaFyJ5kpgovHpU576", + "NodeID-51wXjrXuQkpHqgnyZ6pgQVbiBwTWgVQZi", + "NodeID-5517ZjCrBhnLs1aqw2YVqRopDnAu5z8FT", + "NodeID-56PBmfRBSmT2sYsPLiBPKVq2fQUVGEg9g", + "NodeID-56RnA8AJBddFSt2rrGu5WmsZF8qW4zNeP", + "NodeID-57VYS3UDdnkurTnK9WVzfpNT4H4V2fCmT", + "NodeID-57o8JLPG29tydZsDVGuD8iBZ3rVorYeoB", + "NodeID-57vP1ZP91HztWSRTHurGdrMSw3TWHYumo", + "NodeID-599kjqvHr1rEhyvT2mFA2whFJZS2Yoexg", + "NodeID-5AzNzec73Pth9Acw6jVd2BYZWyY5KjV6y", + "NodeID-5B2Uyysf1nWcRbiCYdKwXzevVF5a7sN6T", + "NodeID-5C5QEUprYutWMbxYicmQd8dUFhc4eh6TW", + "NodeID-5CDfrTrcGndVpY6qtuWsKWLm3j93GXyey", + "NodeID-5CjaXtU43Zar53KzzGHqZrmihayAdbFcb", + "NodeID-5CwgaeHgQgWbeaMB2ERYZ1ntrhKCmSs5D", + "NodeID-5EuG66om4jxQDK8hRFyq89SsMqfdvESew", + "NodeID-5F6HiZ34F4oRtMX8PZoJcfvQiH7K9mGSs", + "NodeID-5GPPVZdPNj8bicXQQcYGCtksCSReksKaw", + "NodeID-5HkCsXm4TQUb9uXxM6Cjy1WzvuDSspPui", + "NodeID-5L14VfdhVJvi4GowA2zgqj78bGriVMLxr", + "NodeID-5LGFWx2kfwMZXpyG52FkRtrfYfVRimjh5", + "NodeID-5PMCtewYFfdxWmE5gcxuZeXAQAxHqMhu3", + "NodeID-5PMGUqdapvGYEATmbQ48hMJTwcYyKFNDg", + "NodeID-5Pc2rnbGHgdmVtThh6fn8JqGVJavn9CrR", + "NodeID-5PeQVPLrJH9xiSQZ8hcmeXWtUzhcArEhQ", + "NodeID-5Pg156uQvovbZQ3F6JKUiyAg5MrdFseMP", + "NodeID-5PvfcnfPd3MLnpq4MujxvBQHPwtdjYk8s", + "NodeID-5PxpmHkfB3gNh3spZWuzEKis3DJ8WKxLt", + "NodeID-5Q8GBt1GY6fUToWZ9txSGzWr8QTDUXKJF", + "NodeID-5QV9Tg6tKyGVWcEQM7vmAvac5w3f9wtp9", + "NodeID-5QzeGmasNDHSxzxBqiUQ9TBPqkkwzJWGe", + "NodeID-5RuEXmu7SJpf8bwuY17UpMpoEsGZRWnuj", + "NodeID-5S729stbM7nFyWHdsoBeFzo5NMUXaTrjR", + "NodeID-5SmDUGU8WwZkvxKMnjwKAYvfa9w2qEe1U", + "NodeID-5UW1pHAXDJi1tRFfGSEgujuExMztq6sCc", + "NodeID-5Uf5RUZ89pWtYj4Sgc7pxf1mkq2f4EEMW", + "NodeID-5WCpR3DKFt9665Wj9jDCTdncLNX7AbzfK", + "NodeID-5YX9uqiPm6hmJEmDy2fUyvFEjvSvSbiWE", + "NodeID-5ZXpg581dpjG8AdoJgTDeXXLnxrQc9Wtd", + "NodeID-5ZYfA8hgaSvUmXbsLjmu9aCy66Ha31obb", + "NodeID-5aCHiSvLejirNRt8Xgw6SNzd1dDq3XviL", + "NodeID-5bJYpPDsUq3JpGJrFjVRtr1GybXQDP1M1", + "NodeID-5bNomTz89SyKffJWnEZGXXdwvSnZanVTS", + "NodeID-5cL4dSEdWWKnzZxvg1rqen4M31YeZhFkf", + "NodeID-5eFuL1vXb4NSxW4ZF16WZsJM3gyjS7i2Z", + "NodeID-5eVCCzU5VQXhj2iqpqneRxTUNSD8aCJki", + "NodeID-5gcdejFBQ3wMPFpo7qKUKBREJ8w3PRTM1", + "NodeID-5gmMRqNob9UjcgroCKH67bQb9PVwtnoeD", + "NodeID-5h3GjwRs4cndBMxxfRpuDMyrX9SF9dPoe", + "NodeID-5hNGcpQHUrBDd19vV5QcugACUAmwiWU3D", + "NodeID-5hSVoN9CgKTxGVj2M3pXBDBYtfZkjQF1D", + "NodeID-5idht8398Yg1AqYyBkTQf2kN7zFK1J7Qn", + "NodeID-5mmVqScHrzTiSa2WVjo99g2yzL83EBS6W", + "NodeID-5nWWPwUZPzdTJYGXJoWxzWj3Xm63vLL7p", + "NodeID-5naWZjifbRQdBoW5bDtAcvuFjKr3k6G2o", + "NodeID-5o4eWuhvE9cmScEoZHr8ngGebxa94rFLo", + "NodeID-5ppnn5JSeWMAznssuPMJujyJhzHkXHN8E", + "NodeID-5qr8okF4mnAB2JhAvaJuwqMGXN3gi9QXD", + "NodeID-5qxuSbJfb3xqgNQ2pFycD4ybuEH3ATg66", + "NodeID-5tUAsBWWmhHrLnjmieom6twf8YREwfosQ", + "NodeID-5uYQ6R4WF7kmGfraM9LtsUJG2CDmh78Lf", + "NodeID-5wCTAXLJSc5i9RpksPG5fFZXemq4dm2A6", + "NodeID-5wQr9SafAyQ6BKMjtTomLB7Bc4tg8iYD4", + "NodeID-5wUKLtxUEckPyuzLQSozcPmqVzMRx6v7j", + "NodeID-5wf3A9TPUALDHaRhufq3Ry4jfH3cA9SEe", + "NodeID-5ww3vwysnrzVzMR7wMTohEYS69tX7sKAQ", + "NodeID-5xEL4zcSuMjZCEzY3WhQ81Sb1Pw4E5VL8", + "NodeID-5xhFgBpc99AjBEXqfzNAG3W8mX8vnmXWZ", + "NodeID-5yYNsLs1TZoj93f27GD1CBr424tZJVpVh", + "NodeID-5yhiTAmJzTBpDLKdXSiZ7Puu5c6VSJtDc", + "NodeID-5zENHPe3oP2SdU13oTAvxZA2cEupejYhD", + "NodeID-5zP7p1nk2KnAL4SHvgFWcF9Xei3Q13CC3", + "NodeID-5zWQQHoMSd29NfKUMziBuccvtt2aahnHH", + "NodeID-5ztBWB4caxbw121xfsXc9JqsknrwxrRob", + "NodeID-61rJbupdhGqaumerueZFVVJT4Sbp4fciN", + "NodeID-62XYpHtuv92hHhJJXVd4wxJqPFv9rbWA8", + "NodeID-62hEBGiabBK34vV52kGT64T6S9QVcdMVN", + "NodeID-62hKwt6g9MMngpDLHapNFJmxXRcDoe2sc", + "NodeID-63JGDZZtRyCMUiGmqQcL2rxXx4MrbNzNt", + "NodeID-643Sjdbh4n7krQXPSNbSK491xfVbh3hqy", + "NodeID-64Y4Dq4dwfnhTjNnZEFjCexmc2Wwi1fyM", + "NodeID-64Zz8dh68ypXYWaUcfkXDm9UuG9VNXrk8", + "NodeID-65KSgMC8R7CjSQoyBc85UMjW9YZ1cTKke", + "NodeID-65zy7gGi1v2US2tkBFfjpwuDoWVPjPsZW", + "NodeID-68ZngAKzsRbzQMq4CpuZ41J7AgCDEijPp", + "NodeID-69vkfdsq14i5HZSd6m2kUwRAu59ePbeWw", + "NodeID-6AKFYXuxWErAD6nqqFkPnbwHzXB1JC4VW", + "NodeID-6AXAfsfvp25QX5Tff6Ag6ERLXQ577wurM", + "NodeID-6By1uWfbKV7Wzdvazj2Xe4Ncf1rTfqWAS", + "NodeID-6CGouDLcYyiuBY9xEi4rEaHCoBzH6UQrS", + "NodeID-6DqFjxDUK7nh68zrFDE7iHfVsXvoM5yzt", + "NodeID-6ETncdUXndB43iT4LijRYLHF711gWeAgJ", + "NodeID-6Ef219qf1xYjFL5SCFQo29ZYKDrcNi6xT", + "NodeID-6F2LZ5hykkwmnRYYabqHH19MnzknJ7rij", + "NodeID-6FSSZuuLEZ4sHJZGfpY4Wuz8M3qnK6ec5", + "NodeID-6FWuMoDyCe1gsmeQj2RsGBmYv1hoGUbzs", + "NodeID-6GEno5sempCQdCZvTEuPZpDLqVvpN2JEB", + "NodeID-6H4xWodWdcEbwJxbyFyz8ycHpKpAPF74W", + "NodeID-6J3LY7ojkK7WCZzmArvxEozaESDMb42hX", + "NodeID-6K9dR5Dx8YkPXzYeNvDRBionRmEo6HGE3", + "NodeID-6KsZqkvobK4vUHJzo2VdwxWMsbHtXCZPb", + "NodeID-6LHDq7hq3PS1xBj7cFQuvxozaM2hJXheF", + "NodeID-6LRbs1K2iPGmhn1EBbX8u2udyPbUt5S5x", + "NodeID-6PS1ECxRbQ5x3wj31utVWecd9Xkgcp8sb", + "NodeID-6QD1KNQkx6wj142Tv6demd3FYbghQvCM2", + "NodeID-6RsvR4PCfMrZN4u1fYdx2Xi6Lu9rUjBUT", + "NodeID-6S8zAjmFJ4JdZwPURyFGp8Q8tqQ5NcEbX", + "NodeID-6SwnPJLH8cWfrJ162JjZekbmzaFpjPcf", + "NodeID-6TG73ofz7EU4keEwv6jt2xLrpaFzqXnYR", + "NodeID-6TzpKmXTYp2f1ok4rEzEAgP5b87FSQ9G", + "NodeID-6UMb71Emubx62ZEsNBPhhuEzZdqgGpKZY", + "NodeID-6UpNHJdkRQM9TRX1m1wb1sfNX32Ze7ZhA", + "NodeID-6WwTZqp76ms4iEUepaagpeEsf4N4saDGb", + "NodeID-6X1FD9gZjzSfGP7E8v9cxXBo2ofhHLfGq", + "NodeID-6XwiaBfuKwKG761Bc28jDAsiFJ2gDuVgQ", + "NodeID-6YNW6QK3JDpCaEnVNsG5wsNA1SvxT1dhP", + "NodeID-6aZ3KyGBPTcn6NF9K2jpvxTjhhDjks3Ev", + "NodeID-6anRg13mVkUeZmpjf2Mm41sug56BH7Jof", + "NodeID-6biB22M9yY6jfRUeKHvLvz7dyVVZ2XYNy", + "NodeID-6cRZQD9AsdBxSPSoHcBfqXeSAwzKNYsBe", + "NodeID-6cem8uPoUwQ6o45VYS3D5mmFFzTuNC2M7", + "NodeID-6eLQBH9yJUPLiZGXToPxQPj2gTWv15Lf7", + "NodeID-6eS6iDVjh54ww1pGHmCAoKiDhkNGi6xTM", + "NodeID-6gAC5LaDoT9EWJezcQ7ijFjcsYa61Atdb", + "NodeID-6gFsNyzYU474fgL7t7x43Efjbak7Vx7Wp", + "NodeID-6gRx5vFhuMTDtaRYP82ZSGuBq7eR5s3jw", + "NodeID-6ghBh6yof5ouMCya2n9fHzhpWouiZFVVj", + "NodeID-6iLoGX7rEPJW2GZMekiNPEDNZKmsbn3iU", + "NodeID-6izbDmxXdSqHwnBdWkGWuJtxVuTh7AZyA", + "NodeID-6kZ9aC6TPxRtXaWgDR7UHz1aWyfkU6o6h", + "NodeID-6mRmWBQmMyFzSD75SJzjx4VmToenpMt5u", + "NodeID-6mSXCB3r7oeP8Suy1AWroDY2KEF9hT9Mi", + "NodeID-6na5rkzi37wtt5piHV62y11XYfN2kTsTH", + "NodeID-6o65ccWJmdcMSDkDphL2i9ajLCZRsvAfj", + "NodeID-6oBNaAUr67MFY9Gtu4eis7bsGY1RswvAR", + "NodeID-6p7pSJ2hoYnpRAXUt14cr1tsA5kEm9vXE", + "NodeID-6pShVkG6mZsinZNWZr48xvQSuSnmnyh5o", + "NodeID-6pXaVajr1G1nj8Z4rEXisGUajXGcFPh14", + "NodeID-6pzGb1VVyQT4RLChXUQYfhvjLrqEmWiNi", + "NodeID-6qPNz3b5VZpMWkVNjmLmpBrL1sYxr38bs", + "NodeID-6rJMJqgEbTGJCv3hBzDaY3axQ3Fq98yFX", + "NodeID-6rjd7h5dPJwVEytA9zm86ZBfqEfBuSjKi", + "NodeID-6rtV2pPKXyf2Ek7nWnmuzdiXvk2Ma3ynn", + "NodeID-6sLdnpLBDDMG2eEzgdiGjTkne7a1iETEu", + "NodeID-6sywKjSw7tS2qgFAmLSyJR5D6oB2BHT3Z", + "NodeID-6tkBfGVTgfpbaiv5HFX8LpfKdu386tfwr", + "NodeID-6upkG4FRNCoUQ8nz2by26m5vdVSthXCtK", + "NodeID-6w8o4bbNdVLscimLv4X6BA7QuSqX37TFL", + "NodeID-6xPTxaGM5hVHVKKFuC2MjpCL7ZD6xT3wN", + "NodeID-6xQ5oYAQ348ntvsshCMMSd7uduReey2wC", + "NodeID-6xjnXHhLrLDafewh5t69uRqtHea75RSGv", + "NodeID-6yS1J9HFdHgdX2ruW6XMouQvECDF2Fta4", + "NodeID-6yf4tK8VmAKhQHC7tdQwy5FTw39i9mXVV", + "NodeID-6yi5sG94i8wSHhqFuuUip6RuZGkKDHzxy", + "NodeID-6zcpV968BV1e3BrZoPmcKuoUNRcP6vjxt", + "NodeID-6zytvHVN3xs7VRFG8RBhjWVmcvaYxWHDo", + "NodeID-71ZzUv6td3aKrZG4LhGDDAnjsEcEchwDe", + "NodeID-71taHoSLZsm1Aqe4spXKJvNXw3o7982Hz", + "NodeID-72D6UYvQjfgKuSrSFtMfyCtHq1jZZ2gN6", + "NodeID-72ncx4NEgf4cziN5GPDRhn7i71rgwH1wV", + "NodeID-74Nra7czmjgHAtKCqDwheX79SDMgnddsa", + "NodeID-74oLbJEptxh1cVzvh3QTwaykED3FXjPYK", + "NodeID-76GDFDnZW2ihXCsum843HEDmrvcVuMDZ5", + "NodeID-76KcZZBhWfiWuFqrx21KyeBHdXxsaVyX2", + "NodeID-76nqFaqDGakCDcm7kDsgP7GJn2VSM33xh", + "NodeID-77kWbGy45j1Scbvgh5z3zhoUBL1S3qjAi", + "NodeID-7843EeyboY1mZSmdzjqdJodxHycNn7Kv2", + "NodeID-793wJG3RHeLFVCXkNTQxsM1pSUHNyDyMv", + "NodeID-799wg9bHu8gGe83SHdioqQ6hUg8QCYRv3", + "NodeID-79NUUnbkpDfvGzGtq3Q9FArGK9D1Wzpgq", + "NodeID-7AVurguoWJggFMe8WBEBuTzZjmN8AmN8y", + "NodeID-7BvjRu2P26PSUXWzCSh8LLxLNdSpHEq8f", + "NodeID-7CK2DghfK6VgUpPr8vz3EHxBYhpfYGEpB", + "NodeID-7DR9yUKc8S5d9xwGoaT488hRn9LiHhKTz", + "NodeID-7EEYbCpedmA4bgHnnvhx4zXgMUpKe5Gkd", + "NodeID-7HgUf4o1UiEGh2Z2tWp2erbkn5JaXYYZG", + "NodeID-7HsxnZQnGRWYG5jFVWDX2L26zEAYaUwAP", + "NodeID-7JijGwmqUuditkaCwdcCAr4Xc6AAMy89A", + "NodeID-7KKSDmFVJ4YXsdcnxjDnV4girXR32yRni", + "NodeID-7KvAj74Y1Aixv1CRWfNMGj73S6qsSGzhg", + "NodeID-7P5SGZLFp95WbF2yv3A9WbQaQDzqfsAFF", + "NodeID-7PUdh6Mzq4NfJR6wpng6cRAYDraESgWCe", + "NodeID-7Pjqo8qr8Gd78Wmzgo5xqF85qcafKQ7W6", + "NodeID-7PsjAayJQ4g5wiQ4QF3qokruC7aSUMqDn", + "NodeID-7Pt1CaFRMYN1azEC7SFoVjeXLmRF3s7EC", + "NodeID-7RBkUCXxXbZ8m1dAH76jFxABESmVnzT9H", + "NodeID-7SL1bpLt2gmSSppWDzmHcVwf5xSmrayXt", + "NodeID-7Tv2ubT5xnAXWNRf8X61Eyw7VcU9J1w5b", + "NodeID-7ULxX37k6SSaTX3oF5RdrxL9r5aGZu75M", + "NodeID-7UaxuvJw9C9FytVkUjRCQ3csmDiNzujGW", + "NodeID-7XrrK8iL25SJfWrrkyz3gZSo2t5iEadvL", + "NodeID-7a1GnsoFxviSiL8gJyFqrkazv29xY48mr", + "NodeID-7a5FbgWRUJeRWPzyidAyL3ENC8wQDJ1eK", + "NodeID-7aBosQAfHykUE3rmubktp5zZtZmavTzow", + "NodeID-7bnk7Pi7ihTpoyKndMJw53PVM3DJ9QKZ8", + "NodeID-7c866Md3Geveoz9G9XvP1TroT4LKdz5hL", + "NodeID-7cwvfriG4LFWV4iF89E7GhYfLB14hFjMa", + "NodeID-7cyp41vXvj62jBRh7y2j6VjLXhoJ6Hoab", + "NodeID-7fJWXpi4Bj2XgeVXG7Tj3JkNNrGnnJhdp", + "NodeID-7g7qvfKvRXmPZAxhBMfj8XCGuWVVHexHe", + "NodeID-7gLtM9D45daj6WJfqrT6uUje4muznwKwQ", + "NodeID-7gqKK3aZ6m81v2138yfc4fsAdzFHsB3xb", + "NodeID-7gu4gthY5YhpmpUpQvuAy5CDDvDs2yEVt", + "NodeID-7hQFksPPW1Y5hZukNcQn6bTQjuTZPnj42", + "NodeID-7haZar18iKUdnps7YZEYbJCSwnFw4KMY1", + "NodeID-7hnK4EoWzm7V5qFPqJvpcRQti59au2BD8", + "NodeID-7iFGXSHq1R8MvEM88EkS64rW5z7MwukYk", + "NodeID-7idSkp4X9MwUacdNn32NkE9SXo1XWveLj", + "NodeID-7jqH9PXuyYhoTaaQDAF1eVzLtCVSgmSpz", + "NodeID-7kfCqUsmvGEEfgas81FXNFx833U9xZtWL", + "NodeID-7o1ubnZAYsiV5DUD5R5oDYXkQQvWo69i", + "NodeID-7oH51vMj4hQ6pUniSp6xGpyAFfvvU7JhM", + "NodeID-7oHSQLPBV4EzZurguKU4a2FUvPxShuVzf", + "NodeID-7oKBFksJjAcBCNEY3ZcRLQeXLX7iA9dNE", + "NodeID-7oyvSG1pLLp3zf2ouSAT6rUeehDuQcNtQ", + "NodeID-7p8akVY9Z56XkLykaohLpNGp9sU9PLTvh", + "NodeID-7qZBqVK1XAPXPqA6jPeDwimDqMTo1ZudW", + "NodeID-7qrESfShxxqXfa35MfBC8D62t6enjm2RC", + "NodeID-7rE4BjdFpwUk2igXEeauKaZT8mCjkt9Hs", + "NodeID-7rXi72Jm76kAKUi6BiyJChnAm9xuKrud9", + "NodeID-7sTpQZFCZVzhLTugv8PKhNE8tdQ394LRo", + "NodeID-7seuWZpGnhEox3dL8T363sghDtCT5UNp4", + "NodeID-7sitbRzmAsrFjKRitC7bub1soEaHXsgbA", + "NodeID-7stntWreGt1wPeFuY9Z8bNURuHxW4JN3D", + "NodeID-7t5yL3rJ5JgME7vxa8em5sUNTPeYfmMop", + "NodeID-7tZXydqQqbjAQaNDK9MNEZFMsSFCp4xJW", + "NodeID-7ts1Uhry9k5qkmpYZNfdivuzj2eBPemKa", + "NodeID-7v2CCw3NVjU9UxBhGzN1jhSmatHKE2mXZ", + "NodeID-7vWb35jCnXGxAhLStVtKKZhWiw1ByhBdT", + "NodeID-7wMUdN6T9awYChEoRgzQ4eg8qZj1BFrne", + "NodeID-7wSVhYSmrwcts5o98Yg863PoHhJWWQcbt", + "NodeID-7wqgzXaTtJLobuBUxbp8yGtQe75TxmaDW", + "NodeID-7wyu3EXASVzsJpRPoqhssRWdmTWa6Fycd", + "NodeID-7x5HbUJqp763SUw8Sz27yU3bKWCdQiqAk", + "NodeID-7xCJtVM3wTprzgDBhXeXCXEUy4NEuqUvi", + "NodeID-7xcqn3xNHBxreF7mzRx7qEDbpJguaYg3i", + "NodeID-7yBDXjCcqHCnfqC8LfQ1oL9Yyx1se2Rj9", + "NodeID-7yUhoXtjqGABwMeSgQG42cWX56r1DkBwh", + "NodeID-7ynNyRtZx8re55eU1CwJ1Ga5cEaRMPJ5s", + "NodeID-7zA1m9YUevKKyKdyJK3snpSiAnXhUG12R", + "NodeID-7zQLzhnMhaj5SbRXVpUUsMP4c4r8yQAD1", + "NodeID-7zVSqXr1f2wcEnMtMRBzMh1VczoEXsu2", + "NodeID-7zeJ5VBLvTF7LvTn1VRZCJfdt5EsWUg3e", + "NodeID-81U2wpq95De12KchbFhatf2fBt6KTFmAr", + "NodeID-82qNDEtRpFygtdH5AL4Fu5ZV12k6WCLqL", + "NodeID-84RAL3MngQcrLpLgTgJwtLobhryyt6TiM", + "NodeID-84XTAh1VM9QmfdewNnqFVhz2kbjrFvK4Y", + "NodeID-85QtYSfGWxkvQjbiFJzv8R6ajAutwFS4F", + "NodeID-863ca1dX7NxyiWH6Hf3Bp4ipNokKdzJbp", + "NodeID-86HV89ZFehy2HHmnkpgBuUn6vRxg25if4", + "NodeID-86LjyKDK2eKVUpdesMPWJtvo9gadfW9m3", + "NodeID-86oHZkq55eBsPNFwrFX7kV5w97BPHhtgD", + "NodeID-88fsGoe69sPGtRjqe21SK72KrJNezzz5u", + "NodeID-88ik4ovrpTx4dTExqhXhSQ4JwAQnHbuGA", + "NodeID-89ucgJfiRvHtGXynRbta7VcaX6MEcJ7K6", + "NodeID-89zA8HBgsSce4Ut5hzWgfMRKshqooJWdu", + "NodeID-8ALyunjeYV85zBSrD2rjJdQ754z9jasvq", + "NodeID-8DLefLvLwgb6fkcghkLgj8w91MSrnPdjh", + "NodeID-8DVxsXms5opComNTHqFMgR9pRS99gt27r", + "NodeID-8E3UaD6hjNK8aqK2BBUmqPXyrfB19WJJ2", + "NodeID-8Fiuf4Uucg4x3ijMfkyVvYXdfgdBFvsFk", + "NodeID-8Fn8YCu76VUHny7MHQTkm3mPSuGPkVeqn", + "NodeID-8GLed1n4Xtqh7RaYHWjm4BMxKT6AnhXbW", + "NodeID-8Gct3pDyuCEY5xH1F9RdYjvk9ry23cTtX", + "NodeID-8HHLzk7pF96soZ45bJ1tfHNcSp7moXiTB", + "NodeID-8Hg2J3s2MQVf1GtFLcRpfWjvJZkMesX3z", + "NodeID-8JYJVijgzBsSTK5EUsXitrMEYNGkqeba5", + "NodeID-8LVdUgSHBFouhLBef7orFrHTeHgmTW9r3", + "NodeID-8Mk5Kpvp3oTpLbRSnwmCJmPbvRwsR48ra", + "NodeID-8Nr7TDSiK215oiNDY17SaDgF5nfty4KUi", + "NodeID-8PmuHd5fRb8VWpTTyNhytQuv3sy83P2jT", + "NodeID-8Q1uX2BfyLbmCCor1t2h9qvn414WXfQ92", + "NodeID-8QKheMcZ1jn5n9RVi5MFBkzGrKjFJNNAX", + "NodeID-8SJJiFHcGfH8KErq78txDKhNGARL1K9mp", + "NodeID-8ST5juiAQzVfXhNAgER1UapEpNowZyMoj", + "NodeID-8TArWpFgH3sazEH8qP4gUjtGtFMvjw1aR", + "NodeID-8TXq3f5WiXqZuyQWF3Sa7ncoW3YRRaevh", + "NodeID-8TubANvEGU3Zkz6nKeRx3ShmHyULLjD89", + "NodeID-8TviTXQLiqxcxkCikPTut9DwifYjFaMcT", + "NodeID-8UynAEU8PuuGetmjiiPcbGmvD3EyycuN6", + "NodeID-8WvUBZyrk6XyF7pvcg3NJZk8jtJGi1W9G", + "NodeID-8Xt57NiwBsGKt3CjYZ1ymKx5h3nHU3vcX", + "NodeID-8Y4i7kpWyv3pvvwJSk4EsGx7frk5mU1Ah", + "NodeID-8YCf3nhXEnz8vthaxYRWR87ez2orwP7yW", + "NodeID-8YNtmpa8fe2dt12PqDzhDCBtwcQDTXa9p", + "NodeID-8YqEZ2ufMNUFPXyNpUAvLJWRXLKqC6D2H", + "NodeID-8Zvnq1815CaYYegXmuyBD5BVtJnurtpC2", + "NodeID-8byZLbVuVJbedEvsAjZxTTSqorsjz7ThK", + "NodeID-8cKy5FzzP2CHV1rcwdKq62vuYP9yUzYuG", + "NodeID-8cmpcebMMbqJuUTqnz5hoHzqZkDduNttZ", + "NodeID-8dCZ9beUGmAWyCZPwdM8YZ5FDBRPXUxFf", + "NodeID-8e5R9yoryWwUCYDxqKdV3PNPAFme4nZMX", + "NodeID-8f27M6Ju9Dnh7YU5pHqpkBLhCmBq9EBBD", + "NodeID-8fLXgVYgby12VunVnSMrRrvcgEijVknbo", + "NodeID-8fq1H8oStMi9BZrEk8qiE8QAV7AtqGnXt", + "NodeID-8gLyc1WmUgnTJh6TAjg1nbqsqdF6xGSeL", + "NodeID-8gndDR9ULm3ywRNbh3FUveaSyo5g7V3ns", + "NodeID-8ja1C24FM5FyQgUGjsm4qwpD6shiu71KH", + "NodeID-8nNsX4HqDV4UoewbWjcrQv4aDnsh9fCAe", + "NodeID-8qkeNyB3cbs7LqzP4AB7rHcrcHLAYVDEs", + "NodeID-8rEmSGNj5VW2HUjGYMyynpWTYJuDrMpFE", + "NodeID-8sczBhZjP4BGoCqbn7SaRCnerh6cJ6jE8", + "NodeID-8uDtidG6poHRfZfZJXXSVBwivoMogXQ66", + "NodeID-8ugXJLrq8DW4m7m7vBTpkh9rCLn3sUmmc", + "NodeID-8vuV1UF3KHF98EdqFyuFAMDJUzwkQWEA7", + "NodeID-8z8rezdB9vXDxBurBeCYnNBfNcD1kVrJP", + "NodeID-91W73TnEik6kseSpBHSAZzsNVRGk8Qfkm", + "NodeID-92aEQicro9Pht1HRiexK9ado2BToyi7fY", + "NodeID-93LVjgmjMcBmcJSByxYiTuyPNbdVw9q3n", + "NodeID-93bNuNqHUpmiZiT9bvcm4YdRU6ADQnESy", + "NodeID-94CDXgCTFRPKPDmK55UcfG8KqVQfy4QsV", + "NodeID-954wbYhWNWY3mbqATFyrHostqC5EBwPHp", + "NodeID-955GU1MqWL8yXAtoc8AsE7FNx4nGC9JyL", + "NodeID-95rcDYyjGNKckKCF8PKuTyEV1wxkQvP3n", + "NodeID-96tBuFHLkXJwyYug768fE2GDEFmebUUTy", + "NodeID-96tjSzF58iKJUG1hDQve6HJdzjwLNMzFW", + "NodeID-972yzi4wAgqU7RGmcQGED4ueQeBXzccka", + "NodeID-98JuUPhpQBgiY9ozqFTh8rEjx3jL9D3aJ", + "NodeID-99Dk6vNf7RaX4S9e4oAAbuhubzzRnrGxC", + "NodeID-99hQvpQKJi1y7gTjD2icHKYwk1pNMHFhg", + "NodeID-99sqQME296SfcnyYWTmGrLXQJxaGUKAA7", + "NodeID-9ANDYM7So3ZPNwbMMd9xBKUiyJirXN3vF", + "NodeID-9AjYPCvDWKnwzFgRiy7jeTEKmVxK42LSz", + "NodeID-9BCUhY6Q2Eji4J1u6MV9XKnPspciWWdLR", + "NodeID-9Bb6E7B6GMd1MnAuxYVVYF9CSf1XiBCEY", + "NodeID-9CkG9MBNavnw7EVSRsuFr7ws9gascDQy3", + "NodeID-9CnrQBBFSkE2Xzfcz3Tk1e8iauq8iNR88", + "NodeID-9D33RPjZwKx3gV6MVs77z4uPJcKgqy4ns", + "NodeID-9D63iEsgkSKzSz1aBLpELbh47Y7aT5ujj", + "NodeID-9DCqby2EWyUKFsKs1VNH5mX7V9FDkqUnL", + "NodeID-9DmoV3n9Sb1A2aLkYuv9wZV7uPJo5JhpG", + "NodeID-9EMH1m2oZQsbSFvrMzx5YXZWFfqSwjuUx", + "NodeID-9Ef44CXDWWfP63UaLr8XSCsmEWUFY5i2z", + "NodeID-9FZQBRnW2jMU1PW99pqVTnxkPHF2Srfeb", + "NodeID-9G5DhsoBgHjDA3j1FqFXKyEJH8AGPeB67", + "NodeID-9GEnATgHgKGpkf6nJdS1jcmXz19ekHWkc", + "NodeID-9HT8KtMkcxP5aWjmxaVVGBCMZ1r6jGmgz", + "NodeID-9Hp3rH2xzTzDoZj6JgYqhbmTFGVeS1BnL", + "NodeID-9KjtB2xC9aehpcYRuqJR4myLGJaq1tVse", + "NodeID-9Lyd45k1mXNkksF2C3nwgCJRX9YY42FT6", + "NodeID-9MCd77R8qxsNg1ajgHqFMsRYCaQ4KpGot", + "NodeID-9NEeo3Ayq5qGodBbMZ1gdCQ4bmGH59BBo", + "NodeID-9P6CxSTDfAi7cRr4LUW4bbdA4F1nK89T1", + "NodeID-9PbbhiQbQitcLLEiVwMCThVLWj2zFsbp3", + "NodeID-9PzVetjSSSY4Xtk3VnNcGzQdEjZSSkR4g", + "NodeID-9S8duheEvrp7gKW4qLLrWVCnC2wvo39w8", + "NodeID-9SQzWXUh9SF4b4qDmYy7p6LcqWSgxtu6o", + "NodeID-9SoQgX7kSvnBcYsajQNeDsp6KDkZ34vJN", + "NodeID-9T7NXBFpp8LWCyc58YdKNoowDipdVKAWz", + "NodeID-9TMnzP54UVfmYmYcxAzVuNC9rpVr8zvgB", + "NodeID-9UWtBGvW7G2RVSwcR15MS8gesUvLk6f24", + "NodeID-9UgnxmEX92MdaAFQc7FG9SAfPECeT6Qp3", + "NodeID-9Uis3D51cjQauBaBPnqsvKjKg8Byj6Xwb", + "NodeID-9W3QhxVhg9EncK9438UUepFBrCxdtFp2w", + "NodeID-9W5RaY7LA6so9hGCPGfLezBXMnWNRQb8V", + "NodeID-9YiwE69B2wcvXtEW986YcgQxGg9ctzmKZ", + "NodeID-9YqDsggitZTgCi2WnnrKBz3jAcD1S7oin", + "NodeID-9Z7jK8jN5FsTXSqkG1fV2QNG7GktPU8az", + "NodeID-9awX4ceeXavKKmccnAuDU7uvhqGfaEDSS", + "NodeID-9azF97hpcwpzj3t7S9mD4VKY1S5eJDrcW", + "NodeID-9bU9jwHLH6KxcTu8pBbqJQqkHYR4woY7L", + "NodeID-9bmxQyFJCrENbZgmMdy6xXorVN1RL5qWY", + "NodeID-9cazV2uY7efo1f9bjbixH87FFNG5wGyts", + "NodeID-9csVHpVMwxCY7G3bYvr6fMSinoHWGSsbR", + "NodeID-9dN9NU5XCr3WQGYnFjGudKRScQ1HKGmBn", + "NodeID-9eH3Zu7LN7kNwvUy3Am8mkgvvekrkxD6d", + "NodeID-9g6keiiMr9vXhaSNP3oqdxhu42LEZ3pWu", + "NodeID-9hW5Lb3t5JMgP945DB8wHUJP73uLuDLAZ", + "NodeID-9hj2xhiHktPCpcD9koLLH17a1GKoWY7QQ", + "NodeID-9hksERdA8ypkBykmHuch4mw24RR2sg5js", + "NodeID-9iGXJ935QZWkp5j2v6KNSTr8b45a7Xbfs", + "NodeID-9iiCATASsRcosMQ811KpxSMHsGdM38rPJ", + "NodeID-9ipN26YdR2YZFyz4hdoyMSXFYNFMDgDfy", + "NodeID-9iuMMyL7LZyUxMK9s735hcRng58bSj3gw", + "NodeID-9izFTRjPnyph3GJu1sp4Cf7zHiwaK7KbS", + "NodeID-9kNp7yMjHnDg1QLQboms9ACgQ7BGu8zpS", + "NodeID-9kgmvmU19mNsTxPS4f2F7ZiSZSwZ7dfGk", + "NodeID-9kq3kK1diyhu37xTwNHVxBkpVKHZhTEKj", + "NodeID-9m519rUcX9um2PdgG3h8tYSZzCRPZ3Dwr", + "NodeID-9mtTuxamXQyiePCNyheFEyjr4cAQo4Wbg", + "NodeID-9ntqrySGMSMwqYR8yFdChFdU2ABj5zSEp", + "NodeID-9oMGbzXR5wDWa1f1BjxmhvsjkPYcFMz89", + "NodeID-9oP7KmQjtxi7rK5GKmRXFNuNpPmr2vzfw", + "NodeID-9odH3Jbw7uPuRrbaVkVoYeitdzwX6o69A", + "NodeID-9okkd3AwB3eurfQxdP46mcSM5sVhD9jxm", + "NodeID-9opRroLX5zG47LVmyw8hGnQJx6dxmfGsf", + "NodeID-9pBxdzsJRoGFdAjEJzcdWbzKEEkdzyGCr", + "NodeID-9tAAt3ADXpmStdjfpUKsgKCBowaPjXueE", + "NodeID-9tJaF6mjrwczuEZk3oQRJsB2AzPk7QFHn", + "NodeID-9tLM44jzwQqnsLmQTfhv6Q2GaAEkCdev6", + "NodeID-9u5MGjm2Y2BvQSZBqwDkqjUrqFKffDund", + "NodeID-9ucNhNpdx1QhUnivTY35AtNEVpjY8AAK4", + "NodeID-9wCVwfdLGJe14xss2yjAT8ntowavfe6Cu", + "NodeID-9xTBvp3kCUiUGu8aM8XpBWPf2co3vJTJN", + "NodeID-9zPtXnScuWRvoiTDe498ZtjgoTXwTwxr9", + "NodeID-A21bAN3Nk96xfoAh8auwqP4uQRbk1xAPz", + "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", + "NodeID-A2aPfvr1t99Nm1K82U2XyWtxse3CNmZ64", + "NodeID-A3azVkFN8rEsnnw7yQoXHDze3gVSSF4YB", + "NodeID-A45ZieXX9VhAjrz2jhACBGYYypn2HEjaS", + "NodeID-A49YH2FmGteFpSV46b9WDxZWDEebAnH4q", + "NodeID-A4amNjJyWX5kd1wNhxZVqDFqWKomCndp2", + "NodeID-A4ebHxQGYx1fUuJWf3uWzSaQttx4VwKaA", + "NodeID-A58AWZohmoEPEG2FDjqdT8m5XeUL63FZc", + "NodeID-A5CGvttTf2Bv3KvCeGwzUkxTd6Ux4MURA", + "NodeID-A5SHWeGWKUiuvPZhRvNAXKyiEnyDhJzdh", + "NodeID-A5djhLPbKEsfiWZn9na9vFEHThJ6Ud6Hg", + "NodeID-A5y781VL74i4yfFdcMLnjxr2qLbtjaAgi", + "NodeID-A6onFGyJjA37EZ7kYHANMR1PFRT8NmXrF", + "NodeID-A7GwTSd47AcDVqpTVj7YtxtjHREM33EJw", + "NodeID-A8jypu63CWp76STwKdqP6e9hjL675kdiG", + "NodeID-A9vXzVChTULcBPwXnFoNTfQENgrYRUyMS", + "NodeID-ABHKUic6BDS8Kg95tSWoYv71CXWeuS1Re", + "NodeID-ABaXv5WwxLamczWpE6o58Dm5FyngUbFrg", + "NodeID-ACB5BBC2RNLSGZVEGkRRQdWg8hqXjnTpM", + "NodeID-ACMpxS8rnwkAA4JfCUm4vNoWQaznNCqGV", + "NodeID-AEtF29pZDpKEkZ625bg3reDrux4wyMjhh", + "NodeID-AEtKZyYiqnWqzsrwSKEPWrciPHEAn2Q2T", + "NodeID-AFWbdZEPvWxEq6A5SThDPVydUj9FSHjCQ", + "NodeID-AFZVPKaEHwRZgWvcqRpT6mTd4k8xDubGg", + "NodeID-AFnD2mSUo1cB9HSMxGT9hQREHX6V2aCmm", + "NodeID-AFtmZMo4p7AZVenJtT9D2Tbk1od5mrJge", + "NodeID-AG9hZpGAPNtzpPJWKmJHDjyhFppqM16uc", + "NodeID-AGEnkaodYJksMTnwS8LHHD2X7MDQBSMJU", + "NodeID-AGurvCTxa6JFJkk3553Wx8XPtgz6w4xMw", + "NodeID-AHTFPmvMrQBt1hcoGS7HugNCuu15Q5gY6", + "NodeID-AJR4Z9bAx8tom9ygqv3PkpQtdxDV8JeLD", + "NodeID-AMMTYTe6uZR7yGL1AbEMuwYayd4N1J4bL", + "NodeID-ANQn6yF5HqoipSTWowYpMjyiHifhewv5y", + "NodeID-ANeoZC7jBSmoDSYVLip5uASJW48GwWLLG", + "NodeID-APrWZpt6HP8qQjvLR9R64BcskxsCfJD6Y", + "NodeID-AQT1i38PMJQxRqjpwrQ98QESW3EJzG3p7", + "NodeID-AR44a1cyPrD8cCNZgyhv7Tc2Lvw3ryhEu", + "NodeID-ASgm7N2wwZKYc5dZPiHExfDdNcfyZQx3T", + "NodeID-ATZ8pFjm1rjV8o6Hp7icMqapoGycT8Pi5", + "NodeID-AThE3ad1aiPLKsj1XfmhCsNbai8sMyPc", + "NodeID-AU27Fz35YmQuM6d2pM9HsvLtgwGT5xwnd", + "NodeID-AUeAjRR7q12Pps6Qckyy1PUzFwP34pFij", + "NodeID-AV1uDZqWGSheRS3M6RHUbQJHDGXy6f8Y7", + "NodeID-AVAXg2LFFdkWJjZi4554GBNprWUepqKxm", + "NodeID-AVAXnRLmetkBadrUoqtLSVkohnoEpeSm4", + "NodeID-AVp7QsomV2auUPqPXQesRcuKwxn4JmDRh", + "NodeID-AWLRFc3R7oCqHd6qe95QsEaoBPPTQYpuv", + "NodeID-AWMoYmhjbfpWphJ3nmgxGAPpVFzQbdp1G", + "NodeID-AWirVtsoiwvNdqhqQRwz7vQQEiEyvhq3y", + "NodeID-AX9Fkm7jKPuY9Mit6AyZoS73tFKWvTMF2", + "NodeID-AYJX8inuAUYHEWMWn6V3x5w9sN5tSkFAT", + "NodeID-AZPULN7CsYdfSq1zepSS3CZNhxJsU3a4n", + "NodeID-AZfAXX6qyLxVXBUJZPwEgR1iJYwjwozm8", + "NodeID-AZiGXCQ7UJvsVjmBpUMmXAQ12GRj1iaz9", + "NodeID-AZszYbUsVw7PhcssGJYM5274dwoe3gQem", + "NodeID-Aa6HmCaYwZzNoNXRf2xd1aqgtaWdnnryn", + "NodeID-AaxT2P4uuPAHb7vAD8mNvjQ3jgyaV7tu9", + "NodeID-AbfdkS6u8F8kxh2pPuK32KASNK4sSr4QR", + "NodeID-Ac4RdT7r2vj7J8s68DB6mpoqPQ9sq6oro", + "NodeID-AcUWiUhdsfAAD4gyVUfQNokZXpDD2SF5J", + "NodeID-AcVHs6PgeipByAajqn3h7PHDk9cZXDZ2K", + "NodeID-AcZuWDkVDZy32y8YSxMVU57sLtkyHbVFQ", + "NodeID-Acigg3i7aU9j7coVrns9SEtyq9dox6cKz", + "NodeID-AdSMHubbQcGeJYMcY9nufaieoYjh57uzp", + "NodeID-Adk8ovrBBu1dbaZ7c6Qy52EWMQuUr6WZ7", + "NodeID-AejE54hVtRxSm2e8KW4zUHpBTgHz9fpEw", + "NodeID-Ag1ZLeovcUsR8V9C3EH6NQpGZoQBhT5Q6", + "NodeID-AgfJSHN4yaVjgxanEWMfQXKGDNScwrVZL", + "NodeID-AhFT8H88EZjd7K1dhrRPfhatXKuz2iBiY", + "NodeID-Ahq7qT8wG6ufLoM8MrvB5G65SbEfZC85B", + "NodeID-Ahy3pk9UZEeVLzks1BRSqsLL6zvJt4bN4", + "NodeID-AiVA6rmmPhouiy3ERwF7k1eoLTrPErd2p", + "NodeID-Aix93q3XbWsEcoNuuWjYuQM49ZeCX7NLS", + "NodeID-AkWM2duSrGSfWNEdN1pmWm9ZLrwZDg5MN", + "NodeID-AoGM9c6bKC46YpEecEe9tHG5HfcjqPxtb", + "NodeID-AoHdNKxXdndkKrbQegnB2TCaJF8JDEXLX", + "NodeID-AoU4gTzEVKVmopKx7s9hKXBbQ14VYyAcc", + "NodeID-AqBVQzsBnqMjTuoMoCAQH7NgTz9vC5APv", + "NodeID-Aua1pVxQsWLvTTf8bNVw2ZCA2NfogNqiE", + "NodeID-AuqWFe8yzJxPgaZShBZpa3AhEnKT8SmEk", + "NodeID-AvTYuKYvu8oB8dXCbAsLh7nTpCvih4fdd", + "NodeID-AvYo16nRcdMuFmsEps6STb7faiRoCRgHx", + "NodeID-AwBfjtuNZk2Cu8wmQjYsNipqWK6nYMnv2", + "NodeID-AwmHrKdtkhnuEVY5TvbwxVksQ8dWd4a1P", + "NodeID-Ax97guVgJnjpDYiZkHghBpjELMVrbhKLq", + "NodeID-AxSapUskp62c3KkAnzd2WSDammmNXaG53", + "NodeID-AyByRGSrfbDaeW4njEYwCzhsnMyZ2KMcw", + "NodeID-B39dR3Zj4ZtiqSHTPLxck66yqxTZ9pRmK", + "NodeID-B4EU3Tk8BsVczMpkPtJAqS9FSYxNjYNBz", + "NodeID-B4Pubug4ct7TKPRuSAWGqS4Hq79v912VF", + "NodeID-B5MJkFe7GoyrXY3MqrpjMrrTqj9J5oprQ", + "NodeID-B5N5hVfEFbTrG5QGKvXQBGqfvR9GJvSLg", + "NodeID-B6NVZDFoLAErvcUafQ3EzJeynFnGffCQd", + "NodeID-B8RQVdW7nFrVR4Peh6oMfsdK8Muuwfeme", + "NodeID-B8rRoKwovNH4Hv4cgREBqjHcGSCN5Lrcq", + "NodeID-B9dnZzwTmygKPxEP7GvyqDh1F6pQHkmmi", + "NodeID-B9o1a3g4PFp4JWyMJxRv2nvnWHsq1rSvC", + "NodeID-BAePtWtdsqk26YVfucEAJTA9spGpuLf9r", + "NodeID-BDFwWjNUNeLYrrfGmYqBMqZSGZQtmCcxx", + "NodeID-BDnEyGooDS9w6bk2Ty7UncMyQ8t1iLLqh", + "NodeID-BE6YSS6Dw6tsEv4fj8smNNkHpqQvAf242", + "NodeID-BFgsRa6TLCKcHZhN9iuufSqRengbXuxQy", + "NodeID-BGEvsCNRi5gr4ga83cVx1E7PTSiBZjyhK", + "NodeID-BHPTN8HM5xA9HNiwUPceNa314kh3YnDpp", + "NodeID-BHsQhBq2NYN4YYB9t9VxoxcL2xkCD4zPj", + "NodeID-BMaQ42mVapxbCcX2RLPRTeRW3th91XdaX", + "NodeID-BPsD5nsuqTKR7ToqUMDFqanYioFnAVo8C", + "NodeID-BQ6uwBhrSU3mwDpguw4rGPXa7kVkk6FyM", + "NodeID-BQEo5Fy1FRKLbX51ejqDd14cuSXJKArH2", + "NodeID-BQjBjtF6gz6AXUqRbEvN1M5EnFL3Hcnv", + "NodeID-BQpbmskmST3wkcSbypVuFZu7YULXG6pKR", + "NodeID-BQsr3wEWirFH6C81M1LYsYagHXVxXRFSS", + "NodeID-BR8ysKTDMKpwbgH9fsfCdVQWMsniMQBWp", + "NodeID-BRPKnug3F8vq9aV7VFU8YL7fASHF4L43J", + "NodeID-BRRp1FdWN4PepbmQNUksWPsRJaZ1mFP7q", + "NodeID-BRrFzQrJs8nnmeSZxWwr9yCRcq4U7resP", + "NodeID-BSornzAY2Y4SmDcQw4Pgsf5zH4Wdv6d1S", + "NodeID-BTUXn6xfxjtA8P4nXYHiwEJpso9Q9t8FZ", + "NodeID-BTjbJK42vkCLo8LnJfXHHtVeDrZJgfTbw", + "NodeID-BTybEYu3y8aW54EK9SSivLUYn2fiCosjD", + "NodeID-BURrZL8SidbaotZ1cNxvPxNH5DGvXS7gN", + "NodeID-BVSFJU3T86CWXQxSTc2Y7cHo7nYJx1Jn8", + "NodeID-BVWu8imNSLAnVc2bz3LRKyKa8jfA6YgPR", + "NodeID-BXTBUqX8gitUDtVam4fhRWGD1SfeHGoBx", + "NodeID-BYGnq6ZKg5ncN419eBsxd2YQcxoewxfrQ", + "NodeID-BaPYDXQYeS9aCFHv76r38gUhYrtfpzq6A", + "NodeID-BaTDuWRvZkEy8gg4FRYmNYXASWL4QKzFD", + "NodeID-BaaUYiEUD9ogi7dDikVZAzaVu5yxAHjGs", + "NodeID-BcfnNieXDpsvkMApb8FcCmGAoQdtyu8jH", + "NodeID-BdD2fp6PXxbSdGshiVrHDzarWpgLFEMF9", + "NodeID-Bf6sxEpjBCbnoouk6sdrPNPfHfxfNumDB", + "NodeID-BfeJfXUfFveZPbS5tFaJar7X2uQQ7S7so", + "NodeID-Bh9vBw87fdqVzMzrFrPiTQqA4irjDP6G4", + "NodeID-BhSpBoma36qXxym3XPxM2E9xisXh2hBmL", + "NodeID-BjoNuhod6yNfMJJDJgyfNWWRBUG38ZPCs", + "NodeID-BmKvEFG1hXNQ52rPBTXwQ3ZxEmcCmxXZx", + "NodeID-BmmaSGfGKxQNMsaBSnxvhQdLCNchGEcUo", + "NodeID-Bn4LPbETjf8D9pZE45abJgcCk5KSQCbo7", + "NodeID-Bn8ZcnL352FHc4utgVPVDjD3o1HfYwtdA", + "NodeID-BoN8r3MqeJiqVcvrQx1VubZMGDQE5pJi7", + "NodeID-Bom5dUsayGwdagVLoNNxe1t1FFDZXGGK", + "NodeID-Bp4nG1LrP7JCg9eSQpfBE91mBSd8biThQ", + "NodeID-BqtSwNPmkfSi5W3Zz7CRffeLmYrUYuEmJ", + "NodeID-Br6QnUhtZGAC4CymYLPRSMCrsNyhLMmH7", + "NodeID-BrexWemEB1Vgpbpnnriy3k8e2CyRvxsPR", + "NodeID-BtPauDeR52DaiZeBXuJSvRWaFnNhVFMSf", + "NodeID-BtcHfm5o3A4WhAmkTm6YPWRhPCChDPLMM", + "NodeID-Btr5hkRibMyYztC9jQg5T3fpKNeYf3Qdq", + "NodeID-BvDJUkrDJotTxgZi96zsEe6iYQBLtz958", + "NodeID-BvHFTM6QMuaxmk1xXZAUS7N4amyNn3Fbu", + "NodeID-BvpPGydG4inQCbkwRZ3nPMp1zAGToUTxz", + "NodeID-Bw6s9DYKi2V9jRqNmaheGGg2Wz2Dv7DQo", + "NodeID-BwCLnFCE3ipnmkT3V814hGsb6sCRFqScn", + "NodeID-BwsGZ6YpSqF2j3QRRiQJDf9JC4FmCGXq5", + "NodeID-BxzE2rHWw4hBSTVqP17p9earG4qYKpCwv", + "NodeID-C1oRu2mGfJHUD3UyNCWVJnJ4T6AWXhj5Q", + "NodeID-C3aMR9tsKqTNQra8FbqpFkMgHV5DtuJGx", + "NodeID-C4UwtB1v86mBctdWgoQZGCCUk9EUtjHSh", + "NodeID-C4emGUFHEeCEZgoeMDHZddr5nyZBgEUKf", + "NodeID-C5Gqdho8U8fTWHhBvymcyRVBU43D1WMpc", + "NodeID-C5VJTAsWjmjh4KU6DpR58X8QMYFZjc8di", + "NodeID-C6b58cQGYSqm1FeQyvXKXUgZ3R7Q9D9es", + "NodeID-C6fd6GFYMnbD44LpZR6AuddMDRXTvR5Nn", + "NodeID-C6zVv1ab5JKn2j8DDCGWGai9jgWhmpLVA", + "NodeID-C7VsWUVsE7uFmSgkRQpcjAJWB6gRdm9Pc", + "NodeID-C7YyYDva6rvbpY5GEu2Su653eLBNt49TA", + "NodeID-C8b7aGd2caAe7PgtP2vnJcWta1wUezAAa", + "NodeID-C8zmJazq2HwujDgsjKpmYJsvSuNMD1kwt", + "NodeID-C9Bcji6rXUp22qyWhvYKm4v45hJAkzvpU", + "NodeID-C9CJ3oVhdeLf2Db71JPuzvEUKjy3BdoAA", + "NodeID-C9FY2J7xE6f6sGSaThsmcWva6FU5y5Qi5", + "NodeID-C9eHQ7iCCpW7zy7Vk5UJEXd1zwXEdFtS8", + "NodeID-C9eewJtL6WMZi2ce8YoPxhHTCYemhvnKm", + "NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg", + "NodeID-CBPbPrYDbghbAP4RLSCQr7bHQqHWh1c9Y", + "NodeID-CCBWkqmiTdwUCR9ExH1mNSLzvrt9JRKF2", + "NodeID-CCPtDzjuJWjt1VuV3yiHPwQr35qh2rbJN", + "NodeID-CCh6Pin5Z4pVLfqyCsZqQfg7ZAZi8QZb9", + "NodeID-CDjuct2YS1o4d14nHtszWmyVUmFjo6AHm", + "NodeID-CEHgpbVVJh676muJTUNKzP3jmZ6Cs2zar", + "NodeID-CF8WKgeNBHxWFmijN7tysmmRSHfJFEKD9", + "NodeID-CFoWfGyYw9HPuDK79fjor9d96S9wLAbpR", + "NodeID-CGrPauwXiEvvY3yLBxR9HM25B8HpNTVfV", + "NodeID-CHxae1CeKzs6DNxur9rHcjSAecpdN1p9Q", + "NodeID-CL3N5kkR7HsmVtKavcuofwQGgMNjppY4N", + "NodeID-CM5KJnEvKQfjFirjbUzHa7WbanH6dLHva", + "NodeID-CMFSQ9wzby52sJqTBeajH2MaJq8HwnZPL", + "NodeID-CNPUVCHqT8Jpjpix7SJfXhh184EjPSsu6", + "NodeID-CNyGDr2EvPqxfybfNLkpGWqMQHiZthJ3Q", + "NodeID-CPWtTaJjKj3uiQnNKeKVk5yKfEiE5mok8", + "NodeID-CPkJH4zTnyhERzo7H1usRiSmMVDeUszm", + "NodeID-CSmSE2veuHYG3dJD9WuqobvsAdJ8iF5pF", + "NodeID-CTry2Hj2aXeA1rfWq1s6pDL8SzaCFGLMC", + "NodeID-CU7T6w5aj2hPEtfHSf1GWXpXKLWnN8uWG", + "NodeID-CUTxQEQariSZiwv88qRoGtmUMWabjJoce", + "NodeID-CVJCnaM2gVKr6WCmJxKSPjEA6GFtmBknY", + "NodeID-CVXpUPtPZnsEM4mSnJbctBpL6Sgj1rCRt", + "NodeID-CWTULAJzqphbmedDkRpcHuCvGiHARvodz", + "NodeID-CWuWBhX2WaAY1pBTAmLRTGsjX9y3EqWAe", + "NodeID-CY9BmJwkVatHX86Pt3Fkxts1QoKTovyAs", + "NodeID-CYdCC4uTyAmEHW2CNB6oivzBtzqJn55mS", + "NodeID-CZRwtJDY1KeQspzxqmHfSdwvhA8xAeV9K", + "NodeID-CZVcr8ZP7njdQynukR8B1RcCcG9qxSdD5", + "NodeID-CaNQUnkzWJFcsYNhdx4iyRk31McfqtKhX", + "NodeID-CadcH2YHzeVWDSBT2LR9bfqHvMVfH6bTs", + "NodeID-CbFmga7as6xEZXwhgCTmcvU8hix4Kf7ru", + "NodeID-CciiJQMXRWQ5967qBS5XncuEiyor1Png1", + "NodeID-Ccx7u3SwfPt52GxWbNc74kjVJvqktTkn8", + "NodeID-CeaG1icxFWcMkTzsqQjpwt82nePJrk5gZ", + "NodeID-CfM5DQx47iD6AWMsFdHGfWUnt97Sbt9n7", + "NodeID-CgXPRNG5FeVSz8qC31u5UDpZ51pJ2mN2X", + "NodeID-CgbgB1UFpUESETV1CVGDM17bE9JA4tVHK", + "NodeID-ChjgtCzFxwhCYQGsUzGHUUTi9nFYrLsXh", + "NodeID-CiKdcSyNH27re2W17ygscpZ4xG7474E5U", + "NodeID-CjX7mnJM1qasMtuyyxeuKoKy6b9fdSSbE", + "NodeID-CjooWTHxne1o2w1hetMGgDL5Et8JzKMiw", + "NodeID-Ck4VEAv4JTMgnijLQDeGCWST8Zdgxe9Q6", + "NodeID-CkMG3CThWnfAYCYE1MDsFqSU1n4NESoFt", + "NodeID-Cmp153iz82jTqJNoNFSvGr8wsaVyV93S2", + "NodeID-Cn4ocmPe1Hqo29RyYCC1QXr8b763Wpw92", + "NodeID-CoRQHCd3aSKe7FrhHSUnvNVZzW52xu2YA", + "NodeID-Conr75BBUMBFNXD2VP6gvEbCRihCvjfej", + "NodeID-CpAhCB1gu11mLxBZJfgGLExwwvKobprLQ", + "NodeID-CpS69JexgMfH1sy7a77fiwQgN3c5QtrXa", + "NodeID-CqbkQ1txNkMjeroDyJpAtvUAbJf2VbV6x", + "NodeID-Cqc4sovCY4ypZww5envqKgtrvd6zrRPTz", + "NodeID-Crfqdz3qPavSYvQUWSXMawWjUXxnr3Gg5", + "NodeID-CsGzEmegg1sVokBzrSKkMygKy9YCVEzkq", + "NodeID-CskPetRMvtH5Xr6gLa5cwfY4hR34UgkM5", + "NodeID-CuEMaXrtX3tdegH3BPJowHr7cMUyf7P19", + "NodeID-CuF2PsXiuZESJWa5itRLmXWQ66qL1NSE4", + "NodeID-Cve7X2y1c9WG3AvnWrMGBLkorLdmQTrL4", + "NodeID-CvzmyAWqVXtrEcJWfXDP742oE9PsnCyoB", + "NodeID-CzW1jKjZwFXgkB2Ria2nNPvah4bMq85bH", + "NodeID-D12qpTYhB3feogxvMBzS1QPvwyKyhRK8G", + "NodeID-D1H3GmiDVvoMsp3foTPmWi9YPXweYv9fn", + "NodeID-D1rgZbjdrevpXXDF1orhAvnUmojVfeZwM", + "NodeID-D2hsJkh6oAf5X9WEuNgbChFvkeUgC99Ns", + "NodeID-D2iAoisJf33uGaaKh9uCUMrEjN9HG5dib", + "NodeID-D3onstuMsGRctDjbksXU6BV3rrCbWHkB9", + "NodeID-D47UrYCDdkfrDrv9gUvYKLUyT44TXYCJZ", + "NodeID-D4fXiW66E7QQoTTaFjdNuhbim6RVK8f98", + "NodeID-D5aUrNtb3vKUBKYpdapiaGEaBTmUz3Jr2", + "NodeID-D7JFYevRv4N7LXa8ihCwdzVtc5szT9Q7j", + "NodeID-D8vyyYopHECxjFCQ2K4X1sttJjC1B7zva", + "NodeID-D98ujhSFuA5pXc8bnKPPpbP1VNFnfESVk", + "NodeID-D99fW2bCQpU6QCN1pu4UccDLZTQdVEwMj", + "NodeID-DAMYbaM35qcXWvuEKt6spGK6EzVKDJUkT", + "NodeID-DAZNmxJPADAnk53993F5wntS7LUhxNH2i", + "NodeID-DAtCoXfLT6Y83dgJ7FmQg8eR53hz37J79", + "NodeID-DBB8Ve4B6dXejYtFhwcQ8ZMFbmZu3VpSC", + "NodeID-DCUpFFgVWQBseGis77N45cBAZudSbaZyg", + "NodeID-DDzbSLsiD9qMPr9eaUhxwrChfbbXW8Zu1", + "NodeID-DEa3uaa1iztrxytaMqaP3PdydErzjWEgh", + "NodeID-DFH5SbPENeErMmeys9FcQTMvdKkYrdLU2", + "NodeID-DFUyhAzXyYi3TUaQYBvm5cezyEaREeSYB", + "NodeID-DFuM24ytt31NZquBMCS6X3EHmrbfJXMa8", + "NodeID-DHEd8i3AGxYG4irHHShuBuxztefU8QCxj", + "NodeID-DHUX369UfTJb2vVuWSRdJr9s27owdMbkS", + "NodeID-DHpKTzduyCvN3x2G4svUD2T7LZDD1T7nC", + "NodeID-DJ6nZjHBeTwdQiikyuz1foaQ6dWLLYm4u", + "NodeID-DJbw4TrSRu9uovTKqo6w12axPLHWHsjJD", + "NodeID-DKSq9hmU318ceXbU4LBEcSacDPZ5oSNAf", + "NodeID-DKgP4pe8GtAwQ3oVgvHJFG3WexnLjkkSt", + "NodeID-DKxvuUSqd8xtyWejxXC2JvQfP79SAsPvG", + "NodeID-DLFjLpQupsWf5UdaKRFiGELdeY2ViJfwT", + "NodeID-DLwFM6gfY5wWfHHMf5tC1NjttQqxZq7gr", + "NodeID-DMn1E4EyXZu8GZGKHV3p1naTmpKkpf4fM", + "NodeID-DN3fqQmgTBvk5JDxKjCFzmbs2XSVXTKny", + "NodeID-DTpuMKcnryCN2VyDse3VdSiQjkspJu17P", + "NodeID-DUmZowZh6nxKskHUybupqNAhnXVA5yQ1r", + "NodeID-DVh35F3R11HAAxzeSTbk3eR9w2BzPrJQt", + "NodeID-DY2Tk5ZqUir1NpSiTwXVGdETCGGEV8wHe", + "NodeID-DaKj4jkyyCN4B5zVW65krECqpjxYGUFzX", + "NodeID-Dbf2zdJeUXfi3bFzmjhJTSgyME2o8iEaY", + "NodeID-DcCkk2wqS6L9XpNX41DVN5RZnwgixCYqE", + "NodeID-DceQxAzA4nCGFm9BKa1PEJ4c1zwx3YLuu", + "NodeID-Dcs4UwSwQe7vKaopXi9AcM891ybKatAvp", + "NodeID-Dd6BPwCsmEQaAgx9hpck23LYe1SopA3p9", + "NodeID-DdJNZBekdB5EVLEe2vE9LusaHjbGmsMYh", + "NodeID-Ddm8dYWWMgiZv5dyNWuzgkDprubqB1wkN", + "NodeID-DeT8Fw4Tp875GUQNxfcfKoBSPjKpGi6eR", + "NodeID-DhNYzUwYHPF24Wfz9MmmVyqLBUF6tkEpb", + "NodeID-DhuG2YhqQy26zabyLqTqNr85T9XscsWpY", + "NodeID-Do5ZUHCK8DHm194KGqdcwFc5wWE4fCQ6s", + "NodeID-DoEC8uw9qRNi33EiYrPoK6Vu9pnsH2rnW", + "NodeID-DoTTJmp8cmERizJdYQGFsPVFgZPJxfcis", + "NodeID-DomnwLG65RUJM41RgCJ2tRdR4iZEkVCkk", + "NodeID-Doy4qhTgun22byNDyHxNSRceygqwhwXCn", + "NodeID-Dpba952dAUnayPmf52GJzQj1PLoqtXahS", + "NodeID-DpwJ1uaLSpSqKu8ZTa7XpmFp5BuBYN4Ns", + "NodeID-DqqpR7tQ3goBbudggakvzYs2K9TzR7daR", + "NodeID-DrijBGc9SonJrGUwex3vXtzzEGW3cB5DY", + "NodeID-Drv1Qh7iJvW3zGBBeRnYfCzk56VCRM2GQ", + "NodeID-Ds3ri3EksrtyjtAJ3RbX8Wku19LRdKTti", + "NodeID-DsMTbudbrnZtFyexvZihGfb9qETaxFBm2", + "NodeID-DsZ2yLdYvfHZptxMZqmHKgs4T5ehRTx35", + "NodeID-DtCpt2Bi6gvmQqwgKE59fanof5F3bepnd", + "NodeID-Du1Ebao2uJG8LukNGcUrzAevtVRhHdtKW", + "NodeID-Du7SAKQLR3j5iK7tGv7NvTSxiEVTfYfeS", + "NodeID-DueWyGi3B9jtKfa9mPoecd4YSDJ1ftF69", + "NodeID-Dv4KWhKB56So4dZNxRRi3J2V74TaUXWMg", + "NodeID-DvCdC1yWp8a9NNLBR7agvTV4YNmJY7zb4", + "NodeID-DvKgKdhkDk6CUf68iqA5Kwaa44RkBa4zN", + "NodeID-DvMo3a7eJYQexjLrR1rykrc1jsNuVwnPn", + "NodeID-DvVgVUfihpm93kUJs381BdFcS6goazwUn", + "NodeID-DvwWC5ed3j5iG6e4Y5yxAUacPkXvrxLFT", + "NodeID-Dw7tuwxpAmcpvVGp9JzaHAR3REPoJ8f2R", + "NodeID-Dy47rtrYr4eiyRTSnbaFi8KZVnR56XrUC", + "NodeID-DyXd5SxgwWWadT9PdEpieSPtjcKxYCMjE", + "NodeID-E1c6FEFavQ1RiaNARpxGx4sWnXAGh2YHN", + "NodeID-E4KwVKcddwozth12cNvNYApyHhVbvnby6", + "NodeID-E4pVcU7hgYn962iz8sQRSf2R7jNKDQewK", + "NodeID-E5DL2H2CxUUdxe6TcMW7uTHC5mFujF1eD", + "NodeID-E6GJmPWBnGKad7hPfxCK9GRwsuAKc2MJQ", + "NodeID-E6uwzybtqQ8H7aArfxxVJWVsEcaCPLT7t", + "NodeID-E8rXzDkKySREDECoXPqaPPhQA7QuxL9M2", + "NodeID-E9cBEoCDBGi6qFGcW6bfFoyhWpq6Vc57Q", + "NodeID-EA7WyeKRdVx34ixXFCvfWbv5P9DSNsj1E", + "NodeID-EBF7imfP93Sc4cv3cUAK21maYDvaFMS5j", + "NodeID-EBHJ9gHUbjtNQMnNNcJEsqojFpAbLrnVS", + "NodeID-ECNKxnabxDwevTW7bLgP2Meaid1j8ztVn", + "NodeID-ED4xkYFhZPNNj3WXDQiogcTULeBpDVjSY", + "NodeID-EEipCNkeRgfvwiDHbaBdQ2WeRnsRVSH7P", + "NodeID-EFd4jseGxHxQmYX1ATcJUSZoCnE7z6dFe", + "NodeID-EG6gFe5McNc2EyFzARxuvTApN995FdBZj", + "NodeID-EGKLqBNabvY52737RGARiuGgvu2vHRY6v", + "NodeID-EHJoNS9sgSnjg5gkvKL4AF5vyi8c4qTvg", + "NodeID-EHpoaNccurjGvMCc4fFHKXvWKCzCeFsCw", + "NodeID-EJDb7Gfu7w4vJeBA5VGa4k6d2foKVE9P4", + "NodeID-EKH5gkuABvZWiZGHvWuZLgGar4Zts6qX6", + "NodeID-ELNdDSKVpamvTWSQvqqBWzuAKFiJLzoT7", + "NodeID-ELcEoPFQPwAQmnndhM7QXtVc6sQiJiTHu", + "NodeID-ELjBQTBvaEAMk7Qx7qJNJsEh2DYC4nxUn", + "NodeID-ELx4yRvGiDRcG8r8Tow1LUAhMXkVYVzHo", + "NodeID-ELxAoLLT4rkHwrAxxo6Ubkg11P4ye32kL", + "NodeID-EM1NUe17RtPAJ4ofro1qPc8vEfcvEhjZM", + "NodeID-EMETD23g2Bne8CuQKyR8HB15KWomaAuFe", + "NodeID-EMq3MvHvWctiQ5CC2ioXpeyKPsHteXAeR", + "NodeID-EN2aDGGjPAqm4Npzk9wCjCdGfg5hVrWgp", + "NodeID-ENc7M77QRhgtpDojDQY5nqjndjiYCWR4i", + "NodeID-EPqYJkZ7knGWY2TNe4rxRtNgkqc6spyDC", + "NodeID-ESRpVRqLwts8M93Ly9QPm4ZSdMF4wEpbt", + "NodeID-ESVMWUoEkKz8uAEDfKcEpu5UUCkA6GeyC", + "NodeID-ETwxZVMHXcikZmKsKfjiZuVG84KsZDdqz", + "NodeID-EVchqoADmKDHejumCGQDgZKc1RoqAWnFY", + "NodeID-EWNvJxWq2UBBsn2UH35soQugQJn8CVKdS", + "NodeID-EY4iiXyj2TfoHspEHBHFfBYrHxXESnSN5", + "NodeID-EYDcoNgbX22og1oyEn5s7iH1BYSmR5yF1", + "NodeID-EYgNPuFCT4Qy7YhvsM2s8WKTT74QECvTV", + "NodeID-EZ38CcWHoSyoEfAkDN9zaieJ5Yq64YePY", + "NodeID-EZ7FxvAP8MCsQgCz36DMBUGA1tcHL2PG7", + "NodeID-EaEUnvUyfTr19uMW8g51bvFXfi7r9xL1W", + "NodeID-EbwYUq8FZAK4jf65nZ4dcb5kk5WZ7RBgb", + "NodeID-EbzFVG1XWNeioXm9KKPCvidgkZELPrj86", + "NodeID-Ec6W7Mq2fnotBFoiD6rwQSsZq2XKVEyTF", + "NodeID-EcPEgrRgf6CDahJR7mJpPvHct2EHi7jNM", + "NodeID-EcoA7iNFXhc2DwrmWxiEvjvsDvDmQrEKK", + "NodeID-Ed7NMisAoxzWRjxQVrWnBvMShLNcydRa6", + "NodeID-Eeg2Huipo4K5oURLwd6EJNm286b1js6rL", + "NodeID-EekL2aJ7TdkbiXDzSsPo5PKyaaQuQqVg7", + "NodeID-EfnXCVeLUtW24v8gwW1VYiNuqDeRPEVYC", + "NodeID-EgAUHBUiTj1QTvNmw7cdqWDe7W7P8B2PH", + "NodeID-EgzctrMz5jVPbfUEWGufKxf9CXUMLBRGG", + "NodeID-Eht1FjvmFncRbagWk1PGMyE7hVrCS9Acp", + "NodeID-EibWFSUHeLNNjWZrEznmuxH7ZWNsavRgh", + "NodeID-EiyGqDavdQ8dMUtN5wjAezDXAWwVBdSBK", + "NodeID-EjJCGURmZ76FsztnHPZMn7AvwSDZXZhsV", + "NodeID-Ek1pare46s7nXPF9JtsoyM7PcaFnCBms5", + "NodeID-EmPwabyobnM3jYDvQuxZdLBTut5V5pq2n", + "NodeID-EmRTfxEKTLpzTyWJmYTXVxyGr79bsv4Bp", + "NodeID-EmVPjC4ePzg8perYoF3c3ut6fHHDDfAqF", + "NodeID-EmWrMTi9PcnYH3ZPCXky3FDDTatB7bfuk", + "NodeID-EmhfRnDPSzpEMhGy3KSC4BWhPdtoxmqqV", + "NodeID-EnANSJ3hrErv6v7ZGSi8p5RCHhdhbGrb", + "NodeID-EnVDmm6dUgePaWbtBem6HcbzptaigBxDe", + "NodeID-Eo31HyvvA1Madeagm6U8CM376cEfgS4Bj", + "NodeID-EoJirncHtvkCuiLac47FracheuCHmMxnL", + "NodeID-EoNXC39QyT1eHFPXb5PgvDNigBN8tMeCC", + "NodeID-EpU1DGKMMvDRtag9u9G7uwZHRsJF5NodL", + "NodeID-EqauaQBwVXnpamJvLi84aeZLTQra4GDep", + "NodeID-Ess2uf91CDTfKsLezaTLKqqsWcpEHGvJv", + "NodeID-EtFG3SrbbudeFQCaWRxhwvv28wHpo8VRq", + "NodeID-EvY8p6SYho6VwicRvVasSBBv1MtanH19D", + "NodeID-EvZXX2K2eVEV7n6Y8cnmeSRgj4JhkCVad", + "NodeID-EvdPJG2AAVGCP2s3543KDx1LZ1g5SiH2Y", + "NodeID-EzKkVMd9y6XqzQsvRDLuaaiXqXK8fFipU", + "NodeID-Ezk1hTiN5bogETxygJ5NciRvHXgXvUVVM", + "NodeID-F1K4jks15y71PthvXVNks8pgutgBwdHZH", + "NodeID-F1KpunDAMisiGKLX3R6k9uBoJoeLwzJoU", + "NodeID-F1qvuNMn9XBXSjv9iWyyMGfV2PQ2Na7KM", + "NodeID-F3SZA2ZNdRjTBe3GYyRQFDaCXB3DyaZQQ", + "NodeID-F3b5mj8PWnMP53hFbfGNxkiXpbK6tPyDU", + "NodeID-F3r4EqguPQgupLCYrTG3SeJSCi5qtc3x4", + "NodeID-F4Q66oFkqCmRnBjDUAh28iXvWx6WxbxJJ", + "NodeID-F4SmFmnXuFBkW5fgFgh5RT2T5w8KseGRN", + "NodeID-F4kKmjMhZJWkYwsWyPSLFxtNcj7BhELmY", + "NodeID-F5sBP4yNA2YXHbD6FJUjsZJ5zhoMqMi6g", + "NodeID-F6QBpEsQZXXqtW8PxZRm3Znx4fVaAr5Sf", + "NodeID-F8HvQKYDbonSeJ3x42Ynb6ibxiJa3FWVL", + "NodeID-F8VWioW7dC64159mMhswhzpkHxnB34cjS", + "NodeID-F8Yq4R4Mx1LHGbQ7g8s3beNB4LGnCUBpv", + "NodeID-FBtCkPRmkfDry8GGpNenBW2fn3fD3qoKn", + "NodeID-FCnZCi7LDQH6Jx1L4ArW3jYZUxD9q4rqT", + "NodeID-FDMe6hokunP6wTY3GFQ9u2uVPMtrfXGFw", + "NodeID-FDTRdm7eS7sBuzAnQqMrXUmNiuNHP7VM3", + "NodeID-FDZXWAQeuMzZVq8tv53b1NdiwyJDUHGpB", + "NodeID-FELjhENFRLHTgVrwiKTdL7aSQbU8mBd5Q", + "NodeID-FEUSZzFmjF2JyrniKXksGfRjkQUH5R4eH", + "NodeID-FEsoMJf2VjoRPdnm1Ux7CGg5RrHnAH3VX", + "NodeID-FEtgjYGndfWGzLZELTJJoikpSobjVKTjk", + "NodeID-FF2Szx54cN5iys83j9H5xaEqHiz3RipkG", + "NodeID-FFWS6gV9FrKecNWCYJQuyR67t7GY6UiVq", + "NodeID-FGRoKnyYKFWYFMb6Xbocf4hKuyCBENgWM", + "NodeID-FGt2J8WREPFbbTXgVU9YC5NjdERhoMa7E", + "NodeID-FHGwnPLGdU3FBzbwnhayx1sDjxiiyb9sD", + "NodeID-FHHEXLYRNrnQhKFneEwDPX8TZV8WtUpQY", + "NodeID-FJ7WdKoGBkqb78mMGrr3r6kSL45R5Vspp", + "NodeID-FJfF4TPzajcf4QNHjHUi4ctGPq2AxkGJt", + "NodeID-FKCbGm3jmceEEpfSdA4uQUVANpmqFLAty", + "NodeID-FKGhEFYnHUdFadoR2ePvdTTM5Sz8tgjHp", + "NodeID-FLQ8ifj1DwXuRWKShjck624SAgYXVpQzz", + "NodeID-FNfrZNBD1bxGj1VmdgSrEKT8oMePC448e", + "NodeID-FPwgrsmgeX4DSkG4abJ28zZQhjcqirPYi", + "NodeID-FQKJ8yATVmwGuy3LN2ExsURDEtZNWgr3v", + "NodeID-FRTCPrh8YwxmR9L1XJWjLuMA1r9SjPrRu", + "NodeID-FS8PXhYXxoo5GoTHoki5Y3Fqk5zzdMY6E", + "NodeID-FUpfjb5sPRnT3XxMbtephYBc1MHZE2RYL", + "NodeID-FVMb2XgKVaeonehFbPMe714kMJ7DRxhpt", + "NodeID-FVgPdpTafzx8jazSNoxvQmJNxoEcAMmxm", + "NodeID-FVgkUobMuUBABuMA2KngEsm2SG9XLGvdW", + "NodeID-FXsyWrGvZZEns2iZr4d2h3pW9piH9ZE5h", + "NodeID-FXzsVMpT3ipDikUzabDtmeLrXW8JYyNZp", + "NodeID-FYv1Lb29SqMpywYXH7yNkcFAzRF2jvm3K", + "NodeID-FZHUwdFr4rndHpmSFXLK9dJwKVcijv4yW", + "NodeID-FaS5J4D4a2FE7GRG6SG5aTizazC1QNqWA", + "NodeID-FapbxinG8eCCXzZQKCjxicKcXijmnKzD3", + "NodeID-Fd4DMc88ELLiTHHSLVZ7L4MB3Z7jbDEAy", + "NodeID-Fe3121hoArBshDTJEEeMeJTNW6HcLXxT1", + "NodeID-FeddPuWb8xtJeuXCDa4CAbjgv3n4PBQXV", + "NodeID-Ff4Fx8mcbfBVZSpMFwQKDUURzufmLjLgS", + "NodeID-Ff4s5gpeGMf5HaBKNxBX1uRxB2hxRx5By", + "NodeID-FfRKiU9BpTzMx2KGmrN4YyiwftTAXZ6FH", + "NodeID-Ffh3UfBYLouumUQgGuFbSTBbD5wLXn7xG", + "NodeID-Fg3L1eo53UWpf3J9Y45PK2ksQ1zyqajHL", + "NodeID-Fh3Yr8SejArPdA3eHfg75sLAt1ypeSpCV", + "NodeID-FhH7R1HX2ipEetm1eH7u9aKfBCtCQyuQM", + "NodeID-FjPxKjpGqPNj8NyEVVdJgGT2bXFVkNyW5", + "NodeID-Fjgs4ALe7yajXjZYmcRAvaQBGrFE61QME", + "NodeID-FjpAr4XXwanzuhLMajEVdm6bwdcGgtZNv", + "NodeID-FkHyxMuq6DGNLdQtMKiLzhQQuwjSCqwHj", + "NodeID-Fo9rQ4aPdfbA2TZbj3Ppcp4pkQGumuNTZ", + "NodeID-FoVyB5QV1hmvAxsNunHRRzonCBJGkLvtj", + "NodeID-FpA1n8w3xHmJ1QK3iDAS49vbLJokejfMA", + "NodeID-FqiffXvatKSLPRhkkc5y2MkALrZ8EFN91", + "NodeID-FrGVKPnD3xVmoMK1RjtbD6evNGk3wrpv7", + "NodeID-FrPwbz7L7qvxbxR63g6CMpWPDEyHiiqrD", + "NodeID-FrTRZzNgZZoHMGvC5t6XtJKAv7E2LvYYU", + "NodeID-FrWaLbhUVQHEzXfeekv6MCbkmLfx74HrP", + "NodeID-FrhMaTxsagqjYCetCyxLxpbcpkN3cjVLH", + "NodeID-FroHhWhFsUAh3s6Y4hjh7mx3E79mBUZGj", + "NodeID-FsmksgteqNTPjyrwVV7xPgsC8SwEwKrgb", + "NodeID-FtJRoxeiXq4D4hsM9PCAZkoerJDTqPEW7", + "NodeID-Fugfqxb9NKZ3h7vTe7XsjqqKqxYwSrTsh", + "NodeID-Fv3t2shrpkmvLnvNzcv1rqRKbDAYFnUor", + "NodeID-FvAAKfRTbxB5ANcapWNtQ2VGMFWxX3LCh", + "NodeID-FvFBsrTf6BhCcS1nFPJtRrWZ5Nosb47h6", + "NodeID-FxZHg1hxvYyBWFCHzqQPhFYsXte84UT9A", + "NodeID-FxaeyWwirpBBbBwRgpytNrtR3NY6xTiwT", + "NodeID-FyTHAQeNPFhoDetc7pznBMJ5BRj5s6FJr", + "NodeID-FzJA5i97oBDNiKeePSfHc2t3zt5cRHnjJ", + "NodeID-G1KHG6SL2B9jnfbzdTudhjRPa9hp5tuRQ", + "NodeID-G36WdNdkGY4aSh77e1DziUy9SXTgohYCE", + "NodeID-G36seLQVfXnaUgaNobbSWg8anRta2WUwE", + "NodeID-G4dtkvboFCTYpnLyHYMVPq8GLxns99NPq", + "NodeID-G5QuntEfMZS7A1TPSHN4owEa81C6MAGC2", + "NodeID-G6nXgtucmeKn4nkCp8YTDdM4btVSnW4ad", + "NodeID-G6oS8Nbb74RyJatPe34iwhTUPDqJNtuwD", + "NodeID-G7aPjXRfR2XtrB4PGATDS8NoqxmqZmryS", + "NodeID-G7kG9MRuLaJuMLopdfnWEKUPQp54qc2T3", + "NodeID-G8uVCikgvakai25byQwYx1z56N33unmj", + "NodeID-G8yv8mWQy8FLdFfAhJ4v294T5Z2DWDVEH", + "NodeID-G9aa4VXB19wnUzrmVq2SheaxnKEieUW3S", + "NodeID-G9ucCcZoHdXC6mrVpKVqKzHsMrnoVZLU8", + "NodeID-GAEZpCd2Lg5RSrPtQhGvxw6Kid5tAL6bw", + "NodeID-GBvezLieTFYRqHsd8QzWqH1JUhuwD21mJ", + "NodeID-GCL85wyq71aw2FMRTct2PJ2F4qGQL7WH8", + "NodeID-GD3XH39S9feuK74XEh8AhhNEapSt2hqHo", + "NodeID-GDmLiXrEtmFvBiE2s1ZGDYdZZXdkkLW5F", + "NodeID-GDp4P4Jo84yyVRkL3UTkJDuTNno81BBxN", + "NodeID-GE2jerBVdHtvfKkqfNHwBr2MCkDf6tLir", + "NodeID-GFbG2ARoztCgE1FxUekg5KjEaA1bwThjW", + "NodeID-GFw4C6SgNLkbVq5EeaGtZTjGKwZzmWbUz", + "NodeID-GGHpri3tVbRgLUEFKqxNivRbegTKBAnyG", + "NodeID-GGfhdfGbqenvgChEXpdngjkKYAByo9di7", + "NodeID-GHBthsGgAzrPLXuXk7vbq4qsc9CvSbwXS", + "NodeID-GHY8D7pCGPY2qScDmtLp2PAvpbnAiVib7", + "NodeID-GHZZWcg26qxY8K9uDLXu6Gc9Gh3P11dK4", + "NodeID-GHd5dmrKvYkAbxii5V7wmJw8sRf4JqYAi", + "NodeID-GHomCXMMRTSPRZrrxEULYPFHHXEhb7qvY", + "NodeID-GKBykzpxeALzYee1fGQjFn6oZiA18W26m", + "NodeID-GL87o4Z7DghVRLf4z6befUxjDoWXZUDqg", + "NodeID-GLSSsNA2oHSaebdYDBQ3u98kvHfH7zjYf", + "NodeID-GMJcCQwhNFDGQy4NAkKM563BMudjmHpXb", + "NodeID-GMUutmiNAryEiuGU25DtGiUmdijYqzWH9", + "NodeID-GMoxCucPFt2LPSpTh5hPbDPAp71fiV648", + "NodeID-GNHgGvi7xri6CckDAzmQYL4YgR42WkVsX", + "NodeID-GPYurKNwtkhJ7M7UQoDinFz5P7Rsu9yUo", + "NodeID-GR11oP3kLHf82Xbi3H2kewqoM7ydHF5ES", + "NodeID-GRReUAPgHbGdXcv5Btpm4ByGvLrD1NgXG", + "NodeID-GRrpJze5AEaBezaYp5QRtVcLAF6AzdJSy", + "NodeID-GS68HENWev9AWcUrhLqxYvsv2opJBZ7km", + "NodeID-GSgaA47umS1px2ohVjodW9621Ks63xDxD", + "NodeID-GTiNyt8W8giLsJbH6A8jXuLjDesZKwo6a", + "NodeID-GTu4yYzFRv4QGXyyvcorGDUMWjzzMWuqN", + "NodeID-GU7boimY7cxeqdDmnPRyYrwLiRmwiHxhn", + "NodeID-GYAMwLv3XViragqqJUQyTNRcUtoRWbi5F", + "NodeID-GYYGoe6y5TtL8vNBVkvTqk8sPTVVqbGaR", + "NodeID-GZpKzj11mC7eg52BWpL6x5YpQHBAhKPaD", + "NodeID-GbhKbbABkTdzExgzbbsvCdc4gZe8eHpgP", + "NodeID-Ges52zCMZimxqri3ia1J32mUAKyUsvcpV", + "NodeID-Gey3HmUZyAXuvawThT1McvEjrofAwrGi6", + "NodeID-Gf2f3hWkqxbYtdwPHFRJXQwf6PFzvFigx", + "NodeID-GfDdBdRqzEKK55gCKqThE2LVxLdLhJY3A", + "NodeID-GfRY31feBaTknS7uvpF7XHromUfckDeWh", + "NodeID-Gfeb3fWPCSpA4g9edG68NS5aJcYpXn6T3", + "NodeID-Gg8SEQhx4vU2KWzQS8ESCrSpcjzEqQ7kY", + "NodeID-GhG3ac1x2g1Fc4xPWXxXRoTLmMuT2asMV", + "NodeID-GhUSE8wcdouEgd3xeCvmYhmevkdNetfXk", + "NodeID-GjYkDpBkCueF4vTkZVdtq3yFiMJha2XpF", + "NodeID-GjjemGsR2kXtPLSwv4oNV3JFt579oJUnn", + "NodeID-GkiJ8CRTibePNf3Y2F7LbGTinHm71HvnF", + "NodeID-Gmitibwg27b6WqHLjqmGiXZAh1kmZVq5P", + "NodeID-GmzoRvWfUdTTUZBmWFM8rswgmwMKkcDAB", + "NodeID-Gn7jLTVPuvdrx6mF5hxSbazRoKPWsM14s", + "NodeID-GnKLq2ipT4D2CMcrrGYndSCuQL58yhCR7", + "NodeID-GpDhyVHYVaL8qXFB2a1QPBsXyUMZjiXLF", + "NodeID-GpEnAaYG182MkURWh8KY4wL5KgWB7cBw8", + "NodeID-Gq6cTyqtHRGHSHELPNdwXCjQJH6vwUkBc", + "NodeID-GqRuMoELZus5EYMwBpiBVtWFDnvLmaJj7", + "NodeID-Gr9xzzL6emX5jWv1LoMKLpCebYR2V2nYs", + "NodeID-GrUepNEsZ6CNa4MvP2r7XS96mywaWxvHP", + "NodeID-GrkiQsGvbv9PSqJf9r3eE79fUgbZqydmK", + "NodeID-GryC4h9okVKe5e9iZAWFxPWtbtMSMervo", + "NodeID-GsQoMs5GAL8inkh88XPVJWKMwmJqm5T8N", + "NodeID-GuTDsR1tBFgQUbKqCf7J29yBo8ofudHEZ", + "NodeID-GuWMRuFkQPvPjdnuegSQYDmTMbj3UtPBm", + "NodeID-GujHWE263qNN3MjEYhEeAQdPpQdhHquLJ", + "NodeID-GvEoakPRjaB9jTKup6nAMpFSF3HiEeocP", + "NodeID-GvQdXQD6qFzfAYBvnvxiep7WaXVj2FSnJ", + "NodeID-GwcsDtmQrD8thUHiQWgrpRvhuMjxTqZP6", + "NodeID-GwfPzhzby4Ur8mgdqPDjR3jSTevtmfmY", + "NodeID-Gx4oY9nZmAzJrHUfobrmuK9LrJhwejykC", + "NodeID-GxUaibkyR88sErviW2WK3ukDJsT3DFpoU", + "NodeID-GzSFF2tfNMc7YdJzGeNeNxfSWjDvENJUt", + "NodeID-GzhNocnYWSCziBTP5Jj4xAKn29xDKW9Yr", + "NodeID-H1R3mBHFDeBoQzVYyHzX6RGnVV4nMTrWZ", + "NodeID-H1YSzbspeyANTzErprmBQgV2Crq5hXSW8", + "NodeID-H4mD37NM384RtLGjz5aERQoNCrtGEjgK4", + "NodeID-H94Q5zdkBByZVWvqrB5ByiX4dZdG1J45y", + "NodeID-HAYp8Bi1yZ4dy4JeBQRBydGC8NqPEURXC", + "NodeID-HCvPALEtcP4HX3HbPk4P4SQcrriBgsvCG", + "NodeID-HCw7S2TVbFPDWNBo1GnFWqJ47f9rDJtt1", + "NodeID-HDXjAjk4rG42HXey7gzQPx6dMBfpWeh5k", + "NodeID-HDmmLUSLtok2sGQEruUsYSMjBeQbUrwpH", + "NodeID-HEXgWUqyRHf8KkRLMccJ7gNaDGZQAjDWF", + "NodeID-HFFiNVtYmv2YF2WHCZWHSCigo25RxgnFz", + "NodeID-HGGdFL79J8hGBoMMoimh48CcKRpCxHcb", + "NodeID-HGtZapUapv9uNq2JyUA3njmdFCPJbjdqR", + "NodeID-HHQ4BFhNMVJwMz8b5tenWtkzdcSYvonmi", + "NodeID-HHV1onrMrN68JdRoKfQGeZphebgRrcADT", + "NodeID-HHXrPaqfJVquBsJnCam9KRdNcQY35sPrG", + "NodeID-HKskHZG5zu629RsEkScAaGrpfGQABqep7", + "NodeID-HM1vYJWnjWhJkJi8dErcu4p5UDxwUKbp9", + "NodeID-HMFqHmnsaeBGdeg83uXsraRJSH67DNsi6", + "NodeID-HQ4Nfe891SxSJ2FTx3e9AdabywKG2ufYF", + "NodeID-HRM3t2N67g9R4nWc1DhoL4GohVhHEbgFm", + "NodeID-HRZAiPM3BaZJpAq9jy3UME2EGsrv1ZMaa", + "NodeID-HRmKWRK8HjqqTKWvYMBNv9hcddSYrhqnF", + "NodeID-HRsnjv1s8VzZz8Ybuiyx9MgfDevUcPeYF", + "NodeID-HS1PKAMjZczSb5ZQRastn1WG6eJeNmahd", + "NodeID-HTAhjx3CNb84CJUMsGj4SbpyvEsuehcWC", + "NodeID-HTG7W4VHoGJBUTip1gKXzXGtEBhiW1DXT", + "NodeID-HUNYARt6cNSXgANtsSakokNpRCUKCFoVS", + "NodeID-HWwYYkiTKnXgYycNN5gXQfxhhA8TZdBvs", + "NodeID-HX7H9nBZX3nZRvLVUxCDBesVX6n8Uv4a", + "NodeID-HYBD7r66XFw2Kx5UydvFNAb3w3nnJVtY2", + "NodeID-HYwzPrs3tDR6yyMtKZo22fq8grJsP1DVF", + "NodeID-HZnBEWRUGocZ4HYX8EuMP2YEY94NtySWR", + "NodeID-HauVjq2twoqYvMdNe2dCqzSJoyvG3DJc1", + "NodeID-HaxdTdeEr1sWMRZvXwRN2iotd6RYd9XYM", + "NodeID-Hbf2ZY1Zs1s8KMp3rA1zK36N7zt5fSLkz", + "NodeID-HbmSiec8zTKiPWxaBwStg58a3N5KePhC9", + "NodeID-HcFuyTmh2wPEDBCQc7T7YqUS3N3qj4oRe", + "NodeID-Hcq3gpdMqAEiVwq19E5DZhsjggbkxFx2L", + "NodeID-HdG8EdGWAy8LR8YPA8hndoa1uwwgGv1si", + "NodeID-HeWgNLFa4623i2Ha67tpjnA8RdDNpV32j", + "NodeID-Hfa96c7a4xF9vYHuMh3cRsKUHa6YkDsYN", + "NodeID-Hgs8rDmSTASnKigsVfz7k3yZ3DgXP5s1j", + "NodeID-HhEvRMAeXAuXqULRysWKNLK2XZKzYwCnK", + "NodeID-Hhkq3c3UzzX3UpwC2kq9TcbJdguht164A", + "NodeID-HiFv1DpKXkAAfJ1NHWVqQoojjznibZXHP", + "NodeID-HkE9eyj5U8saYexeGWuPcQQbiu5MyRHHa", + "NodeID-HkEQ2sJogxEps4tmqFRDuVG9hyfxe8vMg", + "NodeID-HkpgaE4YB9Z7KmueQ2mz2cZFyfttvo6GP", + "NodeID-Hn7YWxiVC9JufWW5n8u1mvaYgNgqWG8VT", + "NodeID-HnCFvKLXEVsT1fJtMxCnkNj5fs9ExEugv", + "NodeID-HoC4UxP4UuJyda7MZs5jUkZRk8Rfj3pzD", + "NodeID-Hp82btBefk1ffBD7d1qtoBL3DuuNUv6qa", + "NodeID-HpEw7munmgQtTNd8PWqp8T4GNU738Jvc2", + "NodeID-HpMSfYT2ox1vkr1hFNMwmdWuq8QWhvH2u", + "NodeID-Hq2aEQ2RYhEo7BkVR83c78n6wbVLPrbqJ", + "NodeID-Hq5vdoGnZLMfasw4ykMzdM6PhUFDmp7FL", + "NodeID-HqPSHk6fxtJW1EsF9Y8RPH7KvPvdRpnzy", + "NodeID-Hr78Fy8uDYiRYocRYHXp4eLCYeb8x5UuM", + "NodeID-HrGKtuSRaRj9b4CNy2JeLfv1WAULmhwtF", + "NodeID-HrPfqGPogaKpTTcBhNBhmYfLRHZhiMWyR", + "NodeID-HsBEx3L71EHWSXaE6gvk2VsNntFEZsxqc", + "NodeID-HsSzvb9mMLFcidMWoQYXwHrnG2gZKQtPC", + "NodeID-HuPCfRaLN2cXoXDYyi8GYvjATLDmNJMHs", + "NodeID-HvmgHvMoe15ks8rbGXHyKHvJWDyN5yAGU", + "NodeID-HvxZoKdC58RkD4ZVTYwjVZ3TsiQoTESEP", + "NodeID-HwD5fu2NCooHXCPc2GMuNHrhfsThpsQYY", + "NodeID-HwQ8H4zxykyXmR9dZgxsiKiu2u6s8Mppw", + "NodeID-HwTU12fiGyZoyqaShTAFgTadY2w4DnazT", + "NodeID-Hwo6hDmWvSH3rQGrxCoujGvsDWzC9NgyG", + "NodeID-Hxx8vTs8kH3stQWgPw1XdHKqpbuD2nMRi", + "NodeID-Hy2aSw3vVNwwQhKas9ETUxtfZgcefsPZD", + "NodeID-Hyr1U8Tbw1Q9wgJYRfraYsEp9EzMugRte", + "NodeID-HysvJteG6zyScbEu5WKiqAetFXHNrnJHA", + "NodeID-Hzfy8c2s9PyC7CPiUB1PmPckWYs7nj9Tm", + "NodeID-Hzwoqn1Vmj46T1HZzEUNG9kb633SLLHxZ", + "NodeID-J1CD2Nw1eX7iNUVw3iXjFJkUgrSm9qbm6", + "NodeID-J2RTGUXRNDSx2kBU8w7Am6Y7k3LABR5iU", + "NodeID-J4NNvkEUScCLYG4aN7eW5RYx15vSCHrui", + "NodeID-J7GwUKfHXhxTqgFbuQd4us6yKYdwahHHx", + "NodeID-J7PV3mKZgSJRDy3atopJhh15Y1TqYsySk", + "NodeID-J7PjfVJgpLL3mBMUwpicPqiqDFAmNWhKA", + "NodeID-J7gmHAAEPkSPbNeurMqhg6bknPXWgJgS2", + "NodeID-J7n7bUvog8Zdgj4bCNxRzjzrSKAirk7vi", + "NodeID-J7vWeKgzhtKNy14NLT82Vkz5N6L9sqB38", + "NodeID-JAkZxmCTCkBmscBpSisz5xPFDWcrBbkUC", + "NodeID-JAqrskRRwjmmU8fRp6RAf5wDoEtjXFyXu", + "NodeID-JCT5WWZVaKqcMNDXuuYm3Gpgah9TpKevV", + "NodeID-JDH5gzcB2DTfbEokaFU7EvpLN7E1RHzpH", + "NodeID-JDS6pq6tZxZxePaDc77TvrmNnY5HBUNX4", + "NodeID-JDYxVGLrUb8SHwuu5jZBXNC9rqYWd29PG", + "NodeID-JE8JBF8Kb7xWQ4U59wKp3PcZMBfzvKo8h", + "NodeID-JE8niwmtgpDARKNUqTEdXPQY41uHtb1PN", + "NodeID-JFMBphfETbxfarEkQBHw1RSpfoFhdhUSR", + "NodeID-JH744d6NN5DbtYR3fwuonjNGqUNwhYG5V", + "NodeID-JKCgdbWtCa8BreNP3xftfUuoWGXoy8hWX", + "NodeID-JKxZwnEvK2MAsL9SQ46fyCnTo1ZDkz22D", + "NodeID-JPSnjdvcPjD2NQNaTgC8YP6dhcGeKhse8", + "NodeID-JPvThCax26E5wEh4HSpjhfbfGn8LnvGx8", + "NodeID-JQb8aC4ny7Np8CVAasacpby9moWWzZXzT", + "NodeID-JR96tvzbG8L6xdoGLUWUWhQiGkCfNFP7z", + "NodeID-JR9oQgVHfNBybNVMm64AB2AGvHFCfaaxA", + "NodeID-JRCLnbo62xRaNLhNeNd3HzSHK4dW5iMx4", + "NodeID-JRNiPWVdV7Vq7MzBmAQB4jekNTfvRAedj", + "NodeID-JSKsSxV74dyp94CvBKqEKUcEEKBXyNbge", + "NodeID-JUncQvtGY9EVfsfHNHrdsiv4kRfAQSsvu", + "NodeID-JVTZ5F1RvjDd4dA4Th7hiV3furipAaKTF", + "NodeID-JWBfuYPeFXRkuL1AeW6p2fquqoQTVJsV2", + "NodeID-JWRFL3w3x2xjxYZGun74vRjNofTw4Gpd5", + "NodeID-JWwGze2HXQq7THFQj5zWRmBa5XaMj55jZ", + "NodeID-JXT4uEeTEuFcEEgRZYFusfRm8c5iH3rqj", + "NodeID-JYRSy3bCaQMdn5792isxetF1m98urfFWq", + "NodeID-JYoS8akGmcoeLq4kxpxfsPJxwi3UWeXu2", + "NodeID-JZg54UPtzhHhXoVkX4r6WSTc74cAgdFjY", + "NodeID-JZoTeECdroSJ8sDK3nwpeBz2cYCEPPjiu", + "NodeID-JaS7Df16bwZUSL87wersMaXez7836EH2X", + "NodeID-JbXcSSwYvmnwD85nw8Yro79xaNuAJKxqp", + "NodeID-JbsnKEwxa9J6arKtZ52j4obF7FwvH634k", + "NodeID-JbyG4cewqSwjatqGtg7mDYbcvb299Cb8Z", + "NodeID-JcVg17s5KwKNv2yJtYfBjEFfB6GdHDmXN", + "NodeID-JdwZvLUi1hnwuidkpJnR2ZfryBb3FbkGG", + "NodeID-Je9mYMihjzv2oDF3ebvzDKs96zfaXDLHF", + "NodeID-Jfx9FcVMQuy1FXGd53EuigXnCEgRQUUMg", + "NodeID-JgEayrUnvk1tvMFS5Qvr6LPNSE9wNYNik", + "NodeID-JgdYonZgwW2LRYGMwcDcHywQ4GmvjJoe2", + "NodeID-JgfyD94R76Wj1KBXWkGpnsSAXLM6f6dnN", + "NodeID-JgnwfnQC9MeT7Tba3i62KGhZiCpSNNQUe", + "NodeID-JkjTJNKyJwjEfxdfgQhvrUuf9x3ovpQBs", + "NodeID-Jm1k2q2WAkH99w4ZBEgzrmm6Kte39qCWJ", + "NodeID-Jmvu5u8svgTa716m6xBEcrB6wweP9tX5h", + "NodeID-JnREhSP5nvBcrCY1L3it6odDaHKZDryA6", + "NodeID-Jp4dLMTHd6huttS1jZhqNnBN9ZMNmTmWC", + "NodeID-Jpad4xARtJKgtzo199VoEaGbmYdBYbN39", + "NodeID-JpgUnEssGrh9NBagctXHVP2cXhYZHxgwf", + "NodeID-JqHkFFzz1tYoGHzPuTsueqF1yKifPiBEG", + "NodeID-JqVwhr995DJVkh8z6u79nRknt34pmdjNY", + "NodeID-JqXD8Tsj1nKXCBEp65ESmFhBrEhPL4WCs", + "NodeID-Jr2wjVqKeLpnyK23Y4EgDpCBf1HJ8XpJg", + "NodeID-JrHvS97Avz8uqX3E1RgG6mCSaiedjWf5E", + "NodeID-Js3ahWihoTLJWTrWzpth9mttniJNuyoki", + "NodeID-JsNnvXMTu37NctoU7tHx8mt4f5oswJk93", + "NodeID-JwiikR8FhmnYxxGjywAZeJMFjxfpfD3L3", + "NodeID-JxJxzCNp5c2p447FF24jEDPdHkbB2mhJY", + "NodeID-JxxUAnbxUYQXzTQ8eNeE4jWQt9fTzWd8o", + "NodeID-Jy9zeyBRu9XvAxXfSGQ7pdZ1opTHeERgq", + "NodeID-JyCGTjJaPELmLZdtn5J1HwKHZzki6Ae9W", + "NodeID-Jym9FJcjAbqezV5HUbFT3eG3NraSQSLMZ", + "NodeID-JyomXASU2NoPhoGGzQtiVKUAHFpm3NeU7", + "NodeID-Jz2nuAFAfyvgni96rviZWsXxyYYBgSmXf", + "NodeID-Jz9EUhGBC19bzUE7kurEPyoKTRjVMgi3v", + "NodeID-K1E6w1DSaHzZky2aUM4qyQfPYMxF6Mixi", + "NodeID-K1JfVJnvPQ9ThN4FUqU2iyAQywjx1Gf5K", + "NodeID-K2fyNZcrWA4DBUNyFme4pNshAgSw2YSSL", + "NodeID-K3gyeR7GXuuf4coJXD4CxviWpRopysX4j", + "NodeID-K3unRwiJFD4p6dXDHJcdeQn6CaoFiqo2", + "NodeID-K3wvYyc46fLE7sSy3G81uta4wDKVkdKbZ", + "NodeID-K484QXg69NxbC2BUsB7Bgc511t22E6MAs", + "NodeID-K5ecmXoCnxQPFTwrDxqL63kfdh8X4Z3oJ", + "NodeID-K6qqr2J2JcYZnSMRSqpbVv5ysZfnwMreQ", + "NodeID-K7ZsFPBybHPuD3YbzBpp1fe9QTj81WYSU", + "NodeID-K8EaudGE2PS93rgD6aayqS4dPRfrseWdi", + "NodeID-K8tzccU8StAHuSZfS5trxHKbvA17wixN2", + "NodeID-K8zr3RfHUQuupNJdPDKnbhFhwcD3TTbuD", + "NodeID-KALbip9YkRerN81YxU32ySYk5PbGrkysz", + "NodeID-KAjUQ36dNGmMpw35iavX7i8Cr5XGXwby7", + "NodeID-KB5e5rq9ioGR5uicmKdmgjR5hU7iRUFTz", + "NodeID-KBcYcnQmw47qpb49rKtRr5tZgsxnsdkrZ", + "NodeID-KBvpDcnJ9ztfqA4jiAoMwARqfDaS91xqx", + "NodeID-KCQARVq1pjYw31EPSaW9571giKoFH498X", + "NodeID-KCX4L5dr83TbmBnE4UeFtzGeE2NSLskt8", + "NodeID-KDHVpdM7PeMtoVm2mmNNXjFfs93cABSut", + "NodeID-KFhoZ7aZMtAReBrb8KgcKG322q27akhN4", + "NodeID-KGQWaR3xNXewSaQhp4zAu8ZkZv6DAdipn", + "NodeID-KGYVGbz1pbyuJpujtJAkXhSY3AtLqBG2Z", + "NodeID-KH8r5RoMBBpy4XHHb9DMrbMLc2a1WJKWC", + "NodeID-KH9WnxfcrJLod4JWXHxESehVTAqE5DoLy", + "NodeID-KHRscCPBynyUHXSz4nXrxmFmoMgUPZBTn", + "NodeID-KHaBbtVbSMHmkqs5SKsdCPCgRbouNcwy1", + "NodeID-KHqznMCanU1tA9DcNLBwJQ7zUkRHC9yDW", + "NodeID-KJLkmhbvSYUqdMybmRScnyo7aDY6X2mYa", + "NodeID-KJfoYJrDRXdmLaaaaRMjNbNKAwqSj3pWT", + "NodeID-KK6ifknXca7VGbqB3d5ccUzKta1zJiVM7", + "NodeID-KKz1wXitLQWsfKSSUPE5JL6Wxw35S2218", + "NodeID-KLPimX5rN51nsSg9UQQahoRvKapDLD1pc", + "NodeID-KLiUDfG672VocEHwbAwGxxFdCHovg1Zp5", + "NodeID-KLsfWtM1cJLWNG21LdwPxaLk83pZo99oV", + "NodeID-KN84FZ7Bwp8y6tvNa52iwTGs4LwWgTU1v", + "NodeID-KNLkh3KVKFFhBWujmcZ5P3p2fJc3BbdNA", + "NodeID-KNPCT1vLFcbVsFvLzgQqrbCS2kvEyZKBz", + "NodeID-KNm1ZqZXdAMJxggBGJkSs7A4tSwYLAjEb", + "NodeID-KQfghSuT1CskYLvgrQAt6oxUQU7ask2QS", + "NodeID-KQfmZVTmDMvuSEW2kts1rmVNmspyzUwVq", + "NodeID-KQocfzJn3D4V4gBGPYsUB9Es7nT28Atvq", + "NodeID-KRhtytNVPjiSeZMJrqqE1vdHTCoMTHCer", + "NodeID-KUgJ4Tiwfx9di8h6oPCkTEcrBBDiDq4hg", + "NodeID-KVB8F5Gy8adXA2zCg3i3m3qJ23NoCDDiA", + "NodeID-KVF3A8uB916AuexeZWS6eeeMdK2ep2vi2", + "NodeID-KVXQMie2X9quytg2ZdRq8rsadxfQCvNHF", + "NodeID-KWnYciu66jjGTmiqs5U8hyeexiHEUa1eu", + "NodeID-KXuvoHe9KgzW6KfVNHXW4CUNunzWDDC4M", + "NodeID-KZLSjb8umvkj4nUVdARnY55NBKQcYfVV8", + "NodeID-KZiZi4sS44KZjmGtkeF6r1vs2MNN7p2kZ", + "NodeID-KZnxZckzgz9eQWzB3iuvM5GC2QdJLE5yv", + "NodeID-KbqaQBQVzCb44wByiZX4ZChg7CtmX1pVK", + "NodeID-KdEdrTAZpr9rdfqcpXjJxEbHC1oSWnvZP", + "NodeID-KdxMzeB5ubHBCbk8SqgesC4BAUx7fCT6q", + "NodeID-Keh97V9b6k4QvYt4JewbkabSmGoQ4sA3Q", + "NodeID-KeyQeQwf1D4bzdcHVP34xXXWhJzFjVTSj", + "NodeID-KfPXTUa3haWHCr1z91ULmY9Pit4VwUQ9C", + "NodeID-Kfqu9wo9FhcXG1jK9nVwbTrBV3d3kzmKR", + "NodeID-KhvVVixdSrBD6u9q25YYNbayxBnNsw9h", + "NodeID-Kk1UZNLJiyf57AL7vYPHntjPYLBdmTyu6", + "NodeID-KkCG4Sktn8zxkaFRV9bi5RaJxZNu1XyMq", + "NodeID-KkZX7xaSAUZ2sGBwpGWLSfLRER4pzR8Fs", + "NodeID-KnSegLyDRx7V29WU6PgTAy5FnWwQwdz2x", + "NodeID-KqKMF5JYhxjkMVpYWQz8zTiv1N1qm2nSf", + "NodeID-KqmFvyCFfsaTcs2XDquCerCfWx3S6Zhj9", + "NodeID-KsSwTshRyF2xV75YDNXcEB5psLaBFHKfr", + "NodeID-KsUkk3D4hSKJGM1WBmeu1yj8Ab7h512X1", + "NodeID-KtJJDa5PVQYChXaNd1fKVmF5LSsBB8NHP", + "NodeID-KtJLagoYnWfw2oBnRki63NcguiGjuA2Cr", + "NodeID-KtKf9AuKyBvofsQE7Jn4eAzAndKHu1f4M", + "NodeID-KtSsjRubDzNuGP6FsXphHmtjWx62KCqvf", + "NodeID-KuStLqzCMZmLv3NigAtKPt2BEE12q71wQ", + "NodeID-KvBcQpCDXbb3w8x7ktMhsx6rCq8eSYcd3", + "NodeID-KvN79EtxbHdT86o7w9GBQEVeRWZ5woAJx", + "NodeID-KwWsJneoQZaVzUaUjjkKDj44BxJqoXT7D", + "NodeID-KwqhQAGTv8eemSuH4yEv3x3jE8VJQPZ5D", + "NodeID-L1RcwxtQjb72GiCABuonnV3PWFZKPTV4P", + "NodeID-L1u2bQdMywnBLHVkrMiAoTSCYJTGSwE9k", + "NodeID-L3JrbBLmihsqtaXAPXg7acKQbGa9tjhEc", + "NodeID-L3SyWrZH6uorqgExkkmGuXPx9neqELqXA", + "NodeID-L6MwdnCDs69eZBXJJZ4jw4ZHW3CyZahyK", + "NodeID-L9D4FZhAGu8xGd6LL6Kn4ZqfpXuXSxTXJ", + "NodeID-L9HsJPQ9TF5aXjdx3KnQrh1eWaHJaNXNj", + "NodeID-L9eaKWJQNkywXWVg7FKMZNWFno52oh3J6", + "NodeID-LAk2MapcDFFxS7HZ9KeuwxPhdCD3YtZDm", + "NodeID-LBA1YYYBbxwYMMAA9odGhR69d9SCbyq8v", + "NodeID-LCQBGoE9MtECsDjNLohwAP6L4rXDbSooL", + "NodeID-LCRMLuFKUYvcdAemtKiudy1XNM9oMN5Wv", + "NodeID-LCVUCE4bvtPopRuYvoWwTopRScmpLHTcg", + "NodeID-LCvxVSwts7BQAS5mVuXH8XYGuVJZSRtCn", + "NodeID-LDgwboNU4iVyy5MQgArg2rcDPssiAe6jT", + "NodeID-LF7ktpNDXo1fjHYN6MYHnitMPrHwN3pup", + "NodeID-LFNBojkAbg1az3ys8htBJHmyQ96hYhFzP", + "NodeID-LG2NYC4RxxzCG4zFGWoAwSo4U8mjMux1f", + "NodeID-LGrCunBRJPWSqZLEw2QTHruuQtZai5P64", + "NodeID-LJ5SMSqLy1x6NRLdz7FC7y57QZMfR4W4r", + "NodeID-LJBZ5j8beyjdcnVdNk5fwtThNn4LokYpV", + "NodeID-LKPvVELtRehiZPQo3aSWuch123JpA7H48", + "NodeID-LKbxWKUAE7s5dtGWhm4Cr8hsosDxLsNzu", + "NodeID-LLVMxBRYjgvczhD9u9RJDSmZ48bbXdWx5", + "NodeID-LN7tsaTsJaPDTJHjUPUX4ePk2HFBWZVh9", + "NodeID-LP9FxV6iBCayBiupHa4QiPxtqDWNoBoVx", + "NodeID-LPf42gVqz97N6bogZGXJNTWhgBABEe4qE", + "NodeID-LQP4aci528q8z4KMe8Ug3Gh1aHj4yojPX", + "NodeID-LQhwkBnuj2vjE786WcgsGneFVWcjiH6KA", + "NodeID-LRBqzoj2mB8eD4AHE2oCTBziNdssTfxuf", + "NodeID-LS7NEp4LEVzAsjFRaRm6RFKDDL5tWARVo", + "NodeID-LTM3DRAzRtWoWHVtB58s5CohXKYexiqVp", + "NodeID-LUFJGzAfqkmUaTDBVScjvdWtrruDkbFvr", + "NodeID-LUhB7mVaTMnkYLQsqf2RV2PUerJfsq2wW", + "NodeID-LUqMj414dv39Z5SNRXRb3bz9YhLJ2oWrS", + "NodeID-LVqsakFrQLyqNiChxcYqsBzKaKFRMiBsN", + "NodeID-LXBLi3qaqXWjkawWZLtvpYCK2LzcPutRc", + "NodeID-LXVb4LZEU53c7XCk2v4bU2qacG7ux5dUB", + "NodeID-LXpULpbU1A4AobEzCSBy6wYLEbogwsMK1", + "NodeID-LZMN1BDS3u6pe7T5Umjuhg1Z1MahXkK9C", + "NodeID-Lai2VTTYk897ae9uq6cGk9FbhKD1KHvFS", + "NodeID-Lb2X2hJpi6krux6aRpYSG7xcNvCXNg6M7", + "NodeID-LbAkNKxyv3kCs1C2ngkb91STbKpYHKs1q", + "NodeID-LcBGn2kscipZRgqhKqDCA5dq4WmHuuvai", + "NodeID-LcNseW1dfEL8FnXQB5HidFpzNu452vuGc", + "NodeID-Le5rVEBBPdgYEcEJpvYeKo36hRs75WE5S", + "NodeID-LeZUTECdpTLux94oAXKruxYgz5ppx7tfr", + "NodeID-LeesBWnR4x3zWaDmYTPQHmNhsMwm6KqWK", + "NodeID-LeyuRqXk3UxoDMZWjgqSY8gR9wDVg4ht6", + "NodeID-Lg6HaVBjndKUjyXiq8ZjHookjqzkDxH6Y", + "NodeID-Lga7mB6EfqgSJv4VTPaUwDjEtq6utiNQH", + "NodeID-Lgjda988AdujVYMYdwuEM4Tc8aopF6DRk", + "NodeID-LhjS7bvahdBn2BomUUBHHFNbnzLRjri6D", + "NodeID-LhkzuEyUkHR9SW4cMxB55QQRbbGF83zzc", + "NodeID-LjxLvskdhxQ5jAhBKSzKrxU9NQD1DPuKR", + "NodeID-LkDLSLrAW1E7Sga1zng17L1AqrtkyWTGg", + "NodeID-LmZ33PJKkQqueDDzPnmVSyHMgFFmaADrb", + "NodeID-LnR5bqTLkmeGjsDKiPdJNSbRPr4pjAURR", + "NodeID-Lp887ddQT84DG8ub2kfu19RuzAJKzriSu", + "NodeID-LqLgyDEyMbd1uXfRa6kf8EPjnRhpF4KCF", + "NodeID-LqUHsZZeoCvhiwunLtAJMSXx1GxYpozzq", + "NodeID-Ltq93eHazD1AtdGNuWb739t4fyvnRLryC", + "NodeID-LuAPt3GG24RsuzmjPL5neGBwca7r1h31E", + "NodeID-Luoxf3Y7sPVwS6xjZTTHR7yJANwG9C9No", + "NodeID-LvWcDhi9d75T8dwerYcQRoVWD6yDtywFN", + "NodeID-LvioWzV19k7FxhFZC4Z2Xq4qxnswkL46C", + "NodeID-LvpYyT4UY4UAgP4quynTFzffYmjoxqZtR", + "NodeID-LwiNyRJeqRfAGS5phAQvvKhX9xj8LbQ86", + "NodeID-LxrJtyQXpdweZH7LR3ujcEQZJ9VDTW3tC", + "NodeID-LydNf31SmNLztbKL7iNsHXPhnKxz7g3Cw", + "NodeID-M17yakji8RzPBFJNPXnksjoeabg7BXUJH", + "NodeID-M1SrBrn1szYR6jQJkyrJzd6YXsbAeWSnj", + "NodeID-M1Zsz7o9AiDgUqA6KFE8hrCkvybN6EqcP", + "NodeID-M33qUGE35HbVRppTTMY1qyyfK5T52id2a", + "NodeID-M3VrNcHHd3LGpwm6U6Gw1vfuJHoJzfG7g", + "NodeID-M4AhBqhjwLxGixtjxaLvenUpTe8mxNfhg", + "NodeID-M4Yxuz5MrQd5K6dxhnVaCYPe4Y56w3pE8", + "NodeID-M4ojoWJoEmsVD3vf7KxZ2BnfR5Ue2wr41", + "NodeID-M4psvzu2dS7hQ8gHgCUzXfipVKuFEsoFU", + "NodeID-M51d2sDyE92NjgRaiTnSjSLaG3U9eJ3BD", + "NodeID-M5wUvCymq18DUFjXk9s2UCZmyWzgo9ZtJ", + "NodeID-M64wor3rGStFTBWuzvkGPYYsWUu2dX7S2", + "NodeID-M6tt22qVLnGoaYY4aVUXTpKCCCEiupNHA", + "NodeID-M77VJM2GfeAzueJ6DjumoM5enZma86Zop", + "NodeID-M7GC8ZPn3JACK7sxBXqzeoNW6Q2XZeCpM", + "NodeID-M96ypSznK7ECF4EGd5KfxcxCiboyAZnAQ", + "NodeID-M9Q4Fc2StCtFCofjppsy6DC7JDGmtRfUA", + "NodeID-MBuKQwYxNAttaiugN4eMt1aV7vhLUo7Qh", + "NodeID-MBucJmfSNuMy7CiXWb9Zzd1Gf1yCoKwGy", + "NodeID-MEnWKkj5iUC3Z2rNhKuDTm5EVDu2ZUZZo", + "NodeID-MFp5wwuKzSfCNESpdD3avbZBkZ3KMkEeK", + "NodeID-MFxpZAcCZZagmDn9LtJoidGktKPpoZoBt", + "NodeID-MGJcpxBEXDn2Yk94uTXQwxgmYtuX6Ky99", + "NodeID-MHBrAomZpJhaYjqWKWXSS3YusVo7afBn6", + "NodeID-MJvk5Su2t8dFhcGe6z58Fx8A2QAAZTMGd", + "NodeID-MK6HYMwXj3k3HZfzjdegdnd9p9LQ1dk8x", + "NodeID-MKfE4StupLg6ts5v7u6Drs7HhFf1rHjEj", + "NodeID-MLDFMQwHyrvXrYtJvhuXDkHAS3kRxydrU", + "NodeID-MLRgfkWbezKNtcH2ghSyE5J3C4Rcxg5Sy", + "NodeID-MLkE5eQrTGa4BoQSR9QLEZKQB9yPJEnuN", + "NodeID-MMemzZih83vtU6TRK5oiJt6bJpNSWm1uE", + "NodeID-MN3pkk9h9anNMuCpUuXPVxGKw1rUw177u", + "NodeID-MNm7zKhCHwqQ3a3oqqEqDSXM9uVFMcEA7", + "NodeID-MP8NsoqJxPMUfCbw1izND6n4i5pTJJkhS", + "NodeID-MPLzWkWAbT3937j7U1uWfxdTMg3iw3BqY", + "NodeID-MR5cJw9vYb2cA6TExPE4ZXioGV11zErUq", + "NodeID-MSbDAksgjGPoKE4azGEgvrDj1EK2GG8T7", + "NodeID-MSrtdRQ9bEWLhi5d8YLQtnB9E2biVkkrJ", + "NodeID-MTEbgxTNBdL6GWh8SdQMfMXvEU1jC9aws", + "NodeID-MTQbFuBcjcQ7TuVQjvoXC7hiWAWPkouzA", + "NodeID-MTdVMzfENtZAEGdji5EGgiLsLkG3hV9D3", + "NodeID-MTmtdGgEg6gSEVhG5ShyfReR8ubtcZhbb", + "NodeID-MV2a235PcwYscp7qq8N9M4pYQBqMnfZ6T", + "NodeID-MVRcFZmxaMJWedF4oVqsxT2YYkX3kSuGG", + "NodeID-MVUMPzSBAtrHwTD5SZSNPRVTLkYnDPDz4", + "NodeID-MVayMsZd2VrMvEwFMDreTrauJHGBZu3Xa", + "NodeID-MWqZRLNFJzDPKnEuUHJSpEg56ejrzY56V", + "NodeID-MXxYFnzdP24DpJmdtUKqzMEN7nh69aYqD", + "NodeID-MXzyYAXy4JPVDjmXapcJXW6HUq9Yxmnr1", + "NodeID-MZV1PpqVuFPa56t7TmfA8VVdXxDSHnQW7", + "NodeID-MZxjrRvxrjvAdaz6pDS82v65xLwckmiti", + "NodeID-Ma3Ztm2A48bCVjfiSmoZS5MKNzKVTRN7j", + "NodeID-MdQZNCCZN5gTEMVaJkSekNYCZkvp5xp4L", + "NodeID-Mdpo4kYtg8eqn61AhjTrZ51exnHLJmcpA", + "NodeID-Mf3rZ5w3aEtM1bzRBwFqhZYZMwks6FYF5", + "NodeID-MfVDQRZ6jSUmke5aofBuNXruEQunxZ5F7", + "NodeID-MikkG849wcdpBdeUJ2HTV2gTEDfeXWseg", + "NodeID-Mm8qGQPb5tHF96ENH1MuYsYwhA5Nj2DHj", + "NodeID-MmTfUacXsPdKryR3WkVteMqoFvyxEdYf4", + "NodeID-Mn2isVXFR85bfjMHPM1DT8EY8wig7YhTW", + "NodeID-MnQoJXMCgPk3zxKQ7kkYdmoZwj2dcDcmb", + "NodeID-Moz5Jcjj2JoDgay9ScwcRDQReSqX8sjyz", + "NodeID-Mq7hjS5ySKApHMKCGw16YFo1tW7xA5DXm", + "NodeID-MrGm83LnY7pRQCQz9mG5TTpRWSBgNhDr", + "NodeID-Mrh4UKAifNZtd8RJXqokDzajQnAsZuw8Q", + "NodeID-Mss1z2VZYsNSa4LyqD99vXeNd8h3hUMDA", + "NodeID-MtJWp4WidtWe1jzPf5u8hFtxMy6TCmaRX", + "NodeID-MtiHM2m6jKECmfTDBcfCut99JHzFm91T5", + "NodeID-Mu35k31HAXFbEp1SqJr1uUrue9nwqVFe6", + "NodeID-MuEFvXvbZ964sk1rdQKWNtUc5PJAGkWeL", + "NodeID-MvfTRb81PAx9AHYxbz5xACaoG84PM7YQe", + "NodeID-MyaTMxwSKbtrFRRypqr1nWKJ3EK6di3dF", + "NodeID-MydZ4Ju3KA959gXeERXvqxN88EtUrAaGc", + "NodeID-MyeSQZnEZDzTfFFQvxZ5qqfqVDwg15NPB", + "NodeID-N1aFXom4C5ALmH33bXHuRpPBo7Nwqeu8t", + "NodeID-N21EWyi4Y5D8MNapwZ5tXs9D5A3rrfPi1", + "NodeID-N2nTLuaVwKk8EF3NBsSygCVmpGHwNz2Nz", + "NodeID-N2t1CAS75972obgtRPHwVanMnRF1rRo1B", + "NodeID-N35BjCN6ARikprxERf4WiMeUnh2ZsfwJJ", + "NodeID-N3WnyXmV89jbtQgmjqpoxBxpi5Rah86az", + "NodeID-N3e9W3EngjabGnTZVqyZwunVcbCdrY5Qy", + "NodeID-N46bdSibDXA2hx5pFFTuVG117Khi8j8db", + "NodeID-N4eXezpVzti1ssWvyQKqkuGB15dJNJsp5", + "NodeID-N4r8sLfeDVa2c9eDFpE4wuxJccUku3LKu", + "NodeID-N5FWBAn5j1UVxb3nH45N9DyXEAaeZiU4q", + "NodeID-N6p8Do6bVJi9xHtCkgxdP3x6wQBZHDoy4", + "NodeID-N6z9WSBMoSxLSRtdPDz8jZvasAskYcCrd", + "NodeID-N7WPJ9DXvEx8xLJdtDswNh1JdNmCKejSq", + "NodeID-N7iZFQdtUfPRcWGs8DB3JQRZt3Pq33eoZ", + "NodeID-N8tijV4qwWMep4STmLzWJEkqbg6bSdCmn", + "NodeID-N95GoeyiprvxNj6E3G8QvYg3gpQ7x8NKE", + "NodeID-N9S6JJT2VKRZ48vA5vtWgboDnfzXXycQn", + "NodeID-N9c2YTRzGpRNp2J6qyPEEiAvyrViL4cGH", + "NodeID-NBjvikZcadcyCJ2hEJsUn9EcCjys5hav9", + "NodeID-NCVrEpmYjJBHqj9vx9r5usFiMd1PooCfZ", + "NodeID-NDMPc8h9L6keJw8F82NBobc874zZ6bDa6", + "NodeID-NG15fF5qJuD737tg4u3PUw2hyZ8RZYNNU", + "NodeID-NGFHFagkdYNsjJ94n2nZwLhiDZtV3gwbT", + "NodeID-NGspMWkA7FgT6DnDghg4B95pQ468j7DK8", + "NodeID-NGxhFFwufwUSXGHjxdCUZW1hNpodfTrmj", + "NodeID-NHBv1LqcCdrcwatzQ9pGbGXPZQTi462Ur", + "NodeID-NHEESrJJNnyCPn5c5Uyp9EZYHCCkZwzuW", + "NodeID-NJZWC8HxGtLkxjQk5F9KSG44WC3gCm8a9", + "NodeID-NLBgQfsmCGFzXDehvwvmzjyfmkWQndx9L", + "NodeID-NM6RqsshepCVojpp7R8747TGBLRvYpLLB", + "NodeID-NMfBW4PDVkVZhJzJa6SiCDZ4M7wAkXbAc", + "NodeID-NN5j35c8DsuMydM5icoxhKePqc7AjwH1K", + "NodeID-NN6iut3SAWZqM56kbg8EhtpTU2NkMJgWV", + "NodeID-NNWrYMQgNFRNbvwAUA8grXiAVVE9VEyV6", + "NodeID-NNrbnhLBjgzBvhi3JXK48ckVFcg6FXVnn", + "NodeID-NNyxDSovcVYmXHacSM8aK2pg67oPjkRrE", + "NodeID-NPexpo2AXQ7RZC3wCKugj9q4y599pSfrb", + "NodeID-NQWgSd85RNm2um4AywRNozgczjAwpmzbp", + "NodeID-NSAi8z5XtoagdADeMNAPuWxfZpzUxacYB", + "NodeID-NSNWfQTGX38pRWaky2MGe4ShCSkuLnqip", + "NodeID-NST51yBNtgVkXWuofyacbR1MbqYJEYdor", + "NodeID-NSUM9tzmeZ1DujarhTwjXAcnCeAH273v3", + "NodeID-NSa8Z4kZo8KnHzKHsVUkV9gW83NoNc6uR", + "NodeID-NSngpSyxjXz3ErfjsFoc6CpfVPLxApJen", + "NodeID-NTTNYBYdkf3n5U4zrZknt1nst9rHzpuCj", + "NodeID-NTvJb2gZdvYU2kaMUrMbtu79KUMgyJNPW", + "NodeID-NUgiF4juieHZmcR6ekc9EDaRyG8qHUyjC", + "NodeID-NUur4HBKXj8GS5TX11jZhtPHLH6zMa6L5", + "NodeID-NVSSRYMjjYyMkUpt7AHXWnKNTTJCd8UbS", + "NodeID-NVkHd9WCbVAr79r3gtA7AmKBkVkNL9EXb", + "NodeID-NWwQRYczsB8gf2tiiLLrk1foSgNUyrFLe", + "NodeID-NYjgvA2mJy4kTCQeEHnSuycnu5Kgo9gEq", + "NodeID-NZEnXQpa55wAhwpcUZFgSAREXW1FLdkzQ", + "NodeID-NZGsXrgoEuExZdJn8WxmyrLt4Cxb7LFyD", + "NodeID-NZYwtzqeQFeNZHjYgdukRvsZb4xQ43Fdj", + "NodeID-NaGEfmLttvK5r93aqaoxLKoADVcs2HASy", + "NodeID-NbYMJFDrhNhubNus3qsw3kJBy6HNEV9UU", + "NodeID-NcPHhZ4wgGywviLVxEQ6s2q5NZm6Wgrqb", + "NodeID-NcSLm9skkUrfA9mKGjdtmT163iDjqAw6H", + "NodeID-NcZtrWEjPY7XDT5PHgZbwXLCW3LGBjxui", + "NodeID-NfJFVKNj7kCUUWCRYFJULe1AR82f8a5ox", + "NodeID-NfgHajZM47C3CaAXFa1B2YrwZmc4EdSgk", + "NodeID-Nfz4ZGQ8ZPvNQ3yHoRNMT7aTCiFYjMnSA", + "NodeID-NgkksDCWH73BnfgN2ALUBykc2kftsquff", + "NodeID-NhL9H8VSfhrktdjmQQ3P47wYXzRfQwBiy", + "NodeID-NiW2qTm2fSKHGuMqeo1twtM8j7LoAGzHR", + "NodeID-NkXpMv916WuB4Np5P31BZmByna2poFAby", + "NodeID-Nom39tjDi1Vf51VxuaZvJiDeQHwbyg6MU", + "NodeID-NovHTxGVasNU2y33YPwmQ39DbYDkXiEfe", + "NodeID-Nr584bLpGgbCUbZFSBaBz3Xum5wpca9Ym", + "NodeID-NrVSfY4zCbPjYTe4XPjmQB7qLJhYW3V6h", + "NodeID-Nrs246dXUZmALw7a2HRTANx6U1LeawsKq", + "NodeID-Ns1eDN3K9HTnavgiBQhtpzRxUCxJ55Xhc", + "NodeID-NsVdtyjprgWXLsvmuWvYe749tx3tdbY55", + "NodeID-Nsdn6eemD7KUpKEaGYjYFuJjxC36c3qXC", + "NodeID-NtDMBzQGPnp7suCbyCMcdE2CFU4JXcvwX", + "NodeID-NtX4Q64xT4Yad8wdhQ4erSG6mi3DPUwzX", + "NodeID-NtgR3kDx7Mm2szCiDTs3rtWaqUDWRMDyY", + "NodeID-NuJhcXgmQMbFJwm9yTTmdvGN86qygnXwP", + "NodeID-NuXW8S95Hvv2eq6JoY1qCDmK1h8yuAAt3", + "NodeID-NudTZgq7DKGQsY1Gkt1v3ZG7pgaWbbBuj", + "NodeID-NvsbNmirter6SLhta1kkvoEjcgvaHxEt9", + "NodeID-NwZ4wmDE8DrbaDY7V2nZscmLBKdRUtUyN", + "NodeID-Nwr26Q5CPcRfSHQKgQ5y3ayVPgjziWkkT", + "NodeID-NxgyyDw6YGHprTJjZv7qh9X1yoj3yZN7u", + "NodeID-NxzZe138M8B3MQh7N9u4qetqMS5ViAgqV", + "NodeID-Nz93c8UB78eEVVtfxpcecxHmiy2gZ4iAi", + "NodeID-NzQnRDwTYZJPwYMcDkyNGCnhH7S1HQZgy", + "NodeID-Nza7rHanhSFgJ6m9D8fFWgrx7fqbxp7q9", + "NodeID-NzaVh4SaZh7zaT5uFmHyAT99zRbQhzvvd", + "NodeID-P2EM7MDMhKVo4LLgSqtxYSyc39wfPe2TL", + "NodeID-P2Jp7sd5mv4ZGBqThYfjHkz1EyJUXoMcE", + "NodeID-P2xEUig1YeBTwrUF3Xj52pxaNH6gSHjsb", + "NodeID-P3EhUmKXJ5F2BiZw1TwNftAC1y4XyGufz", + "NodeID-P3budG9yRu9ph2UedCGdf3KaLQKQLehy2", + "NodeID-P4tSY1ZLb4q2xTdYGXCkgwXWeQN7mUUWq", + "NodeID-P5hTsAQgfSLJumMDVDK2773U4gjyPtYnr", + "NodeID-P5q5numCvCNo6GmD8vhDqq1tU25Yok4Ky", + "NodeID-P5zxQ1Y22ztxzjunvJU1y8BiSjdP4RUwY", + "NodeID-P6Gv97A5P1rFfm3NrAskXWKZKA1immX3K", + "NodeID-P6M41urqadxF7NBcxEHNFxKkGPkHjC95v", + "NodeID-P6pnhwbrATbNUU2GXcEYCkfryyoBNHyoW", + "NodeID-P8pP9viiCuazxFMPmgkai4v3j9WNEKj1x", + "NodeID-P9FGdfCp7sHRcUwHERp2hzo98ifUaCZ5x", + "NodeID-P9kf9VSRrgD8B1MQKMsjravHvMHVxvoaZ", + "NodeID-PD54wi24ENhbBnKKhoD68MGXCDc3A3iA8", + "NodeID-PDZYy4rfhPZWskL32EMt45zuLD2rWjDLs", + "NodeID-PERaNX2PDtAr8zkXgbZvwXHfjq4VKtbew", + "NodeID-PF9fY3h6ZMMqPmTZZUwc7wyLnZ1rSoz5u", + "NodeID-PGonFPDqHgyAWCFaoLxQvAQEz6uJYzZpW", + "NodeID-PH5DLzGXEhe6RMHgod3CH9T3s3WVfQm8Z", + "NodeID-PJA7yH2ZVtccSj4RrB94a8MtHboS9xozZ", + "NodeID-PKiUH3xw8SmVNVJsAqFV1mXwDXToFVATi", + "NodeID-PL7xq98yQ9kTYyGDvVQg3efowKeHug3HN", + "NodeID-PLTGkonfx3iubqTEpwsiDCMmRmwmh2HuZ", + "NodeID-PLs2JZXeTtfZvYx4DJqkA3sKXz8ynvKLM", + "NodeID-PMGyPdRXPKRPRiWXAqR3XqbAHke2gNDUe", + "NodeID-PPH8k8RGmrTuc6Dun92atkbDkgs3sj6ws", + "NodeID-PPYetyVA4dk3bYdNtvTsy5Cqg4L31EUze", + "NodeID-PPoo9VFqdSWsrZZHrnrBBfi3uE2cw9JgW", + "NodeID-PRxbx3LZSnwvLqFa5audJBsSqAJe9rmsP", + "NodeID-PT45awwLjTTiEqvFufS4nCkVN7wtEsDmf", + "NodeID-PUw5p37RZKVjpK8kxBa12TBtZZdhykGUP", + "NodeID-PXZcW18N1BcYiDy7iWgHLGKwiQMQuBSyg", + "NodeID-PY3QRSGTdYzmPTQEwrH2AmYUMBnrcge9Y", + "NodeID-PYFkkThWT79Sc7QqHijAc1yZjSqfXu6Eb", + "NodeID-PYecKsWbPTayLsHDdopKjB1Mw5NP3kDUJ", + "NodeID-PYmftFnrKf6y9k6kXXuB5GWwjLtkP7sLB", + "NodeID-PYwMEam56vM4Nix3AG1vufHZbMvdv8zwy", + "NodeID-PZ66baswBL8xsSHaFVG2Yx7qH8MkBfXSK", + "NodeID-PZvapthv5iRB7txuVNTrKCo2fWovBExLh", + "NodeID-PaSvEqWq5ZESHSuNGTZeQL6sybzsQzoZ5", + "NodeID-PaYLWdJGvpxC63eK3RWXLLS8w37442aV8", + "NodeID-PcDGg5a4P3XK1E7PXS5YedYL7vi8vSXvB", + "NodeID-PczCXQXPxNgeKy3P4jtAt1ycvrjvghVw1", + "NodeID-Pd7Hexv94PQNVnEbYXWUttEAAybG34Yiy", + "NodeID-PdsZ7ZyzUrcW5BxgRBKdH2hcR3wAdWEAS", + "NodeID-Pe1pUMoFAts11s2kA3F7EPmzLyZwj6Msv", + "NodeID-Pe5xmD9DhTrSCDykMqFdG8CazG3QyJxos", + "NodeID-PfY5X2GWsSaj8y6usEji4HZmokHHdWsqi", + "NodeID-Pfj9qXo6LGR3goGzcLSJsCZwYNFFndV75", + "NodeID-PhB7iV3nDxiotJnAMetF6puzg6fxTqZCP", + "NodeID-PhDmCZH4R8VFjVzQLRBquKMVss5sKukw3", + "NodeID-Phds7RN13xWBmpe9MTPhJde3hajVpUB38", + "NodeID-PiaUvMvdFCWXwhRcrb2K1iPn4h7NugKjk", + "NodeID-PmH5X1xavW8PjgvkW1u4K9qTHAbMx36hq", + "NodeID-PmJQ7UjZo5db9XL494EbbEufAbYxqWswU", + "NodeID-PnuVZDXvdSNRbC92ibq5w1FtPvbTFvwmM", + "NodeID-PpYToPR9XKswScUX1ypXKjDUP7G7utRDz", + "NodeID-PqL7ZLMh4fFQNxKrKt9uWuZKa3UGsdcdQ", + "NodeID-PqPwxtYAt6AmikigAwkRzTQCaeMqPvpff", + "NodeID-PrPRAipDzRmPYPSDhm1dKnomZNR1YjLwu", + "NodeID-PuF1sG8hh4CLLznER6vf4d1o6bWZc5Vof", + "NodeID-PuYX3u6gfLje9bt6fCDFHkSwqaL8VSpv6", + "NodeID-Puv7ksUTmwsxqEx7XLikRicKtKss6QNNi", + "NodeID-Pv5X1dBk1wfZJwRqm8Aj9QecxvA87r31j", + "NodeID-PvZnYX1Nz8jp1GjQFixs1TAX9C9QXwrwL", + "NodeID-PxmdCJV62VecySivang3vVymEBwjPQeTm", + "NodeID-PzEsAB7RCHTFwHszw3yfs99GshYm6Qs5b", + "NodeID-PzQafFPgbCLkvMgrP7nh7aCG1eKypdNi2", + "NodeID-Q3iFBGVU6gka1yX9EMjpNuezkocDTq1MB", + "NodeID-Q44XVjVEhgxacoq2ETj7yLBuUra9ru2BA", + "NodeID-Q4mUNVKvwEHF3tkxQcCYbrQA8XWdybLzv", + "NodeID-Q5rNbr5yFwotdbeRPGeTagHP1hbHYuaJg", + "NodeID-Q5wrexzsrQ94xJcXsqRQmyvRHCuYbrZof", + "NodeID-Q5xvrPQSjHhJX8eLKbBnZMWbS648NqnsZ", + "NodeID-Q6ZLZ1EifMyNd6evH83FJrVGyauaUSP9S", + "NodeID-QBowbP1jz8zA86CtSzRwsFsxr5q1rY6pB", + "NodeID-QCfTXZ1cdPt5XT1jiJfycHKTFo6Yg164L", + "NodeID-QCkFTaWJg5ixVhZoNbePxzs9HWrTutVy4", + "NodeID-QDLrtBngMA6mFveLNZTXxKQVEYx518fG8", + "NodeID-QDfLjUuR9D5a6G5ZAQdPPbggJxtLnbPj3", + "NodeID-QHX9w6oLs8zjHdBvbzx1ZadHvy9aUNLr5", + "NodeID-QJMNxwTLjdg9C1vY2BKNtapWUuoeCgHFj", + "NodeID-QKGoUvqcgormCoMj6yPw9isY7DX9H4mdd", + "NodeID-QKdEYKG21HJ5DCQQaotjG4rJmcTgjno7f", + "NodeID-QKfhLAkwYPwAZNKTanfuNfmm7cYRTzfYo", + "NodeID-QKn4ujiEcP1n8iFbEJqNsKZUYbUG4fHAc", + "NodeID-QisfDcwSCUGaw6CwsBLA4mjJmTDto3he", + "NodeID-QmTPCR33deSWVwZ4Ri2jUw6cDAhoUwZP", + "NodeID-RSzGBBq5w69Gh14hRTVUQ3AR2WnErtGq", + "NodeID-TJ6G6FU4QtQFVNjzdjhjknqek5SZZGcy", + "NodeID-TzsHrNrY8qaAkg9MPAmJd7LfzCUDjvzi", + "NodeID-UC1qmKMoMcfShU6idcreEAsxSHs3BDBj", + "NodeID-V3fYZv2vHtLB5gQF548JRnSyk4tZfZ2o", + "NodeID-V5R4XjWDtjs8Zi2g3TRNzngnGJiXm2ic", + "NodeID-VT3YhgFaWEzy4Ap937qMeNEDscCammzG", + "NodeID-WAHX8MXekynX6xZSFiSewY9Qxnhq5HZh", + "NodeID-WRz6mTt6LCdSSvuHdqsrBYxi4hdfecTW", + "NodeID-WrL5pKhhp8e2YLp6h1e62NBUPhuR6pGa", + "NodeID-XYAkZN1GfMwcYRRyGLiZsGV2thZbqDGT", + "NodeID-YdCKQdXecSPWqABWcRtPZvBaLd3MPPR8", + "NodeID-ZVLPagHUUrQ2vB7mjsWQ44wNGf5SVKKW", + "NodeID-ZwShn4JT1Bg91QphD3VBLryA88GFnAg5", + "NodeID-aFRSyUykQjScZiWASVqmdTGzBfV9KKj1", + "NodeID-bTSBn4p38MofpJvhDgfNxuKAQkKxdqEi", + "NodeID-bx2UN8z5nfLMTFphQqnYeyngQnccL6tN", + "NodeID-cmcBnV62GZxrLLmebZdeofd3AesueXac", + "NodeID-cme6KToKFLCwqj27F7a7Ys9iC4cLrqMz", + "NodeID-duaNgYtghtCRzj2rkiRDDs51BPX8CCjn", + "NodeID-fr4FFtJ5PF5UZpyA3RyoxhNks6Yfhu7u", + "NodeID-i9uQjR8P5Wzd1wTLeALkZ2oXqKjMKQbs", + "NodeID-iTKqsK6Qhjj9RT2ZA9PVAC96FTiDvK7k", + "NodeID-jB3tEp5oBcHYRLLmNaMgP4v59dyr1a9E", + "NodeID-jjTi6fViUUkPwZQbE9N8Bm7AThmVyjGW", + "NodeID-jz1mR5zZukizoZEZ1Wa17h18Kou1Rfzt", + "NodeID-kCLme7NNnAVrbQGZadzgWwtoPJpkQcJR", + "NodeID-kXTWkRtur8X9vchkcXAiG6qD8PDogo2N", + "NodeID-kZNuQMHhydefgnwjYX1fhHMpRNAs9my1", + "NodeID-krdJFoXmC68zd4pSFCwMnCM4dhiR8gnq", + "NodeID-mEbcN58z2esHFnnXHeR3T2UTfsR5H6WJ", + "NodeID-mRrTBjdn3s4oSyxjKEzLG2ibWU6V6Vzm", + "NodeID-mfUNFSM9ak3NuCvaiFCtcmEcHF9ptfrU", + "NodeID-mwty8tviuGBvDEG8e6vTQByDZN2MKnNo", + "NodeID-mzhghLeMzv8qrRrK76wABwrf3LrL6mP1", + "NodeID-nJm8Ltnf7MDCiuP3PzU4hv3RqXXKmeqd", + "NodeID-nT4KHRTgD9Lq44epZo7GPhjQTEFcGbT7", + "NodeID-oZyu1tEJrBeFkquoqZ5rYpvsEAkfFiwD", + "NodeID-rA57yc1JzDdo6Fc4gND6Mwz8hQ4RBxJM", + "NodeID-rKCpkJKNAZeE8sKEHduq8Co7GwrAdTJb", + "NodeID-rS4TWt8iuAbQTsg6ez6u5tXvUzicRzuq", + "NodeID-rU9hLEWJCxRksiPuEYm2qqof6uwWEDeo", + "NodeID-rroLHLixQkZMTsTnePdWhDrGpWenYX7t", + "NodeID-sAyLfHTC8ZQRn5HtfjNKxXDbnZTaJUqa", + "NodeID-tHkVEqdhWPdX2vJGbqDWebw2VPrho4Aq", + "NodeID-vV5S1LUtAxCWq9ASiDSjZpX88y2WcFGM", + "NodeID-w6kJAMpdT4hB9jE4NnEfBm47PzD1UXfW", + "NodeID-xQU1Ntg4uYkkSgXivV2ELwr8s8FovRCS", + "NodeID-xVVbmFL3eww4dmBkgQ2akBxcnEy4VyLh", + "NodeID-z3Z8s8xoYQhN8A1fmNZcQx9CyXN6zxJz", + "NodeID-z3rX3CnWLi5KBXQ8nVB4W8NnLNdUBcPD", + "NodeID-zbFM8qH7MnQ8uo6rm4tZaq6vhbF4cpgt" + ] +} \ No newline at end of file From 27206baaf6a5fb21a97ada3519d78fc8b9d773c8 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 19 Feb 2024 17:47:37 -0500 Subject: [PATCH 05/85] Fetch checkpoints during bootstrapping --- snow/engine/snowman/bootstrap/bootstrapper.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 29754a24d734..cee4419d9fed 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -13,6 +13,7 @@ import ( "go.uber.org/zap" + "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/proto/pb/p2p" "github.com/ava-labs/avalanchego/snow" @@ -389,15 +390,19 @@ func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs [] // Initialize the fetch from set to the currently preferred peers b.fetchFrom = b.StartupTracker.PreferredPeers() + knownContainerIDs := genesis.GetCheckpoints(b.Ctx.NetworkID, b.Ctx.ChainID) pendingContainerIDs := b.Blocked.MissingIDs() - // Append the list of accepted container IDs to pendingContainerIDs to ensure - // we iterate over every container that must be traversed. - pendingContainerIDs = append(pendingContainerIDs, acceptedContainerIDs...) b.Ctx.Log.Debug("starting bootstrapping", + zap.Int("numKnownBlocks", knownContainerIDs.Len()), zap.Int("numPendingBlocks", len(pendingContainerIDs)), zap.Int("numAcceptedBlocks", len(acceptedContainerIDs)), ) + // Append the list of accepted container IDs to pendingContainerIDs to ensure + // we iterate over every container that must be traversed. + pendingContainerIDs = append(pendingContainerIDs, acceptedContainerIDs...) + pendingContainerIDs = append(pendingContainerIDs, knownContainerIDs.List()...) + toProcess := make([]snowman.Block, 0, len(pendingContainerIDs)) for _, blkID := range pendingContainerIDs { b.Blocked.AddMissingID(blkID) From 31ca68f6239b6545842b39c2cd52f8f92f79e377 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 19 Feb 2024 18:03:54 -0500 Subject: [PATCH 06/85] Fix comment --- genesis/generate/checkpoints/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go index 22878482c783..217ba2a602b1 100644 --- a/genesis/generate/checkpoints/main.go +++ b/genesis/generate/checkpoints/main.go @@ -28,8 +28,8 @@ var ( mainnetCChainID = ids.FromStringOrPanic("2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5") ) -// This example program continuously polls for the next X-Chain block -// and prints the ID of the block and its transactions. +// This fetches IDs of blocks periodically accepted on the P-chain, X-chain, and +// C-chain on both Fuji and Mainnet. func main() { ctx := context.Background() From a1a9f182983fd095227a01ffdef3194eeb7deda3 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 19 Feb 2024 18:06:17 -0500 Subject: [PATCH 07/85] Improve comment --- genesis/checkpoints.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/genesis/checkpoints.go b/genesis/checkpoints.go index f2e39a282860..0a9ff78d1980 100644 --- a/genesis/checkpoints.go +++ b/genesis/checkpoints.go @@ -27,8 +27,8 @@ func init() { } } -// GetCheckpoints returns all specified checkpoints for the chain on the -// requested network. +// GetCheckpoints returns all known checkpoints for the chain on the requested +// network. func GetCheckpoints(networkID uint32, chainID ids.ID) set.Set[ids.ID] { networkName := constants.NetworkIDToNetworkName[networkID] return checkpointsPerNetwork[networkName][chainID] From c5b7aa911cab7699549a25b970b3312a062a491e Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 20 Feb 2024 18:00:57 -0500 Subject: [PATCH 08/85] Implement interval tree for syncing --- .../snowman/bootstrap/interval/interval.go | 27 +++ .../snowman/bootstrap/interval/state.go | 74 ++++++ .../engine/snowman/bootstrap/interval/tree.go | 77 +++++++ .../snowman/bootstrap/interval/tree_test.go | 218 ++++++++++++++++++ 4 files changed, 396 insertions(+) create mode 100644 snow/engine/snowman/bootstrap/interval/interval.go create mode 100644 snow/engine/snowman/bootstrap/interval/state.go create mode 100644 snow/engine/snowman/bootstrap/interval/tree.go create mode 100644 snow/engine/snowman/bootstrap/interval/tree_test.go diff --git a/snow/engine/snowman/bootstrap/interval/interval.go b/snow/engine/snowman/bootstrap/interval/interval.go new file mode 100644 index 000000000000..d83d0c6143d2 --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/interval.go @@ -0,0 +1,27 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package interval + +type interval struct { + lowerBound uint64 + upperBound uint64 +} + +func (i *interval) Less(other *interval) bool { + return i.upperBound < other.upperBound +} + +func (i *interval) Contains(height uint64) bool { + return i != nil && i.lowerBound <= height && height <= i.upperBound +} + +// AdjacentToUpperBound returns true if height is 1 greater than upperBound. +func (i *interval) AdjacentToUpperBound(height uint64) bool { + return i != nil && i.upperBound+1 == height +} + +// AdjacentToLowerBound returns true if height is 1 less than lowerBound. +func (i *interval) AdjacentToLowerBound(height uint64) bool { + return i != nil && height+1 == i.lowerBound +} diff --git a/snow/engine/snowman/bootstrap/interval/state.go b/snow/engine/snowman/bootstrap/interval/state.go new file mode 100644 index 000000000000..0d5974a04e3e --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/state.go @@ -0,0 +1,74 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package interval + +import "github.com/ava-labs/avalanchego/database" + +const ( + rangePrefixByte byte = iota + blockPrefixByte +) + +var ( + rangePrefix = []byte{rangePrefixByte} + blockPrefix = []byte{blockPrefixByte} +) + +func GetIntervals(db database.Iteratee) ([]*interval, error) { + it := db.NewIteratorWithPrefix(rangePrefix) + defer it.Release() + + var intervals []*interval + for it.Next() { + dbKey := it.Key() + rangeKey := dbKey[len(rangePrefix):] + upperBound, err := database.ParseUInt64(rangeKey) + if err != nil { + return nil, err + } + + value := it.Value() + lowerBound, err := database.ParseUInt64(value) + if err != nil { + return nil, err + } + + intervals = append(intervals, &interval{ + lowerBound: lowerBound, + upperBound: upperBound, + }) + } + return intervals, it.Error() +} + +func PutInterval(db database.KeyValueWriter, upperBound uint64, lowerBound uint64) error { + rangeKey := database.PackUInt64(upperBound) + return database.PutUInt64( + db, + append(rangePrefix, rangeKey...), + lowerBound, + ) +} + +func DeleteInterval(db database.KeyValueDeleter, upperBound uint64) error { + rangeKey := database.PackUInt64(upperBound) + return db.Delete( + append(rangePrefix, rangeKey...), + ) +} + +func PutBlock(db database.KeyValueWriter, height uint64, bytes []byte) error { + blockKey := database.PackUInt64(height) + return db.Put( + append(blockPrefix, blockKey...), + bytes, + ) +} + +func DeleteBlock(db database.KeyValueDeleter, height uint64) error { + blockKey := database.PackUInt64(height) + return db.Delete( + append(blockPrefix, blockKey...), + ) +} diff --git a/snow/engine/snowman/bootstrap/interval/tree.go b/snow/engine/snowman/bootstrap/interval/tree.go new file mode 100644 index 000000000000..680c3f3dcabe --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/tree.go @@ -0,0 +1,77 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package interval + +import ( + "github.com/google/btree" +) + +type Tree struct { + knownBlocks *btree.BTreeG[*interval] +} + +func NewTree() *Tree { + knownBlocks := btree.NewG(2, (*interval).Less) + return &Tree{ + knownBlocks: knownBlocks, + } +} + +func (t *Tree) Add(height uint64) { + var ( + newInterval = &interval{ + lowerBound: height, + upperBound: height, + } + upper *interval + lower *interval + ) + t.knownBlocks.AscendGreaterOrEqual(newInterval, func(item *interval) bool { + upper = item + return false + }) + if upper.Contains(height) { + // height is already in the tree + return + } + + t.knownBlocks.DescendLessOrEqual(newInterval, func(item *interval) bool { + lower = item + return false + }) + + var ( + adjacentToLowerBound = upper.AdjacentToLowerBound(height) + adjacentToUpperBound = lower.AdjacentToUpperBound(height) + ) + switch { + case adjacentToLowerBound && adjacentToUpperBound: + // the upper and lower ranges should be merged + upper.lowerBound = lower.lowerBound + t.knownBlocks.Delete(lower) + case adjacentToLowerBound: + // the upper range should be extended by one on the lower side + upper.lowerBound = height + case adjacentToUpperBound: + // the lower range should be extended by one on the upper side + lower.upperBound = height + default: + t.knownBlocks.ReplaceOrInsert(newInterval) + } +} + +func (t *Tree) Contains(height uint64) bool { + var ( + i = &interval{ + lowerBound: height, + upperBound: height, + } + higher *interval + ) + t.knownBlocks.AscendGreaterOrEqual(i, func(item *interval) bool { + higher = item + return false + }) + return higher.Contains(height) +} diff --git a/snow/engine/snowman/bootstrap/interval/tree_test.go b/snow/engine/snowman/bootstrap/interval/tree_test.go new file mode 100644 index 000000000000..fa9a68a911a3 --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/tree_test.go @@ -0,0 +1,218 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package interval + +import ( + "testing" + + "github.com/google/btree" + "github.com/stretchr/testify/require" +) + +func flatten(tree *btree.BTreeG[*interval]) []*interval { + intervals := make([]*interval, 0, tree.Len()) + tree.Ascend(func(item *interval) bool { + intervals = append(intervals, item) + return true + }) + return intervals +} + +func newTree(intervals []*interval) *Tree { + tree := NewTree() + for _, toAdd := range intervals { + for i := toAdd.lowerBound; i <= toAdd.upperBound; i++ { + tree.Add(i) + } + } + return tree +} + +func TestTreeAdd(t *testing.T) { + tests := []struct { + name string + toAdd []*interval + expected []*interval + }{ + { + name: "single addition", + toAdd: []*interval{ + { + lowerBound: 10, + upperBound: 10, + }, + }, + expected: []*interval{ + { + lowerBound: 10, + upperBound: 10, + }, + }, + }, + { + name: "extend above", + toAdd: []*interval{ + { + lowerBound: 10, + upperBound: 11, + }, + }, + expected: []*interval{ + { + lowerBound: 10, + upperBound: 11, + }, + }, + }, + { + name: "extend below", + toAdd: []*interval{ + { + lowerBound: 11, + upperBound: 11, + }, + { + lowerBound: 10, + upperBound: 10, + }, + }, + expected: []*interval{ + { + lowerBound: 10, + upperBound: 11, + }, + }, + }, + { + name: "merge", + toAdd: []*interval{ + { + lowerBound: 10, + upperBound: 10, + }, + { + lowerBound: 12, + upperBound: 12, + }, + { + lowerBound: 11, + upperBound: 11, + }, + }, + expected: []*interval{ + { + lowerBound: 10, + upperBound: 12, + }, + }, + }, + { + name: "ignore duplicate", + toAdd: []*interval{ + { + lowerBound: 10, + upperBound: 11, + }, + { + lowerBound: 11, + upperBound: 11, + }, + }, + expected: []*interval{ + { + lowerBound: 10, + upperBound: 11, + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + tree := newTree(test.toAdd) + require.Equal(t, test.expected, flatten(tree.knownBlocks)) + }) + } +} + +func TestTreeContains(t *testing.T) { + tests := []struct { + name string + tree []*interval + height uint64 + expected bool + }{ + { + name: "below", + tree: []*interval{ + { + lowerBound: 10, + upperBound: 10, + }, + }, + height: 9, + expected: false, + }, + { + name: "above", + tree: []*interval{ + { + lowerBound: 10, + upperBound: 10, + }, + }, + height: 11, + expected: false, + }, + { + name: "equal both", + tree: []*interval{ + { + lowerBound: 10, + upperBound: 10, + }, + }, + height: 10, + expected: true, + }, + { + name: "equal lower", + tree: []*interval{ + { + lowerBound: 10, + upperBound: 11, + }, + }, + height: 10, + expected: true, + }, + { + name: "equal upper", + tree: []*interval{ + { + lowerBound: 9, + upperBound: 10, + }, + }, + height: 10, + expected: true, + }, + { + name: "inside", + tree: []*interval{ + { + lowerBound: 9, + upperBound: 11, + }, + }, + height: 10, + expected: true, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + tree := newTree(test.tree) + require.Equal(t, test.expected, tree.Contains(test.height)) + }) + } +} From 63efd3bdd3d25eb4a6f7f7db35e29d97413f9443 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 20 Feb 2024 18:13:02 -0500 Subject: [PATCH 09/85] Persist intervals --- .../engine/snowman/bootstrap/interval/tree.go | 34 ++++++++++++++++--- .../snowman/bootstrap/interval/tree_test.go | 27 +++++++++++---- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/tree.go b/snow/engine/snowman/bootstrap/interval/tree.go index 680c3f3dcabe..49a1329863d1 100644 --- a/snow/engine/snowman/bootstrap/interval/tree.go +++ b/snow/engine/snowman/bootstrap/interval/tree.go @@ -5,20 +5,34 @@ package interval import ( "github.com/google/btree" + + "github.com/ava-labs/avalanchego/database" ) +const treeDegree = 2 + type Tree struct { + db database.Database knownBlocks *btree.BTreeG[*interval] } -func NewTree() *Tree { - knownBlocks := btree.NewG(2, (*interval).Less) +func NewTree(db database.Database) (*Tree, error) { + intervals, err := GetIntervals(db) + if err != nil { + return nil, err + } + + knownBlocks := btree.NewG(treeDegree, (*interval).Less) + for _, i := range intervals { + knownBlocks.ReplaceOrInsert(i) + } return &Tree{ + db: db, knownBlocks: knownBlocks, - } + }, nil } -func (t *Tree) Add(height uint64) { +func (t *Tree) Add(height uint64) error { var ( newInterval = &interval{ lowerBound: height, @@ -33,7 +47,7 @@ func (t *Tree) Add(height uint64) { }) if upper.Contains(height) { // height is already in the tree - return + return nil } t.knownBlocks.DescendLessOrEqual(newInterval, func(item *interval) bool { @@ -48,16 +62,26 @@ func (t *Tree) Add(height uint64) { switch { case adjacentToLowerBound && adjacentToUpperBound: // the upper and lower ranges should be merged + if err := DeleteInterval(t.db, lower.upperBound); err != nil { + return err + } upper.lowerBound = lower.lowerBound t.knownBlocks.Delete(lower) + return PutInterval(t.db, upper.upperBound, lower.lowerBound) case adjacentToLowerBound: // the upper range should be extended by one on the lower side upper.lowerBound = height + return PutInterval(t.db, upper.upperBound, height) case adjacentToUpperBound: // the lower range should be extended by one on the upper side + if err := DeleteInterval(t.db, lower.upperBound); err != nil { + return err + } lower.upperBound = height + return PutInterval(t.db, height, lower.lowerBound) default: t.knownBlocks.ReplaceOrInsert(newInterval) + return PutInterval(t.db, height, height) } } diff --git a/snow/engine/snowman/bootstrap/interval/tree_test.go b/snow/engine/snowman/bootstrap/interval/tree_test.go index fa9a68a911a3..d0f94aab56cf 100644 --- a/snow/engine/snowman/bootstrap/interval/tree_test.go +++ b/snow/engine/snowman/bootstrap/interval/tree_test.go @@ -8,6 +8,9 @@ import ( "github.com/google/btree" "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/database/memdb" ) func flatten(tree *btree.BTreeG[*interval]) []*interval { @@ -19,11 +22,13 @@ func flatten(tree *btree.BTreeG[*interval]) []*interval { return intervals } -func newTree(intervals []*interval) *Tree { - tree := NewTree() +func newTree(require *require.Assertions, db database.Database, intervals []*interval) *Tree { + tree, err := NewTree(db) + require.NoError(err) + for _, toAdd := range intervals { for i := toAdd.lowerBound; i <= toAdd.upperBound; i++ { - tree.Add(i) + require.NoError(tree.Add(i)) } } return tree @@ -129,8 +134,14 @@ func TestTreeAdd(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tree := newTree(test.toAdd) - require.Equal(t, test.expected, flatten(tree.knownBlocks)) + require := require.New(t) + + db := memdb.New() + treeFromAdditions := newTree(require, db, test.toAdd) + require.Equal(test.expected, flatten(treeFromAdditions.knownBlocks)) + + treeFromDB := newTree(require, db, nil) + require.Equal(test.expected, flatten(treeFromDB.knownBlocks)) }) } } @@ -211,8 +222,10 @@ func TestTreeContains(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tree := newTree(test.tree) - require.Equal(t, test.expected, tree.Contains(test.height)) + require := require.New(t) + + tree := newTree(require, memdb.New(), test.tree) + require.Equal(test.expected, tree.Contains(test.height)) }) } } From 2454c460c0cd8cc1ad5448964e3ca258598834cc Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 20 Feb 2024 18:30:33 -0500 Subject: [PATCH 10/85] rename --- .../engine/snowman/bootstrap/interval/tree.go | 22 +++++++++---------- .../snowman/bootstrap/interval/tree_test.go | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/tree.go b/snow/engine/snowman/bootstrap/interval/tree.go index 49a1329863d1..945f84ceaafe 100644 --- a/snow/engine/snowman/bootstrap/interval/tree.go +++ b/snow/engine/snowman/bootstrap/interval/tree.go @@ -12,8 +12,8 @@ import ( const treeDegree = 2 type Tree struct { - db database.Database - knownBlocks *btree.BTreeG[*interval] + db database.Database + knownHeights *btree.BTreeG[*interval] } func NewTree(db database.Database) (*Tree, error) { @@ -22,13 +22,13 @@ func NewTree(db database.Database) (*Tree, error) { return nil, err } - knownBlocks := btree.NewG(treeDegree, (*interval).Less) + knownHeights := btree.NewG(treeDegree, (*interval).Less) for _, i := range intervals { - knownBlocks.ReplaceOrInsert(i) + knownHeights.ReplaceOrInsert(i) } return &Tree{ - db: db, - knownBlocks: knownBlocks, + db: db, + knownHeights: knownHeights, }, nil } @@ -41,7 +41,7 @@ func (t *Tree) Add(height uint64) error { upper *interval lower *interval ) - t.knownBlocks.AscendGreaterOrEqual(newInterval, func(item *interval) bool { + t.knownHeights.AscendGreaterOrEqual(newInterval, func(item *interval) bool { upper = item return false }) @@ -50,7 +50,7 @@ func (t *Tree) Add(height uint64) error { return nil } - t.knownBlocks.DescendLessOrEqual(newInterval, func(item *interval) bool { + t.knownHeights.DescendLessOrEqual(newInterval, func(item *interval) bool { lower = item return false }) @@ -66,7 +66,7 @@ func (t *Tree) Add(height uint64) error { return err } upper.lowerBound = lower.lowerBound - t.knownBlocks.Delete(lower) + t.knownHeights.Delete(lower) return PutInterval(t.db, upper.upperBound, lower.lowerBound) case adjacentToLowerBound: // the upper range should be extended by one on the lower side @@ -80,7 +80,7 @@ func (t *Tree) Add(height uint64) error { lower.upperBound = height return PutInterval(t.db, height, lower.lowerBound) default: - t.knownBlocks.ReplaceOrInsert(newInterval) + t.knownHeights.ReplaceOrInsert(newInterval) return PutInterval(t.db, height, height) } } @@ -93,7 +93,7 @@ func (t *Tree) Contains(height uint64) bool { } higher *interval ) - t.knownBlocks.AscendGreaterOrEqual(i, func(item *interval) bool { + t.knownHeights.AscendGreaterOrEqual(i, func(item *interval) bool { higher = item return false }) diff --git a/snow/engine/snowman/bootstrap/interval/tree_test.go b/snow/engine/snowman/bootstrap/interval/tree_test.go index d0f94aab56cf..5d8bad92a7cf 100644 --- a/snow/engine/snowman/bootstrap/interval/tree_test.go +++ b/snow/engine/snowman/bootstrap/interval/tree_test.go @@ -138,10 +138,10 @@ func TestTreeAdd(t *testing.T) { db := memdb.New() treeFromAdditions := newTree(require, db, test.toAdd) - require.Equal(test.expected, flatten(treeFromAdditions.knownBlocks)) + require.Equal(test.expected, flatten(treeFromAdditions.knownHeights)) treeFromDB := newTree(require, db, nil) - require.Equal(test.expected, flatten(treeFromDB.knownBlocks)) + require.Equal(test.expected, flatten(treeFromDB.knownHeights)) }) } } From 0efa5eba8f87c9f45f7b4874e96bab55e898b9c6 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 20 Feb 2024 19:44:13 -0500 Subject: [PATCH 11/85] Add block execution --- .../snowman/bootstrap/interval/blocks.go | 119 ++++++++ .../snowman/bootstrap/interval/interval.go | 22 +- .../snowman/bootstrap/interval/state.go | 17 +- .../engine/snowman/bootstrap/interval/tree.go | 96 +++++-- .../snowman/bootstrap/interval/tree_test.go | 267 +++++++++++++----- 5 files changed, 410 insertions(+), 111 deletions(-) create mode 100644 snow/engine/snowman/bootstrap/interval/blocks.go diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go new file mode 100644 index 000000000000..309864396c6b --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -0,0 +1,119 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package interval + +import ( + "context" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/utils/set" +) + +type Parser interface { + ParseBlock(context.Context, []byte) (snowman.Block, error) +} + +func GetMissingBlockIDs( + ctx context.Context, + parser Parser, + tree *Tree, + lastAcceptedHeight uint64, +) (set.Set[ids.ID], error) { + var ( + missingBlocks set.Set[ids.ID] + intervals = tree.Flatten() + lastHeightToFetch = lastAcceptedHeight + 1 + ) + for _, i := range intervals { + if i.LowerBound <= lastHeightToFetch { + continue + } + + blkBytes, err := GetBlock(tree.db, i.LowerBound) + if err != nil { + return nil, err + } + + blk, err := parser.ParseBlock(ctx, blkBytes) + if err != nil { + return nil, err + } + + parentID := blk.Parent() + missingBlocks.Add(parentID) + } + return missingBlocks, nil +} + +// Add the block to the tree and return if the parent block should be fetched. +func Add(tree *Tree, lastAcceptedHeight uint64, blk snowman.Block) (bool, error) { + var ( + height = blk.Height() + lastHeightToFetch = lastAcceptedHeight + 1 + ) + if height < lastHeightToFetch { + return false, nil + } + if tree.Contains(height) { + return false, nil + } + + blkBytes := blk.Bytes() + if err := PutBlock(tree.db, height, blkBytes); err != nil { + return false, err + } + + if err := tree.Add(height); err != nil { + return false, err + } + + if height == lastHeightToFetch { + return false, nil + } + + parentHeight := height - 1 + return !tree.Contains(parentHeight), nil +} + +func Execute( + ctx context.Context, + parser Parser, + tree *Tree, + lastAcceptedHeight uint64, +) error { + it := tree.db.NewIteratorWithPrefix(blockPrefix) + defer func() { + it.Release() + }() + + for it.Next() { + blkBytes := it.Value() + blk, err := parser.ParseBlock(ctx, blkBytes) + if err != nil { + return err + } + + height := blk.Height() + if err := DeleteBlock(tree.db, height); err != nil { + return err + } + + if err := tree.Remove(height); err != nil { + return err + } + + if height <= lastAcceptedHeight { + continue + } + + if err := blk.Verify(ctx); err != nil { + return err + } + if err := blk.Accept(ctx); err != nil { + return err + } + } + return it.Error() +} diff --git a/snow/engine/snowman/bootstrap/interval/interval.go b/snow/engine/snowman/bootstrap/interval/interval.go index d83d0c6143d2..a79e3ce12369 100644 --- a/snow/engine/snowman/bootstrap/interval/interval.go +++ b/snow/engine/snowman/bootstrap/interval/interval.go @@ -3,25 +3,25 @@ package interval -type interval struct { - lowerBound uint64 - upperBound uint64 +type Interval struct { + LowerBound uint64 + UpperBound uint64 } -func (i *interval) Less(other *interval) bool { - return i.upperBound < other.upperBound +func (i *Interval) Less(other *Interval) bool { + return i.UpperBound < other.UpperBound } -func (i *interval) Contains(height uint64) bool { - return i != nil && i.lowerBound <= height && height <= i.upperBound +func (i *Interval) Contains(height uint64) bool { + return i != nil && i.LowerBound <= height && height <= i.UpperBound } // AdjacentToUpperBound returns true if height is 1 greater than upperBound. -func (i *interval) AdjacentToUpperBound(height uint64) bool { - return i != nil && i.upperBound+1 == height +func (i *Interval) AdjacentToUpperBound(height uint64) bool { + return i != nil && i.UpperBound+1 == height } // AdjacentToLowerBound returns true if height is 1 less than lowerBound. -func (i *interval) AdjacentToLowerBound(height uint64) bool { - return i != nil && height+1 == i.lowerBound +func (i *Interval) AdjacentToLowerBound(height uint64) bool { + return i != nil && height+1 == i.LowerBound } diff --git a/snow/engine/snowman/bootstrap/interval/state.go b/snow/engine/snowman/bootstrap/interval/state.go index 0d5974a04e3e..f0f47e28b6d8 100644 --- a/snow/engine/snowman/bootstrap/interval/state.go +++ b/snow/engine/snowman/bootstrap/interval/state.go @@ -15,11 +15,11 @@ var ( blockPrefix = []byte{blockPrefixByte} ) -func GetIntervals(db database.Iteratee) ([]*interval, error) { +func GetIntervals(db database.Iteratee) ([]*Interval, error) { it := db.NewIteratorWithPrefix(rangePrefix) defer it.Release() - var intervals []*interval + var intervals []*Interval for it.Next() { dbKey := it.Key() rangeKey := dbKey[len(rangePrefix):] @@ -34,9 +34,9 @@ func GetIntervals(db database.Iteratee) ([]*interval, error) { return nil, err } - intervals = append(intervals, &interval{ - lowerBound: lowerBound, - upperBound: upperBound, + intervals = append(intervals, &Interval{ + LowerBound: lowerBound, + UpperBound: upperBound, }) } return intervals, it.Error() @@ -58,6 +58,13 @@ func DeleteInterval(db database.KeyValueDeleter, upperBound uint64) error { ) } +func GetBlock(db database.KeyValueReader, height uint64) ([]byte, error) { + blockKey := database.PackUInt64(height) + return db.Get( + append(blockPrefix, blockKey...), + ) +} + func PutBlock(db database.KeyValueWriter, height uint64, bytes []byte) error { blockKey := database.PackUInt64(height) return db.Put( diff --git a/snow/engine/snowman/bootstrap/interval/tree.go b/snow/engine/snowman/bootstrap/interval/tree.go index 945f84ceaafe..42057aad7f6b 100644 --- a/snow/engine/snowman/bootstrap/interval/tree.go +++ b/snow/engine/snowman/bootstrap/interval/tree.go @@ -13,7 +13,7 @@ const treeDegree = 2 type Tree struct { db database.Database - knownHeights *btree.BTreeG[*interval] + knownHeights *btree.BTreeG[*Interval] } func NewTree(db database.Database) (*Tree, error) { @@ -22,7 +22,7 @@ func NewTree(db database.Database) (*Tree, error) { return nil, err } - knownHeights := btree.NewG(treeDegree, (*interval).Less) + knownHeights := btree.NewG(treeDegree, (*Interval).Less) for _, i := range intervals { knownHeights.ReplaceOrInsert(i) } @@ -34,14 +34,14 @@ func NewTree(db database.Database) (*Tree, error) { func (t *Tree) Add(height uint64) error { var ( - newInterval = &interval{ - lowerBound: height, - upperBound: height, + newInterval = &Interval{ + LowerBound: height, + UpperBound: height, } - upper *interval - lower *interval + upper *Interval + lower *Interval ) - t.knownHeights.AscendGreaterOrEqual(newInterval, func(item *interval) bool { + t.knownHeights.AscendGreaterOrEqual(newInterval, func(item *Interval) bool { upper = item return false }) @@ -50,7 +50,7 @@ func (t *Tree) Add(height uint64) error { return nil } - t.knownHeights.DescendLessOrEqual(newInterval, func(item *interval) bool { + t.knownHeights.DescendLessOrEqual(newInterval, func(item *Interval) bool { lower = item return false }) @@ -62,40 +62,92 @@ func (t *Tree) Add(height uint64) error { switch { case adjacentToLowerBound && adjacentToUpperBound: // the upper and lower ranges should be merged - if err := DeleteInterval(t.db, lower.upperBound); err != nil { + if err := DeleteInterval(t.db, lower.UpperBound); err != nil { return err } - upper.lowerBound = lower.lowerBound + upper.LowerBound = lower.LowerBound t.knownHeights.Delete(lower) - return PutInterval(t.db, upper.upperBound, lower.lowerBound) + return PutInterval(t.db, upper.UpperBound, lower.LowerBound) case adjacentToLowerBound: // the upper range should be extended by one on the lower side - upper.lowerBound = height - return PutInterval(t.db, upper.upperBound, height) + upper.LowerBound = height + return PutInterval(t.db, upper.UpperBound, height) case adjacentToUpperBound: // the lower range should be extended by one on the upper side - if err := DeleteInterval(t.db, lower.upperBound); err != nil { + if err := DeleteInterval(t.db, lower.UpperBound); err != nil { return err } - lower.upperBound = height - return PutInterval(t.db, height, lower.lowerBound) + lower.UpperBound = height + return PutInterval(t.db, height, lower.LowerBound) default: t.knownHeights.ReplaceOrInsert(newInterval) return PutInterval(t.db, height, height) } } +func (t *Tree) Remove(height uint64) error { + var ( + newInterval = &Interval{ + LowerBound: height, + UpperBound: height, + } + higher *Interval + ) + t.knownHeights.AscendGreaterOrEqual(newInterval, func(item *Interval) bool { + higher = item + return false + }) + if !higher.Contains(height) { + // height isn't in the tree + return nil + } + + switch { + case higher.LowerBound == higher.UpperBound: + t.knownHeights.Delete(higher) + return DeleteInterval(t.db, higher.UpperBound) + case higher.LowerBound == height: + higher.LowerBound++ + return PutInterval(t.db, higher.UpperBound, higher.LowerBound) + case higher.UpperBound == height: + if err := DeleteInterval(t.db, higher.UpperBound); err != nil { + return err + } + higher.UpperBound-- + return PutInterval(t.db, higher.UpperBound, higher.LowerBound) + default: + newInterval.LowerBound = higher.LowerBound + newInterval.UpperBound = height - 1 + t.knownHeights.ReplaceOrInsert(newInterval) + if err := PutInterval(t.db, newInterval.UpperBound, newInterval.LowerBound); err != nil { + return err + } + + higher.LowerBound = height + 1 + return PutInterval(t.db, higher.UpperBound, higher.LowerBound) + } +} + func (t *Tree) Contains(height uint64) bool { var ( - i = &interval{ - lowerBound: height, - upperBound: height, + i = &Interval{ + LowerBound: height, + UpperBound: height, } - higher *interval + higher *Interval ) - t.knownHeights.AscendGreaterOrEqual(i, func(item *interval) bool { + t.knownHeights.AscendGreaterOrEqual(i, func(item *Interval) bool { higher = item return false }) return higher.Contains(height) } + +func (t *Tree) Flatten() []*Interval { + intervals := make([]*Interval, 0, t.knownHeights.Len()) + t.knownHeights.Ascend(func(item *Interval) bool { + intervals = append(intervals, item) + return true + }) + return intervals +} diff --git a/snow/engine/snowman/bootstrap/interval/tree_test.go b/snow/engine/snowman/bootstrap/interval/tree_test.go index 5d8bad92a7cf..6822e9c62780 100644 --- a/snow/engine/snowman/bootstrap/interval/tree_test.go +++ b/snow/engine/snowman/bootstrap/interval/tree_test.go @@ -6,28 +6,18 @@ package interval import ( "testing" - "github.com/google/btree" "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" ) -func flatten(tree *btree.BTreeG[*interval]) []*interval { - intervals := make([]*interval, 0, tree.Len()) - tree.Ascend(func(item *interval) bool { - intervals = append(intervals, item) - return true - }) - return intervals -} - -func newTree(require *require.Assertions, db database.Database, intervals []*interval) *Tree { +func newTree(require *require.Assertions, db database.Database, intervals []*Interval) *Tree { tree, err := NewTree(db) require.NoError(err) for _, toAdd := range intervals { - for i := toAdd.lowerBound; i <= toAdd.upperBound; i++ { + for i := toAdd.LowerBound; i <= toAdd.UpperBound; i++ { require.NoError(tree.Add(i)) } } @@ -37,97 +27,97 @@ func newTree(require *require.Assertions, db database.Database, intervals []*int func TestTreeAdd(t *testing.T) { tests := []struct { name string - toAdd []*interval - expected []*interval + toAdd []*Interval + expected []*Interval }{ { name: "single addition", - toAdd: []*interval{ + toAdd: []*Interval{ { - lowerBound: 10, - upperBound: 10, + LowerBound: 10, + UpperBound: 10, }, }, - expected: []*interval{ + expected: []*Interval{ { - lowerBound: 10, - upperBound: 10, + LowerBound: 10, + UpperBound: 10, }, }, }, { name: "extend above", - toAdd: []*interval{ + toAdd: []*Interval{ { - lowerBound: 10, - upperBound: 11, + LowerBound: 10, + UpperBound: 11, }, }, - expected: []*interval{ + expected: []*Interval{ { - lowerBound: 10, - upperBound: 11, + LowerBound: 10, + UpperBound: 11, }, }, }, { name: "extend below", - toAdd: []*interval{ + toAdd: []*Interval{ { - lowerBound: 11, - upperBound: 11, + LowerBound: 11, + UpperBound: 11, }, { - lowerBound: 10, - upperBound: 10, + LowerBound: 10, + UpperBound: 10, }, }, - expected: []*interval{ + expected: []*Interval{ { - lowerBound: 10, - upperBound: 11, + LowerBound: 10, + UpperBound: 11, }, }, }, { name: "merge", - toAdd: []*interval{ + toAdd: []*Interval{ { - lowerBound: 10, - upperBound: 10, + LowerBound: 10, + UpperBound: 10, }, { - lowerBound: 12, - upperBound: 12, + LowerBound: 12, + UpperBound: 12, }, { - lowerBound: 11, - upperBound: 11, + LowerBound: 11, + UpperBound: 11, }, }, - expected: []*interval{ + expected: []*Interval{ { - lowerBound: 10, - upperBound: 12, + LowerBound: 10, + UpperBound: 12, }, }, }, { name: "ignore duplicate", - toAdd: []*interval{ + toAdd: []*Interval{ { - lowerBound: 10, - upperBound: 11, + LowerBound: 10, + UpperBound: 11, }, { - lowerBound: 11, - upperBound: 11, + LowerBound: 11, + UpperBound: 11, }, }, - expected: []*interval{ + expected: []*Interval{ { - lowerBound: 10, - upperBound: 11, + LowerBound: 10, + UpperBound: 11, }, }, }, @@ -138,10 +128,141 @@ func TestTreeAdd(t *testing.T) { db := memdb.New() treeFromAdditions := newTree(require, db, test.toAdd) - require.Equal(test.expected, flatten(treeFromAdditions.knownHeights)) + require.Equal(test.expected, treeFromAdditions.Flatten()) + + treeFromDB := newTree(require, db, nil) + require.Equal(test.expected, treeFromDB.Flatten()) + }) + } +} + +func TestTreeRemove(t *testing.T) { + tests := []struct { + name string + toAdd []*Interval + toRemove []*Interval + expected []*Interval + }{ + { + name: "single removal", + toAdd: []*Interval{ + { + LowerBound: 10, + UpperBound: 10, + }, + }, + toRemove: []*Interval{ + { + LowerBound: 10, + UpperBound: 10, + }, + }, + expected: []*Interval{}, + }, + { + name: "reduce above", + toAdd: []*Interval{ + { + LowerBound: 10, + UpperBound: 11, + }, + }, + toRemove: []*Interval{ + { + LowerBound: 11, + UpperBound: 11, + }, + }, + expected: []*Interval{ + { + LowerBound: 10, + UpperBound: 10, + }, + }, + }, + { + name: "reduce below", + toAdd: []*Interval{ + { + LowerBound: 10, + UpperBound: 11, + }, + }, + toRemove: []*Interval{ + { + LowerBound: 10, + UpperBound: 10, + }, + }, + expected: []*Interval{ + { + LowerBound: 11, + UpperBound: 11, + }, + }, + }, + { + name: "split", + toAdd: []*Interval{ + { + LowerBound: 10, + UpperBound: 12, + }, + }, + toRemove: []*Interval{ + { + LowerBound: 11, + UpperBound: 11, + }, + }, + expected: []*Interval{ + { + LowerBound: 10, + UpperBound: 10, + }, + { + LowerBound: 12, + UpperBound: 12, + }, + }, + }, + { + name: "ignore missing", + toAdd: []*Interval{ + { + LowerBound: 10, + UpperBound: 10, + }, + }, + toRemove: []*Interval{ + { + LowerBound: 11, + UpperBound: 11, + }, + }, + expected: []*Interval{ + { + LowerBound: 10, + UpperBound: 10, + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + db := memdb.New() + treeFromModifications := newTree(require, db, test.toAdd) + for _, toRemove := range test.toRemove { + for i := toRemove.LowerBound; i <= toRemove.UpperBound; i++ { + require.NoError(treeFromModifications.Remove(i)) + } + } + require.Equal(test.expected, treeFromModifications.Flatten()) treeFromDB := newTree(require, db, nil) - require.Equal(test.expected, flatten(treeFromDB.knownHeights)) + require.Equal(test.expected, treeFromDB.Flatten()) }) } } @@ -149,16 +270,16 @@ func TestTreeAdd(t *testing.T) { func TestTreeContains(t *testing.T) { tests := []struct { name string - tree []*interval + tree []*Interval height uint64 expected bool }{ { name: "below", - tree: []*interval{ + tree: []*Interval{ { - lowerBound: 10, - upperBound: 10, + LowerBound: 10, + UpperBound: 10, }, }, height: 9, @@ -166,10 +287,10 @@ func TestTreeContains(t *testing.T) { }, { name: "above", - tree: []*interval{ + tree: []*Interval{ { - lowerBound: 10, - upperBound: 10, + LowerBound: 10, + UpperBound: 10, }, }, height: 11, @@ -177,10 +298,10 @@ func TestTreeContains(t *testing.T) { }, { name: "equal both", - tree: []*interval{ + tree: []*Interval{ { - lowerBound: 10, - upperBound: 10, + LowerBound: 10, + UpperBound: 10, }, }, height: 10, @@ -188,10 +309,10 @@ func TestTreeContains(t *testing.T) { }, { name: "equal lower", - tree: []*interval{ + tree: []*Interval{ { - lowerBound: 10, - upperBound: 11, + LowerBound: 10, + UpperBound: 11, }, }, height: 10, @@ -199,10 +320,10 @@ func TestTreeContains(t *testing.T) { }, { name: "equal upper", - tree: []*interval{ + tree: []*Interval{ { - lowerBound: 9, - upperBound: 10, + LowerBound: 9, + UpperBound: 10, }, }, height: 10, @@ -210,10 +331,10 @@ func TestTreeContains(t *testing.T) { }, { name: "inside", - tree: []*interval{ + tree: []*Interval{ { - lowerBound: 9, - upperBound: 11, + LowerBound: 9, + UpperBound: 11, }, }, height: 10, From 6a65a2a33500e67565663cd0c3519f521d44e907 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 20 Feb 2024 21:32:18 -0500 Subject: [PATCH 12/85] Add length + TODOs --- .../snowman/bootstrap/interval/blocks.go | 3 ++ .../engine/snowman/bootstrap/interval/tree.go | 25 ++++++++++++--- .../snowman/bootstrap/interval/tree_test.go | 32 ++++++++++++++----- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 309864396c6b..ad4ce06d9e0c 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -88,6 +88,9 @@ func Execute( it.Release() }() + // TODO: Periodically release the iterator here + // TODO: Periodically log progress + // TODO: Add metrics for it.Next() { blkBytes := it.Value() blk, err := parser.ParseBlock(ctx, blkBytes) diff --git a/snow/engine/snowman/bootstrap/interval/tree.go b/snow/engine/snowman/bootstrap/interval/tree.go index 42057aad7f6b..38dd52f54718 100644 --- a/snow/engine/snowman/bootstrap/interval/tree.go +++ b/snow/engine/snowman/bootstrap/interval/tree.go @@ -12,8 +12,9 @@ import ( const treeDegree = 2 type Tree struct { - db database.Database - knownHeights *btree.BTreeG[*Interval] + db database.Database + knownHeights *btree.BTreeG[*Interval] + numKnownHeights uint64 } func NewTree(db database.Database) (*Tree, error) { @@ -22,13 +23,18 @@ func NewTree(db database.Database) (*Tree, error) { return nil, err } - knownHeights := btree.NewG(treeDegree, (*Interval).Less) + var ( + knownHeights = btree.NewG(treeDegree, (*Interval).Less) + numKnownHeights uint64 + ) for _, i := range intervals { knownHeights.ReplaceOrInsert(i) + numKnownHeights += i.UpperBound - i.LowerBound + 1 } return &Tree{ - db: db, - knownHeights: knownHeights, + db: db, + knownHeights: knownHeights, + numKnownHeights: numKnownHeights, }, nil } @@ -55,6 +61,8 @@ func (t *Tree) Add(height uint64) error { return false }) + t.numKnownHeights++ + var ( adjacentToLowerBound = upper.AdjacentToLowerBound(height) adjacentToUpperBound = lower.AdjacentToUpperBound(height) @@ -102,6 +110,8 @@ func (t *Tree) Remove(height uint64) error { return nil } + t.numKnownHeights-- + switch { case higher.LowerBound == higher.UpperBound: t.knownHeights.Delete(higher) @@ -151,3 +161,8 @@ func (t *Tree) Flatten() []*Interval { }) return intervals } + +// Len returns the number of heights in the tree; not the number of intervals. +func (t *Tree) Len() uint64 { + return t.numKnownHeights +} diff --git a/snow/engine/snowman/bootstrap/interval/tree_test.go b/snow/engine/snowman/bootstrap/interval/tree_test.go index 6822e9c62780..250943434843 100644 --- a/snow/engine/snowman/bootstrap/interval/tree_test.go +++ b/snow/engine/snowman/bootstrap/interval/tree_test.go @@ -26,9 +26,10 @@ func newTree(require *require.Assertions, db database.Database, intervals []*Int func TestTreeAdd(t *testing.T) { tests := []struct { - name string - toAdd []*Interval - expected []*Interval + name string + toAdd []*Interval + expected []*Interval + expectedLen uint64 }{ { name: "single addition", @@ -44,6 +45,7 @@ func TestTreeAdd(t *testing.T) { UpperBound: 10, }, }, + expectedLen: 1, }, { name: "extend above", @@ -59,6 +61,7 @@ func TestTreeAdd(t *testing.T) { UpperBound: 11, }, }, + expectedLen: 2, }, { name: "extend below", @@ -78,6 +81,7 @@ func TestTreeAdd(t *testing.T) { UpperBound: 11, }, }, + expectedLen: 2, }, { name: "merge", @@ -101,6 +105,7 @@ func TestTreeAdd(t *testing.T) { UpperBound: 12, }, }, + expectedLen: 3, }, { name: "ignore duplicate", @@ -120,6 +125,7 @@ func TestTreeAdd(t *testing.T) { UpperBound: 11, }, }, + expectedLen: 2, }, } for _, test := range tests { @@ -129,19 +135,22 @@ func TestTreeAdd(t *testing.T) { db := memdb.New() treeFromAdditions := newTree(require, db, test.toAdd) require.Equal(test.expected, treeFromAdditions.Flatten()) + require.Equal(test.expectedLen, treeFromAdditions.Len()) treeFromDB := newTree(require, db, nil) require.Equal(test.expected, treeFromDB.Flatten()) + require.Equal(test.expectedLen, treeFromDB.Len()) }) } } func TestTreeRemove(t *testing.T) { tests := []struct { - name string - toAdd []*Interval - toRemove []*Interval - expected []*Interval + name string + toAdd []*Interval + toRemove []*Interval + expected []*Interval + expectedLen uint64 }{ { name: "single removal", @@ -157,7 +166,8 @@ func TestTreeRemove(t *testing.T) { UpperBound: 10, }, }, - expected: []*Interval{}, + expected: []*Interval{}, + expectedLen: 0, }, { name: "reduce above", @@ -179,6 +189,7 @@ func TestTreeRemove(t *testing.T) { UpperBound: 10, }, }, + expectedLen: 1, }, { name: "reduce below", @@ -200,6 +211,7 @@ func TestTreeRemove(t *testing.T) { UpperBound: 11, }, }, + expectedLen: 1, }, { name: "split", @@ -225,6 +237,7 @@ func TestTreeRemove(t *testing.T) { UpperBound: 12, }, }, + expectedLen: 2, }, { name: "ignore missing", @@ -246,6 +259,7 @@ func TestTreeRemove(t *testing.T) { UpperBound: 10, }, }, + expectedLen: 1, }, } for _, test := range tests { @@ -260,9 +274,11 @@ func TestTreeRemove(t *testing.T) { } } require.Equal(test.expected, treeFromModifications.Flatten()) + require.Equal(test.expectedLen, treeFromModifications.Len()) treeFromDB := newTree(require, db, nil) require.Equal(test.expected, treeFromDB.Flatten()) + require.Equal(test.expectedLen, treeFromDB.Len()) }) } } From f2234bd5b41b6520206f7e612c19d729259be600 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 20 Feb 2024 21:44:05 -0500 Subject: [PATCH 13/85] nit --- snow/engine/snowman/bootstrap/interval/blocks.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index ad4ce06d9e0c..7b08bcf58079 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -53,10 +53,7 @@ func Add(tree *Tree, lastAcceptedHeight uint64, blk snowman.Block) (bool, error) height = blk.Height() lastHeightToFetch = lastAcceptedHeight + 1 ) - if height < lastHeightToFetch { - return false, nil - } - if tree.Contains(height) { + if height < lastHeightToFetch || tree.Contains(height) { return false, nil } @@ -69,12 +66,7 @@ func Add(tree *Tree, lastAcceptedHeight uint64, blk snowman.Block) (bool, error) return false, err } - if height == lastHeightToFetch { - return false, nil - } - - parentHeight := height - 1 - return !tree.Contains(parentHeight), nil + return height != lastHeightToFetch && !tree.Contains(height-1), nil } func Execute( From 1f6323869ddd11f2a598b4b9531395e265c63e76 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 20 Feb 2024 21:47:50 -0500 Subject: [PATCH 14/85] error rather than panic --- snow/engine/snowman/bootstrap/interval/state.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/state.go b/snow/engine/snowman/bootstrap/interval/state.go index f0f47e28b6d8..320d5c97105f 100644 --- a/snow/engine/snowman/bootstrap/interval/state.go +++ b/snow/engine/snowman/bootstrap/interval/state.go @@ -3,16 +3,24 @@ package interval -import "github.com/ava-labs/avalanchego/database" +import ( + "errors" + + "github.com/ava-labs/avalanchego/database" +) const ( rangePrefixByte byte = iota blockPrefixByte + + prefixLen = 1 ) var ( rangePrefix = []byte{rangePrefixByte} blockPrefix = []byte{blockPrefixByte} + + errInvalidKeyLength = errors.New("invalid key length") ) func GetIntervals(db database.Iteratee) ([]*Interval, error) { @@ -22,7 +30,11 @@ func GetIntervals(db database.Iteratee) ([]*Interval, error) { var intervals []*Interval for it.Next() { dbKey := it.Key() - rangeKey := dbKey[len(rangePrefix):] + if len(dbKey) < prefixLen { + return nil, errInvalidKeyLength + } + + rangeKey := dbKey[prefixLen:] upperBound, err := database.ParseUInt64(rangeKey) if err != nil { return nil, err From 6947876c026fa34e449eea4c19c5a9253de6cf9f Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 21 Feb 2024 10:52:58 -0500 Subject: [PATCH 15/85] Refactor database passing --- .../snowman/bootstrap/interval/blocks.go | 120 ++++++++++++++++-- .../engine/snowman/bootstrap/interval/tree.go | 32 +++-- .../snowman/bootstrap/interval/tree_test.go | 4 +- 3 files changed, 123 insertions(+), 33 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 7b08bcf58079..d6ab83382649 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -5,10 +5,22 @@ package interval import ( "context" + "time" + "go.uber.org/zap" + + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/timer" +) + +const ( + batchWritePeriod = 1 + iteratorReleasePeriod = 1024 + logPeriod = 5 * time.Second ) type Parser interface { @@ -17,6 +29,7 @@ type Parser interface { func GetMissingBlockIDs( ctx context.Context, + db database.KeyValueReader, parser Parser, tree *Tree, lastAcceptedHeight uint64, @@ -31,7 +44,7 @@ func GetMissingBlockIDs( continue } - blkBytes, err := GetBlock(tree.db, i.LowerBound) + blkBytes, err := GetBlock(db, i.LowerBound) if err != nil { return nil, err } @@ -48,7 +61,12 @@ func GetMissingBlockIDs( } // Add the block to the tree and return if the parent block should be fetched. -func Add(tree *Tree, lastAcceptedHeight uint64, blk snowman.Block) (bool, error) { +func Add( + db database.KeyValueWriterDeleter, + tree *Tree, + lastAcceptedHeight uint64, + blk snowman.Block, +) (bool, error) { var ( height = blk.Height() lastHeightToFetch = lastAcceptedHeight + 1 @@ -58,11 +76,11 @@ func Add(tree *Tree, lastAcceptedHeight uint64, blk snowman.Block) (bool, error) } blkBytes := blk.Bytes() - if err := PutBlock(tree.db, height, blkBytes); err != nil { + if err := PutBlock(db, height, blkBytes); err != nil { return false, err } - if err := tree.Add(height); err != nil { + if err := tree.Add(db, height); err != nil { return false, err } @@ -71,34 +89,97 @@ func Add(tree *Tree, lastAcceptedHeight uint64, blk snowman.Block) (bool, error) func Execute( ctx context.Context, + log logging.Logger, + db database.Database, parser Parser, tree *Tree, lastAcceptedHeight uint64, ) error { - it := tree.db.NewIteratorWithPrefix(blockPrefix) + var ( + batch = db.NewBatch() + processedSinceBatchWrite uint + writeBatch = func() error { + if processedSinceBatchWrite == 0 { + return nil + } + processedSinceBatchWrite %= batchWritePeriod + + if err := batch.Write(); err != nil { + return err + } + batch.Reset() + return nil + } + + iterator = db.NewIteratorWithPrefix(blockPrefix) + processedSinceIteratorRelease uint + + startTime = time.Now() + timeOfNextLog = startTime.Add(logPeriod) + totalNumberToProcess = tree.Len() + ) defer func() { - it.Release() + iterator.Release() }() - // TODO: Periodically release the iterator here - // TODO: Periodically log progress - // TODO: Add metrics - for it.Next() { - blkBytes := it.Value() + log.Info("executing blocks", + zap.Uint64("numToExecute", totalNumberToProcess), + ) + + for iterator.Next() { + blkBytes := iterator.Value() blk, err := parser.ParseBlock(ctx, blkBytes) if err != nil { return err } height := blk.Height() - if err := DeleteBlock(tree.db, height); err != nil { + if err := DeleteBlock(batch, height); err != nil { return err } - if err := tree.Remove(height); err != nil { + if err := tree.Remove(batch, height); err != nil { return err } + // Periodically write the batch to disk to avoid memory pressure. + processedSinceBatchWrite++ + if processedSinceBatchWrite >= batchWritePeriod { + if err := writeBatch(); err != nil { + return err + } + } + + // Periodically release and re-grab the database iterator to avoid + // keeping a reference to an old database revision. + processedSinceIteratorRelease++ + if processedSinceIteratorRelease >= iteratorReleasePeriod { + if err := iterator.Error(); err != nil { + return err + } + + // The batch must be written here to avoid re-processing a block. + if err := writeBatch(); err != nil { + return err + } + + iterator.Release() + iterator = db.NewIteratorWithPrefix(blockPrefix) + } + + now := time.Now() + if now.After(timeOfNextLog) { + numProcessed := totalNumberToProcess - tree.Len() + eta := timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) + + log.Info("executing blocks", + zap.Duration("eta", eta), + zap.Uint64("numExecuted", numProcessed), + zap.Uint64("numToExecute", totalNumberToProcess), + ) + timeOfNextLog = now.Add(logPeriod) + } + if height <= lastAcceptedHeight { continue } @@ -110,5 +191,16 @@ func Execute( return err } } - return it.Error() + if err := writeBatch(); err != nil { + return err + } + if err := iterator.Error(); err != nil { + return err + } + + log.Info("executed blocks", + zap.Uint64("numExecuted", totalNumberToProcess), + zap.Duration("duration", time.Since(startTime)), + ) + return nil } diff --git a/snow/engine/snowman/bootstrap/interval/tree.go b/snow/engine/snowman/bootstrap/interval/tree.go index 38dd52f54718..a4f07102f04a 100644 --- a/snow/engine/snowman/bootstrap/interval/tree.go +++ b/snow/engine/snowman/bootstrap/interval/tree.go @@ -12,12 +12,11 @@ import ( const treeDegree = 2 type Tree struct { - db database.Database knownHeights *btree.BTreeG[*Interval] numKnownHeights uint64 } -func NewTree(db database.Database) (*Tree, error) { +func NewTree(db database.Iteratee) (*Tree, error) { intervals, err := GetIntervals(db) if err != nil { return nil, err @@ -32,13 +31,12 @@ func NewTree(db database.Database) (*Tree, error) { numKnownHeights += i.UpperBound - i.LowerBound + 1 } return &Tree{ - db: db, knownHeights: knownHeights, numKnownHeights: numKnownHeights, }, nil } -func (t *Tree) Add(height uint64) error { +func (t *Tree) Add(db database.KeyValueWriterDeleter, height uint64) error { var ( newInterval = &Interval{ LowerBound: height, @@ -70,30 +68,30 @@ func (t *Tree) Add(height uint64) error { switch { case adjacentToLowerBound && adjacentToUpperBound: // the upper and lower ranges should be merged - if err := DeleteInterval(t.db, lower.UpperBound); err != nil { + if err := DeleteInterval(db, lower.UpperBound); err != nil { return err } upper.LowerBound = lower.LowerBound t.knownHeights.Delete(lower) - return PutInterval(t.db, upper.UpperBound, lower.LowerBound) + return PutInterval(db, upper.UpperBound, lower.LowerBound) case adjacentToLowerBound: // the upper range should be extended by one on the lower side upper.LowerBound = height - return PutInterval(t.db, upper.UpperBound, height) + return PutInterval(db, upper.UpperBound, height) case adjacentToUpperBound: // the lower range should be extended by one on the upper side - if err := DeleteInterval(t.db, lower.UpperBound); err != nil { + if err := DeleteInterval(db, lower.UpperBound); err != nil { return err } lower.UpperBound = height - return PutInterval(t.db, height, lower.LowerBound) + return PutInterval(db, height, lower.LowerBound) default: t.knownHeights.ReplaceOrInsert(newInterval) - return PutInterval(t.db, height, height) + return PutInterval(db, height, height) } } -func (t *Tree) Remove(height uint64) error { +func (t *Tree) Remove(db database.KeyValueWriterDeleter, height uint64) error { var ( newInterval = &Interval{ LowerBound: height, @@ -115,26 +113,26 @@ func (t *Tree) Remove(height uint64) error { switch { case higher.LowerBound == higher.UpperBound: t.knownHeights.Delete(higher) - return DeleteInterval(t.db, higher.UpperBound) + return DeleteInterval(db, higher.UpperBound) case higher.LowerBound == height: higher.LowerBound++ - return PutInterval(t.db, higher.UpperBound, higher.LowerBound) + return PutInterval(db, higher.UpperBound, higher.LowerBound) case higher.UpperBound == height: - if err := DeleteInterval(t.db, higher.UpperBound); err != nil { + if err := DeleteInterval(db, higher.UpperBound); err != nil { return err } higher.UpperBound-- - return PutInterval(t.db, higher.UpperBound, higher.LowerBound) + return PutInterval(db, higher.UpperBound, higher.LowerBound) default: newInterval.LowerBound = higher.LowerBound newInterval.UpperBound = height - 1 t.knownHeights.ReplaceOrInsert(newInterval) - if err := PutInterval(t.db, newInterval.UpperBound, newInterval.LowerBound); err != nil { + if err := PutInterval(db, newInterval.UpperBound, newInterval.LowerBound); err != nil { return err } higher.LowerBound = height + 1 - return PutInterval(t.db, higher.UpperBound, higher.LowerBound) + return PutInterval(db, higher.UpperBound, higher.LowerBound) } } diff --git a/snow/engine/snowman/bootstrap/interval/tree_test.go b/snow/engine/snowman/bootstrap/interval/tree_test.go index 250943434843..b0a13d5ed59c 100644 --- a/snow/engine/snowman/bootstrap/interval/tree_test.go +++ b/snow/engine/snowman/bootstrap/interval/tree_test.go @@ -18,7 +18,7 @@ func newTree(require *require.Assertions, db database.Database, intervals []*Int for _, toAdd := range intervals { for i := toAdd.LowerBound; i <= toAdd.UpperBound; i++ { - require.NoError(tree.Add(i)) + require.NoError(tree.Add(db, i)) } } return tree @@ -270,7 +270,7 @@ func TestTreeRemove(t *testing.T) { treeFromModifications := newTree(require, db, test.toAdd) for _, toRemove := range test.toRemove { for i := toRemove.LowerBound; i <= toRemove.UpperBound; i++ { - require.NoError(treeFromModifications.Remove(i)) + require.NoError(treeFromModifications.Remove(db, i)) } } require.Equal(test.expected, treeFromModifications.Flatten()) From be64296df381b980399f935816f91934a30aed6d Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 14:35:30 -0400 Subject: [PATCH 16/85] Add interval tests --- .../snowman/bootstrap/interval/interval.go | 22 +- .../bootstrap/interval/interval_test.go | 255 ++++++++++++++++++ 2 files changed, 270 insertions(+), 7 deletions(-) create mode 100644 snow/engine/snowman/bootstrap/interval/interval_test.go diff --git a/snow/engine/snowman/bootstrap/interval/interval.go b/snow/engine/snowman/bootstrap/interval/interval.go index a79e3ce12369..35ae260e446a 100644 --- a/snow/engine/snowman/bootstrap/interval/interval.go +++ b/snow/engine/snowman/bootstrap/interval/interval.go @@ -3,6 +3,8 @@ package interval +import "math" + type Interval struct { LowerBound uint64 UpperBound uint64 @@ -13,15 +15,21 @@ func (i *Interval) Less(other *Interval) bool { } func (i *Interval) Contains(height uint64) bool { - return i != nil && i.LowerBound <= height && height <= i.UpperBound -} - -// AdjacentToUpperBound returns true if height is 1 greater than upperBound. -func (i *Interval) AdjacentToUpperBound(height uint64) bool { - return i != nil && i.UpperBound+1 == height + return i != nil && + i.LowerBound <= height && + height <= i.UpperBound } // AdjacentToLowerBound returns true if height is 1 less than lowerBound. func (i *Interval) AdjacentToLowerBound(height uint64) bool { - return i != nil && height+1 == i.LowerBound + return i != nil && + height < math.MaxUint64 && + height+1 == i.LowerBound +} + +// AdjacentToUpperBound returns true if height is 1 greater than upperBound. +func (i *Interval) AdjacentToUpperBound(height uint64) bool { + return i != nil && + i.UpperBound < math.MaxUint64 && + i.UpperBound+1 == height } diff --git a/snow/engine/snowman/bootstrap/interval/interval_test.go b/snow/engine/snowman/bootstrap/interval/interval_test.go new file mode 100644 index 000000000000..2213302925fd --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/interval_test.go @@ -0,0 +1,255 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package interval + +import ( + "math" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestIntervalLess(t *testing.T) { + tests := []struct { + name string + left *Interval + right *Interval + expected bool + }{ + { + name: "less", + left: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + right: &Interval{ + LowerBound: 11, + UpperBound: 11, + }, + expected: true, + }, + { + name: "greater", + left: &Interval{ + LowerBound: 11, + UpperBound: 11, + }, + right: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + expected: false, + }, + { + name: "equal", + left: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + right: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + expected: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + less := test.left.Less(test.right) + require.Equal(t, test.expected, less) + }) + } +} + +func TestIntervalContains(t *testing.T) { + tests := []struct { + name string + interval *Interval + height uint64 + expected bool + }{ + { + name: "nil does not contain anything", + interval: nil, + height: 10, + expected: false, + }, + { + name: "too low", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 9, + expected: false, + }, + { + name: "inside", + interval: &Interval{ + LowerBound: 9, + UpperBound: 11, + }, + height: 10, + expected: true, + }, + { + name: "equal", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 10, + expected: true, + }, + { + name: "too high", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 11, + expected: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + contains := test.interval.Contains(test.height) + require.Equal(t, test.expected, contains) + }) + } +} + +func TestIntervalAdjacentToLowerBound(t *testing.T) { + tests := []struct { + name string + interval *Interval + height uint64 + expected bool + }{ + { + name: "nil is not adjacent to anything", + interval: nil, + height: 10, + expected: false, + }, + { + name: "too low", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 8, + expected: false, + }, + { + name: "equal", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 10, + expected: false, + }, + { + name: "adjacent to both", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 9, + expected: true, + }, + { + name: "adjacent to lower", + interval: &Interval{ + LowerBound: 10, + UpperBound: 11, + }, + height: 9, + expected: true, + }, + { + name: "check for overflow", + interval: &Interval{ + LowerBound: 0, + UpperBound: math.MaxUint64 - 1, + }, + height: math.MaxUint64, + expected: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + adjacent := test.interval.AdjacentToLowerBound(test.height) + require.Equal(t, test.expected, adjacent) + }) + } +} + +func TestIntervalAdjacentToUpperBound(t *testing.T) { + tests := []struct { + name string + interval *Interval + height uint64 + expected bool + }{ + { + name: "nil is not adjacent to anything", + interval: nil, + height: 10, + expected: false, + }, + { + name: "too low", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 8, + expected: false, + }, + { + name: "equal", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 10, + expected: false, + }, + { + name: "adjacent to both", + interval: &Interval{ + LowerBound: 10, + UpperBound: 10, + }, + height: 11, + expected: true, + }, + { + name: "adjacent to higher", + interval: &Interval{ + LowerBound: 9, + UpperBound: 10, + }, + height: 11, + expected: true, + }, + { + name: "check for overflow", + interval: &Interval{ + LowerBound: 1, + UpperBound: math.MaxUint64, + }, + height: 0, + expected: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + adjacent := test.interval.AdjacentToUpperBound(test.height) + require.Equal(t, test.expected, adjacent) + }) + } +} From 884f39c4d2765a75c2908f106c83de263c97867b Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 14:46:42 -0400 Subject: [PATCH 17/85] Fix too frequent iterator releases and batch writes --- snow/engine/snowman/bootstrap/interval/blocks.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index d6ab83382649..e330c593e4ac 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -102,7 +102,7 @@ func Execute( if processedSinceBatchWrite == 0 { return nil } - processedSinceBatchWrite %= batchWritePeriod + processedSinceBatchWrite = 0 if err := batch.Write(); err != nil { return err @@ -163,6 +163,7 @@ func Execute( return err } + processedSinceIteratorRelease = 0 iterator.Release() iterator = db.NewIteratorWithPrefix(blockPrefix) } From e4e92cca72d8098d8c41b3bb7c206d12866c98a3 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 16:10:10 -0400 Subject: [PATCH 18/85] nit + support cancellation --- .../snowman/bootstrap/interval/blocks.go | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index e330c593e4ac..6c6ba26b8b05 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -60,7 +60,8 @@ func GetMissingBlockIDs( return missingBlocks, nil } -// Add the block to the tree and return if the parent block should be fetched. +// Add the block to the tree and return if the parent block should be fetched, +// but wasn't desired before. func Add( db database.KeyValueWriterDeleter, tree *Tree, @@ -126,7 +127,7 @@ func Execute( zap.Uint64("numToExecute", totalNumberToProcess), ) - for iterator.Next() { + for ctx.Err() == nil && iterator.Next() { blkBytes := iterator.Value() blk, err := parser.ParseBlock(ctx, blkBytes) if err != nil { @@ -170,8 +171,10 @@ func Execute( now := time.Now() if now.After(timeOfNextLog) { - numProcessed := totalNumberToProcess - tree.Len() - eta := timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) + var ( + numProcessed = totalNumberToProcess - tree.Len() + eta = timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) + ) log.Info("executing blocks", zap.Duration("eta", eta), @@ -199,9 +202,15 @@ func Execute( return err } + var ( + numProcessed = totalNumberToProcess - tree.Len() + err = ctx.Err() + ) log.Info("executed blocks", - zap.Uint64("numExecuted", totalNumberToProcess), + zap.Uint64("numExecuted", numProcessed), + zap.Uint64("numToExecute", totalNumberToProcess), zap.Duration("duration", time.Since(startTime)), + zap.Error(err), ) - return nil + return err } From 72314d1b2d33ed53bf4cba3d4191a37eae337383 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 16:32:33 -0400 Subject: [PATCH 19/85] Add invariant comment + tests --- .../snowman/bootstrap/interval/blocks.go | 1 + .../snowman/bootstrap/interval/blocks_test.go | 450 ++++++++++++++++++ 2 files changed, 451 insertions(+) create mode 100644 snow/engine/snowman/bootstrap/interval/blocks_test.go diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 6c6ba26b8b05..613814868bfa 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -88,6 +88,7 @@ func Add( return height != lastHeightToFetch && !tree.Contains(height-1), nil } +// Invariant: Execute assumes that GetMissingBlockIDs would return an empty set. func Execute( ctx context.Context, log logging.Logger, diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go new file mode 100644 index 000000000000..48b269d9b1fc --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -0,0 +1,450 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package interval + +import ( + "bytes" + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/database/memdb" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/choices" + "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" +) + +func TestGetMissingBlockIDs(t *testing.T) { + blocks := generateBlockchain(7) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := NewTree(db) + require.NoError(t, err) + lastAcceptedHeight := uint64(1) + + t.Run("initially empty", func(t *testing.T) { + require := require.New(t) + + missing, err := GetMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Empty(missing) + }) + + t.Run("adding first block", func(t *testing.T) { + require := require.New(t) + + _, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[5], + ) + require.NoError(err) + + missing, err := GetMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[4].ID(), + ), + missing, + ) + }) + + t.Run("adding second block", func(t *testing.T) { + require := require.New(t) + + _, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[3], + ) + require.NoError(err) + + missing, err := GetMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[2].ID(), + blocks[4].ID(), + ), + missing, + ) + }) + + t.Run("adding last desired block", func(t *testing.T) { + require := require.New(t) + + _, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[2], + ) + require.NoError(err) + + missing, err := GetMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[4].ID(), + ), + missing, + ) + }) + + t.Run("adding block with known parent", func(t *testing.T) { + require := require.New(t) + + _, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[6], + ) + require.NoError(err) + + missing, err := GetMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[4].ID(), + ), + missing, + ) + }) +} + +func TestAdd(t *testing.T) { + blocks := generateBlockchain(7) + + db := memdb.New() + tree, err := NewTree(db) + require.NoError(t, err) + lastAcceptedHeight := uint64(1) + + t.Run("adding first block", func(t *testing.T) { + require := require.New(t) + + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[5], + ) + require.NoError(err) + require.True(newlyWantsParent) + require.Equal(uint64(1), tree.Len()) + + bytes, err := GetBlock(db, blocks[5].Height()) + require.NoError(err) + require.Equal(blocks[5].Bytes(), bytes) + }) + + t.Run("adding duplicate block", func(t *testing.T) { + require := require.New(t) + + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[5], + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(1), tree.Len()) + }) + + t.Run("adding second block", func(t *testing.T) { + require := require.New(t) + + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[3], + ) + require.NoError(err) + require.True(newlyWantsParent) + require.Equal(uint64(2), tree.Len()) + + bytes, err := GetBlock(db, blocks[3].Height()) + require.NoError(err) + require.Equal(blocks[3].Bytes(), bytes) + }) + + t.Run("adding last desired block", func(t *testing.T) { + require := require.New(t) + + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[2], + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(3), tree.Len()) + + bytes, err := GetBlock(db, blocks[2].Height()) + require.NoError(err) + require.Equal(blocks[2].Bytes(), bytes) + }) + + t.Run("adding undesired block", func(t *testing.T) { + require := require.New(t) + + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[1], + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(3), tree.Len()) + + _, err = GetBlock(db, blocks[1].Height()) + require.ErrorIs(err, database.ErrNotFound) + }) + + t.Run("adding block with known parent", func(t *testing.T) { + require := require.New(t) + + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + blocks[6], + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(4), tree.Len()) + + bytes, err := GetBlock(db, blocks[6].Height()) + require.NoError(err) + require.Equal(blocks[6].Bytes(), bytes) + }) +} + +func TestExecute(t *testing.T) { + require := require.New(t) + + const numBlocks = 2*max(batchWritePeriod, iteratorReleasePeriod) + 1 + blocks := generateBlockchain(numBlocks) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := NewTree(db) + require.NoError(err) + const lastAcceptedHeight = 1 + + for i, block := range blocks[lastAcceptedHeight+1:] { + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + block, + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(i+1), tree.Len()) + } + + err = Execute( + context.Background(), + logging.NoLog{}, + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + + for _, block := range blocks[lastAcceptedHeight+1:] { + require.Equal(choices.Accepted, block.Status()) + } + + size, err := database.Count(db) + require.NoError(err) + require.Zero(size) +} + +func TestExecuteExitsWhenCancelled(t *testing.T) { + require := require.New(t) + + blocks := generateBlockchain(7) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := NewTree(db) + require.NoError(err) + const lastAcceptedHeight = 1 + + for i, block := range blocks[lastAcceptedHeight+1:] { + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeight, + block, + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(i+1), tree.Len()) + } + + startSize, err := database.Count(db) + require.NoError(err) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + err = Execute( + ctx, + logging.NoLog{}, + db, + parser, + tree, + lastAcceptedHeight, + ) + require.ErrorIs(err, context.Canceled) + + for _, block := range blocks[lastAcceptedHeight+1:] { + require.Equal(choices.Processing, block.Status()) + } + + endSize, err := database.Count(db) + require.NoError(err) + require.Equal(startSize, endSize) +} + +func TestExecuteSkipsAcceptedBlocks(t *testing.T) { + require := require.New(t) + + blocks := generateBlockchain(7) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := NewTree(db) + require.NoError(err) + const ( + lastAcceptedHeightWhenAdding = 1 + lastAcceptedHeightWhenExecuting = 3 + ) + + for i, block := range blocks[lastAcceptedHeightWhenAdding+1:] { + newlyWantsParent, err := Add( + db, + tree, + lastAcceptedHeightWhenAdding, + block, + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(i+1), tree.Len()) + } + + err = Execute( + context.Background(), + logging.NoLog{}, + db, + parser, + tree, + lastAcceptedHeightWhenExecuting, + ) + require.NoError(err) + + for _, block := range blocks[lastAcceptedHeightWhenAdding+1 : lastAcceptedHeightWhenExecuting] { + require.Equal(choices.Processing, block.Status()) + } + for _, block := range blocks[lastAcceptedHeightWhenExecuting+1:] { + require.Equal(choices.Accepted, block.Status()) + } + + size, err := database.Count(db) + require.NoError(err) + require.Zero(size) +} + +func generateBlockchain(length uint64) []snowman.Block { + if length == 0 { + return nil + } + + blocks := make([]snowman.Block, length) + blocks[0] = &snowman.TestBlock{ + TestDecidable: choices.TestDecidable{ + IDV: ids.GenerateTestID(), + StatusV: choices.Processing, + }, + ParentV: ids.Empty, + HeightV: 0, + BytesV: utils.RandomBytes(1024), + } + for height := uint64(1); height < length; height++ { + blocks[height] = &snowman.TestBlock{ + TestDecidable: choices.TestDecidable{ + IDV: ids.GenerateTestID(), + StatusV: choices.Processing, + }, + ParentV: blocks[height-1].ID(), + HeightV: height, + BytesV: utils.RandomBytes(1024), + } + } + return blocks +} + +type testParser func(context.Context, []byte) (snowman.Block, error) + +func (f testParser) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block, error) { + return f(ctx, bytes) +} + +func makeParser(blocks []snowman.Block) Parser { + return testParser(func(_ context.Context, b []byte) (snowman.Block, error) { + for _, block := range blocks { + if bytes.Equal(b, block.Bytes()) { + return block, nil + } + } + return nil, database.ErrNotFound + }) +} From a64b8639b63d8c4af51d1be964138d7c77e43633 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 19:56:41 -0400 Subject: [PATCH 20/85] wip --- chains/manager.go | 26 +-- snow/engine/snowman/bootstrap/block_job.go | 116 ----------- snow/engine/snowman/bootstrap/bootstrapper.go | 194 ++++++++---------- .../snowman/bootstrap/bootstrapper_test.go | 35 +--- snow/engine/snowman/bootstrap/config.go | 9 +- .../snowman/bootstrap/interval/blocks.go | 8 +- .../snowman/bootstrap/interval/blocks_test.go | 6 +- utils/logging/logger.go | 2 + 8 files changed, 117 insertions(+), 279 deletions(-) delete mode 100644 snow/engine/snowman/bootstrap/block_job.go diff --git a/chains/manager.go b/chains/manager.go index 6393f7ca58e8..c91a57e7cffc 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -82,10 +82,11 @@ var ( VMDBPrefix = []byte("vm") // Bootstrapping prefixes for LinearizableVMs - VertexDBPrefix = []byte("vertex") - VertexBootstrappingDBPrefix = []byte("vertex_bs") - TxBootstrappingDBPrefix = []byte("tx_bs") - BlockBootstrappingDBPrefix = []byte("block_bs") + VertexDBPrefix = []byte("vertex") + VertexBootstrappingDBPrefix = []byte("vertex_bs") + TxBootstrappingDBPrefix = []byte("tx_bs") + BlockBootstrappingDBPrefix = []byte("block_bs") + NewBlockBootstrappingDBPrefix = []byte("new_block_bs") // Bootstrapping prefixes for ChainVMs ChainBootstrappingDBPrefix = []byte("bs") @@ -569,7 +570,7 @@ func (m *manager) createAvalancheChain( vertexDB := prefixdb.New(VertexDBPrefix, prefixDB) vertexBootstrappingDB := prefixdb.New(VertexBootstrappingDBPrefix, prefixDB) txBootstrappingDB := prefixdb.New(TxBootstrappingDBPrefix, prefixDB) - blockBootstrappingDB := prefixdb.New(BlockBootstrappingDBPrefix, prefixDB) + newBlockBootstrappingDB := prefixdb.New(NewBlockBootstrappingDBPrefix, prefixDB) vtxBlocker, err := queue.NewWithMissing(vertexBootstrappingDB, "vtx", ctx.AvalancheRegisterer) if err != nil { @@ -579,10 +580,6 @@ func (m *manager) createAvalancheChain( if err != nil { return nil, err } - blockBlocker, err := queue.NewWithMissing(blockBootstrappingDB, "block", ctx.Registerer) - if err != nil { - return nil, err - } // Passes messages from the avalanche engines to the network avalancheMessageSender, err := sender.New( @@ -837,7 +834,7 @@ func (m *manager) createAvalancheChain( BootstrapTracker: sb, Timer: h, AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, - Blocked: blockBlocker, + DB: newBlockBootstrappingDB, VM: vmWrappingProposerVM, } var snowmanBootstrapper common.BootstrapableEngine @@ -950,12 +947,7 @@ func (m *manager) createSnowmanChain( } prefixDB := prefixdb.New(ctx.ChainID[:], meterDB) vmDB := prefixdb.New(VMDBPrefix, prefixDB) - bootstrappingDB := prefixdb.New(ChainBootstrappingDBPrefix, prefixDB) - - blocked, err := queue.NewWithMissing(bootstrappingDB, "block", ctx.Registerer) - if err != nil { - return nil, err - } + newBootstrappingDB := prefixdb.New(NewBlockBootstrappingDBPrefix, prefixDB) // Passes messages from the consensus engine to the network messageSender, err := sender.New( @@ -1175,7 +1167,7 @@ func (m *manager) createSnowmanChain( BootstrapTracker: sb, Timer: h, AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, - Blocked: blocked, + DB: newBootstrappingDB, VM: vm, Bootstrapped: bootstrapFunc, } diff --git a/snow/engine/snowman/bootstrap/block_job.go b/snow/engine/snowman/bootstrap/block_job.go deleted file mode 100644 index a9496316f1fb..000000000000 --- a/snow/engine/snowman/bootstrap/block_job.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package bootstrap - -import ( - "context" - "errors" - "fmt" - - "github.com/prometheus/client_golang/prometheus" - "go.uber.org/zap" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/choices" - "github.com/ava-labs/avalanchego/snow/consensus/snowman" - "github.com/ava-labs/avalanchego/snow/engine/common/queue" - "github.com/ava-labs/avalanchego/snow/engine/snowman/block" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/set" -) - -var errMissingDependenciesOnAccept = errors.New("attempting to accept a block with missing dependencies") - -type parser struct { - log logging.Logger - numAccepted, numDropped prometheus.Counter - vm block.ChainVM -} - -func (p *parser) Parse(ctx context.Context, blkBytes []byte) (queue.Job, error) { - blk, err := p.vm.ParseBlock(ctx, blkBytes) - if err != nil { - return nil, err - } - return &blockJob{ - log: p.log, - numAccepted: p.numAccepted, - numDropped: p.numDropped, - blk: blk, - vm: p.vm, - }, nil -} - -type blockJob struct { - log logging.Logger - numAccepted, numDropped prometheus.Counter - blk snowman.Block - vm block.Getter -} - -func (b *blockJob) ID() ids.ID { - return b.blk.ID() -} - -func (b *blockJob) MissingDependencies(ctx context.Context) (set.Set[ids.ID], error) { - missing := set.Set[ids.ID]{} - parentID := b.blk.Parent() - if parent, err := b.vm.GetBlock(ctx, parentID); err != nil || parent.Status() != choices.Accepted { - missing.Add(parentID) - } - return missing, nil -} - -func (b *blockJob) HasMissingDependencies(ctx context.Context) (bool, error) { - parentID := b.blk.Parent() - if parent, err := b.vm.GetBlock(ctx, parentID); err != nil || parent.Status() != choices.Accepted { - return true, nil - } - return false, nil -} - -func (b *blockJob) Execute(ctx context.Context) error { - hasMissingDeps, err := b.HasMissingDependencies(ctx) - if err != nil { - return err - } - if hasMissingDeps { - b.numDropped.Inc() - return errMissingDependenciesOnAccept - } - status := b.blk.Status() - switch status { - case choices.Unknown, choices.Rejected: - b.numDropped.Inc() - return fmt.Errorf("attempting to execute block with status %s", status) - case choices.Processing: - blkID := b.blk.ID() - if err := b.blk.Verify(ctx); err != nil { - b.log.Error("block failed verification during bootstrapping", - zap.Stringer("blkID", blkID), - zap.Error(err), - ) - return fmt.Errorf("failed to verify block in bootstrapping: %w", err) - } - - b.numAccepted.Inc() - b.log.Trace("accepting block in bootstrapping", - zap.Stringer("blkID", blkID), - zap.Uint64("height", b.blk.Height()), - zap.Time("timestamp", b.blk.Timestamp()), - ) - if err := b.blk.Accept(ctx); err != nil { - b.log.Debug("failed to accept block during bootstrapping", - zap.Stringer("blkID", blkID), - zap.Error(err), - ) - return fmt.Errorf("failed to accept block in bootstrapping: %w", err) - } - } - return nil -} - -func (b *blockJob) Bytes() []byte { - return b.blk.Bytes() -} diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 29754a24d734..ac452c72ed15 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -13,14 +13,15 @@ import ( "go.uber.org/zap" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/proto/pb/p2p" "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/consensus/snowman/bootstrapper" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer" @@ -95,13 +96,6 @@ type Bootstrapper struct { // tracks which validators were asked for which containers in which requests outstandingRequests *bimap.BiMap[common.Request, ids.ID] - // number of state transitions executed - executedStateTransitions int - - parser *parser - - awaitingTimeout bool - // fetchFrom is the set of nodes that we can fetch the next container from. // When a container is fetched, the nodeID is removed from [fetchFrom] to // attempt to limit a single request to a peer at any given time. When the @@ -111,6 +105,13 @@ type Bootstrapper struct { // again. fetchFrom set.Set[ids.NodeID] + // number of state transitions executed + executedStateTransitions uint64 + awaitingTimeout bool + + tree *interval.Tree + missingBlockIDs set.Set[ids.ID] + // bootstrappedOnce ensures that the [Bootstrapped] callback is only invoked // once, even if bootstrapping is retried. bootstrappedOnce sync.Once @@ -149,10 +150,11 @@ func (b *Bootstrapper) Clear(context.Context) error { b.Ctx.Lock.Lock() defer b.Ctx.Lock.Unlock() - if err := b.Config.Blocked.Clear(); err != nil { - return err - } - return b.Config.Blocked.Commit() + return database.AtomicClear(b.DB, b.DB) + // if err := b.Config.Blocked.Clear(); err != nil { + // return err + // } + // return b.Config.Blocked.Commit() } func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { @@ -163,18 +165,7 @@ func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { State: snow.Bootstrapping, }) if err := b.VM.SetState(ctx, snow.Bootstrapping); err != nil { - return fmt.Errorf("failed to notify VM that bootstrapping has started: %w", - err) - } - - b.parser = &parser{ - log: b.Ctx.Log, - numAccepted: b.numAccepted, - numDropped: b.numDropped, - vm: b.VM, - } - if err := b.Blocked.SetParser(ctx, b.parser); err != nil { - return err + return fmt.Errorf("failed to notify VM that bootstrapping has started: %w", err) } // Set the starting height @@ -189,6 +180,17 @@ func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { b.startingHeight = lastAccepted.Height() b.requestID = startReqID + tree, err := interval.NewTree(b.DB) + if err != nil { + return fmt.Errorf("failed to initialize interval tree: %w", err) + } + b.tree = tree + + b.missingBlockIDs, err = interval.GetMissingBlockIDs(ctx, b.DB, b.VM, tree, b.startingHeight) + if err != nil { + return fmt.Errorf("failed to initialize missing block IDs: %w", err) + } + return b.tryStartBootstrapping(ctx) } @@ -389,7 +391,7 @@ func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs [] // Initialize the fetch from set to the currently preferred peers b.fetchFrom = b.StartupTracker.PreferredPeers() - pendingContainerIDs := b.Blocked.MissingIDs() + pendingContainerIDs := b.missingBlockIDs.List() // Append the list of accepted container IDs to pendingContainerIDs to ensure // we iterate over every container that must be traversed. pendingContainerIDs = append(pendingContainerIDs, acceptedContainerIDs...) @@ -400,7 +402,7 @@ func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs [] toProcess := make([]snowman.Block, 0, len(pendingContainerIDs)) for _, blkID := range pendingContainerIDs { - b.Blocked.AddMissingID(blkID) + b.missingBlockIDs.Add(blkID) // TODO: if `GetBlock` returns an error other than // `database.ErrNotFound`, then the error should be propagated. @@ -414,7 +416,7 @@ func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs [] toProcess = append(toProcess, blk) } - b.initiallyFetched = b.Blocked.PendingJobs() + b.initiallyFetched = b.tree.Len() b.startTime = time.Now() // Process received blocks @@ -434,11 +436,6 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { return nil } - // Make sure we don't already have this block - if _, err := b.VM.GetBlock(ctx, blkID); err == nil { - return b.tryStartExecuting(ctx) - } - validatorID, ok := b.fetchFrom.Peek() if !ok { return fmt.Errorf("dropping request for %s as there are no validators", blkID) @@ -532,7 +529,11 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request for _, block := range blocks[1:] { blockSet[block.ID()] = block } - return b.process(ctx, requestedBlock, blockSet) + if err := b.process(ctx, requestedBlock, blockSet); err != nil { + return err + } + + return b.tryStartExecuting(ctx) } func (b *Bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { @@ -579,65 +580,38 @@ func (b *Bootstrapper) markUnavailable(nodeID ids.NodeID) { // If [blk]'s height is <= the last accepted height, then it will be removed // from the missingIDs set. func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processingBlocks map[ids.ID]snowman.Block) error { + lastAcceptedID, err := b.VM.LastAccepted(ctx) + if err != nil { + return fmt.Errorf("couldn't get last accepted ID: %w", err) + } + lastAccepted, err := b.VM.GetBlock(ctx, lastAcceptedID) + if err != nil { + return fmt.Errorf("couldn't get last accepted block: %w", err) + } + lastAcceptedHeight := lastAccepted.Height() + + batch := b.DB.NewBatch() for { - blkID := blk.ID() if b.Halted() { - // We must add in [blkID] to the set of missing IDs so that we are - // guaranteed to continue processing from this state when the - // bootstrapper is restarted. - b.Blocked.AddMissingID(blkID) - return b.Blocked.Commit() - } - - b.Blocked.RemoveMissingID(blkID) - - status := blk.Status() - // The status should never be rejected here - but we check to fail as - // quickly as possible - if status == choices.Rejected { - return fmt.Errorf("bootstrapping wants to accept %s, however it was previously rejected", blkID) + return batch.Write() } - blkHeight := blk.Height() - if status == choices.Accepted || blkHeight <= b.startingHeight { - // We can stop traversing, as we have reached the accepted frontier - if err := b.Blocked.Commit(); err != nil { - return err - } - return b.tryStartExecuting(ctx) - } + blkID := blk.ID() + b.missingBlockIDs.Remove(blkID) - // If this block is going to be accepted, make sure to update the - // tipHeight for logging - if blkHeight > b.tipHeight { - b.tipHeight = blkHeight - } + height := blk.Height() + b.tipHeight = max(b.tipHeight, height) - pushed, err := b.Blocked.Push(ctx, &blockJob{ - log: b.Ctx.Log, - numAccepted: b.numAccepted, - numDropped: b.numDropped, - blk: blk, - vm: b.VM, - }) + wantsParent, err := interval.Add(batch, b.tree, lastAcceptedHeight, blk) if err != nil { return err } - if !pushed { - // We can stop traversing, as we have reached a block that we - // previously pushed onto the jobs queue - if err := b.Blocked.Commit(); err != nil { - return err - } - return b.tryStartExecuting(ctx) - } - // We added a new block to the queue, so track that it was fetched b.numFetched.Inc() // Periodically log progress - blocksFetchedSoFar := b.Blocked.Jobs.PendingJobs() + blocksFetchedSoFar := b.tree.Len() if blocksFetchedSoFar%statusUpdateFrequency == 0 { totalBlocksToFetch := b.tipHeight - b.startingHeight eta := timer.EstimateETA( @@ -662,8 +636,13 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin } } + if !wantsParent { + return batch.Write() + } + // Attempt to traverse to the next block parentID := blk.Parent() + b.missingBlockIDs.Add(parentID) // First check if the parent is in the processing blocks set parent, ok := processingBlocks[parentID] @@ -683,15 +662,11 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin // If the block wasn't able to be acquired immediately, attempt to fetch // it - b.Blocked.AddMissingID(parentID) if err := b.fetch(ctx, parentID); err != nil { return err } - if err := b.Blocked.Commit(); err != nil { - return err - } - return b.tryStartExecuting(ctx) + return batch.Write() } } @@ -699,7 +674,7 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin // being fetched. After executing all pending blocks it will either restart // bootstrapping, or transition into normal operations. func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { - if numPending := b.Blocked.NumMissingIDs(); numPending != 0 { + if numPending := b.missingBlockIDs.Len(); numPending != 0 { return nil } @@ -707,34 +682,45 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { return nil } - if !b.restarted { - b.Ctx.Log.Info("executing blocks", - zap.Uint64("numPendingJobs", b.Blocked.PendingJobs()), - ) - } else { - b.Ctx.Log.Debug("executing blocks", - zap.Uint64("numPendingJobs", b.Blocked.PendingJobs()), - ) + lastAcceptedID, err := b.VM.LastAccepted(ctx) + if err != nil { + return fmt.Errorf("couldn't get last accepted ID: %w", err) } + lastAccepted, err := b.VM.GetBlock(ctx, lastAcceptedID) + if err != nil { + return fmt.Errorf("couldn't get last accepted block: %w", err) + } + lastAcceptedHeight := lastAccepted.Height() - executedBlocks, err := b.Blocked.ExecuteAll( - ctx, - b.Config.Ctx, - b, - b.restarted, - b.Ctx.BlockAcceptor, - ) + // TODO: Remove after testing + { + expectedMissingIDs, err := interval.GetMissingBlockIDs(ctx, b.DB, b.VM, b.tree, lastAcceptedHeight) + if err != nil { + return err + } + if expectedMissingIDs.Len() > 0 { + return fmt.Errorf("unexpectedly had missing IDs: %d", expectedMissingIDs.Len()) + } + } + + log := b.Ctx.Log.Info + if b.restarted { + log = b.Ctx.Log.Debug + } + + numToExecute := b.tree.Len() + err = interval.Execute(ctx, log, b.DB, b.VM, b.tree, lastAcceptedHeight) if err != nil || b.Halted() { return err } previouslyExecuted := b.executedStateTransitions - b.executedStateTransitions = executedBlocks + b.executedStateTransitions = numToExecute // Note that executedBlocks < c*previouslyExecuted ( 0 <= c < 1 ) is enforced // so that the bootstrapping process will terminate even as new blocks are // being issued. - if executedBlocks > 0 && executedBlocks < previouslyExecuted/2 { + if numToExecute > 0 && numToExecute < previouslyExecuted/2 { return b.restartBootstrapping(ctx) } @@ -750,11 +736,7 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { // If the subnet hasn't finished bootstrapping, this chain should remain // syncing. if !b.Config.BootstrapTracker.IsBootstrapped() { - if !b.restarted { - b.Ctx.Log.Info("waiting for the remaining chains in this subnet to finish syncing") - } else { - b.Ctx.Log.Debug("waiting for the remaining chains in this subnet to finish syncing") - } + log("waiting for the remaining chains in this subnet to finish syncing") // Restart bootstrapping after [bootstrappingDelay] to keep up to date // on the latest tip. b.Config.Timer.RegisterTimeout(bootstrappingDelay) diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index d5cb9cc763fc..f146309b8e32 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -10,7 +10,6 @@ import ( "testing" "time" - "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/database" @@ -21,14 +20,13 @@ import ( "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" - "github.com/ava-labs/avalanchego/snow/engine/common/queue" "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" "github.com/ava-labs/avalanchego/snow/engine/snowman/getter" "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/version" ) @@ -79,7 +77,6 @@ func newConfig(t *testing.T) (Config, ids.NodeID, *common.SenderTest, *block.Tes snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) require.NoError(err) - blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) return Config{ AllGetsServer: snowGetHandler, Ctx: ctx, @@ -90,7 +87,7 @@ func newConfig(t *testing.T) (Config, ids.NodeID, *common.SenderTest, *block.Tes BootstrapTracker: bootstrapTracker, Timer: &common.TimerTest{}, AncestorsMaxContainersReceived: 2000, - Blocked: blocker, + DB: memdb.New(), VM: vm, }, peer, sender, vm } @@ -117,7 +114,6 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { startupTracker := tracker.NewStartup(peerTracker, startupAlpha) peers.RegisterCallbackListener(ctx.SubnetID, startupTracker) - blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) require.NoError(err) cfg := Config{ @@ -130,7 +126,7 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { BootstrapTracker: &common.BootstrapTrackerTest{}, Timer: &common.TimerTest{}, AncestorsMaxContainersReceived: 2000, - Blocked: blocker, + DB: memdb.New(), VM: vm, } @@ -1310,7 +1306,7 @@ func TestBootstrapContinueAfterHalt(t *testing.T) { require.NoError(bs.startSyncing(context.Background(), []ids.ID{blk2.ID()})) - require.Equal(1, bs.Blocked.NumMissingIDs()) + require.Equal(1, bs.missingBlockIDs.Len()) } func TestBootstrapNoParseOnNew(t *testing.T) { @@ -1355,10 +1351,6 @@ func TestBootstrapNoParseOnNew(t *testing.T) { snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) require.NoError(err) - queueDB := memdb.New() - blocker, err := queue.NewWithMissing(queueDB, "", prometheus.NewRegistry()) - require.NoError(err) - blk0 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: ids.GenerateTestID(), @@ -1383,23 +1375,14 @@ func TestBootstrapNoParseOnNew(t *testing.T) { return blk0, nil } - pushed, err := blocker.Push(context.Background(), &blockJob{ - log: logging.NoLog{}, - numAccepted: prometheus.NewCounter(prometheus.CounterOpts{}), - numDropped: prometheus.NewCounter(prometheus.CounterOpts{}), - blk: blk1, - vm: vm, - }) + intervalDB := memdb.New() + tree, err := interval.NewTree(intervalDB) + require.NoError(err) + _, err = interval.Add(intervalDB, tree, 0, blk1) require.NoError(err) - require.True(pushed) - - require.NoError(blocker.Commit()) vm.GetBlockF = nil - blocker, err = queue.NewWithMissing(queueDB, "", prometheus.NewRegistry()) - require.NoError(err) - config := Config{ AllGetsServer: snowGetHandler, Ctx: ctx, @@ -1410,7 +1393,7 @@ func TestBootstrapNoParseOnNew(t *testing.T) { BootstrapTracker: bootstrapTracker, Timer: &common.TimerTest{}, AncestorsMaxContainersReceived: 2000, - Blocked: blocker, + DB: intervalDB, VM: vm, } diff --git a/snow/engine/snowman/bootstrap/config.go b/snow/engine/snowman/bootstrap/config.go index 6fb8894db96f..9cb951e378b1 100644 --- a/snow/engine/snowman/bootstrap/config.go +++ b/snow/engine/snowman/bootstrap/config.go @@ -4,9 +4,9 @@ package bootstrap import ( + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" - "github.com/ava-labs/avalanchego/snow/engine/common/queue" "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" @@ -28,12 +28,7 @@ type Config struct { // containers in an ancestors message it receives. AncestorsMaxContainersReceived int - // Blocked tracks operations that are blocked on blocks - // - // It should be guaranteed that `MissingIDs` should contain all IDs - // referenced by the `MissingDependencies` that have not already been added - // to the queue. - Blocked *queue.JobsWithMissing + DB database.Database VM block.ChainVM diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 613814868bfa..5c8c20818a1e 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -91,7 +91,7 @@ func Add( // Invariant: Execute assumes that GetMissingBlockIDs would return an empty set. func Execute( ctx context.Context, - log logging.Logger, + log logging.Func, db database.Database, parser Parser, tree *Tree, @@ -124,7 +124,7 @@ func Execute( iterator.Release() }() - log.Info("executing blocks", + log("executing blocks", zap.Uint64("numToExecute", totalNumberToProcess), ) @@ -177,7 +177,7 @@ func Execute( eta = timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) ) - log.Info("executing blocks", + log("executing blocks", zap.Duration("eta", eta), zap.Uint64("numExecuted", numProcessed), zap.Uint64("numToExecute", totalNumberToProcess), @@ -207,7 +207,7 @@ func Execute( numProcessed = totalNumberToProcess - tree.Len() err = ctx.Err() ) - log.Info("executed blocks", + log("executed blocks", zap.Uint64("numExecuted", numProcessed), zap.Uint64("numToExecute", totalNumberToProcess), zap.Duration("duration", time.Since(startTime)), diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go index 48b269d9b1fc..6b27801d13be 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks_test.go +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -291,7 +291,7 @@ func TestExecute(t *testing.T) { err = Execute( context.Background(), - logging.NoLog{}, + logging.NoLog{}.Info, db, parser, tree, @@ -338,7 +338,7 @@ func TestExecuteExitsWhenCancelled(t *testing.T) { cancel() err = Execute( ctx, - logging.NoLog{}, + logging.NoLog{}.Info, db, parser, tree, @@ -383,7 +383,7 @@ func TestExecuteSkipsAcceptedBlocks(t *testing.T) { err = Execute( context.Background(), - logging.NoLog{}, + logging.NoLog{}.Info, db, parser, tree, diff --git a/utils/logging/logger.go b/utils/logging/logger.go index 2ca95bff104c..57ddedf42796 100644 --- a/utils/logging/logger.go +++ b/utils/logging/logger.go @@ -9,6 +9,8 @@ import ( "go.uber.org/zap" ) +type Func func(msg string, fields ...zap.Field) + // Logger defines the interface that is used to keep a record of all events that // happen to the program type Logger interface { From 782a02c11c14f3b9208b766a59d383581ac189c2 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 20:24:11 -0400 Subject: [PATCH 21/85] wip --- chains/manager.go | 17 ++++++++++++++--- .../snowman/bootstrap/bootstrapper_test.go | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index c91a57e7cffc..c5d64da71d54 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -85,11 +85,12 @@ var ( VertexDBPrefix = []byte("vertex") VertexBootstrappingDBPrefix = []byte("vertex_bs") TxBootstrappingDBPrefix = []byte("tx_bs") - BlockBootstrappingDBPrefix = []byte("block_bs") + OldBlockBootstrappingDBPrefix = []byte("block_bs") NewBlockBootstrappingDBPrefix = []byte("new_block_bs") // Bootstrapping prefixes for ChainVMs - ChainBootstrappingDBPrefix = []byte("bs") + OldChainBootstrappingDBPrefix = []byte("bs") + NewChainBootstrappingDBPrefix = []byte("new_bs") errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM") errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM") @@ -570,6 +571,11 @@ func (m *manager) createAvalancheChain( vertexDB := prefixdb.New(VertexDBPrefix, prefixDB) vertexBootstrappingDB := prefixdb.New(VertexBootstrappingDBPrefix, prefixDB) txBootstrappingDB := prefixdb.New(TxBootstrappingDBPrefix, prefixDB) + + oldBlockBootstrappingDB := prefixdb.New(OldBlockBootstrappingDBPrefix, prefixDB) + if err := database.AtomicClear(oldBlockBootstrappingDB, oldBlockBootstrappingDB); err != nil { + return nil, fmt.Errorf("failed to clear legacy bootstrapping database: %w", err) + } newBlockBootstrappingDB := prefixdb.New(NewBlockBootstrappingDBPrefix, prefixDB) vtxBlocker, err := queue.NewWithMissing(vertexBootstrappingDB, "vtx", ctx.AvalancheRegisterer) @@ -947,7 +953,12 @@ func (m *manager) createSnowmanChain( } prefixDB := prefixdb.New(ctx.ChainID[:], meterDB) vmDB := prefixdb.New(VMDBPrefix, prefixDB) - newBootstrappingDB := prefixdb.New(NewBlockBootstrappingDBPrefix, prefixDB) + + oldBootstrappingDB := prefixdb.New(OldChainBootstrappingDBPrefix, prefixDB) + if err := database.AtomicClear(oldBootstrappingDB, oldBootstrappingDB); err != nil { + return nil, fmt.Errorf("failed to clear legacy bootstrapping database: %w", err) + } + newBootstrappingDB := prefixdb.New(NewChainBootstrappingDBPrefix, prefixDB) // Passes messages from the consensus engine to the network messageSender, err := sender.New( diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index f146309b8e32..d8dca8f69122 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -270,7 +270,7 @@ func TestBootstrapperSingleFrontier(t *testing.T) { } require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) - require.Equal(snow.NormalOp, config.Ctx.State.Get().State) + require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk1.Status()) } From 5358587306d08830203b90b472ea67c02b62470b Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 21:34:48 -0400 Subject: [PATCH 22/85] support cancellation --- snow/engine/snowman/bootstrap/bootstrapper.go | 17 +++++++++-- snow/engine/snowman/bootstrap/context.go | 29 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 snow/engine/snowman/bootstrap/context.go diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index ac452c72ed15..60c14f1cee89 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -709,8 +709,21 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { } numToExecute := b.tree.Len() - err = interval.Execute(ctx, log, b.DB, b.VM, b.tree, lastAcceptedHeight) - if err != nil || b.Halted() { + err = interval.Execute( + &haltableContext{ + Context: ctx, + Haltable: b, + }, + log, + b.DB, + b.VM, + b.tree, + lastAcceptedHeight, + ) + if errors.Is(err, errHalted) { + return nil + } + if err != nil { return err } diff --git a/snow/engine/snowman/bootstrap/context.go b/snow/engine/snowman/bootstrap/context.go new file mode 100644 index 000000000000..e87cadc9bcfb --- /dev/null +++ b/snow/engine/snowman/bootstrap/context.go @@ -0,0 +1,29 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package bootstrap + +import ( + "context" + "errors" + + "github.com/ava-labs/avalanchego/snow/engine/common" +) + +var ( + _ context.Context = (*haltableContext)(nil) + + errHalted = errors.New("halted") +) + +type haltableContext struct { + context.Context + common.Haltable +} + +func (c *haltableContext) Err() error { + if c.Halted() { + return context.Canceled + } + return c.Context.Err() +} From 9d24b20abd9ec2c0f16edeae0334afe2a442de0c Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 21:40:24 -0400 Subject: [PATCH 23/85] save --- snow/engine/snowman/bootstrap/context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snow/engine/snowman/bootstrap/context.go b/snow/engine/snowman/bootstrap/context.go index e87cadc9bcfb..3aa14bef5e98 100644 --- a/snow/engine/snowman/bootstrap/context.go +++ b/snow/engine/snowman/bootstrap/context.go @@ -23,7 +23,7 @@ type haltableContext struct { func (c *haltableContext) Err() error { if c.Halted() { - return context.Canceled + return errHalted } return c.Context.Err() } From 0de614228456f31866cb70bf38f8ac3fa9a85710 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 21:47:49 -0400 Subject: [PATCH 24/85] remove test code --- snow/engine/snowman/bootstrap/bootstrapper.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 60c14f1cee89..dea64ba4d880 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -692,17 +692,6 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { } lastAcceptedHeight := lastAccepted.Height() - // TODO: Remove after testing - { - expectedMissingIDs, err := interval.GetMissingBlockIDs(ctx, b.DB, b.VM, b.tree, lastAcceptedHeight) - if err != nil { - return err - } - if expectedMissingIDs.Len() > 0 { - return fmt.Errorf("unexpectedly had missing IDs: %d", expectedMissingIDs.Len()) - } - } - log := b.Ctx.Log.Info if b.restarted { log = b.Ctx.Log.Debug From e658404ff87ca5ab8a1d6d6d9724818f1bf0a243 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 22:09:35 -0400 Subject: [PATCH 25/85] keep acceptor callback --- snow/engine/snowman/bootstrap/acceptor.go | 46 +++++++++++++++++++ snow/engine/snowman/bootstrap/bootstrapper.go | 5 +- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 snow/engine/snowman/bootstrap/acceptor.go diff --git a/snow/engine/snowman/bootstrap/acceptor.go b/snow/engine/snowman/bootstrap/acceptor.go new file mode 100644 index 000000000000..30e75ad2c6a3 --- /dev/null +++ b/snow/engine/snowman/bootstrap/acceptor.go @@ -0,0 +1,46 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package bootstrap + +import ( + "context" + + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" +) + +var ( + _ interval.Parser = (*parseAcceptor)(nil) + _ snowman.Block = (*blockAcceptor)(nil) +) + +type parseAcceptor struct { + parser interval.Parser + ctx *snow.ConsensusContext +} + +func (p *parseAcceptor) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block, error) { + blk, err := p.parser.ParseBlock(ctx, bytes) + if err != nil { + return nil, err + } + return &blockAcceptor{ + Block: blk, + ctx: p.ctx, + }, nil +} + +type blockAcceptor struct { + snowman.Block + + ctx *snow.ConsensusContext +} + +func (b *blockAcceptor) Accept(ctx context.Context) error { + if err := b.ctx.BlockAcceptor.Accept(b.ctx, b.ID(), b.Bytes()); err != nil { + return err + } + return b.Block.Accept(ctx) +} diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index dea64ba4d880..2e02134f8943 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -705,7 +705,10 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { }, log, b.DB, - b.VM, + &parseAcceptor{ + parser: b.VM, + ctx: b.Ctx, + }, b.tree, lastAcceptedHeight, ) From 03f60c6418027bec6b6cdbd5c3d18afdb84b1796 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 22:18:07 -0400 Subject: [PATCH 26/85] lint --- snow/engine/snowman/bootstrap/interval/blocks_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go index 48b269d9b1fc..1673fffb1ae8 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks_test.go +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -289,15 +289,14 @@ func TestExecute(t *testing.T) { require.Equal(uint64(i+1), tree.Len()) } - err = Execute( + require.NoError(Execute( context.Background(), logging.NoLog{}, db, parser, tree, lastAcceptedHeight, - ) - require.NoError(err) + )) for _, block := range blocks[lastAcceptedHeight+1:] { require.Equal(choices.Accepted, block.Status()) @@ -381,15 +380,14 @@ func TestExecuteSkipsAcceptedBlocks(t *testing.T) { require.Equal(uint64(i+1), tree.Len()) } - err = Execute( + require.NoError(Execute( context.Background(), logging.NoLog{}, db, parser, tree, lastAcceptedHeightWhenExecuting, - ) - require.NoError(err) + )) for _, block := range blocks[lastAcceptedHeightWhenAdding+1 : lastAcceptedHeightWhenExecuting] { require.Equal(choices.Processing, block.Status()) From f81281a9cd5c8325d98c509b135ec22ba203abf8 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 22:31:43 -0400 Subject: [PATCH 27/85] fix test --- vms/platformvm/vm_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index fdeb4a316047..2a54db8b55e4 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -24,7 +24,6 @@ import ( "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowball" "github.com/ava-labs/avalanchego/snow/engine/common" - "github.com/ava-labs/avalanchego/snow/engine/common/queue" "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap" "github.com/ava-labs/avalanchego/snow/networking/benchlist" @@ -1253,9 +1252,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { baseDB := memdb.New() vmDB := prefixdb.New(chains.VMDBPrefix, baseDB) - bootstrappingDB := prefixdb.New(chains.ChainBootstrappingDBPrefix, baseDB) - blocked, err := queue.NewWithMissing(bootstrappingDB, "", prometheus.NewRegistry()) - require.NoError(err) + bootstrappingDB := prefixdb.New(chains.NewChainBootstrappingDBPrefix, baseDB) vm := &VM{Config: config.Config{ Chains: chains.TestManager, @@ -1431,7 +1428,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { Sender: sender, BootstrapTracker: bootstrapTracker, AncestorsMaxContainersReceived: 2000, - Blocked: blocked, + DB: bootstrappingDB, VM: vm, } From 984849c81d5c83c43e26760c2ba808b91790c744 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 22:37:23 -0400 Subject: [PATCH 28/85] remove incorrect db cleanup --- chains/manager.go | 30 +++++++++--------------------- vms/platformvm/vm_test.go | 2 +- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index c5d64da71d54..c62519c757c9 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -82,15 +82,13 @@ var ( VMDBPrefix = []byte("vm") // Bootstrapping prefixes for LinearizableVMs - VertexDBPrefix = []byte("vertex") - VertexBootstrappingDBPrefix = []byte("vertex_bs") - TxBootstrappingDBPrefix = []byte("tx_bs") - OldBlockBootstrappingDBPrefix = []byte("block_bs") - NewBlockBootstrappingDBPrefix = []byte("new_block_bs") + VertexDBPrefix = []byte("vertex") + VertexBootstrappingDBPrefix = []byte("vertex_bs") + TxBootstrappingDBPrefix = []byte("tx_bs") + BlockBootstrappingDBPrefix = []byte("interval_block_bs") // Bootstrapping prefixes for ChainVMs - OldChainBootstrappingDBPrefix = []byte("bs") - NewChainBootstrappingDBPrefix = []byte("new_bs") + ChainBootstrappingDBPrefix = []byte("interval_bs") errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM") errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM") @@ -571,12 +569,7 @@ func (m *manager) createAvalancheChain( vertexDB := prefixdb.New(VertexDBPrefix, prefixDB) vertexBootstrappingDB := prefixdb.New(VertexBootstrappingDBPrefix, prefixDB) txBootstrappingDB := prefixdb.New(TxBootstrappingDBPrefix, prefixDB) - - oldBlockBootstrappingDB := prefixdb.New(OldBlockBootstrappingDBPrefix, prefixDB) - if err := database.AtomicClear(oldBlockBootstrappingDB, oldBlockBootstrappingDB); err != nil { - return nil, fmt.Errorf("failed to clear legacy bootstrapping database: %w", err) - } - newBlockBootstrappingDB := prefixdb.New(NewBlockBootstrappingDBPrefix, prefixDB) + blockBootstrappingDB := prefixdb.New(BlockBootstrappingDBPrefix, prefixDB) vtxBlocker, err := queue.NewWithMissing(vertexBootstrappingDB, "vtx", ctx.AvalancheRegisterer) if err != nil { @@ -840,7 +833,7 @@ func (m *manager) createAvalancheChain( BootstrapTracker: sb, Timer: h, AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, - DB: newBlockBootstrappingDB, + DB: blockBootstrappingDB, VM: vmWrappingProposerVM, } var snowmanBootstrapper common.BootstrapableEngine @@ -953,12 +946,7 @@ func (m *manager) createSnowmanChain( } prefixDB := prefixdb.New(ctx.ChainID[:], meterDB) vmDB := prefixdb.New(VMDBPrefix, prefixDB) - - oldBootstrappingDB := prefixdb.New(OldChainBootstrappingDBPrefix, prefixDB) - if err := database.AtomicClear(oldBootstrappingDB, oldBootstrappingDB); err != nil { - return nil, fmt.Errorf("failed to clear legacy bootstrapping database: %w", err) - } - newBootstrappingDB := prefixdb.New(NewChainBootstrappingDBPrefix, prefixDB) + bootstrappingDB := prefixdb.New(ChainBootstrappingDBPrefix, prefixDB) // Passes messages from the consensus engine to the network messageSender, err := sender.New( @@ -1178,7 +1166,7 @@ func (m *manager) createSnowmanChain( BootstrapTracker: sb, Timer: h, AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, - DB: newBootstrappingDB, + DB: bootstrappingDB, VM: vm, Bootstrapped: bootstrapFunc, } diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 2a54db8b55e4..f6df4db96036 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -1252,7 +1252,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { baseDB := memdb.New() vmDB := prefixdb.New(chains.VMDBPrefix, baseDB) - bootstrappingDB := prefixdb.New(chains.NewChainBootstrappingDBPrefix, baseDB) + bootstrappingDB := prefixdb.New(chains.ChainBootstrappingDBPrefix, baseDB) vm := &VM{Config: config.Config{ Chains: chains.TestManager, From f4a724af613c618c4cb873017420cbfb5ccf8927 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 23:23:02 -0400 Subject: [PATCH 29/85] nits --- snow/engine/snowman/bootstrap/bootstrapper.go | 4 ---- snow/engine/snowman/bootstrap/config.go | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 2e02134f8943..90c613106ef8 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -151,10 +151,6 @@ func (b *Bootstrapper) Clear(context.Context) error { defer b.Ctx.Lock.Unlock() return database.AtomicClear(b.DB, b.DB) - // if err := b.Config.Blocked.Clear(); err != nil { - // return err - // } - // return b.Config.Blocked.Commit() } func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { diff --git a/snow/engine/snowman/bootstrap/config.go b/snow/engine/snowman/bootstrap/config.go index 9cb951e378b1..5ddef07970d3 100644 --- a/snow/engine/snowman/bootstrap/config.go +++ b/snow/engine/snowman/bootstrap/config.go @@ -28,6 +28,8 @@ type Config struct { // containers in an ancestors message it receives. AncestorsMaxContainersReceived int + // Database used to track the fetched, but not yet executed, blocks during + // bootstrapping. DB database.Database VM block.ChainVM From f01b6a38222319e414997fff4556269bba526600 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 23:26:06 -0400 Subject: [PATCH 30/85] allow specifying the log level --- snow/engine/snowman/bootstrap/interval/blocks.go | 8 ++++---- snow/engine/snowman/bootstrap/interval/blocks_test.go | 6 +++--- utils/logging/logger.go | 4 ++++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 613814868bfa..5c8c20818a1e 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -91,7 +91,7 @@ func Add( // Invariant: Execute assumes that GetMissingBlockIDs would return an empty set. func Execute( ctx context.Context, - log logging.Logger, + log logging.Func, db database.Database, parser Parser, tree *Tree, @@ -124,7 +124,7 @@ func Execute( iterator.Release() }() - log.Info("executing blocks", + log("executing blocks", zap.Uint64("numToExecute", totalNumberToProcess), ) @@ -177,7 +177,7 @@ func Execute( eta = timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) ) - log.Info("executing blocks", + log("executing blocks", zap.Duration("eta", eta), zap.Uint64("numExecuted", numProcessed), zap.Uint64("numToExecute", totalNumberToProcess), @@ -207,7 +207,7 @@ func Execute( numProcessed = totalNumberToProcess - tree.Len() err = ctx.Err() ) - log.Info("executed blocks", + log("executed blocks", zap.Uint64("numExecuted", numProcessed), zap.Uint64("numToExecute", totalNumberToProcess), zap.Duration("duration", time.Since(startTime)), diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go index 1673fffb1ae8..4bfc8b0da64f 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks_test.go +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -291,7 +291,7 @@ func TestExecute(t *testing.T) { require.NoError(Execute( context.Background(), - logging.NoLog{}, + logging.NoLog{}.Info, db, parser, tree, @@ -337,7 +337,7 @@ func TestExecuteExitsWhenCancelled(t *testing.T) { cancel() err = Execute( ctx, - logging.NoLog{}, + logging.NoLog{}.Info, db, parser, tree, @@ -382,7 +382,7 @@ func TestExecuteSkipsAcceptedBlocks(t *testing.T) { require.NoError(Execute( context.Background(), - logging.NoLog{}, + logging.NoLog{}.Info, db, parser, tree, diff --git a/utils/logging/logger.go b/utils/logging/logger.go index 2ca95bff104c..f6b3b66a77b8 100644 --- a/utils/logging/logger.go +++ b/utils/logging/logger.go @@ -9,6 +9,10 @@ import ( "go.uber.org/zap" ) +// Func defines the method signature used for all logging methods on the Logger +// interface. +type Func func(msg string, fields ...zap.Field) + // Logger defines the interface that is used to keep a record of all events that // happen to the program type Logger interface { From 0021f3edc06e93b56b69910ab1aaa0f09864a729 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 23:55:03 -0400 Subject: [PATCH 31/85] cleanup metrics --- snow/engine/snowman/bootstrap/acceptor.go | 15 ++++++++++----- snow/engine/snowman/bootstrap/bootstrapper.go | 5 +++-- snow/engine/snowman/bootstrap/metrics.go | 10 ++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/snow/engine/snowman/bootstrap/acceptor.go b/snow/engine/snowman/bootstrap/acceptor.go index 30e75ad2c6a3..4c2affe3f96c 100644 --- a/snow/engine/snowman/bootstrap/acceptor.go +++ b/snow/engine/snowman/bootstrap/acceptor.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" + "github.com/prometheus/client_golang/prometheus" ) var ( @@ -17,8 +18,9 @@ var ( ) type parseAcceptor struct { - parser interval.Parser - ctx *snow.ConsensusContext + parser interval.Parser + ctx *snow.ConsensusContext + numAccepted prometheus.Counter } func (p *parseAcceptor) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block, error) { @@ -27,18 +29,21 @@ func (p *parseAcceptor) ParseBlock(ctx context.Context, bytes []byte) (snowman.B return nil, err } return &blockAcceptor{ - Block: blk, - ctx: p.ctx, + Block: blk, + ctx: p.ctx, + numAccepted: p.numAccepted, }, nil } type blockAcceptor struct { snowman.Block - ctx *snow.ConsensusContext + ctx *snow.ConsensusContext + numAccepted prometheus.Counter } func (b *blockAcceptor) Accept(ctx context.Context) error { + b.numAccepted.Inc() if err := b.ctx.BlockAcceptor.Accept(b.ctx, b.ID(), b.Bytes()); err != nil { return err } diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 90c613106ef8..137887b3744c 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -702,8 +702,9 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { log, b.DB, &parseAcceptor{ - parser: b.VM, - ctx: b.Ctx, + parser: b.VM, + ctx: b.Ctx, + numAccepted: b.numAccepted, }, b.tree, lastAcceptedHeight, diff --git a/snow/engine/snowman/bootstrap/metrics.go b/snow/engine/snowman/bootstrap/metrics.go index f6ad90d16419..aea46d2a93e8 100644 --- a/snow/engine/snowman/bootstrap/metrics.go +++ b/snow/engine/snowman/bootstrap/metrics.go @@ -10,8 +10,8 @@ import ( ) type metrics struct { - numFetched, numDropped, numAccepted prometheus.Counter - fetchETA prometheus.Gauge + numFetched, numAccepted prometheus.Counter + fetchETA prometheus.Gauge } func newMetrics(namespace string, registerer prometheus.Registerer) (*metrics, error) { @@ -21,11 +21,6 @@ func newMetrics(namespace string, registerer prometheus.Registerer) (*metrics, e Name: "fetched", Help: "Number of blocks fetched during bootstrapping", }), - numDropped: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: namespace, - Name: "dropped", - Help: "Number of blocks dropped during bootstrapping", - }), numAccepted: prometheus.NewCounter(prometheus.CounterOpts{ Namespace: namespace, Name: "accepted", @@ -40,7 +35,6 @@ func newMetrics(namespace string, registerer prometheus.Registerer) (*metrics, e err := utils.Err( registerer.Register(m.numFetched), - registerer.Register(m.numDropped), registerer.Register(m.numAccepted), registerer.Register(m.fetchETA), ) From f1933d6593cf012a0ea3026a3924bbd088bb1ea9 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 00:06:59 -0400 Subject: [PATCH 32/85] lint --- snow/engine/snowman/bootstrap/acceptor.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/snow/engine/snowman/bootstrap/acceptor.go b/snow/engine/snowman/bootstrap/acceptor.go index 4c2affe3f96c..9ca718f3ab52 100644 --- a/snow/engine/snowman/bootstrap/acceptor.go +++ b/snow/engine/snowman/bootstrap/acceptor.go @@ -6,10 +6,11 @@ package bootstrap import ( "context" + "github.com/prometheus/client_golang/prometheus" + "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" - "github.com/prometheus/client_golang/prometheus" ) var ( From dd4a57fc8b8b06117ffc5ec737e8b9673f9d468c Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 00:41:08 -0400 Subject: [PATCH 33/85] add error information --- snow/engine/snowman/bootstrap/interval/blocks.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 5c8c20818a1e..4a7e11a1226b 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -5,6 +5,7 @@ package interval import ( "context" + "fmt" "time" "go.uber.org/zap" @@ -190,10 +191,18 @@ func Execute( } if err := blk.Verify(ctx); err != nil { - return err + return fmt.Errorf("failed to verify block %s (%d) in bootstrapping: %w", + blk.ID(), + height, + err, + ) } if err := blk.Accept(ctx); err != nil { - return err + return fmt.Errorf("failed to accept block %s (%d) in bootstrapping: %w", + blk.ID(), + height, + err, + ) } } if err := writeBatch(); err != nil { From d5da1e935b85d3836c25220ca841097ad4eea2ff Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 02:25:33 -0400 Subject: [PATCH 34/85] upstream --- snow/engine/snowman/bootstrap/interval/blocks.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 5c8c20818a1e..4a7e11a1226b 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -5,6 +5,7 @@ package interval import ( "context" + "fmt" "time" "go.uber.org/zap" @@ -190,10 +191,18 @@ func Execute( } if err := blk.Verify(ctx); err != nil { - return err + return fmt.Errorf("failed to verify block %s (%d) in bootstrapping: %w", + blk.ID(), + height, + err, + ) } if err := blk.Accept(ctx); err != nil { - return err + return fmt.Errorf("failed to accept block %s (%d) in bootstrapping: %w", + blk.ID(), + height, + err, + ) } } if err := writeBatch(); err != nil { From 25e28011015d29f6e15b13753acc460e01782fe9 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 13:50:44 -0400 Subject: [PATCH 35/85] cleanup --- .../snowman/bootstrap/interval/blocks.go | 15 ++++- .../snowman/bootstrap/interval/state.go | 56 +++++++++---------- .../engine/snowman/bootstrap/interval/tree.go | 24 +++++++- 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 4a7e11a1226b..1adc6153da53 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -19,7 +19,7 @@ import ( ) const ( - batchWritePeriod = 1 + batchWritePeriod = 64 iteratorReleasePeriod = 1024 logPeriod = 5 * time.Second ) @@ -28,6 +28,13 @@ type Parser interface { ParseBlock(context.Context, []byte) (snowman.Block, error) } +// GetMissingBlockIDs returns the ID of the blocks that should be fetched to +// attempt to make a single continuous range from +// (lastAcceptedHeight, highestTrackedHeight]. +// +// For example, if the tree currently contains heights [1, 4, 6, 7] and the +// lastAcceptedHeight is 2, this function will return the IDs corresponding to +// blocks [3, 5]. func GetMissingBlockIDs( ctx context.Context, db database.KeyValueReader, @@ -89,7 +96,11 @@ func Add( return height != lastHeightToFetch && !tree.Contains(height-1), nil } -// Invariant: Execute assumes that GetMissingBlockIDs would return an empty set. +// Execute all the blocks tracked by the tree. If a block is in the tree but is +// already accepted based on the lastAcceptedHeight, it will be removed from the +// tree but not executed. +// +// Execute assumes that GetMissingBlockIDs would return an empty set. func Execute( ctx context.Context, log logging.Func, diff --git a/snow/engine/snowman/bootstrap/interval/state.go b/snow/engine/snowman/bootstrap/interval/state.go index 320d5c97105f..31bb5540c387 100644 --- a/snow/engine/snowman/bootstrap/interval/state.go +++ b/snow/engine/snowman/bootstrap/interval/state.go @@ -10,21 +10,21 @@ import ( ) const ( - rangePrefixByte byte = iota + intervalPrefixByte byte = iota blockPrefixByte prefixLen = 1 ) var ( - rangePrefix = []byte{rangePrefixByte} - blockPrefix = []byte{blockPrefixByte} + intervalPrefix = []byte{intervalPrefixByte} + blockPrefix = []byte{blockPrefixByte} errInvalidKeyLength = errors.New("invalid key length") ) func GetIntervals(db database.Iteratee) ([]*Interval, error) { - it := db.NewIteratorWithPrefix(rangePrefix) + it := db.NewIteratorWithPrefix(intervalPrefix) defer it.Release() var intervals []*Interval @@ -34,8 +34,8 @@ func GetIntervals(db database.Iteratee) ([]*Interval, error) { return nil, errInvalidKeyLength } - rangeKey := dbKey[prefixLen:] - upperBound, err := database.ParseUInt64(rangeKey) + intervalKey := dbKey[prefixLen:] + upperBound, err := database.ParseUInt64(intervalKey) if err != nil { return nil, err } @@ -55,39 +55,39 @@ func GetIntervals(db database.Iteratee) ([]*Interval, error) { } func PutInterval(db database.KeyValueWriter, upperBound uint64, lowerBound uint64) error { - rangeKey := database.PackUInt64(upperBound) - return database.PutUInt64( - db, - append(rangePrefix, rangeKey...), - lowerBound, - ) + return database.PutUInt64(db, makeIntervalKey(upperBound), lowerBound) } func DeleteInterval(db database.KeyValueDeleter, upperBound uint64) error { - rangeKey := database.PackUInt64(upperBound) - return db.Delete( - append(rangePrefix, rangeKey...), - ) + return db.Delete(makeIntervalKey(upperBound)) +} + +// makeIntervalKey uses the upperBound rather than the lowerBound because blocks +// are fetched from tip towards genesis. This means that it is more common for +// the lowerBound to change than the upperBound. Modifying the lowerBound only +// requires a single write rather than a write and a delete when modifying the +// upperBound. +func makeIntervalKey(upperBound uint64) []byte { + intervalKey := database.PackUInt64(upperBound) + return append(intervalPrefix, intervalKey...) } func GetBlock(db database.KeyValueReader, height uint64) ([]byte, error) { - blockKey := database.PackUInt64(height) - return db.Get( - append(blockPrefix, blockKey...), - ) + return db.Get(makeBlockKey(height)) } func PutBlock(db database.KeyValueWriter, height uint64, bytes []byte) error { - blockKey := database.PackUInt64(height) - return db.Put( - append(blockPrefix, blockKey...), - bytes, - ) + return db.Put(makeBlockKey(height), bytes) } func DeleteBlock(db database.KeyValueDeleter, height uint64) error { + return db.Delete(makeBlockKey(height)) +} + +// makeBlockKey ensures that the returned key maintains the same sorted order as +// the height. This ensures that database iteration of block keys will iterate +// from lower height to higher height. +func makeBlockKey(height uint64) []byte { blockKey := database.PackUInt64(height) - return db.Delete( - append(blockPrefix, blockKey...), - ) + return append(blockPrefix, blockKey...) } diff --git a/snow/engine/snowman/bootstrap/interval/tree.go b/snow/engine/snowman/bootstrap/interval/tree.go index a4f07102f04a..51d1083c1e21 100644 --- a/snow/engine/snowman/bootstrap/interval/tree.go +++ b/snow/engine/snowman/bootstrap/interval/tree.go @@ -9,13 +9,31 @@ import ( "github.com/ava-labs/avalanchego/database" ) +// TODO: Benchmark what degree to use. const treeDegree = 2 +// Tree implements a set of numbers by tracking intervals. It supports adding +// and removing new values. It also allows checking if a value is included in +// the set. +// +// Tree is more space efficient than a map implementation if the values that it +// contains are continuous. The tree takes O(n) space where n is the number of +// continuous ranges that have been inserted into the tree. +// +// Add, Remove, and Contains all run in O(log n) where n is the number of +// continuous ranges that have been inserted into the tree. type Tree struct { - knownHeights *btree.BTreeG[*Interval] + knownHeights *btree.BTreeG[*Interval] + // If knownHeights contains the full range [0, MaxUint64], then + // numKnownHeights overflows to 0. numKnownHeights uint64 } +// NewTree creates a new interval tree from the provided database. +// +// It is assumed that persisted intervals are non-overlapping. Providing a +// database with overlapping intervals will result in undefined behavior of the +// structure. func NewTree(db database.Iteratee) (*Tree, error) { intervals, err := GetIntervals(db) if err != nil { @@ -161,6 +179,10 @@ func (t *Tree) Flatten() []*Interval { } // Len returns the number of heights in the tree; not the number of intervals. +// +// Because Len returns a uint64 and is describing the number of values in the +// range of uint64s, it will return 0 if the tree contains the full interval +// [0, MaxUint64]. func (t *Tree) Len() uint64 { return t.numKnownHeights } From 5ca206b043d810447cf14b112a54413e59958ab7 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 14:00:39 -0400 Subject: [PATCH 36/85] reduce copied code --- snow/engine/snowman/bootstrap/bootstrapper.go | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 137887b3744c..8f4ec62aaff6 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -165,15 +165,11 @@ func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { } // Set the starting height - lastAcceptedID, err := b.VM.LastAccepted(ctx) - if err != nil { - return fmt.Errorf("couldn't get last accepted ID: %w", err) - } - lastAccepted, err := b.VM.GetBlock(ctx, lastAcceptedID) + lastAcceptedHeight, err := b.getLastAcceptedHeight(ctx) if err != nil { - return fmt.Errorf("couldn't get last accepted block: %w", err) + return err } - b.startingHeight = lastAccepted.Height() + b.startingHeight = lastAcceptedHeight b.requestID = startReqID tree, err := interval.NewTree(b.DB) @@ -576,15 +572,10 @@ func (b *Bootstrapper) markUnavailable(nodeID ids.NodeID) { // If [blk]'s height is <= the last accepted height, then it will be removed // from the missingIDs set. func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processingBlocks map[ids.ID]snowman.Block) error { - lastAcceptedID, err := b.VM.LastAccepted(ctx) + lastAcceptedHeight, err := b.getLastAcceptedHeight(ctx) if err != nil { - return fmt.Errorf("couldn't get last accepted ID: %w", err) - } - lastAccepted, err := b.VM.GetBlock(ctx, lastAcceptedID) - if err != nil { - return fmt.Errorf("couldn't get last accepted block: %w", err) + return err } - lastAcceptedHeight := lastAccepted.Height() batch := b.DB.NewBatch() for { @@ -678,15 +669,10 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { return nil } - lastAcceptedID, err := b.VM.LastAccepted(ctx) + lastAcceptedHeight, err := b.getLastAcceptedHeight(ctx) if err != nil { - return fmt.Errorf("couldn't get last accepted ID: %w", err) - } - lastAccepted, err := b.VM.GetBlock(ctx, lastAcceptedID) - if err != nil { - return fmt.Errorf("couldn't get last accepted block: %w", err) + return err } - lastAcceptedHeight := lastAccepted.Height() log := b.Ctx.Log.Info if b.restarted { @@ -749,6 +735,18 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { return b.onFinished(ctx, b.requestID) } +func (b *Bootstrapper) getLastAcceptedHeight(ctx context.Context) (uint64, error) { + lastAcceptedID, err := b.VM.LastAccepted(ctx) + if err != nil { + return 0, fmt.Errorf("couldn't get last accepted ID: %w", err) + } + lastAccepted, err := b.VM.GetBlock(ctx, lastAcceptedID) + if err != nil { + return 0, fmt.Errorf("couldn't get last accepted block: %w", err) + } + return lastAccepted.Height(), nil +} + func (b *Bootstrapper) Timeout(ctx context.Context) error { if !b.awaitingTimeout { return errUnexpectedTimeout From d9a7f8aa91aec8a4124c5a5d66c866468dc420d7 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 14:07:45 -0400 Subject: [PATCH 37/85] nit cleanup --- snow/engine/snowman/bootstrap/bootstrapper.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 8f4ec62aaff6..fa9c759d86a0 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -383,19 +383,15 @@ func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs [] // Initialize the fetch from set to the currently preferred peers b.fetchFrom = b.StartupTracker.PreferredPeers() - pendingContainerIDs := b.missingBlockIDs.List() - // Append the list of accepted container IDs to pendingContainerIDs to ensure - // we iterate over every container that must be traversed. - pendingContainerIDs = append(pendingContainerIDs, acceptedContainerIDs...) + b.missingBlockIDs.Add(acceptedContainerIDs...) + numMissingBlockIDs := b.missingBlockIDs.Len() b.Ctx.Log.Debug("starting bootstrapping", - zap.Int("numPendingBlocks", len(pendingContainerIDs)), + zap.Int("numMissingBlocks", numMissingBlockIDs), zap.Int("numAcceptedBlocks", len(acceptedContainerIDs)), ) - toProcess := make([]snowman.Block, 0, len(pendingContainerIDs)) - for _, blkID := range pendingContainerIDs { - b.missingBlockIDs.Add(blkID) - + toProcess := make([]snowman.Block, 0, numMissingBlockIDs) + for blkID := range b.missingBlockIDs { // TODO: if `GetBlock` returns an error other than // `database.ErrNotFound`, then the error should be propagated. blk, err := b.VM.GetBlock(ctx, blkID) From bd2b2d2d6ef64f6504666b2c45cb713827ca7ab8 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 14:12:42 -0400 Subject: [PATCH 38/85] nit cleanup --- snow/engine/snowman/bootstrap/bootstrapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index fa9c759d86a0..28d23b6e983e 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -657,7 +657,7 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin // being fetched. After executing all pending blocks it will either restart // bootstrapping, or transition into normal operations. func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { - if numPending := b.missingBlockIDs.Len(); numPending != 0 { + if numMissingBlockIDs := b.missingBlockIDs.Len(); numMissingBlockIDs != 0 { return nil } From f05e3241a60f6ae09548e3db9f1afe52481d00fa Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Mar 2024 19:04:22 -0400 Subject: [PATCH 39/85] nit --- snow/engine/snowman/bootstrap/bootstrapper.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index a1a8733182e7..1e72a4beb019 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -380,17 +380,17 @@ func (b *Bootstrapper) GetAcceptedFailed(ctx context.Context, nodeID ids.NodeID, return b.sendBootstrappingMessagesOrFinish(ctx) } -func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs []ids.ID) error { +func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedBlockIDs []ids.ID) error { // Initialize the fetch from set to the currently preferred peers b.fetchFrom = b.StartupTracker.PreferredPeers() - knownContainerIDs := genesis.GetCheckpoints(b.Ctx.NetworkID, b.Ctx.ChainID) - b.missingBlockIDs.Union(knownContainerIDs) - b.missingBlockIDs.Add(acceptedContainerIDs...) + knownBlockIDs := genesis.GetCheckpoints(b.Ctx.NetworkID, b.Ctx.ChainID) + b.missingBlockIDs.Union(knownBlockIDs) + b.missingBlockIDs.Add(acceptedBlockIDs...) numMissingBlockIDs := b.missingBlockIDs.Len() b.Ctx.Log.Debug("starting bootstrapping", - zap.Int("numKnownBlocks", knownContainerIDs.Len()), - zap.Int("numAcceptedBlocks", len(acceptedContainerIDs)), + zap.Int("numKnownBlocks", knownBlockIDs.Len()), + zap.Int("numAcceptedBlocks", len(acceptedBlockIDs)), zap.Int("numMissingBlocks", numMissingBlockIDs), ) From 175ab8e7d123659626a31b524f5ef853305d3cd4 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Thu, 21 Mar 2024 16:08:13 -0400 Subject: [PATCH 40/85] nit --- snow/engine/snowman/bootstrap/bootstrapper.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index a9ab472a1cc7..c4151a2d5aa8 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -172,13 +172,12 @@ func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { b.startingHeight = lastAcceptedHeight b.requestID = startReqID - tree, err := interval.NewTree(b.DB) + b.tree, err = interval.NewTree(b.DB) if err != nil { return fmt.Errorf("failed to initialize interval tree: %w", err) } - b.tree = tree - b.missingBlockIDs, err = interval.GetMissingBlockIDs(ctx, b.DB, b.VM, tree, b.startingHeight) + b.missingBlockIDs, err = interval.GetMissingBlockIDs(ctx, b.DB, b.VM, b.tree, b.startingHeight) if err != nil { return fmt.Errorf("failed to initialize missing block IDs: %w", err) } From c89d24d0a03046ed850f15a183cdae808ba9675d Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Thu, 21 Mar 2024 16:37:57 -0400 Subject: [PATCH 41/85] Remove redundent interface --- snow/engine/snowman/bootstrap/interval/blocks.go | 9 +++------ snow/engine/snowman/bootstrap/interval/blocks_test.go | 3 ++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 1adc6153da53..b825735a1b35 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer" @@ -24,10 +25,6 @@ const ( logPeriod = 5 * time.Second ) -type Parser interface { - ParseBlock(context.Context, []byte) (snowman.Block, error) -} - // GetMissingBlockIDs returns the ID of the blocks that should be fetched to // attempt to make a single continuous range from // (lastAcceptedHeight, highestTrackedHeight]. @@ -38,7 +35,7 @@ type Parser interface { func GetMissingBlockIDs( ctx context.Context, db database.KeyValueReader, - parser Parser, + parser block.Parser, tree *Tree, lastAcceptedHeight uint64, ) (set.Set[ids.ID], error) { @@ -105,7 +102,7 @@ func Execute( ctx context.Context, log logging.Func, db database.Database, - parser Parser, + parser block.Parser, tree *Tree, lastAcceptedHeight uint64, ) error { diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go index 4bfc8b0da64f..03492698ecea 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks_test.go +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" @@ -436,7 +437,7 @@ func (f testParser) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block return f(ctx, bytes) } -func makeParser(blocks []snowman.Block) Parser { +func makeParser(blocks []snowman.Block) block.Parser { return testParser(func(_ context.Context, b []byte) (snowman.Block, error) { for _, block := range blocks { if bytes.Equal(b, block.Bytes()) { From a736e6c6eeb146d2d2e9c03d768ef3f76ee1aba9 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Thu, 21 Mar 2024 17:45:06 -0400 Subject: [PATCH 42/85] nit --- snow/engine/snowman/bootstrap/acceptor.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/snow/engine/snowman/bootstrap/acceptor.go b/snow/engine/snowman/bootstrap/acceptor.go index 9ca718f3ab52..81db1decf388 100644 --- a/snow/engine/snowman/bootstrap/acceptor.go +++ b/snow/engine/snowman/bootstrap/acceptor.go @@ -10,16 +10,16 @@ import ( "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/consensus/snowman" - "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" ) var ( - _ interval.Parser = (*parseAcceptor)(nil) - _ snowman.Block = (*blockAcceptor)(nil) + _ block.Parser = (*parseAcceptor)(nil) + _ snowman.Block = (*blockAcceptor)(nil) ) type parseAcceptor struct { - parser interval.Parser + parser block.Parser ctx *snow.ConsensusContext numAccepted prometheus.Counter } From faa5329557b7cec54f1b0ead0ca7ff345a3d39aa Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Thu, 21 Mar 2024 17:45:34 -0400 Subject: [PATCH 43/85] nit --- snow/engine/snowman/bootstrap/acceptor.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/snow/engine/snowman/bootstrap/acceptor.go b/snow/engine/snowman/bootstrap/acceptor.go index 81db1decf388..eae4be879afa 100644 --- a/snow/engine/snowman/bootstrap/acceptor.go +++ b/snow/engine/snowman/bootstrap/acceptor.go @@ -44,9 +44,10 @@ type blockAcceptor struct { } func (b *blockAcceptor) Accept(ctx context.Context) error { - b.numAccepted.Inc() if err := b.ctx.BlockAcceptor.Accept(b.ctx, b.ID(), b.Bytes()); err != nil { return err } - return b.Block.Accept(ctx) + err := b.Block.Accept(ctx) + b.numAccepted.Inc() + return err } From bc3fedfa992dba7f3f092bd0bbdfd4c7f8838620 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 25 Mar 2024 15:04:03 -0400 Subject: [PATCH 44/85] nit --- snow/engine/snowman/bootstrap/interval/blocks.go | 4 ++-- snow/engine/snowman/bootstrap/interval/state.go | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index b825735a1b35..8124f96e5cac 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -122,7 +122,7 @@ func Execute( return nil } - iterator = db.NewIteratorWithPrefix(blockPrefix) + iterator = GetBlockIterator(db) processedSinceIteratorRelease uint startTime = time.Now() @@ -176,7 +176,7 @@ func Execute( processedSinceIteratorRelease = 0 iterator.Release() - iterator = db.NewIteratorWithPrefix(blockPrefix) + iterator = GetBlockIterator(db) } now := time.Now() diff --git a/snow/engine/snowman/bootstrap/interval/state.go b/snow/engine/snowman/bootstrap/interval/state.go index 31bb5540c387..cf2e2bf3a2ef 100644 --- a/snow/engine/snowman/bootstrap/interval/state.go +++ b/snow/engine/snowman/bootstrap/interval/state.go @@ -72,6 +72,12 @@ func makeIntervalKey(upperBound uint64) []byte { return append(intervalPrefix, intervalKey...) } +// GetBlockIterator returns a block iterator that will produce values +// corresponding to persisted blocks in order of increasing height. +func GetBlockIterator(db database.Iteratee) database.Iterator { + return db.NewIteratorWithPrefix(blockPrefix) +} + func GetBlock(db database.KeyValueReader, height uint64) ([]byte, error) { return db.Get(makeBlockKey(height)) } From 8134e16af0e10253e073ad318a5d9ed843a1d90c Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 25 Mar 2024 15:04:54 -0400 Subject: [PATCH 45/85] nit --- .../snowman/bootstrap/interval/blocks.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 8124f96e5cac..85f5d7994027 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -93,6 +93,18 @@ func Add( return height != lastHeightToFetch && !tree.Contains(height-1), nil } +// Remove the block from the tree. +func Remove( + db database.KeyValueWriterDeleter, + tree *Tree, + height uint64, +) error { + if err := DeleteBlock(db, height); err != nil { + return err + } + return tree.Remove(db, height) +} + // Execute all the blocks tracked by the tree. If a block is in the tree but is // already accepted based on the lastAcceptedHeight, it will be removed from the // tree but not executed. @@ -145,11 +157,7 @@ func Execute( } height := blk.Height() - if err := DeleteBlock(batch, height); err != nil { - return err - } - - if err := tree.Remove(batch, height); err != nil { + if err := Remove(batch, tree, height); err != nil { return err } From 9991e39e8f8129888251348021f6337677ca1b8c Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 25 Mar 2024 15:25:18 -0400 Subject: [PATCH 46/85] Move GetMissingBlockIDs and Execute out of the interval package --- .../snowman/bootstrap/interval/blocks.go | 193 ---------- .../snowman/bootstrap/interval/blocks_test.go | 291 ++------------- snow/engine/snowman/bootstrap/storage.go | 202 +++++++++++ snow/engine/snowman/bootstrap/storage_test.go | 338 ++++++++++++++++++ 4 files changed, 561 insertions(+), 463 deletions(-) create mode 100644 snow/engine/snowman/bootstrap/storage.go create mode 100644 snow/engine/snowman/bootstrap/storage_test.go diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 85f5d7994027..5a00e96bafca 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -4,67 +4,10 @@ package interval import ( - "context" - "fmt" - "time" - - "go.uber.org/zap" - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/consensus/snowman" - "github.com/ava-labs/avalanchego/snow/engine/snowman/block" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/timer" -) - -const ( - batchWritePeriod = 64 - iteratorReleasePeriod = 1024 - logPeriod = 5 * time.Second ) -// GetMissingBlockIDs returns the ID of the blocks that should be fetched to -// attempt to make a single continuous range from -// (lastAcceptedHeight, highestTrackedHeight]. -// -// For example, if the tree currently contains heights [1, 4, 6, 7] and the -// lastAcceptedHeight is 2, this function will return the IDs corresponding to -// blocks [3, 5]. -func GetMissingBlockIDs( - ctx context.Context, - db database.KeyValueReader, - parser block.Parser, - tree *Tree, - lastAcceptedHeight uint64, -) (set.Set[ids.ID], error) { - var ( - missingBlocks set.Set[ids.ID] - intervals = tree.Flatten() - lastHeightToFetch = lastAcceptedHeight + 1 - ) - for _, i := range intervals { - if i.LowerBound <= lastHeightToFetch { - continue - } - - blkBytes, err := GetBlock(db, i.LowerBound) - if err != nil { - return nil, err - } - - blk, err := parser.ParseBlock(ctx, blkBytes) - if err != nil { - return nil, err - } - - parentID := blk.Parent() - missingBlocks.Add(parentID) - } - return missingBlocks, nil -} - // Add the block to the tree and return if the parent block should be fetched, // but wasn't desired before. func Add( @@ -104,139 +47,3 @@ func Remove( } return tree.Remove(db, height) } - -// Execute all the blocks tracked by the tree. If a block is in the tree but is -// already accepted based on the lastAcceptedHeight, it will be removed from the -// tree but not executed. -// -// Execute assumes that GetMissingBlockIDs would return an empty set. -func Execute( - ctx context.Context, - log logging.Func, - db database.Database, - parser block.Parser, - tree *Tree, - lastAcceptedHeight uint64, -) error { - var ( - batch = db.NewBatch() - processedSinceBatchWrite uint - writeBatch = func() error { - if processedSinceBatchWrite == 0 { - return nil - } - processedSinceBatchWrite = 0 - - if err := batch.Write(); err != nil { - return err - } - batch.Reset() - return nil - } - - iterator = GetBlockIterator(db) - processedSinceIteratorRelease uint - - startTime = time.Now() - timeOfNextLog = startTime.Add(logPeriod) - totalNumberToProcess = tree.Len() - ) - defer func() { - iterator.Release() - }() - - log("executing blocks", - zap.Uint64("numToExecute", totalNumberToProcess), - ) - - for ctx.Err() == nil && iterator.Next() { - blkBytes := iterator.Value() - blk, err := parser.ParseBlock(ctx, blkBytes) - if err != nil { - return err - } - - height := blk.Height() - if err := Remove(batch, tree, height); err != nil { - return err - } - - // Periodically write the batch to disk to avoid memory pressure. - processedSinceBatchWrite++ - if processedSinceBatchWrite >= batchWritePeriod { - if err := writeBatch(); err != nil { - return err - } - } - - // Periodically release and re-grab the database iterator to avoid - // keeping a reference to an old database revision. - processedSinceIteratorRelease++ - if processedSinceIteratorRelease >= iteratorReleasePeriod { - if err := iterator.Error(); err != nil { - return err - } - - // The batch must be written here to avoid re-processing a block. - if err := writeBatch(); err != nil { - return err - } - - processedSinceIteratorRelease = 0 - iterator.Release() - iterator = GetBlockIterator(db) - } - - now := time.Now() - if now.After(timeOfNextLog) { - var ( - numProcessed = totalNumberToProcess - tree.Len() - eta = timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) - ) - - log("executing blocks", - zap.Duration("eta", eta), - zap.Uint64("numExecuted", numProcessed), - zap.Uint64("numToExecute", totalNumberToProcess), - ) - timeOfNextLog = now.Add(logPeriod) - } - - if height <= lastAcceptedHeight { - continue - } - - if err := blk.Verify(ctx); err != nil { - return fmt.Errorf("failed to verify block %s (%d) in bootstrapping: %w", - blk.ID(), - height, - err, - ) - } - if err := blk.Accept(ctx); err != nil { - return fmt.Errorf("failed to accept block %s (%d) in bootstrapping: %w", - blk.ID(), - height, - err, - ) - } - } - if err := writeBatch(); err != nil { - return err - } - if err := iterator.Error(); err != nil { - return err - } - - var ( - numProcessed = totalNumberToProcess - tree.Len() - err = ctx.Err() - ) - log("executed blocks", - zap.Uint64("numExecuted", numProcessed), - zap.Uint64("numToExecute", totalNumberToProcess), - zap.Duration("duration", time.Since(startTime)), - zap.Error(err), - ) - return err -} diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go index 03492698ecea..9741b29aff48 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks_test.go +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -4,8 +4,6 @@ package interval import ( - "bytes" - "context" "testing" "github.com/stretchr/testify/require" @@ -15,145 +13,9 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" - "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/set" ) -func TestGetMissingBlockIDs(t *testing.T) { - blocks := generateBlockchain(7) - parser := makeParser(blocks) - - db := memdb.New() - tree, err := NewTree(db) - require.NoError(t, err) - lastAcceptedHeight := uint64(1) - - t.Run("initially empty", func(t *testing.T) { - require := require.New(t) - - missing, err := GetMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Empty(missing) - }) - - t.Run("adding first block", func(t *testing.T) { - require := require.New(t) - - _, err := Add( - db, - tree, - lastAcceptedHeight, - blocks[5], - ) - require.NoError(err) - - missing, err := GetMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[4].ID(), - ), - missing, - ) - }) - - t.Run("adding second block", func(t *testing.T) { - require := require.New(t) - - _, err := Add( - db, - tree, - lastAcceptedHeight, - blocks[3], - ) - require.NoError(err) - - missing, err := GetMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[2].ID(), - blocks[4].ID(), - ), - missing, - ) - }) - - t.Run("adding last desired block", func(t *testing.T) { - require := require.New(t) - - _, err := Add( - db, - tree, - lastAcceptedHeight, - blocks[2], - ) - require.NoError(err) - - missing, err := GetMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[4].ID(), - ), - missing, - ) - }) - - t.Run("adding block with known parent", func(t *testing.T) { - require := require.New(t) - - _, err := Add( - db, - tree, - lastAcceptedHeight, - blocks[6], - ) - require.NoError(err) - - missing, err := GetMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[4].ID(), - ), - missing, - ) - }) -} - func TestAdd(t *testing.T) { blocks := generateBlockchain(7) @@ -266,140 +128,46 @@ func TestAdd(t *testing.T) { }) } -func TestExecute(t *testing.T) { - require := require.New(t) - - const numBlocks = 2*max(batchWritePeriod, iteratorReleasePeriod) + 1 - blocks := generateBlockchain(numBlocks) - parser := makeParser(blocks) - - db := memdb.New() - tree, err := NewTree(db) - require.NoError(err) - const lastAcceptedHeight = 1 - - for i, block := range blocks[lastAcceptedHeight+1:] { - newlyWantsParent, err := Add( - db, - tree, - lastAcceptedHeight, - block, - ) - require.NoError(err) - require.False(newlyWantsParent) - require.Equal(uint64(i+1), tree.Len()) - } - - require.NoError(Execute( - context.Background(), - logging.NoLog{}.Info, - db, - parser, - tree, - lastAcceptedHeight, - )) - - for _, block := range blocks[lastAcceptedHeight+1:] { - require.Equal(choices.Accepted, block.Status()) - } - - size, err := database.Count(db) - require.NoError(err) - require.Zero(size) -} - -func TestExecuteExitsWhenCancelled(t *testing.T) { - require := require.New(t) - +func TestRemove(t *testing.T) { blocks := generateBlockchain(7) - parser := makeParser(blocks) db := memdb.New() tree, err := NewTree(db) - require.NoError(err) - const lastAcceptedHeight = 1 + require.NoError(t, err) + lastAcceptedHeight := uint64(1) + + t.Run("adding a block", func(t *testing.T) { + require := require.New(t) - for i, block := range blocks[lastAcceptedHeight+1:] { newlyWantsParent, err := Add( db, tree, lastAcceptedHeight, - block, + blocks[5], ) require.NoError(err) - require.False(newlyWantsParent) - require.Equal(uint64(i+1), tree.Len()) - } - - startSize, err := database.Count(db) - require.NoError(err) - - ctx, cancel := context.WithCancel(context.Background()) - cancel() - err = Execute( - ctx, - logging.NoLog{}.Info, - db, - parser, - tree, - lastAcceptedHeight, - ) - require.ErrorIs(err, context.Canceled) - - for _, block := range blocks[lastAcceptedHeight+1:] { - require.Equal(choices.Processing, block.Status()) - } - - endSize, err := database.Count(db) - require.NoError(err) - require.Equal(startSize, endSize) -} - -func TestExecuteSkipsAcceptedBlocks(t *testing.T) { - require := require.New(t) + require.True(newlyWantsParent) + require.Equal(uint64(1), tree.Len()) - blocks := generateBlockchain(7) - parser := makeParser(blocks) + bytes, err := GetBlock(db, blocks[5].Height()) + require.NoError(err) + require.Equal(blocks[5].Bytes(), bytes) + }) - db := memdb.New() - tree, err := NewTree(db) - require.NoError(err) - const ( - lastAcceptedHeightWhenAdding = 1 - lastAcceptedHeightWhenExecuting = 3 - ) + t.Run("removing a block", func(t *testing.T) { + require := require.New(t) - for i, block := range blocks[lastAcceptedHeightWhenAdding+1:] { - newlyWantsParent, err := Add( + err := Remove( db, tree, - lastAcceptedHeightWhenAdding, - block, + blocks[5].Height(), ) require.NoError(err) - require.False(newlyWantsParent) - require.Equal(uint64(i+1), tree.Len()) - } - - require.NoError(Execute( - context.Background(), - logging.NoLog{}.Info, - db, - parser, - tree, - lastAcceptedHeightWhenExecuting, - )) - - for _, block := range blocks[lastAcceptedHeightWhenAdding+1 : lastAcceptedHeightWhenExecuting] { - require.Equal(choices.Processing, block.Status()) - } - for _, block := range blocks[lastAcceptedHeightWhenExecuting+1:] { - require.Equal(choices.Accepted, block.Status()) - } + require.Zero(tree.Len()) - size, err := database.Count(db) - require.NoError(err) - require.Zero(size) + _, err = GetBlock(db, blocks[5].Height()) + require.ErrorIs(err, database.ErrNotFound) + }) } func generateBlockchain(length uint64) []snowman.Block { @@ -430,20 +198,3 @@ func generateBlockchain(length uint64) []snowman.Block { } return blocks } - -type testParser func(context.Context, []byte) (snowman.Block, error) - -func (f testParser) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block, error) { - return f(ctx, bytes) -} - -func makeParser(blocks []snowman.Block) block.Parser { - return testParser(func(_ context.Context, b []byte) (snowman.Block, error) { - for _, block := range blocks { - if bytes.Equal(b, block.Bytes()) { - return block, nil - } - } - return nil, database.ErrNotFound - }) -} diff --git a/snow/engine/snowman/bootstrap/storage.go b/snow/engine/snowman/bootstrap/storage.go new file mode 100644 index 000000000000..47317abb1aff --- /dev/null +++ b/snow/engine/snowman/bootstrap/storage.go @@ -0,0 +1,202 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package bootstrap + +import ( + "context" + "fmt" + "time" + + "go.uber.org/zap" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/timer" +) + +const ( + batchWritePeriod = 64 + iteratorReleasePeriod = 1024 + logPeriod = 5 * time.Second +) + +// getMissingBlockIDs returns the ID of the blocks that should be fetched to +// attempt to make a single continuous range from +// (lastAcceptedHeight, highestTrackedHeight]. +// +// For example, if the tree currently contains heights [1, 4, 6, 7] and the +// lastAcceptedHeight is 2, this function will return the IDs corresponding to +// blocks [3, 5]. +func getMissingBlockIDs( + ctx context.Context, + db database.KeyValueReader, + parser block.Parser, + tree *interval.Tree, + lastAcceptedHeight uint64, +) (set.Set[ids.ID], error) { + var ( + missingBlocks set.Set[ids.ID] + intervals = tree.Flatten() + lastHeightToFetch = lastAcceptedHeight + 1 + ) + for _, i := range intervals { + if i.LowerBound <= lastHeightToFetch { + continue + } + + blkBytes, err := interval.GetBlock(db, i.LowerBound) + if err != nil { + return nil, err + } + + blk, err := parser.ParseBlock(ctx, blkBytes) + if err != nil { + return nil, err + } + + parentID := blk.Parent() + missingBlocks.Add(parentID) + } + return missingBlocks, nil +} + +// execute all the blocks tracked by the tree. If a block is in the tree but is +// already accepted based on the lastAcceptedHeight, it will be removed from the +// tree but not executed. +// +// execute assumes that getMissingBlockIDs would return an empty set. +func execute( + ctx context.Context, + log logging.Func, + db database.Database, + parser block.Parser, + tree *interval.Tree, + lastAcceptedHeight uint64, +) error { + var ( + batch = db.NewBatch() + processedSinceBatchWrite uint + writeBatch = func() error { + if processedSinceBatchWrite == 0 { + return nil + } + processedSinceBatchWrite = 0 + + if err := batch.Write(); err != nil { + return err + } + batch.Reset() + return nil + } + + iterator = interval.GetBlockIterator(db) + processedSinceIteratorRelease uint + + startTime = time.Now() + timeOfNextLog = startTime.Add(logPeriod) + totalNumberToProcess = tree.Len() + ) + defer func() { + iterator.Release() + }() + + log("executing blocks", + zap.Uint64("numToExecute", totalNumberToProcess), + ) + + for ctx.Err() == nil && iterator.Next() { + blkBytes := iterator.Value() + blk, err := parser.ParseBlock(ctx, blkBytes) + if err != nil { + return err + } + + height := blk.Height() + if err := interval.Remove(batch, tree, height); err != nil { + return err + } + + // Periodically write the batch to disk to avoid memory pressure. + processedSinceBatchWrite++ + if processedSinceBatchWrite >= batchWritePeriod { + if err := writeBatch(); err != nil { + return err + } + } + + // Periodically release and re-grab the database iterator to avoid + // keeping a reference to an old database revision. + processedSinceIteratorRelease++ + if processedSinceIteratorRelease >= iteratorReleasePeriod { + if err := iterator.Error(); err != nil { + return err + } + + // The batch must be written here to avoid re-processing a block. + if err := writeBatch(); err != nil { + return err + } + + processedSinceIteratorRelease = 0 + iterator.Release() + iterator = interval.GetBlockIterator(db) + } + + now := time.Now() + if now.After(timeOfNextLog) { + var ( + numProcessed = totalNumberToProcess - tree.Len() + eta = timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) + ) + + log("executing blocks", + zap.Duration("eta", eta), + zap.Uint64("numExecuted", numProcessed), + zap.Uint64("numToExecute", totalNumberToProcess), + ) + timeOfNextLog = now.Add(logPeriod) + } + + if height <= lastAcceptedHeight { + continue + } + + if err := blk.Verify(ctx); err != nil { + return fmt.Errorf("failed to verify block %s (%d) in bootstrapping: %w", + blk.ID(), + height, + err, + ) + } + if err := blk.Accept(ctx); err != nil { + return fmt.Errorf("failed to accept block %s (%d) in bootstrapping: %w", + blk.ID(), + height, + err, + ) + } + } + if err := writeBatch(); err != nil { + return err + } + if err := iterator.Error(); err != nil { + return err + } + + var ( + numProcessed = totalNumberToProcess - tree.Len() + err = ctx.Err() + ) + log("executed blocks", + zap.Uint64("numExecuted", numProcessed), + zap.Uint64("numToExecute", totalNumberToProcess), + zap.Duration("duration", time.Since(startTime)), + zap.Error(err), + ) + return err +} diff --git a/snow/engine/snowman/bootstrap/storage_test.go b/snow/engine/snowman/bootstrap/storage_test.go new file mode 100644 index 000000000000..0dbb0eb3ed88 --- /dev/null +++ b/snow/engine/snowman/bootstrap/storage_test.go @@ -0,0 +1,338 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package bootstrap + +import ( + "bytes" + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/database/memdb" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/choices" + "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" +) + +func TestGetMissingBlockIDs(t *testing.T) { + blocks := generateBlockchain(7) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := interval.NewTree(db) + require.NoError(t, err) + lastAcceptedHeight := uint64(1) + + t.Run("initially empty", func(t *testing.T) { + require := require.New(t) + + missing, err := getMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Empty(missing) + }) + + t.Run("adding first block", func(t *testing.T) { + require := require.New(t) + + _, err := interval.Add( + db, + tree, + lastAcceptedHeight, + blocks[5], + ) + require.NoError(err) + + missing, err := getMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[4].ID(), + ), + missing, + ) + }) + + t.Run("adding second block", func(t *testing.T) { + require := require.New(t) + + _, err := interval.Add( + db, + tree, + lastAcceptedHeight, + blocks[3], + ) + require.NoError(err) + + missing, err := getMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[2].ID(), + blocks[4].ID(), + ), + missing, + ) + }) + + t.Run("adding last desired block", func(t *testing.T) { + require := require.New(t) + + _, err := interval.Add( + db, + tree, + lastAcceptedHeight, + blocks[2], + ) + require.NoError(err) + + missing, err := getMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[4].ID(), + ), + missing, + ) + }) + + t.Run("adding block with known parent", func(t *testing.T) { + require := require.New(t) + + _, err := interval.Add( + db, + tree, + lastAcceptedHeight, + blocks[6], + ) + require.NoError(err) + + missing, err := getMissingBlockIDs( + context.Background(), + db, + parser, + tree, + lastAcceptedHeight, + ) + require.NoError(err) + require.Equal( + set.Of( + blocks[4].ID(), + ), + missing, + ) + }) +} + +func TestExecute(t *testing.T) { + require := require.New(t) + + const numBlocks = 2*max(batchWritePeriod, iteratorReleasePeriod) + 1 + blocks := generateBlockchain(numBlocks) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := interval.NewTree(db) + require.NoError(err) + const lastAcceptedHeight = 1 + + for i, block := range blocks[lastAcceptedHeight+1:] { + newlyWantsParent, err := interval.Add( + db, + tree, + lastAcceptedHeight, + block, + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(i+1), tree.Len()) + } + + require.NoError(execute( + context.Background(), + logging.NoLog{}.Info, + db, + parser, + tree, + lastAcceptedHeight, + )) + + for _, block := range blocks[lastAcceptedHeight+1:] { + require.Equal(choices.Accepted, block.Status()) + } + + size, err := database.Count(db) + require.NoError(err) + require.Zero(size) +} + +func TestExecuteExitsWhenCancelled(t *testing.T) { + require := require.New(t) + + blocks := generateBlockchain(7) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := interval.NewTree(db) + require.NoError(err) + const lastAcceptedHeight = 1 + + for i, block := range blocks[lastAcceptedHeight+1:] { + newlyWantsParent, err := interval.Add( + db, + tree, + lastAcceptedHeight, + block, + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(i+1), tree.Len()) + } + + startSize, err := database.Count(db) + require.NoError(err) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + err = execute( + ctx, + logging.NoLog{}.Info, + db, + parser, + tree, + lastAcceptedHeight, + ) + require.ErrorIs(err, context.Canceled) + + for _, block := range blocks[lastAcceptedHeight+1:] { + require.Equal(choices.Processing, block.Status()) + } + + endSize, err := database.Count(db) + require.NoError(err) + require.Equal(startSize, endSize) +} + +func TestExecuteSkipsAcceptedBlocks(t *testing.T) { + require := require.New(t) + + blocks := generateBlockchain(7) + parser := makeParser(blocks) + + db := memdb.New() + tree, err := interval.NewTree(db) + require.NoError(err) + const ( + lastAcceptedHeightWhenAdding = 1 + lastAcceptedHeightWhenExecuting = 3 + ) + + for i, block := range blocks[lastAcceptedHeightWhenAdding+1:] { + newlyWantsParent, err := interval.Add( + db, + tree, + lastAcceptedHeightWhenAdding, + block, + ) + require.NoError(err) + require.False(newlyWantsParent) + require.Equal(uint64(i+1), tree.Len()) + } + + require.NoError(execute( + context.Background(), + logging.NoLog{}.Info, + db, + parser, + tree, + lastAcceptedHeightWhenExecuting, + )) + + for _, block := range blocks[lastAcceptedHeightWhenAdding+1 : lastAcceptedHeightWhenExecuting] { + require.Equal(choices.Processing, block.Status()) + } + for _, block := range blocks[lastAcceptedHeightWhenExecuting+1:] { + require.Equal(choices.Accepted, block.Status()) + } + + size, err := database.Count(db) + require.NoError(err) + require.Zero(size) +} + +func generateBlockchain(length uint64) []snowman.Block { + if length == 0 { + return nil + } + + blocks := make([]snowman.Block, length) + blocks[0] = &snowman.TestBlock{ + TestDecidable: choices.TestDecidable{ + IDV: ids.GenerateTestID(), + StatusV: choices.Processing, + }, + ParentV: ids.Empty, + HeightV: 0, + BytesV: utils.RandomBytes(1024), + } + for height := uint64(1); height < length; height++ { + blocks[height] = &snowman.TestBlock{ + TestDecidable: choices.TestDecidable{ + IDV: ids.GenerateTestID(), + StatusV: choices.Processing, + }, + ParentV: blocks[height-1].ID(), + HeightV: height, + BytesV: utils.RandomBytes(1024), + } + } + return blocks +} + +type testParser func(context.Context, []byte) (snowman.Block, error) + +func (f testParser) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block, error) { + return f(ctx, bytes) +} + +func makeParser(blocks []snowman.Block) block.Parser { + return testParser(func(_ context.Context, b []byte) (snowman.Block, error) { + for _, block := range blocks { + if bytes.Equal(b, block.Bytes()) { + return block, nil + } + } + return nil, database.ErrNotFound + }) +} From a7e24582883dcac182219e0e087cfa915156e7a9 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 25 Mar 2024 16:02:20 -0400 Subject: [PATCH 47/85] wip --- snow/engine/snowman/bootstrap/bootstrapper.go | 98 +++++++------------ snow/engine/snowman/bootstrap/storage.go | 47 +++++++++ 2 files changed, 85 insertions(+), 60 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index c4151a2d5aa8..15c4a036121e 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -177,7 +177,7 @@ func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { return fmt.Errorf("failed to initialize interval tree: %w", err) } - b.missingBlockIDs, err = interval.GetMissingBlockIDs(ctx, b.DB, b.VM, b.tree, b.startingHeight) + b.missingBlockIDs, err = getMissingBlockIDs(ctx, b.DB, b.VM, b.tree, b.startingHeight) if err != nil { return fmt.Errorf("failed to initialize missing block IDs: %w", err) } @@ -555,96 +555,74 @@ func (b *Bootstrapper) markUnavailable(nodeID ids.NodeID) { // // - blk is a block that is assumed to have been marked as acceptable by the // bootstrapping engine. -// - processingBlocks is a set of blocks that can be used to lookup blocks. -// This enables the engine to process multiple blocks without relying on the -// VM to have stored blocks during `ParseBlock`. -// -// If [blk]'s height is <= the last accepted height, then it will be removed -// from the missingIDs set. -func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processingBlocks map[ids.ID]snowman.Block) error { +// - ancestors is a set of blocks that can be used to optimisically lookup +// parent blocks. This enables the engine to process multiple blocks without +// relying on the VM to have stored blocks during `ParseBlock`. +func (b *Bootstrapper) process( + ctx context.Context, + blk snowman.Block, + ancestors map[ids.ID]snowman.Block, +) error { lastAcceptedHeight, err := b.getLastAcceptedHeight(ctx) if err != nil { return err } + numPreviouslyFetched := b.tree.Len() + batch := b.DB.NewBatch() - for { - if b.Halted() { - return batch.Write() - } + missingBlockID, foundNewMissingID, err := process( + batch, + b.tree, + blk, + ancestors, + b.missingBlockIDs, + lastAcceptedHeight, + ) + if err != nil { + return err + } - blkID := blk.ID() - b.missingBlockIDs.Remove(blkID) + // Update metrics and log statuses + { + numFetched := b.tree.Len() + b.numFetched.Add(float64(b.tree.Len() - numPreviouslyFetched)) height := blk.Height() b.tipHeight = max(b.tipHeight, height) - wantsParent, err := interval.Add(batch, b.tree, lastAcceptedHeight, blk) - if err != nil { - return err - } - - // We added a new block to the queue, so track that it was fetched - b.numFetched.Inc() - - // Periodically log progress - blocksFetchedSoFar := b.tree.Len() - if blocksFetchedSoFar%statusUpdateFrequency == 0 { + if numFetched%statusUpdateFrequency == 0 { totalBlocksToFetch := b.tipHeight - b.startingHeight eta := timer.EstimateETA( b.startTime, - blocksFetchedSoFar-b.initiallyFetched, // Number of blocks we have fetched during this run + numFetched-b.initiallyFetched, // Number of blocks we have fetched during this run totalBlocksToFetch-b.initiallyFetched, // Number of blocks we expect to fetch during this run ) b.fetchETA.Set(float64(eta)) if !b.restarted { b.Ctx.Log.Info("fetching blocks", - zap.Uint64("numFetchedBlocks", blocksFetchedSoFar), + zap.Uint64("numFetchedBlocks", numFetched), zap.Uint64("numTotalBlocks", totalBlocksToFetch), zap.Duration("eta", eta), ) } else { b.Ctx.Log.Debug("fetching blocks", - zap.Uint64("numFetchedBlocks", blocksFetchedSoFar), + zap.Uint64("numFetchedBlocks", numFetched), zap.Uint64("numTotalBlocks", totalBlocksToFetch), zap.Duration("eta", eta), ) } } + } - if !wantsParent { - return batch.Write() - } - - // Attempt to traverse to the next block - parentID := blk.Parent() - b.missingBlockIDs.Add(parentID) - - // First check if the parent is in the processing blocks set - parent, ok := processingBlocks[parentID] - if ok { - blk = parent - continue - } - - // If the parent is not available in processing blocks, attempt to get - // the block from the vm - parent, err = b.VM.GetBlock(ctx, parentID) - if err == nil { - blk = parent - continue - } - // TODO: report errors that aren't `database.ErrNotFound` - - // If the block wasn't able to be acquired immediately, attempt to fetch - // it - if err := b.fetch(ctx, parentID); err != nil { - return err - } - - return batch.Write() + if err := batch.Write(); err != nil || !foundNewMissingID { + return err } + + b.missingBlockIDs.Add(missingBlockID) + // Attempt to fetch the newly discovered block + return b.fetch(ctx, missingBlockID) } // tryStartExecuting executes all pending blocks if there are no more blocks @@ -670,7 +648,7 @@ func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { } numToExecute := b.tree.Len() - err = interval.Execute( + err = execute( &haltableContext{ Context: ctx, Haltable: b, diff --git a/snow/engine/snowman/bootstrap/storage.go b/snow/engine/snowman/bootstrap/storage.go index 47317abb1aff..b5b5c4971ddd 100644 --- a/snow/engine/snowman/bootstrap/storage.go +++ b/snow/engine/snowman/bootstrap/storage.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" "github.com/ava-labs/avalanchego/utils/logging" @@ -65,6 +66,52 @@ func getMissingBlockIDs( return missingBlocks, nil } +// process a series of consecutive blocks starting at [blk]. +// +// - blk is a block that is assumed to have been marked as acceptable by the +// bootstrapping engine. +// - ancestors is a set of blocks that can be used to lookup blocks. +// +// If [blk]'s height is <= the last accepted height, then it will be removed +// from the missingIDs set. +// +// Returns a newly discovered blockID that should be fetched. +func process( + db database.KeyValueWriterDeleter, + tree *interval.Tree, + blk snowman.Block, + ancestors map[ids.ID]snowman.Block, + missingBlockIDs set.Set[ids.ID], + lastAcceptedHeight uint64, +) (ids.ID, bool, error) { + for { + // It's possible that missingBlockIDs contain values contained inside of + // ancestors. So, it's important to remove IDs from the set for each + // iteration, not just the first block's ID. + blkID := blk.ID() + missingBlockIDs.Remove(blkID) + + wantsParent, err := interval.Add(db, tree, lastAcceptedHeight, blk) + if err != nil { + return ids.Empty, false, err + } + + if !wantsParent { + return ids.Empty, false, nil + } + + // If the parent was provided in the ancestors set, we can immediately + // process it. + parentID := blk.Parent() + parent, ok := ancestors[parentID] + if !ok { + return parentID, true, nil + } + + blk = parent + } +} + // execute all the blocks tracked by the tree. If a block is in the tree but is // already accepted based on the lastAcceptedHeight, it will be removed from the // tree but not executed. From f1dd0a60d0335ee85f9a367c8c55fea19827b268 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 25 Mar 2024 23:59:21 -0400 Subject: [PATCH 48/85] nit --- snow/engine/snowman/bootstrap/interval/blocks_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go index 9741b29aff48..9c04264e1845 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks_test.go +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -157,12 +157,11 @@ func TestRemove(t *testing.T) { t.Run("removing a block", func(t *testing.T) { require := require.New(t) - err := Remove( + require.NoError(Remove( db, tree, blocks[5].Height(), - ) - require.NoError(err) + )) require.Zero(tree.Len()) _, err = GetBlock(db, blocks[5].Height()) From bf29d869cb7a54e4ad64b3c4c9e3abd7253f833c Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:01:11 -0400 Subject: [PATCH 49/85] remove storage --- snow/engine/snowman/bootstrap/storage.go | 202 ----------- snow/engine/snowman/bootstrap/storage_test.go | 338 ------------------ 2 files changed, 540 deletions(-) delete mode 100644 snow/engine/snowman/bootstrap/storage.go delete mode 100644 snow/engine/snowman/bootstrap/storage_test.go diff --git a/snow/engine/snowman/bootstrap/storage.go b/snow/engine/snowman/bootstrap/storage.go deleted file mode 100644 index 47317abb1aff..000000000000 --- a/snow/engine/snowman/bootstrap/storage.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package bootstrap - -import ( - "context" - "fmt" - "time" - - "go.uber.org/zap" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/engine/snowman/block" - "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/timer" -) - -const ( - batchWritePeriod = 64 - iteratorReleasePeriod = 1024 - logPeriod = 5 * time.Second -) - -// getMissingBlockIDs returns the ID of the blocks that should be fetched to -// attempt to make a single continuous range from -// (lastAcceptedHeight, highestTrackedHeight]. -// -// For example, if the tree currently contains heights [1, 4, 6, 7] and the -// lastAcceptedHeight is 2, this function will return the IDs corresponding to -// blocks [3, 5]. -func getMissingBlockIDs( - ctx context.Context, - db database.KeyValueReader, - parser block.Parser, - tree *interval.Tree, - lastAcceptedHeight uint64, -) (set.Set[ids.ID], error) { - var ( - missingBlocks set.Set[ids.ID] - intervals = tree.Flatten() - lastHeightToFetch = lastAcceptedHeight + 1 - ) - for _, i := range intervals { - if i.LowerBound <= lastHeightToFetch { - continue - } - - blkBytes, err := interval.GetBlock(db, i.LowerBound) - if err != nil { - return nil, err - } - - blk, err := parser.ParseBlock(ctx, blkBytes) - if err != nil { - return nil, err - } - - parentID := blk.Parent() - missingBlocks.Add(parentID) - } - return missingBlocks, nil -} - -// execute all the blocks tracked by the tree. If a block is in the tree but is -// already accepted based on the lastAcceptedHeight, it will be removed from the -// tree but not executed. -// -// execute assumes that getMissingBlockIDs would return an empty set. -func execute( - ctx context.Context, - log logging.Func, - db database.Database, - parser block.Parser, - tree *interval.Tree, - lastAcceptedHeight uint64, -) error { - var ( - batch = db.NewBatch() - processedSinceBatchWrite uint - writeBatch = func() error { - if processedSinceBatchWrite == 0 { - return nil - } - processedSinceBatchWrite = 0 - - if err := batch.Write(); err != nil { - return err - } - batch.Reset() - return nil - } - - iterator = interval.GetBlockIterator(db) - processedSinceIteratorRelease uint - - startTime = time.Now() - timeOfNextLog = startTime.Add(logPeriod) - totalNumberToProcess = tree.Len() - ) - defer func() { - iterator.Release() - }() - - log("executing blocks", - zap.Uint64("numToExecute", totalNumberToProcess), - ) - - for ctx.Err() == nil && iterator.Next() { - blkBytes := iterator.Value() - blk, err := parser.ParseBlock(ctx, blkBytes) - if err != nil { - return err - } - - height := blk.Height() - if err := interval.Remove(batch, tree, height); err != nil { - return err - } - - // Periodically write the batch to disk to avoid memory pressure. - processedSinceBatchWrite++ - if processedSinceBatchWrite >= batchWritePeriod { - if err := writeBatch(); err != nil { - return err - } - } - - // Periodically release and re-grab the database iterator to avoid - // keeping a reference to an old database revision. - processedSinceIteratorRelease++ - if processedSinceIteratorRelease >= iteratorReleasePeriod { - if err := iterator.Error(); err != nil { - return err - } - - // The batch must be written here to avoid re-processing a block. - if err := writeBatch(); err != nil { - return err - } - - processedSinceIteratorRelease = 0 - iterator.Release() - iterator = interval.GetBlockIterator(db) - } - - now := time.Now() - if now.After(timeOfNextLog) { - var ( - numProcessed = totalNumberToProcess - tree.Len() - eta = timer.EstimateETA(startTime, numProcessed, totalNumberToProcess) - ) - - log("executing blocks", - zap.Duration("eta", eta), - zap.Uint64("numExecuted", numProcessed), - zap.Uint64("numToExecute", totalNumberToProcess), - ) - timeOfNextLog = now.Add(logPeriod) - } - - if height <= lastAcceptedHeight { - continue - } - - if err := blk.Verify(ctx); err != nil { - return fmt.Errorf("failed to verify block %s (%d) in bootstrapping: %w", - blk.ID(), - height, - err, - ) - } - if err := blk.Accept(ctx); err != nil { - return fmt.Errorf("failed to accept block %s (%d) in bootstrapping: %w", - blk.ID(), - height, - err, - ) - } - } - if err := writeBatch(); err != nil { - return err - } - if err := iterator.Error(); err != nil { - return err - } - - var ( - numProcessed = totalNumberToProcess - tree.Len() - err = ctx.Err() - ) - log("executed blocks", - zap.Uint64("numExecuted", numProcessed), - zap.Uint64("numToExecute", totalNumberToProcess), - zap.Duration("duration", time.Since(startTime)), - zap.Error(err), - ) - return err -} diff --git a/snow/engine/snowman/bootstrap/storage_test.go b/snow/engine/snowman/bootstrap/storage_test.go deleted file mode 100644 index 0dbb0eb3ed88..000000000000 --- a/snow/engine/snowman/bootstrap/storage_test.go +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package bootstrap - -import ( - "bytes" - "context" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/database/memdb" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/choices" - "github.com/ava-labs/avalanchego/snow/consensus/snowman" - "github.com/ava-labs/avalanchego/snow/engine/snowman/block" - "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/set" -) - -func TestGetMissingBlockIDs(t *testing.T) { - blocks := generateBlockchain(7) - parser := makeParser(blocks) - - db := memdb.New() - tree, err := interval.NewTree(db) - require.NoError(t, err) - lastAcceptedHeight := uint64(1) - - t.Run("initially empty", func(t *testing.T) { - require := require.New(t) - - missing, err := getMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Empty(missing) - }) - - t.Run("adding first block", func(t *testing.T) { - require := require.New(t) - - _, err := interval.Add( - db, - tree, - lastAcceptedHeight, - blocks[5], - ) - require.NoError(err) - - missing, err := getMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[4].ID(), - ), - missing, - ) - }) - - t.Run("adding second block", func(t *testing.T) { - require := require.New(t) - - _, err := interval.Add( - db, - tree, - lastAcceptedHeight, - blocks[3], - ) - require.NoError(err) - - missing, err := getMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[2].ID(), - blocks[4].ID(), - ), - missing, - ) - }) - - t.Run("adding last desired block", func(t *testing.T) { - require := require.New(t) - - _, err := interval.Add( - db, - tree, - lastAcceptedHeight, - blocks[2], - ) - require.NoError(err) - - missing, err := getMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[4].ID(), - ), - missing, - ) - }) - - t.Run("adding block with known parent", func(t *testing.T) { - require := require.New(t) - - _, err := interval.Add( - db, - tree, - lastAcceptedHeight, - blocks[6], - ) - require.NoError(err) - - missing, err := getMissingBlockIDs( - context.Background(), - db, - parser, - tree, - lastAcceptedHeight, - ) - require.NoError(err) - require.Equal( - set.Of( - blocks[4].ID(), - ), - missing, - ) - }) -} - -func TestExecute(t *testing.T) { - require := require.New(t) - - const numBlocks = 2*max(batchWritePeriod, iteratorReleasePeriod) + 1 - blocks := generateBlockchain(numBlocks) - parser := makeParser(blocks) - - db := memdb.New() - tree, err := interval.NewTree(db) - require.NoError(err) - const lastAcceptedHeight = 1 - - for i, block := range blocks[lastAcceptedHeight+1:] { - newlyWantsParent, err := interval.Add( - db, - tree, - lastAcceptedHeight, - block, - ) - require.NoError(err) - require.False(newlyWantsParent) - require.Equal(uint64(i+1), tree.Len()) - } - - require.NoError(execute( - context.Background(), - logging.NoLog{}.Info, - db, - parser, - tree, - lastAcceptedHeight, - )) - - for _, block := range blocks[lastAcceptedHeight+1:] { - require.Equal(choices.Accepted, block.Status()) - } - - size, err := database.Count(db) - require.NoError(err) - require.Zero(size) -} - -func TestExecuteExitsWhenCancelled(t *testing.T) { - require := require.New(t) - - blocks := generateBlockchain(7) - parser := makeParser(blocks) - - db := memdb.New() - tree, err := interval.NewTree(db) - require.NoError(err) - const lastAcceptedHeight = 1 - - for i, block := range blocks[lastAcceptedHeight+1:] { - newlyWantsParent, err := interval.Add( - db, - tree, - lastAcceptedHeight, - block, - ) - require.NoError(err) - require.False(newlyWantsParent) - require.Equal(uint64(i+1), tree.Len()) - } - - startSize, err := database.Count(db) - require.NoError(err) - - ctx, cancel := context.WithCancel(context.Background()) - cancel() - err = execute( - ctx, - logging.NoLog{}.Info, - db, - parser, - tree, - lastAcceptedHeight, - ) - require.ErrorIs(err, context.Canceled) - - for _, block := range blocks[lastAcceptedHeight+1:] { - require.Equal(choices.Processing, block.Status()) - } - - endSize, err := database.Count(db) - require.NoError(err) - require.Equal(startSize, endSize) -} - -func TestExecuteSkipsAcceptedBlocks(t *testing.T) { - require := require.New(t) - - blocks := generateBlockchain(7) - parser := makeParser(blocks) - - db := memdb.New() - tree, err := interval.NewTree(db) - require.NoError(err) - const ( - lastAcceptedHeightWhenAdding = 1 - lastAcceptedHeightWhenExecuting = 3 - ) - - for i, block := range blocks[lastAcceptedHeightWhenAdding+1:] { - newlyWantsParent, err := interval.Add( - db, - tree, - lastAcceptedHeightWhenAdding, - block, - ) - require.NoError(err) - require.False(newlyWantsParent) - require.Equal(uint64(i+1), tree.Len()) - } - - require.NoError(execute( - context.Background(), - logging.NoLog{}.Info, - db, - parser, - tree, - lastAcceptedHeightWhenExecuting, - )) - - for _, block := range blocks[lastAcceptedHeightWhenAdding+1 : lastAcceptedHeightWhenExecuting] { - require.Equal(choices.Processing, block.Status()) - } - for _, block := range blocks[lastAcceptedHeightWhenExecuting+1:] { - require.Equal(choices.Accepted, block.Status()) - } - - size, err := database.Count(db) - require.NoError(err) - require.Zero(size) -} - -func generateBlockchain(length uint64) []snowman.Block { - if length == 0 { - return nil - } - - blocks := make([]snowman.Block, length) - blocks[0] = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: ids.Empty, - HeightV: 0, - BytesV: utils.RandomBytes(1024), - } - for height := uint64(1); height < length; height++ { - blocks[height] = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: blocks[height-1].ID(), - HeightV: height, - BytesV: utils.RandomBytes(1024), - } - } - return blocks -} - -type testParser func(context.Context, []byte) (snowman.Block, error) - -func (f testParser) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block, error) { - return f(ctx, bytes) -} - -func makeParser(blocks []snowman.Block) block.Parser { - return testParser(func(_ context.Context, b []byte) (snowman.Block, error) { - for _, block := range blocks { - if bytes.Equal(b, block.Bytes()) { - return block, nil - } - } - return nil, database.ErrNotFound - }) -} From 5a8fadcda784adb6f32d9f966b6567e856109973 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:16:40 -0400 Subject: [PATCH 50/85] nit --- .../snowman/bootstrap/interval/blocks.go | 15 ++--- .../snowman/bootstrap/interval/blocks_test.go | 65 +++++++------------ 2 files changed, 30 insertions(+), 50 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 5a00e96bafca..db953f569b68 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -5,7 +5,6 @@ package interval import ( "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/snow/consensus/snowman" ) // Add the block to the tree and return if the parent block should be fetched, @@ -14,17 +13,13 @@ func Add( db database.KeyValueWriterDeleter, tree *Tree, lastAcceptedHeight uint64, - blk snowman.Block, + height uint64, + blkBytes []byte, ) (bool, error) { - var ( - height = blk.Height() - lastHeightToFetch = lastAcceptedHeight + 1 - ) - if height < lastHeightToFetch || tree.Contains(height) { + if height <= lastAcceptedHeight || tree.Contains(height) { return false, nil } - blkBytes := blk.Bytes() if err := PutBlock(db, height, blkBytes); err != nil { return false, err } @@ -33,7 +28,9 @@ func Add( return false, err } - return height != lastHeightToFetch && !tree.Contains(height-1), nil + // We know that height is greater than lastAcceptedHeight here, so + // lastAcceptedHeight+1 is guaranteed not to overflow. + return height != lastAcceptedHeight+1 && !tree.Contains(height-1), nil } // Remove the block from the tree. diff --git a/snow/engine/snowman/bootstrap/interval/blocks_test.go b/snow/engine/snowman/bootstrap/interval/blocks_test.go index 9c04264e1845..5bd0f9b050fd 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks_test.go +++ b/snow/engine/snowman/bootstrap/interval/blocks_test.go @@ -10,9 +10,6 @@ import ( "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/choices" - "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/utils" ) @@ -31,15 +28,16 @@ func TestAdd(t *testing.T) { db, tree, lastAcceptedHeight, + 5, blocks[5], ) require.NoError(err) require.True(newlyWantsParent) require.Equal(uint64(1), tree.Len()) - bytes, err := GetBlock(db, blocks[5].Height()) + bytes, err := GetBlock(db, 5) require.NoError(err) - require.Equal(blocks[5].Bytes(), bytes) + require.Equal(blocks[5], bytes) }) t.Run("adding duplicate block", func(t *testing.T) { @@ -49,6 +47,7 @@ func TestAdd(t *testing.T) { db, tree, lastAcceptedHeight, + 5, blocks[5], ) require.NoError(err) @@ -63,15 +62,16 @@ func TestAdd(t *testing.T) { db, tree, lastAcceptedHeight, + 3, blocks[3], ) require.NoError(err) require.True(newlyWantsParent) require.Equal(uint64(2), tree.Len()) - bytes, err := GetBlock(db, blocks[3].Height()) + bytes, err := GetBlock(db, 3) require.NoError(err) - require.Equal(blocks[3].Bytes(), bytes) + require.Equal(blocks[3], bytes) }) t.Run("adding last desired block", func(t *testing.T) { @@ -81,15 +81,16 @@ func TestAdd(t *testing.T) { db, tree, lastAcceptedHeight, + 2, blocks[2], ) require.NoError(err) require.False(newlyWantsParent) require.Equal(uint64(3), tree.Len()) - bytes, err := GetBlock(db, blocks[2].Height()) + bytes, err := GetBlock(db, 2) require.NoError(err) - require.Equal(blocks[2].Bytes(), bytes) + require.Equal(blocks[2], bytes) }) t.Run("adding undesired block", func(t *testing.T) { @@ -99,13 +100,14 @@ func TestAdd(t *testing.T) { db, tree, lastAcceptedHeight, + 1, blocks[1], ) require.NoError(err) require.False(newlyWantsParent) require.Equal(uint64(3), tree.Len()) - _, err = GetBlock(db, blocks[1].Height()) + _, err = GetBlock(db, 1) require.ErrorIs(err, database.ErrNotFound) }) @@ -116,15 +118,16 @@ func TestAdd(t *testing.T) { db, tree, lastAcceptedHeight, + 6, blocks[6], ) require.NoError(err) require.False(newlyWantsParent) require.Equal(uint64(4), tree.Len()) - bytes, err := GetBlock(db, blocks[6].Height()) + bytes, err := GetBlock(db, 6) require.NoError(err) - require.Equal(blocks[6].Bytes(), bytes) + require.Equal(blocks[6], bytes) }) } @@ -143,15 +146,16 @@ func TestRemove(t *testing.T) { db, tree, lastAcceptedHeight, + 5, blocks[5], ) require.NoError(err) require.True(newlyWantsParent) require.Equal(uint64(1), tree.Len()) - bytes, err := GetBlock(db, blocks[5].Height()) + bytes, err := GetBlock(db, 5) require.NoError(err) - require.Equal(blocks[5].Bytes(), bytes) + require.Equal(blocks[5], bytes) }) t.Run("removing a block", func(t *testing.T) { @@ -160,40 +164,19 @@ func TestRemove(t *testing.T) { require.NoError(Remove( db, tree, - blocks[5].Height(), + 5, )) require.Zero(tree.Len()) - _, err = GetBlock(db, blocks[5].Height()) + _, err = GetBlock(db, 5) require.ErrorIs(err, database.ErrNotFound) }) } -func generateBlockchain(length uint64) []snowman.Block { - if length == 0 { - return nil - } - - blocks := make([]snowman.Block, length) - blocks[0] = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: ids.Empty, - HeightV: 0, - BytesV: utils.RandomBytes(1024), - } - for height := uint64(1); height < length; height++ { - blocks[height] = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: blocks[height-1].ID(), - HeightV: height, - BytesV: utils.RandomBytes(1024), - } +func generateBlockchain(length uint64) [][]byte { + blocks := make([][]byte, length) + for i := range blocks { + blocks[i] = utils.RandomBytes(1024) } return blocks } From 69ed897acb1115e80dada84f64e8ea2e22606b46 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:17:41 -0400 Subject: [PATCH 51/85] nit --- snow/engine/snowman/bootstrap/interval/blocks.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index db953f569b68..0a7ca95c0801 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -3,9 +3,7 @@ package interval -import ( - "github.com/ava-labs/avalanchego/database" -) +import "github.com/ava-labs/avalanchego/database" // Add the block to the tree and return if the parent block should be fetched, // but wasn't desired before. From 9815047188cfe49f942b23bb893de4e0978d2c78 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:19:06 -0400 Subject: [PATCH 52/85] nit --- snow/engine/snowman/bootstrap/interval/blocks.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 0a7ca95c0801..248e5b31ac92 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -26,9 +26,10 @@ func Add( return false, err } - // We know that height is greater than lastAcceptedHeight here, so - // lastAcceptedHeight+1 is guaranteed not to overflow. - return height != lastAcceptedHeight+1 && !tree.Contains(height-1), nil + // We know that height is greater than lastAcceptedHeight here, so height-1 + // is guaranteed not to underflow. + nextHeight := height - 1 + return nextHeight != lastAcceptedHeight && !tree.Contains(nextHeight), nil } // Remove the block from the tree. From 5bf4899d57079a038c1b15c9fb704aa765eb82e5 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:19:29 -0400 Subject: [PATCH 53/85] nit --- snow/engine/snowman/bootstrap/interval/blocks.go | 1 - 1 file changed, 1 deletion(-) diff --git a/snow/engine/snowman/bootstrap/interval/blocks.go b/snow/engine/snowman/bootstrap/interval/blocks.go index 248e5b31ac92..d7d053c17876 100644 --- a/snow/engine/snowman/bootstrap/interval/blocks.go +++ b/snow/engine/snowman/bootstrap/interval/blocks.go @@ -21,7 +21,6 @@ func Add( if err := PutBlock(db, height, blkBytes); err != nil { return false, err } - if err := tree.Add(db, height); err != nil { return false, err } From 9da3bc1e3d4169ee2c39663d1dd90f5a2eab94db Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:25:15 -0400 Subject: [PATCH 54/85] nit --- .../snowman/bootstrap/interval/tree_test.go | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/snow/engine/snowman/bootstrap/interval/tree_test.go b/snow/engine/snowman/bootstrap/interval/tree_test.go index b0a13d5ed59c..396e4d281a91 100644 --- a/snow/engine/snowman/bootstrap/interval/tree_test.go +++ b/snow/engine/snowman/bootstrap/interval/tree_test.go @@ -4,6 +4,7 @@ package interval import ( + "math" "testing" "github.com/stretchr/testify/require" @@ -366,3 +367,23 @@ func TestTreeContains(t *testing.T) { }) } } + +func TestTreeLenOverflow(t *testing.T) { + require := require.New(t) + + db := memdb.New() + require.NoError(PutInterval(db, math.MaxUint64, 0)) + + tree, err := NewTree(db) + require.NoError(err) + require.Zero(tree.Len()) + require.True(tree.Contains(0)) + require.True(tree.Contains(math.MaxUint64 / 2)) + require.True(tree.Contains(math.MaxUint64)) + + require.NoError(tree.Remove(db, 5)) + require.Equal(uint64(math.MaxUint64), tree.Len()) + + require.NoError(tree.Add(db, 5)) + require.Zero(tree.Len()) +} From bd5687a163d6b778b7e529c12de460dc65fd99d9 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:29:15 -0400 Subject: [PATCH 55/85] nit --- snow/engine/snowman/bootstrap/storage.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/snow/engine/snowman/bootstrap/storage.go b/snow/engine/snowman/bootstrap/storage.go index b5b5c4971ddd..4f6ae615cde5 100644 --- a/snow/engine/snowman/bootstrap/storage.go +++ b/snow/engine/snowman/bootstrap/storage.go @@ -91,15 +91,19 @@ func process( blkID := blk.ID() missingBlockIDs.Remove(blkID) - wantsParent, err := interval.Add(db, tree, lastAcceptedHeight, blk) - if err != nil { + height := blk.Height() + blkBytes := blk.Bytes() + wantsParent, err := interval.Add( + db, + tree, + lastAcceptedHeight, + height, + blkBytes, + ) + if err != nil || !wantsParent { return ids.Empty, false, err } - if !wantsParent { - return ids.Empty, false, nil - } - // If the parent was provided in the ancestors set, we can immediately // process it. parentID := blk.Parent() From b6e3ee14d6702d8c4d11f79d88e679f50b95f945 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:33:14 -0400 Subject: [PATCH 56/85] merged --- .../snowman/bootstrap/bootstrapper_test.go | 2 +- snow/engine/snowman/bootstrap/storage_test.go | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index d8dca8f69122..37853ae2c698 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -1378,7 +1378,7 @@ func TestBootstrapNoParseOnNew(t *testing.T) { intervalDB := memdb.New() tree, err := interval.NewTree(intervalDB) require.NoError(err) - _, err = interval.Add(intervalDB, tree, 0, blk1) + _, err = interval.Add(intervalDB, tree, 0, blk1.Height(), blk1.Bytes()) require.NoError(err) vm.GetBlockF = nil diff --git a/snow/engine/snowman/bootstrap/storage_test.go b/snow/engine/snowman/bootstrap/storage_test.go index 0dbb0eb3ed88..a0ceebaf1577 100644 --- a/snow/engine/snowman/bootstrap/storage_test.go +++ b/snow/engine/snowman/bootstrap/storage_test.go @@ -52,7 +52,8 @@ func TestGetMissingBlockIDs(t *testing.T) { db, tree, lastAcceptedHeight, - blocks[5], + 5, + blocks[5].Bytes(), ) require.NoError(err) @@ -79,7 +80,8 @@ func TestGetMissingBlockIDs(t *testing.T) { db, tree, lastAcceptedHeight, - blocks[3], + 3, + blocks[3].Bytes(), ) require.NoError(err) @@ -107,7 +109,8 @@ func TestGetMissingBlockIDs(t *testing.T) { db, tree, lastAcceptedHeight, - blocks[2], + 2, + blocks[2].Bytes(), ) require.NoError(err) @@ -134,7 +137,8 @@ func TestGetMissingBlockIDs(t *testing.T) { db, tree, lastAcceptedHeight, - blocks[6], + 6, + blocks[6].Bytes(), ) require.NoError(err) @@ -172,7 +176,8 @@ func TestExecute(t *testing.T) { db, tree, lastAcceptedHeight, - block, + block.Height(), + block.Bytes(), ) require.NoError(err) require.False(newlyWantsParent) @@ -213,7 +218,8 @@ func TestExecuteExitsWhenCancelled(t *testing.T) { db, tree, lastAcceptedHeight, - block, + block.Height(), + block.Bytes(), ) require.NoError(err) require.False(newlyWantsParent) @@ -263,7 +269,8 @@ func TestExecuteSkipsAcceptedBlocks(t *testing.T) { db, tree, lastAcceptedHeightWhenAdding, - block, + block.Height(), + block.Bytes(), ) require.NoError(err) require.False(newlyWantsParent) From c376df21bedc3f046f0d3fa9f8bdacc83bfc0b98 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:55:47 -0400 Subject: [PATCH 57/85] add process test --- snow/engine/snowman/bootstrap/storage_test.go | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/snow/engine/snowman/bootstrap/storage_test.go b/snow/engine/snowman/bootstrap/storage_test.go index a0ceebaf1577..e36016ea30ae 100644 --- a/snow/engine/snowman/bootstrap/storage_test.go +++ b/snow/engine/snowman/bootstrap/storage_test.go @@ -159,6 +159,76 @@ func TestGetMissingBlockIDs(t *testing.T) { }) } +func TestProcess(t *testing.T) { + blocks := generateBlockchain(7) + + db := memdb.New() + tree, err := interval.NewTree(db) + require.NoError(t, err) + lastAcceptedHeight := uint64(1) + + t.Run("adding first block", func(t *testing.T) { + require := require.New(t) + + missingIDs := set.Of(blocks[6].ID()) + parentID, shouldFetchParentID, err := process( + db, + tree, + blocks[6], + map[ids.ID]snowman.Block{ + blocks[2].ID(): blocks[2], + }, + missingIDs, + lastAcceptedHeight, + ) + require.NoError(err) + require.True(shouldFetchParentID) + require.Equal(blocks[5].ID(), parentID) + require.Equal(uint64(1), tree.Len()) + require.Empty(missingIDs) + }) + + t.Run("adding multiple blocks", func(t *testing.T) { + require := require.New(t) + + missingIDs := set.Of(blocks[5].ID()) + parentID, shouldFetchParentID, err := process( + db, + tree, + blocks[5], + map[ids.ID]snowman.Block{ + blocks[4].ID(): blocks[4], + blocks[3].ID(): blocks[3], + }, + missingIDs, + lastAcceptedHeight, + ) + require.NoError(err) + require.True(shouldFetchParentID) + require.Equal(blocks[2].ID(), parentID) + require.Equal(uint64(4), tree.Len()) + require.Empty(missingIDs) + }) + + t.Run("do not request last accepted block", func(t *testing.T) { + require := require.New(t) + + missingIDs := set.Of(blocks[2].ID()) + _, shouldFetchParentID, err := process( + db, + tree, + blocks[2], + nil, + missingIDs, + lastAcceptedHeight, + ) + require.NoError(err) + require.False(shouldFetchParentID) + require.Equal(uint64(5), tree.Len()) + require.Empty(missingIDs) + }) +} + func TestExecute(t *testing.T) { require := require.New(t) From 53bdb78305674d3108c17beacc3005c8d0dc16e5 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:59:27 -0400 Subject: [PATCH 58/85] nit --- snow/engine/snowman/bootstrap/bootstrapper.go | 4 ++-- snow/engine/snowman/bootstrap/storage_test.go | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 15c4a036121e..43b0c0b723c0 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -574,10 +574,10 @@ func (b *Bootstrapper) process( missingBlockID, foundNewMissingID, err := process( batch, b.tree, - blk, - ancestors, b.missingBlockIDs, lastAcceptedHeight, + blk, + ancestors, ) if err != nil { return err diff --git a/snow/engine/snowman/bootstrap/storage_test.go b/snow/engine/snowman/bootstrap/storage_test.go index e36016ea30ae..92d927578437 100644 --- a/snow/engine/snowman/bootstrap/storage_test.go +++ b/snow/engine/snowman/bootstrap/storage_test.go @@ -174,12 +174,12 @@ func TestProcess(t *testing.T) { parentID, shouldFetchParentID, err := process( db, tree, + missingIDs, + lastAcceptedHeight, blocks[6], map[ids.ID]snowman.Block{ blocks[2].ID(): blocks[2], }, - missingIDs, - lastAcceptedHeight, ) require.NoError(err) require.True(shouldFetchParentID) @@ -195,13 +195,13 @@ func TestProcess(t *testing.T) { parentID, shouldFetchParentID, err := process( db, tree, + missingIDs, + lastAcceptedHeight, blocks[5], map[ids.ID]snowman.Block{ blocks[4].ID(): blocks[4], blocks[3].ID(): blocks[3], }, - missingIDs, - lastAcceptedHeight, ) require.NoError(err) require.True(shouldFetchParentID) @@ -217,10 +217,10 @@ func TestProcess(t *testing.T) { _, shouldFetchParentID, err := process( db, tree, - blocks[2], - nil, missingIDs, lastAcceptedHeight, + blocks[2], + nil, ) require.NoError(err) require.False(shouldFetchParentID) From 73108325db1f35131bc4011a8656d12060875fb8 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 00:59:46 -0400 Subject: [PATCH 59/85] nit --- snow/engine/snowman/bootstrap/storage.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snow/engine/snowman/bootstrap/storage.go b/snow/engine/snowman/bootstrap/storage.go index 4f6ae615cde5..764d74a7cfcf 100644 --- a/snow/engine/snowman/bootstrap/storage.go +++ b/snow/engine/snowman/bootstrap/storage.go @@ -79,10 +79,10 @@ func getMissingBlockIDs( func process( db database.KeyValueWriterDeleter, tree *interval.Tree, - blk snowman.Block, - ancestors map[ids.ID]snowman.Block, missingBlockIDs set.Set[ids.ID], lastAcceptedHeight uint64, + blk snowman.Block, + ancestors map[ids.ID]snowman.Block, ) (ids.ID, bool, error) { for { // It's possible that missingBlockIDs contain values contained inside of From 7de549931fcdf7a09135665b1526cf6faca9f598 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 11:12:16 -0400 Subject: [PATCH 60/85] wip --- .../snowman/bootstrap/bootstrapper_test.go | 591 +++++++----------- 1 file changed, 243 insertions(+), 348 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index 37853ae2c698..24173ce9cf0b 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -220,14 +220,40 @@ func TestBootstrapperSingleFrontier(t *testing.T) { HeightV: 1, BytesV: blkBytes1, } + blks := map[ids.ID]snowman.Block{ + blkID0: blk0, + blkID1: blk1, + } - vm.CantLastAccepted = false + vm.CantSetState = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil + var ( + lastAcceptedID = blk0.ID() + lastAcceptedHeight = blk0.Height() + ) + for blkID, blk := range blks { + height := blk.Height() + if blk.Status() == choices.Accepted && height > lastAcceptedHeight { + lastAcceptedID = blkID + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil } vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - require.Equal(blk0.ID(), blkID) - return blk0, nil + if blk, ok := blks[blkID]; ok { + return blk, nil + } + return nil, database.ErrNotFound + } + vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { + for _, blk := range blks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } + } + require.FailNow(errUnknownBlock.Error()) + return nil, errUnknownBlock } bs, err := New( @@ -242,41 +268,15 @@ func TestBootstrapperSingleFrontier(t *testing.T) { ) require.NoError(err) - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) acceptedIDs := []ids.ID{blkID1} - - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID1: - return blk1, nil - case blkID0: - return blk0, nil - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes1): - return blk1, nil - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk1.Status()) } -// Requests the unknown block and gets back a Ancestors with unexpected request ID. -// Requests again and gets response from unexpected peer. -// Requests again and gets an unexpected block. +// Requests the unknown block and gets back a Ancestors with unexpected block. // Requests again and gets the expected block. func TestBootstrapperUnknownByzantineResponse(t *testing.T) { require := require.New(t) @@ -285,11 +285,9 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { blkID0 := ids.Empty.Prefix(0) blkID1 := ids.Empty.Prefix(1) - blkID2 := ids.Empty.Prefix(2) blkBytes0 := []byte{0} blkBytes1 := []byte{1} - blkBytes2 := []byte{2} blk0 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ @@ -302,30 +300,46 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { blk1 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID1, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk0.IDV, HeightV: 1, BytesV: blkBytes1, } - blk2 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID2, - StatusV: choices.Processing, - }, - ParentV: blk1.IDV, - HeightV: 2, - BytesV: blkBytes2, + blks := map[ids.ID]snowman.Block{ + blkID0: blk0, + blkID1: blk1, } vm.CantSetState = false - vm.CantLastAccepted = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil + var ( + lastAcceptedID = blk0.ID() + lastAcceptedHeight = blk0.Height() + ) + for blkID, blk := range blks { + height := blk.Height() + if blk.Status() == choices.Accepted && height > lastAcceptedHeight { + lastAcceptedID = blkID + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil } vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - require.Equal(blk0.ID(), blkID) - return blk0, nil + if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { + return blk, nil + } + return nil, database.ErrNotFound + } + vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { + for _, blk := range blks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } + } + require.FailNow(errUnknownBlock.Error()) + return nil, errUnknownBlock } bs, err := New( @@ -342,38 +356,6 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { require.NoError(bs.Start(context.Background(), 0)) - parsedBlk1 := false - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID0: - return blk0, nil - case blkID1: - if parsedBlk1 { - return blk1, nil - } - return nil, database.ErrNotFound - case blkID2: - return blk2, nil - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - case bytes.Equal(blkBytes, blkBytes1): - blk1.StatusV = choices.Processing - parsedBlk1 = true - return blk1, nil - case bytes.Equal(blkBytes, blkBytes2): - return blk2, nil - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } - var requestID uint32 sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { require.Equal(peerID, vdr) @@ -382,7 +364,7 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { } vm.CantSetState = false - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID2})) // should request blk1 + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1})) // should request blk1 oldReqID := requestID require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes0})) // respond with wrong block @@ -393,9 +375,8 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk0.Status()) require.Equal(choices.Accepted, blk1.Status()) - require.Equal(choices.Accepted, blk2.Status()) - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID2})) + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1})) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -426,7 +407,7 @@ func TestBootstrapperPartialFetch(t *testing.T) { blk1 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID1, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk0.IDV, HeightV: 1, @@ -435,7 +416,7 @@ func TestBootstrapperPartialFetch(t *testing.T) { blk2 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID2, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk1.IDV, HeightV: 2, @@ -450,14 +431,42 @@ func TestBootstrapperPartialFetch(t *testing.T) { HeightV: 3, BytesV: blkBytes3, } + blks := map[ids.ID]snowman.Block{ + blkID0: blk0, + blkID1: blk1, + blkID2: blk2, + blkID3: blk3, + } - vm.CantLastAccepted = false + vm.CantSetState = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil + var ( + lastAcceptedID = blk0.ID() + lastAcceptedHeight = blk0.Height() + ) + for blkID, blk := range blks { + height := blk.Height() + if blk.Status() == choices.Accepted && height > lastAcceptedHeight { + lastAcceptedID = blkID + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil } vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - require.Equal(blk0.ID(), blkID) - return blk0, nil + if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { + return blk, nil + } + return nil, database.ErrNotFound + } + vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { + for _, blk := range blks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } + } + require.FailNow(errUnknownBlock.Error()) + return nil, errUnknownBlock } bs, err := New( @@ -472,69 +481,27 @@ func TestBootstrapperPartialFetch(t *testing.T) { ) require.NoError(err) - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) - acceptedIDs := []ids.ID{blkID3} - - parsedBlk1 := false - parsedBlk2 := false - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID0: - return blk0, nil - case blkID1: - if parsedBlk1 { - return blk1, nil - } - return nil, database.ErrNotFound - case blkID2: - if parsedBlk2 { - return blk2, nil - } - return nil, database.ErrNotFound - case blkID3: - return blk3, nil - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - case bytes.Equal(blkBytes, blkBytes1): - blk1.StatusV = choices.Processing - parsedBlk1 = true - return blk1, nil - case bytes.Equal(blkBytes, blkBytes2): - blk2.StatusV = choices.Processing - parsedBlk2 = true - return blk2, nil - case bytes.Equal(blkBytes, blkBytes3): - return blk3, nil - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } - - requestID := new(uint32) - requested := ids.Empty - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(peerID, vdr) - require.Contains([]ids.ID{blkID1, blkID2}, blkID) - *requestID = reqID + var ( + requestID uint32 + requested ids.ID + ) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(peerID, nodeID) + require.Contains([]ids.ID{blkID1, blkID2, blkID3}, blkID) + requestID = reqID requested = blkID } - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk2 + acceptedIDs := []ids.ID{blkID3} + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk3 + require.Equal(blkID3, requested) - require.NoError(bs.Ancestors(context.Background(), peerID, *requestID, [][]byte{blkBytes2})) // respond with blk2 + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes3, blkBytes2})) // respond with blk3 and blk2 require.Equal(blkID1, requested) - require.NoError(bs.Ancestors(context.Background(), peerID, *requestID, [][]byte{blkBytes1})) // respond with blk1 - require.Equal(blkID1, requested) + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes1})) // respond with blk1 require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk0.Status()) @@ -545,8 +512,8 @@ func TestBootstrapperPartialFetch(t *testing.T) { require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } -// There are multiple needed blocks and some validators do not have all the blocks -// This test was modeled after TestBootstrapperPartialFetch. +// There are multiple needed blocks and some validators do not have all the +// blocks. func TestBootstrapperEmptyResponse(t *testing.T) { require := require.New(t) @@ -554,13 +521,9 @@ func TestBootstrapperEmptyResponse(t *testing.T) { blkID0 := ids.Empty.Prefix(0) blkID1 := ids.Empty.Prefix(1) - blkID2 := ids.Empty.Prefix(2) - blkID3 := ids.Empty.Prefix(3) blkBytes0 := []byte{0} blkBytes1 := []byte{1} - blkBytes2 := []byte{2} - blkBytes3 := []byte{3} blk0 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ @@ -573,38 +536,46 @@ func TestBootstrapperEmptyResponse(t *testing.T) { blk1 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID1, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk0.IDV, HeightV: 1, BytesV: blkBytes1, } - blk2 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID2, - StatusV: choices.Unknown, - }, - ParentV: blk1.IDV, - HeightV: 2, - BytesV: blkBytes2, - } - blk3 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID3, - StatusV: choices.Processing, - }, - ParentV: blk2.IDV, - HeightV: 3, - BytesV: blkBytes3, + blks := map[ids.ID]snowman.Block{ + blkID0: blk0, + blkID1: blk1, } - vm.CantLastAccepted = false + vm.CantSetState = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil + var ( + lastAcceptedID = blk0.ID() + lastAcceptedHeight = blk0.Height() + ) + for blkID, blk := range blks { + height := blk.Height() + if blk.Status() == choices.Accepted && height > lastAcceptedHeight { + lastAcceptedID = blkID + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil } vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - require.Equal(blk0.ID(), blkID) - return blk0, nil + if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { + return blk, nil + } + return nil, database.ErrNotFound + } + vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { + for _, blk := range blks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } + } + require.FailNow(errUnknownBlock.Error()) + return nil, errUnknownBlock } bs, err := New( @@ -619,93 +590,40 @@ func TestBootstrapperEmptyResponse(t *testing.T) { ) require.NoError(err) - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) - acceptedIDs := []ids.ID{blkID3} - - parsedBlk1 := false - parsedBlk2 := false - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID0: - return blk0, nil - case blkID1: - if parsedBlk1 { - return blk1, nil - } - return nil, database.ErrNotFound - case blkID2: - if parsedBlk2 { - return blk2, nil - } - return nil, database.ErrNotFound - case blkID3: - return blk3, nil - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - case bytes.Equal(blkBytes, blkBytes1): - blk1.StatusV = choices.Processing - parsedBlk1 = true - return blk1, nil - case bytes.Equal(blkBytes, blkBytes2): - blk2.StatusV = choices.Processing - parsedBlk2 = true - return blk2, nil - case bytes.Equal(blkBytes, blkBytes3): - return blk3, nil - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } - - requestedVdr := ids.EmptyNodeID - requestID := uint32(0) - requestedBlock := ids.Empty - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - requestedVdr = vdr + var ( + requestedNodeID ids.NodeID + requestID uint32 + requestedBlockID ids.ID + ) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(blkID1, blkID) + requestedNodeID = nodeID requestID = reqID - requestedBlock = blkID + requestedBlockID = blkID } - // should request blk2 - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) - require.Equal(peerID, requestedVdr) - require.Equal(blkID2, requestedBlock) - - // add another two validators to the fetch set to test behavior on empty response - newPeerID := ids.GenerateTestNodeID() - bs.fetchFrom.Add(newPeerID) - - newPeerID = ids.GenerateTestNodeID() - bs.fetchFrom.Add(newPeerID) - - require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes2})) - require.Equal(blkID1, requestedBlock) - - peerToBlacklist := requestedVdr + acceptedIDs := []ids.ID{blkID1} + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk3 + require.Equal(requestedNodeID, peerID) + require.Equal(blkID1, requestedBlockID) - // respond with empty - require.NoError(bs.Ancestors(context.Background(), peerToBlacklist, requestID, nil)) - require.NotEqual(peerToBlacklist, requestedVdr) - require.Equal(blkID1, requestedBlock) + // add another 2 validators to the fetch set to test behavior on empty + // response + bs.fetchFrom.Add(ids.GenerateTestNodeID(), ids.GenerateTestNodeID()) - require.NoError(bs.Ancestors(context.Background(), requestedVdr, requestID, [][]byte{blkBytes1})) // respond with blk1 + require.NoError(bs.Ancestors(context.Background(), requestedNodeID, requestID, nil)) // respond with empty + require.NotEqual(requestedNodeID, peerID) + require.Equal(blkID1, requestedBlockID) + require.NoError(bs.Ancestors(context.Background(), requestedNodeID, requestID, [][]byte{blkBytes1})) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk0.Status()) require.Equal(choices.Accepted, blk1.Status()) - require.Equal(choices.Accepted, blk2.Status()) - // check peerToBlacklist was removed from the fetch set - require.NotContains(bs.fetchFrom, peerToBlacklist) + // check that peerID was removed from the fetch set + require.NotContains(bs.fetchFrom, peerID) } // There are multiple needed blocks and Ancestors returns all at once @@ -735,7 +653,7 @@ func TestBootstrapperAncestors(t *testing.T) { blk1 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID1, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk0.IDV, HeightV: 1, @@ -744,7 +662,7 @@ func TestBootstrapperAncestors(t *testing.T) { blk2 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID2, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk1.IDV, HeightV: 2, @@ -759,15 +677,42 @@ func TestBootstrapperAncestors(t *testing.T) { HeightV: 3, BytesV: blkBytes3, } + blks := map[ids.ID]snowman.Block{ + blkID0: blk0, + blkID1: blk1, + blkID2: blk2, + blkID3: blk3, + } vm.CantSetState = false - vm.CantLastAccepted = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil + var ( + lastAcceptedID = blk0.ID() + lastAcceptedHeight = blk0.Height() + ) + for blkID, blk := range blks { + height := blk.Height() + if blk.Status() == choices.Accepted && height > lastAcceptedHeight { + lastAcceptedID = blkID + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil } vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - require.Equal(blk0.ID(), blkID) - return blk0, nil + if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { + return blk, nil + } + return nil, database.ErrNotFound + } + vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { + for _, blk := range blks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } + } + require.FailNow(errUnknownBlock.Error()) + return nil, errUnknownBlock } bs, err := New( @@ -784,67 +729,28 @@ func TestBootstrapperAncestors(t *testing.T) { require.NoError(bs.Start(context.Background(), 0)) - acceptedIDs := []ids.ID{blkID3} - - parsedBlk1 := false - parsedBlk2 := false - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID0: - return blk0, nil - case blkID1: - if parsedBlk1 { - return blk1, nil - } - return nil, database.ErrNotFound - case blkID2: - if parsedBlk2 { - return blk2, nil - } - return nil, database.ErrNotFound - case blkID3: - return blk3, nil - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - case bytes.Equal(blkBytes, blkBytes1): - blk1.StatusV = choices.Processing - parsedBlk1 = true - return blk1, nil - case bytes.Equal(blkBytes, blkBytes2): - blk2.StatusV = choices.Processing - parsedBlk2 = true - return blk2, nil - case bytes.Equal(blkBytes, blkBytes3): - return blk3, nil - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } - - requestID := new(uint32) - requested := ids.Empty + var ( + requestID uint32 + requested ids.ID + ) sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { require.Equal(peerID, vdr) - require.Contains([]ids.ID{blkID1, blkID2}, blkID) - *requestID = reqID + require.Equal(blkID3, blkID) + requestID = reqID requested = blkID } - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk2 - require.NoError(bs.Ancestors(context.Background(), peerID, *requestID, [][]byte{blkBytes2, blkBytes1})) // respond with blk2 and blk1 - require.Equal(blkID2, requested) + acceptedIDs := []ids.ID{blkID3} + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk3 + require.Equal(blkID3, requested) + + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes3, blkBytes2, blkBytes1, blkBytes0})) // respond with all the blocks require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk0.Status()) require.Equal(choices.Accepted, blk1.Status()) require.Equal(choices.Accepted, blk2.Status()) + require.Equal(choices.Accepted, blk3.Status()) require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) @@ -874,7 +780,7 @@ func TestBootstrapperFinalized(t *testing.T) { blk1 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID1, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk0.IDV, HeightV: 1, @@ -883,21 +789,49 @@ func TestBootstrapperFinalized(t *testing.T) { blk2 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID2, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk1.IDV, HeightV: 2, BytesV: blkBytes2, } + blks := map[ids.ID]snowman.Block{ + blkID0: blk0, + blkID1: blk1, + blkID2: blk2, + } - vm.CantLastAccepted = false + vm.CantSetState = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil + var ( + lastAcceptedID = blk0.ID() + lastAcceptedHeight = blk0.Height() + ) + for blkID, blk := range blks { + height := blk.Height() + if blk.Status() == choices.Accepted && height > lastAcceptedHeight { + lastAcceptedID = blkID + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil } vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - require.Equal(blk0.ID(), blkID) - return blk0, nil + if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { + return blk, nil + } + return nil, database.ErrNotFound + } + vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { + for _, blk := range blks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } + } + require.FailNow(errUnknownBlock.Error()) + return nil, errUnknownBlock } + bs, err := New( config, func(context.Context, uint32) error { @@ -910,54 +844,15 @@ func TestBootstrapperFinalized(t *testing.T) { ) require.NoError(err) - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) - parsedBlk1 := false - parsedBlk2 := false - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID0: - return blk0, nil - case blkID1: - if parsedBlk1 { - return blk1, nil - } - return nil, database.ErrNotFound - case blkID2: - if parsedBlk2 { - return blk2, nil - } - return nil, database.ErrNotFound - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - case bytes.Equal(blkBytes, blkBytes1): - blk1.StatusV = choices.Processing - parsedBlk1 = true - return blk1, nil - case bytes.Equal(blkBytes, blkBytes2): - blk2.StatusV = choices.Processing - parsedBlk2 = true - return blk2, nil - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } - requestIDs := map[ids.ID]uint32{} sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { require.Equal(peerID, vdr) requestIDs[blkID] = reqID } - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1, blkID2})) // should request blk2 and blk1 + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1, blkID2})) // should request blk1 and blk2 reqIDBlk2, ok := requestIDs[blkID2] require.True(ok) From 4f88827f7845b2c5b6511eaa91ee577dfe94c837 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 11:21:56 -0400 Subject: [PATCH 61/85] wip --- .../snowman/bootstrap/bootstrapper_test.go | 105 +++++++----------- 1 file changed, 40 insertions(+), 65 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index 24173ce9cf0b..3c5fa925c853 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -363,7 +363,6 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { requestID = reqID } - vm.CantSetState = false require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1})) // should request blk1 oldReqID := requestID @@ -896,7 +895,7 @@ func TestRestartBootstrapping(t *testing.T) { blk1 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID1, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk0.IDV, HeightV: 1, @@ -905,7 +904,7 @@ func TestRestartBootstrapping(t *testing.T) { blk2 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID2, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk1.IDV, HeightV: 2, @@ -914,7 +913,7 @@ func TestRestartBootstrapping(t *testing.T) { blk3 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID3, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk2.IDV, HeightV: 3, @@ -923,70 +922,46 @@ func TestRestartBootstrapping(t *testing.T) { blk4 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ IDV: blkID4, - StatusV: choices.Unknown, + StatusV: choices.Processing, }, ParentV: blk3.IDV, HeightV: 4, BytesV: blkBytes4, } + blks := map[ids.ID]snowman.Block{ + blkID0: blk0, + blkID1: blk1, + blkID2: blk2, + blkID3: blk3, + blkID4: blk4, + } - vm.CantLastAccepted = false + vm.CantSetState = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil + var ( + lastAcceptedID = blk0.ID() + lastAcceptedHeight = blk0.Height() + ) + for blkID, blk := range blks { + height := blk.Height() + if blk.Status() == choices.Accepted && height > lastAcceptedHeight { + lastAcceptedID = blkID + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil } - parsedBlk1 := false - parsedBlk2 := false - parsedBlk3 := false - parsedBlk4 := false vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID0: - return blk0, nil - case blkID1: - if parsedBlk1 { - return blk1, nil - } - return nil, database.ErrNotFound - case blkID2: - if parsedBlk2 { - return blk2, nil - } - return nil, database.ErrNotFound - case blkID3: - if parsedBlk3 { - return blk3, nil - } - return nil, database.ErrNotFound - case blkID4: - if parsedBlk4 { - return blk4, nil - } - return nil, database.ErrNotFound - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound + if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { + return blk, nil } + return nil, database.ErrNotFound } vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - case bytes.Equal(blkBytes, blkBytes1): - blk1.StatusV = choices.Processing - parsedBlk1 = true - return blk1, nil - case bytes.Equal(blkBytes, blkBytes2): - blk2.StatusV = choices.Processing - parsedBlk2 = true - return blk2, nil - case bytes.Equal(blkBytes, blkBytes3): - blk3.StatusV = choices.Processing - parsedBlk3 = true - return blk3, nil - case bytes.Equal(blkBytes, blkBytes4): - blk4.StatusV = choices.Processing - parsedBlk4 = true - return blk4, nil + for _, blk := range blks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } } require.FailNow(errUnknownBlock.Error()) return nil, errUnknownBlock @@ -1004,29 +979,26 @@ func TestRestartBootstrapping(t *testing.T) { ) require.NoError(err) - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) requestIDs := map[ids.ID]uint32{} - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(peerID, vdr) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(peerID, nodeID) requestIDs[blkID] = reqID } - // Force Accept blk3 require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID3})) // should request blk3 reqID, ok := requestIDs[blkID3] require.True(ok) require.NoError(bs.Ancestors(context.Background(), peerID, reqID, [][]byte{blkBytes3, blkBytes2})) - require.Contains(requestIDs, blkID1) // Remove request, so we can restart bootstrapping via startSyncing _, removed := bs.outstandingRequests.DeleteValue(blkID1) require.True(removed) - requestIDs = map[ids.ID]uint32{} + clear(requestIDs) require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID4})) @@ -1036,11 +1008,14 @@ func TestRestartBootstrapping(t *testing.T) { require.True(ok) require.NoError(bs.Ancestors(context.Background(), peerID, blk1RequestID, [][]byte{blkBytes1})) - - require.NotEqual(snow.NormalOp, config.Ctx.State.Get().State) + require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) + require.Equal(choices.Accepted, blk0.Status()) + require.Equal(choices.Processing, blk1.Status()) + require.Equal(choices.Processing, blk2.Status()) + require.Equal(choices.Processing, blk3.Status()) + require.Equal(choices.Processing, blk4.Status()) require.NoError(bs.Ancestors(context.Background(), peerID, blk4RequestID, [][]byte{blkBytes4})) - require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk0.Status()) require.Equal(choices.Accepted, blk1.Status()) From 21d1fd185c0640cc759e7962e6d0b3d3f5c630e4 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 12:55:03 -0400 Subject: [PATCH 62/85] remove duplicate code --- .../snowman/bootstrap/bootstrapper_test.go | 938 ++++-------------- snow/engine/snowman/bootstrap/storage_test.go | 30 - 2 files changed, 178 insertions(+), 790 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index 3c5fa925c853..989dc0774ac4 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -197,64 +197,8 @@ func TestBootstrapperSingleFrontier(t *testing.T) { config, _, _, vm := newConfig(t) - blkID0 := ids.Empty.Prefix(0) - blkID1 := ids.Empty.Prefix(1) - - blkBytes0 := []byte{0} - blkBytes1 := []byte{1} - - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: blkBytes1, - } - blks := map[ids.ID]snowman.Block{ - blkID0: blk0, - blkID1: blk1, - } - - vm.CantSetState = false - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - var ( - lastAcceptedID = blk0.ID() - lastAcceptedHeight = blk0.Height() - ) - for blkID, blk := range blks { - height := blk.Height() - if blk.Status() == choices.Accepted && height > lastAcceptedHeight { - lastAcceptedID = blkID - lastAcceptedHeight = height - } - } - return lastAcceptedID, nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - if blk, ok := blks[blkID]; ok { - return blk, nil - } - return nil, database.ErrNotFound - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - for _, blk := range blks { - if bytes.Equal(blk.Bytes(), blkBytes) { - return blk, nil - } - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks := generateBlockchain(1) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -270,10 +214,8 @@ func TestBootstrapperSingleFrontier(t *testing.T) { require.NoError(bs.Start(context.Background(), 0)) - acceptedIDs := []ids.ID{blkID1} - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) - require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk1.Status()) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[0:1]))) + require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } // Requests the unknown block and gets back a Ancestors with unexpected block. @@ -283,64 +225,8 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { config, peerID, sender, vm := newConfig(t) - blkID0 := ids.Empty.Prefix(0) - blkID1 := ids.Empty.Prefix(1) - - blkBytes0 := []byte{0} - blkBytes1 := []byte{1} - - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: blkBytes1, - } - blks := map[ids.ID]snowman.Block{ - blkID0: blk0, - blkID1: blk1, - } - - vm.CantSetState = false - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - var ( - lastAcceptedID = blk0.ID() - lastAcceptedHeight = blk0.Height() - ) - for blkID, blk := range blks { - height := blk.Height() - if blk.Status() == choices.Accepted && height > lastAcceptedHeight { - lastAcceptedID = blkID - lastAcceptedHeight = height - } - } - return lastAcceptedID, nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { - return blk, nil - } - return nil, database.ErrNotFound - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - for _, blk := range blks { - if bytes.Equal(blk.Bytes(), blkBytes) { - return blk, nil - } - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks := generateBlockchain(2) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -357,116 +243,35 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { require.NoError(bs.Start(context.Background(), 0)) var requestID uint32 - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(peerID, vdr) - require.Equal(blkID1, blkID) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(peerID, nodeID) + require.Equal(blks[1].ID(), blkID) requestID = reqID } - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1})) // should request blk1 + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[1:2]))) // should request blk1 oldReqID := requestID - require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes0})) // respond with wrong block + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, blocksToBytes(blks[0:1]))) // respond with wrong block require.NotEqual(oldReqID, requestID) - require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes1})) + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, blocksToBytes(blks[1:2]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) + requireStatusIs(require, blks, choices.Accepted) - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1})) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[1:2]))) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } -// There are multiple needed blocks and Ancestors returns one at a time +// There are multiple needed blocks and multiple Ancestors are required func TestBootstrapperPartialFetch(t *testing.T) { require := require.New(t) config, peerID, sender, vm := newConfig(t) - blkID0 := ids.Empty.Prefix(0) - blkID1 := ids.Empty.Prefix(1) - blkID2 := ids.Empty.Prefix(2) - blkID3 := ids.Empty.Prefix(3) - - blkBytes0 := []byte{0} - blkBytes1 := []byte{1} - blkBytes2 := []byte{2} - blkBytes3 := []byte{3} - - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: blkBytes1, - } - blk2 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID2, - StatusV: choices.Processing, - }, - ParentV: blk1.IDV, - HeightV: 2, - BytesV: blkBytes2, - } - blk3 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID3, - StatusV: choices.Processing, - }, - ParentV: blk2.IDV, - HeightV: 3, - BytesV: blkBytes3, - } - blks := map[ids.ID]snowman.Block{ - blkID0: blk0, - blkID1: blk1, - blkID2: blk2, - blkID3: blk3, - } - - vm.CantSetState = false - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - var ( - lastAcceptedID = blk0.ID() - lastAcceptedHeight = blk0.Height() - ) - for blkID, blk := range blks { - height := blk.Height() - if blk.Status() == choices.Accepted && height > lastAcceptedHeight { - lastAcceptedID = blkID - lastAcceptedHeight = height - } - } - return lastAcceptedID, nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { - return blk, nil - } - return nil, database.ErrNotFound - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - for _, blk := range blks { - if bytes.Equal(blk.Bytes(), blkBytes) { - return blk, nil - } - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks := generateBlockchain(4) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -488,26 +293,23 @@ func TestBootstrapperPartialFetch(t *testing.T) { ) sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { require.Equal(peerID, nodeID) - require.Contains([]ids.ID{blkID1, blkID2, blkID3}, blkID) + require.Contains([]ids.ID{blks[1].ID(), blks[3].ID()}, blkID) requestID = reqID requested = blkID } - acceptedIDs := []ids.ID{blkID3} - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk3 - require.Equal(blkID3, requested) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[3:4]))) // should request blk3 + require.Equal(blks[3].ID(), requested) - require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes3, blkBytes2})) // respond with blk3 and blk2 - require.Equal(blkID1, requested) + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, blocksToBytes(blks[2:4]))) // respond with blk3 and blk2 + require.Equal(blks[1].ID(), requested) - require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes1})) // respond with blk1 + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, blocksToBytes(blks[1:2]))) // respond with blk1 require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) - require.Equal(choices.Accepted, blk2.Status()) + requireStatusIs(require, blks, choices.Accepted) - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[3:4]))) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -518,64 +320,8 @@ func TestBootstrapperEmptyResponse(t *testing.T) { config, peerID, sender, vm := newConfig(t) - blkID0 := ids.Empty.Prefix(0) - blkID1 := ids.Empty.Prefix(1) - - blkBytes0 := []byte{0} - blkBytes1 := []byte{1} - - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: blkBytes1, - } - blks := map[ids.ID]snowman.Block{ - blkID0: blk0, - blkID1: blk1, - } - - vm.CantSetState = false - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - var ( - lastAcceptedID = blk0.ID() - lastAcceptedHeight = blk0.Height() - ) - for blkID, blk := range blks { - height := blk.Height() - if blk.Status() == choices.Accepted && height > lastAcceptedHeight { - lastAcceptedID = blkID - lastAcceptedHeight = height - } - } - return lastAcceptedID, nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { - return blk, nil - } - return nil, database.ErrNotFound - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - for _, blk := range blks { - if bytes.Equal(blk.Bytes(), blkBytes) { - return blk, nil - } - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks := generateBlockchain(2) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -592,21 +338,17 @@ func TestBootstrapperEmptyResponse(t *testing.T) { require.NoError(bs.Start(context.Background(), 0)) var ( - requestedNodeID ids.NodeID - requestID uint32 - requestedBlockID ids.ID + requestedNodeID ids.NodeID + requestID uint32 ) sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(blkID1, blkID) + require.Equal(blks[1].ID(), blkID) requestedNodeID = nodeID requestID = reqID - requestedBlockID = blkID } - acceptedIDs := []ids.ID{blkID1} - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk3 + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[1:2]))) require.Equal(requestedNodeID, peerID) - require.Equal(blkID1, requestedBlockID) // add another 2 validators to the fetch set to test behavior on empty // response @@ -614,12 +356,10 @@ func TestBootstrapperEmptyResponse(t *testing.T) { require.NoError(bs.Ancestors(context.Background(), requestedNodeID, requestID, nil)) // respond with empty require.NotEqual(requestedNodeID, peerID) - require.Equal(blkID1, requestedBlockID) - require.NoError(bs.Ancestors(context.Background(), requestedNodeID, requestID, [][]byte{blkBytes1})) + require.NoError(bs.Ancestors(context.Background(), requestedNodeID, requestID, blocksToBytes(blks[1:2]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) + requireStatusIs(require, blks, choices.Accepted) // check that peerID was removed from the fetch set require.NotContains(bs.fetchFrom, peerID) @@ -631,88 +371,8 @@ func TestBootstrapperAncestors(t *testing.T) { config, peerID, sender, vm := newConfig(t) - blkID0 := ids.Empty.Prefix(0) - blkID1 := ids.Empty.Prefix(1) - blkID2 := ids.Empty.Prefix(2) - blkID3 := ids.Empty.Prefix(3) - - blkBytes0 := []byte{0} - blkBytes1 := []byte{1} - blkBytes2 := []byte{2} - blkBytes3 := []byte{3} - - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: blkBytes1, - } - blk2 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID2, - StatusV: choices.Processing, - }, - ParentV: blk1.IDV, - HeightV: 2, - BytesV: blkBytes2, - } - blk3 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID3, - StatusV: choices.Processing, - }, - ParentV: blk2.IDV, - HeightV: 3, - BytesV: blkBytes3, - } - blks := map[ids.ID]snowman.Block{ - blkID0: blk0, - blkID1: blk1, - blkID2: blk2, - blkID3: blk3, - } - - vm.CantSetState = false - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - var ( - lastAcceptedID = blk0.ID() - lastAcceptedHeight = blk0.Height() - ) - for blkID, blk := range blks { - height := blk.Height() - if blk.Status() == choices.Accepted && height > lastAcceptedHeight { - lastAcceptedID = blkID - lastAcceptedHeight = height - } - } - return lastAcceptedID, nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { - return blk, nil - } - return nil, database.ErrNotFound - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - for _, blk := range blks { - if bytes.Equal(blk.Bytes(), blkBytes) { - return blk, nil - } - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks := generateBlockchain(4) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -734,24 +394,20 @@ func TestBootstrapperAncestors(t *testing.T) { ) sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { require.Equal(peerID, vdr) - require.Equal(blkID3, blkID) + require.Equal(blks[3].ID(), blkID) requestID = reqID requested = blkID } - acceptedIDs := []ids.ID{blkID3} - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk3 - require.Equal(blkID3, requested) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[3:4]))) // should request blk3 + require.Equal(blks[3].ID(), requested) - require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes3, blkBytes2, blkBytes1, blkBytes0})) // respond with all the blocks + require.NoError(bs.Ancestors(context.Background(), peerID, requestID, blocksToBytes(blks))) // respond with all the blocks require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) - require.Equal(choices.Accepted, blk2.Status()) - require.Equal(choices.Accepted, blk3.Status()) + requireStatusIs(require, blks, choices.Accepted) - require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[3:4]))) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -760,76 +416,8 @@ func TestBootstrapperFinalized(t *testing.T) { config, peerID, sender, vm := newConfig(t) - blkID0 := ids.Empty.Prefix(0) - blkID1 := ids.Empty.Prefix(1) - blkID2 := ids.Empty.Prefix(2) - - blkBytes0 := []byte{0} - blkBytes1 := []byte{1} - blkBytes2 := []byte{2} - - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: blkBytes1, - } - blk2 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID2, - StatusV: choices.Processing, - }, - ParentV: blk1.IDV, - HeightV: 2, - BytesV: blkBytes2, - } - blks := map[ids.ID]snowman.Block{ - blkID0: blk0, - blkID1: blk1, - blkID2: blk2, - } - - vm.CantSetState = false - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - var ( - lastAcceptedID = blk0.ID() - lastAcceptedHeight = blk0.Height() - ) - for blkID, blk := range blks { - height := blk.Height() - if blk.Status() == choices.Accepted && height > lastAcceptedHeight { - lastAcceptedID = blkID - lastAcceptedHeight = height - } - } - return lastAcceptedID, nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { - return blk, nil - } - return nil, database.ErrNotFound - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - for _, blk := range blks { - if bytes.Equal(blk.Bytes(), blkBytes) { - return blk, nil - } - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks := generateBlockchain(3) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -851,19 +439,17 @@ func TestBootstrapperFinalized(t *testing.T) { requestIDs[blkID] = reqID } - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1, blkID2})) // should request blk1 and blk2 + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[1:3]))) // should request blk1 and blk2 - reqIDBlk2, ok := requestIDs[blkID2] + reqIDBlk2, ok := requestIDs[blks[2].ID()] require.True(ok) - require.NoError(bs.Ancestors(context.Background(), peerID, reqIDBlk2, [][]byte{blkBytes2, blkBytes1})) + require.NoError(bs.Ancestors(context.Background(), peerID, reqIDBlk2, blocksToBytes(blks[1:3]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) - require.Equal(choices.Accepted, blk2.Status()) + requireStatusIs(require, blks, choices.Accepted) - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID2})) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[2:3]))) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -872,100 +458,8 @@ func TestRestartBootstrapping(t *testing.T) { config, peerID, sender, vm := newConfig(t) - blkID0 := ids.Empty.Prefix(0) - blkID1 := ids.Empty.Prefix(1) - blkID2 := ids.Empty.Prefix(2) - blkID3 := ids.Empty.Prefix(3) - blkID4 := ids.Empty.Prefix(4) - - blkBytes0 := []byte{0} - blkBytes1 := []byte{1} - blkBytes2 := []byte{2} - blkBytes3 := []byte{3} - blkBytes4 := []byte{4} - - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: blkBytes1, - } - blk2 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID2, - StatusV: choices.Processing, - }, - ParentV: blk1.IDV, - HeightV: 2, - BytesV: blkBytes2, - } - blk3 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID3, - StatusV: choices.Processing, - }, - ParentV: blk2.IDV, - HeightV: 3, - BytesV: blkBytes3, - } - blk4 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID4, - StatusV: choices.Processing, - }, - ParentV: blk3.IDV, - HeightV: 4, - BytesV: blkBytes4, - } - blks := map[ids.ID]snowman.Block{ - blkID0: blk0, - blkID1: blk1, - blkID2: blk2, - blkID3: blk3, - blkID4: blk4, - } - - vm.CantSetState = false - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - var ( - lastAcceptedID = blk0.ID() - lastAcceptedHeight = blk0.Height() - ) - for blkID, blk := range blks { - height := blk.Height() - if blk.Status() == choices.Accepted && height > lastAcceptedHeight { - lastAcceptedID = blkID - lastAcceptedHeight = height - } - } - return lastAcceptedID, nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - if blk, ok := blks[blkID]; ok && blk.Status() == choices.Accepted { - return blk, nil - } - return nil, database.ErrNotFound - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - for _, blk := range blks { - if bytes.Equal(blk.Bytes(), blkBytes) { - return blk, nil - } - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks := generateBlockchain(5) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -987,43 +481,36 @@ func TestRestartBootstrapping(t *testing.T) { requestIDs[blkID] = reqID } - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID3})) // should request blk3 + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[3:4]))) // should request blk3 - reqID, ok := requestIDs[blkID3] + reqID, ok := requestIDs[blks[3].ID()] require.True(ok) - require.NoError(bs.Ancestors(context.Background(), peerID, reqID, [][]byte{blkBytes3, blkBytes2})) - require.Contains(requestIDs, blkID1) + require.NoError(bs.Ancestors(context.Background(), peerID, reqID, blocksToBytes(blks[2:4]))) + require.Contains(requestIDs, blks[1].ID()) // Remove request, so we can restart bootstrapping via startSyncing - _, removed := bs.outstandingRequests.DeleteValue(blkID1) + _, removed := bs.outstandingRequests.DeleteValue(blks[1].ID()) require.True(removed) clear(requestIDs) - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID4})) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[4:5]))) - blk1RequestID, ok := requestIDs[blkID1] + blk1RequestID, ok := requestIDs[blks[1].ID()] require.True(ok) - blk4RequestID, ok := requestIDs[blkID4] + blk4RequestID, ok := requestIDs[blks[4].ID()] require.True(ok) - require.NoError(bs.Ancestors(context.Background(), peerID, blk1RequestID, [][]byte{blkBytes1})) + require.NoError(bs.Ancestors(context.Background(), peerID, blk1RequestID, blocksToBytes(blks[1:2]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Processing, blk1.Status()) - require.Equal(choices.Processing, blk2.Status()) - require.Equal(choices.Processing, blk3.Status()) - require.Equal(choices.Processing, blk4.Status()) + require.Equal(choices.Accepted, blks[0].Status()) + requireStatusIs(require, blks[1:], choices.Processing) - require.NoError(bs.Ancestors(context.Background(), peerID, blk4RequestID, [][]byte{blkBytes4})) + require.NoError(bs.Ancestors(context.Background(), peerID, blk4RequestID, blocksToBytes(blks[4:5]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) - require.Equal(choices.Accepted, blk2.Status()) - require.Equal(choices.Accepted, blk3.Status()) - require.Equal(choices.Accepted, blk4.Status()) + requireStatusIs(require, blks, choices.Accepted) - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID4})) + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[4:5]))) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -1032,48 +519,11 @@ func TestBootstrapOldBlockAfterStateSync(t *testing.T) { config, peerID, sender, vm := newConfig(t) - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - HeightV: 0, - BytesV: utils.RandomBytes(32), - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Accepted, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: utils.RandomBytes(32), - } + blks := generateBlockchain(2) + initializeVMWithBlockchain(vm, blks) - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk1.ID(), nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blk0.ID(): - return nil, database.ErrNotFound - case blk1.ID(): - return blk1, nil - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blk0.Bytes()): - return blk0, nil - case bytes.Equal(blkBytes, blk1.Bytes()): - return blk1, nil - } - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } + blks[0].(*snowman.TestBlock).StatusV = choices.Processing + require.NoError(blks[1].Accept(context.Background())) bs, err := New( config, @@ -1087,25 +537,24 @@ func TestBootstrapOldBlockAfterStateSync(t *testing.T) { ) require.NoError(err) - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) requestIDs := map[ids.ID]uint32{} - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(peerID, vdr) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(peerID, nodeID) requestIDs[blkID] = reqID } // Force Accept, the already transitively accepted, blk0 - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blk0.ID()})) // should request blk0 + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[0:1]))) // should request blk0 - reqID, ok := requestIDs[blk0.ID()] + reqID, ok := requestIDs[blks[0].ID()] require.True(ok) - require.NoError(bs.Ancestors(context.Background(), peerID, reqID, [][]byte{blk0.Bytes()})) + require.NoError(bs.Ancestors(context.Background(), peerID, reqID, blocksToBytes(blks[0:1]))) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) - require.Equal(choices.Processing, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) + require.Equal(choices.Processing, blks[0].Status()) + require.Equal(choices.Accepted, blks[1].Status()) } func TestBootstrapContinueAfterHalt(t *testing.T) { @@ -1113,36 +562,8 @@ func TestBootstrapContinueAfterHalt(t *testing.T) { config, _, _, vm := newConfig(t) - blk0 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: utils.RandomBytes(32), - } - blk1 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: 1, - BytesV: utils.RandomBytes(32), - } - blk2 := &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: blk1.IDV, - HeightV: 2, - BytesV: utils.RandomBytes(32), - } - - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil - } + blks := generateBlockchain(2) + initializeVMWithBlockchain(vm, blks) bs, err := New( config, @@ -1156,26 +577,15 @@ func TestBootstrapContinueAfterHalt(t *testing.T) { ) require.NoError(err) - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blk0.ID(): - return blk0, nil - case blk1.ID(): - bs.Halt(context.Background()) - return blk1, nil - case blk2.ID(): - return blk2, nil - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } + getBlockF := vm.GetBlockF + vm.GetBlockF = func(ctx context.Context, blkID ids.ID) (snowman.Block, error) { + bs.Halt(ctx) + return getBlockF(ctx, blkID) } - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blk2.ID()})) - + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[1:2]))) require.Equal(1, bs.missingBlockIDs.Len()) } @@ -1285,50 +695,9 @@ func TestBootstrapperReceiveStaleAncestorsMessage(t *testing.T) { config, peerID, sender, vm := newConfig(t) - var ( - blkID0 = ids.GenerateTestID() - blkBytes0 = utils.RandomBytes(1024) - blk0 = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID0, - StatusV: choices.Accepted, - }, - HeightV: 0, - BytesV: blkBytes0, - } + blks := generateBlockchain(3) + initializeVMWithBlockchain(vm, blks) - blkID1 = ids.GenerateTestID() - blkBytes1 = utils.RandomBytes(1024) - blk1 = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID1, - StatusV: choices.Processing, - }, - ParentV: blk0.IDV, - HeightV: blk0.HeightV + 1, - BytesV: blkBytes1, - } - - blkID2 = ids.GenerateTestID() - blkBytes2 = utils.RandomBytes(1024) - blk2 = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: blkID2, - StatusV: choices.Processing, - }, - ParentV: blk1.IDV, - HeightV: blk1.HeightV + 1, - BytesV: blkBytes2, - } - ) - - vm.LastAcceptedF = func(context.Context) (ids.ID, error) { - return blk0.ID(), nil - } - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - require.Equal(blkID0, blkID) - return blk0, nil - } bs, err := New( config, func(context.Context, uint32) error { @@ -1341,62 +710,111 @@ func TestBootstrapperReceiveStaleAncestorsMessage(t *testing.T) { ) require.NoError(err) - vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) - vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { - switch blkID { - case blkID0: - return blk0, nil - case blkID1: - if blk1.StatusV == choices.Accepted { - return blk1, nil - } - return nil, database.ErrNotFound - case blkID2: - if blk2.StatusV == choices.Accepted { - return blk2, nil - } - return nil, database.ErrNotFound - default: - require.FailNow(database.ErrNotFound.Error()) - return nil, database.ErrNotFound - } - } - vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { - switch { - case bytes.Equal(blkBytes, blkBytes0): - return blk0, nil - case bytes.Equal(blkBytes, blkBytes1): - return blk1, nil - case bytes.Equal(blkBytes, blkBytes2): - return blk2, nil - default: - require.FailNow(errUnknownBlock.Error()) - return nil, errUnknownBlock - } - } - requestIDs := map[ids.ID]uint32{} - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(peerID, vdr) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(peerID, nodeID) requestIDs[blkID] = reqID } - require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1, blkID2})) // should request blk2 and blk1 + require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[1:3]))) // should request blk1 and blk2 - reqIDBlk1, ok := requestIDs[blkID1] + reqIDBlk1, ok := requestIDs[blks[1].ID()] require.True(ok) - reqIDBlk2, ok := requestIDs[blkID2] + reqIDBlk2, ok := requestIDs[blks[2].ID()] require.True(ok) - require.NoError(bs.Ancestors(context.Background(), peerID, reqIDBlk2, [][]byte{blkBytes2, blkBytes1})) - + require.NoError(bs.Ancestors(context.Background(), peerID, reqIDBlk2, blocksToBytes(blks[1:3]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) - require.Equal(choices.Accepted, blk0.Status()) - require.Equal(choices.Accepted, blk1.Status()) - require.Equal(choices.Accepted, blk2.Status()) + requireStatusIs(require, blks, choices.Accepted) - require.NoError(bs.Ancestors(context.Background(), peerID, reqIDBlk1, [][]byte{blkBytes1})) + require.NoError(bs.Ancestors(context.Background(), peerID, reqIDBlk1, blocksToBytes(blks[1:2]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) } + +func generateBlockchain(length uint64) []snowman.Block { + if length == 0 { + return nil + } + + blocks := make([]snowman.Block, length) + blocks[0] = &snowman.TestBlock{ + TestDecidable: choices.TestDecidable{ + IDV: ids.GenerateTestID(), + StatusV: choices.Accepted, + }, + ParentV: ids.Empty, + HeightV: 0, + BytesV: utils.RandomBytes(1024), + } + for height := uint64(1); height < length; height++ { + blocks[height] = &snowman.TestBlock{ + TestDecidable: choices.TestDecidable{ + IDV: ids.GenerateTestID(), + StatusV: choices.Processing, + }, + ParentV: blocks[height-1].ID(), + HeightV: height, + BytesV: utils.RandomBytes(1024), + } + } + return blocks +} + +func initializeVMWithBlockchain(vm *block.TestVM, blocks []snowman.Block) { + vm.CantSetState = false + vm.LastAcceptedF = func(context.Context) (ids.ID, error) { + var ( + lastAcceptedID ids.ID + lastAcceptedHeight uint64 + ) + for _, blk := range blocks { + height := blk.Height() + if blk.Status() == choices.Accepted && height >= lastAcceptedHeight { + lastAcceptedID = blk.ID() + lastAcceptedHeight = height + } + } + return lastAcceptedID, nil + } + vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { + for _, blk := range blocks { + if blk.Status() == choices.Accepted && blk.ID() == blkID { + return blk, nil + } + } + return nil, database.ErrNotFound + } + vm.ParseBlockF = func(_ context.Context, blkBytes []byte) (snowman.Block, error) { + for _, blk := range blocks { + if bytes.Equal(blk.Bytes(), blkBytes) { + return blk, nil + } + } + return nil, errUnknownBlock + } +} + +func requireStatusIs(require *require.Assertions, blocks []snowman.Block, status choices.Status) { + for i, blk := range blocks { + require.Equal(status, blk.Status(), i) + } +} + +func blocksToIDs(blocks []snowman.Block) []ids.ID { + blkIDs := make([]ids.ID, len(blocks)) + for i, blk := range blocks { + blkIDs[i] = blk.ID() + } + return blkIDs +} + +func blocksToBytes(blocks []snowman.Block) [][]byte { + numBlocks := len(blocks) + blkBytes := make([][]byte, numBlocks) + for i, blk := range blocks { + blkBytes[numBlocks-i-1] = blk.Bytes() + } + return blkBytes +} diff --git a/snow/engine/snowman/bootstrap/storage_test.go b/snow/engine/snowman/bootstrap/storage_test.go index 92d927578437..a0c88c4f623b 100644 --- a/snow/engine/snowman/bootstrap/storage_test.go +++ b/snow/engine/snowman/bootstrap/storage_test.go @@ -17,7 +17,6 @@ import ( "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval" - "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" ) @@ -368,35 +367,6 @@ func TestExecuteSkipsAcceptedBlocks(t *testing.T) { require.Zero(size) } -func generateBlockchain(length uint64) []snowman.Block { - if length == 0 { - return nil - } - - blocks := make([]snowman.Block, length) - blocks[0] = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: ids.Empty, - HeightV: 0, - BytesV: utils.RandomBytes(1024), - } - for height := uint64(1); height < length; height++ { - blocks[height] = &snowman.TestBlock{ - TestDecidable: choices.TestDecidable{ - IDV: ids.GenerateTestID(), - StatusV: choices.Processing, - }, - ParentV: blocks[height-1].ID(), - HeightV: height, - BytesV: utils.RandomBytes(1024), - } - } - return blocks -} - type testParser func(context.Context, []byte) (snowman.Block, error) func (f testParser) ParseBlock(ctx context.Context, bytes []byte) (snowman.Block, error) { From dd98c10edb6fa03fdcc28e1addf69bf73c7fec11 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 12:58:34 -0400 Subject: [PATCH 63/85] nit --- snow/engine/snowman/bootstrap/bootstrapper_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index 989dc0774ac4..45ef9435b3c2 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -392,8 +392,8 @@ func TestBootstrapperAncestors(t *testing.T) { requestID uint32 requested ids.ID ) - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(peerID, vdr) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(peerID, nodeID) require.Equal(blks[3].ID(), blkID) requestID = reqID requested = blkID @@ -434,8 +434,8 @@ func TestBootstrapperFinalized(t *testing.T) { require.NoError(bs.Start(context.Background(), 0)) requestIDs := map[ids.ID]uint32{} - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, blkID ids.ID) { - require.Equal(peerID, vdr) + sender.SendGetAncestorsF = func(_ context.Context, nodeID ids.NodeID, reqID uint32, blkID ids.ID) { + require.Equal(peerID, nodeID) requestIDs[blkID] = reqID } From 81f4b67efe056d19997e75fc286e8d327a538b1f Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 13:40:54 -0400 Subject: [PATCH 64/85] nit fix log check --- snow/engine/snowman/bootstrap/bootstrapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 43b0c0b723c0..9f38dd59bfc0 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -591,7 +591,7 @@ func (b *Bootstrapper) process( height := blk.Height() b.tipHeight = max(b.tipHeight, height) - if numFetched%statusUpdateFrequency == 0 { + if numPreviouslyFetched/statusUpdateFrequency != numFetched/statusUpdateFrequency { totalBlocksToFetch := b.tipHeight - b.startingHeight eta := timer.EstimateETA( b.startTime, From 03a22b804d0e0b7bac02123697a152d71116cd4c Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 26 Mar 2024 13:54:40 -0400 Subject: [PATCH 65/85] nit --- snow/engine/snowman/bootstrap/storage.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snow/engine/snowman/bootstrap/storage.go b/snow/engine/snowman/bootstrap/storage.go index 764d74a7cfcf..4c35772bd082 100644 --- a/snow/engine/snowman/bootstrap/storage.go +++ b/snow/engine/snowman/bootstrap/storage.go @@ -206,9 +206,9 @@ func execute( ) log("executing blocks", - zap.Duration("eta", eta), zap.Uint64("numExecuted", numProcessed), zap.Uint64("numToExecute", totalNumberToProcess), + zap.Duration("eta", eta), ) timeOfNextLog = now.Add(logPeriod) } From ab8688c560ceb116b3df91a36a082b9db3a86674 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 11:04:06 -0400 Subject: [PATCH 66/85] add comment --- genesis/generate/checkpoints/main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go index 217ba2a602b1..b645beb32f61 100644 --- a/genesis/generate/checkpoints/main.go +++ b/genesis/generate/checkpoints/main.go @@ -30,6 +30,9 @@ var ( // This fetches IDs of blocks periodically accepted on the P-chain, X-chain, and // C-chain on both Fuji and Mainnet. +// +// This expects to be able to communicate with a Fuji node at [fujiURI] and a +// Mainnet node at [mainnetURI]. Both nodes must have the index API enabled. func main() { ctx := context.Background() From 29913c9ba94b8a4d3f10631fcec876a9b066c2e1 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 11:28:49 -0400 Subject: [PATCH 67/85] update checkpoints --- genesis/checkpoints.json | 215 ++++++++++++++------------- genesis/generate/checkpoints/main.go | 24 ++- 2 files changed, 130 insertions(+), 109 deletions(-) diff --git a/genesis/checkpoints.json b/genesis/checkpoints.json index df8dae2577fa..f5bc4de13206 100644 --- a/genesis/checkpoints.json +++ b/genesis/checkpoints.json @@ -1,120 +1,133 @@ { "fuji": { "11111111111111111111111111111111LpoYY": [ - "27UyZ7cK8Z4hieP9v7vt8nVzUWWG8dTevG4KG8bD1tdcW1WyLg", - "2JSAgjJYve7X8DGVfffpK3BcaToQhMoJZ99XjM4E2t7ddDuA9Q", - "2VmRST6sy1E9wandsgod7DH2ToenvmUaoDw54EnR2uGj6yzoY3", - "2atCgGVNqVEPFxeXkPx5efYbzPMRHnj4oaiNJmYgTMx2sRH1S1", - "2sDGZLbsjRRfLQHnsjp2fZ7bZNGihV5TJsxTAKXxna9tjQDLc", - "8khC8p1qYwWB5QoEXyQM4p8pRpirYMfb8HiM8k7nSbFHthRej", - "C6TbmVqoFhKZPB5aqqScRRvL6f3W4zKagAA7vfVdARxpJfMkU", - "FtwibNbLTvczaCyEH3FqRqTqQ4bTm2ZUKg6RjdttTFCFmxXBr", - "L472PqnP7C3n6ChqhuUePDWVsspx7J1Akbywuqub22qMqkV4r", - "VPV9gaqfhvggdWe8bEvPxmS5ZmsWe7Y8iFBd9mrzhdYn3GAYG", - "WvqDHkdLFS8LqtZrsmred5nxPYMRU3mN6pQpEp5kw1FVzV54d", - "euNKcrcf1EeDEiRrQtdEL7kj9a6CDjZXWMys7SLNYmu6eLhyj", - "uMvcoswATF22hc4YLNHTaEFqEz2bZdCM9q5HjVZEnhrnhRpTa" + "29tNQN5Q32bctp1utmDYtEQy3HDR1osWSjT6enzPCPu7aZgbfU", + "2ARQJfUoWxLrrdj95fWz5je5UAENyMkNtshxzojbAWLcTJ2Qix", + "2Nmy919z6GipCHTquUAsYbwuqpsPBcmtQPUgdoBDNxHz1wcv5", + "2Vt3MxgZcS9FdADU3EQ23ZDJLyhBLH2vrvvzk83WkFfXUFbCff", + "2WBWBSem499WVH7TLjmJ6eHNMUE97eHPumoQsW3G4Kvaza9bFR", + "2aW19sCe23hHV3U6vdqzBazt1rr5i7eiZwbyzV6BjJA2WTcC6s", + "2ecYzYceek6FAX9DsbryLy6eZKe7Z59DYUjQPhSpSwwza9EPV3", + "2nLRH3B3AFBrMe4nP2GTcnUSbW68agmEJ8G2M1NkcLfJySbQNu", + "2s1ba1qw9WYv87biWumt4A2MatbKhLpqqqCHcFR12en85dGNwv", + "2sy9iEarGLeQKMJiyBaSRDDBeqPJtXqoT2VJBYfZQBxVz3JBH6", + "9oYNsiaLXNAnH1wU5zNzNGYTKr5sBTGMHfBiCwCFmntMwuqPn", + "BKmKYwvvFszxoYaeKHfBikjWfL9fTnmbvcL4UAdhRkni1kF4n", + "DcMURdU3yZVgpqZHZhpsk6dXRpBt9gnhMfrfVGKMGUy15yr9Y", + "XBQLmGiD1oPGURQHp7aVfJJwftB3znK7zZuUGwiJcxp9RtgAz", + "druBcLhhqTyxkGTyieQNcnaBkJ8Z6VCMjbzzvWmXSoVazVdCt", + "g66txMyz1SmTYr8MR4VMCYvcaBD3Uq7hgvA8hZfpho2MnioqN", + "iqf8fdw8vN5wWsNhPTqwUfWdcxZD4ru3yvR7TKaLBtRNSB8n3", + "ue2e6kxrR4ZvgJcmmrQU9FsYkkfYVPBKYDtBK8bNSY1iNWJKv", + "viMudAudCxdqzJNJHpKG5P2Qc12Jna9jBLBeBsxhCCaCxVTVx" ], "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm": [ + "2UFZQKZ1gLuzqeEqX2sHLtZNL3Bxmv1NQL7GdqS6ZvSPMjkftT", + "2V3QXva1iArd88hVB7JsEK8tHn12a5qgifcPBkhpZGWc7fRRis", + "2bKoipmXErGTPCZedKDwPFKR8v6X7yGmtgZr5r3esN9cRZNxud", + "2d9azyeuYybkt25YBwSSVukSdWko2EB8Q1ii2TdvjuNoRwigJj", + "2hLra7rDjb77NNF3U9LHMAZ9MqnJzkAY5xEG8ebMjs2DGR1KQD", + "2hNwDNBFeaHZ93VicpE74a5PuLDbQYb71WHQUVdrHyy5ExXPLv", "2pCJ9gCnbCFC8e1xQNYgu63XQzCLqp9uupk7ePgDX3vWvwoPGb", - "3oxSU7pEZzr7MMSBLeWprp1e851JtwHT4YCvEzs4vzamAVCfj" + "2pWxqGSc8vPJQheXoJNaRRSA2NZKQ6wSdCvdhWXjuKS4VPdDCX", + "2wfMYUvLzxtHK5b8PE938LrMLpzL7pMkoFfVZ2P1wb65FVSMDt", + "3oxSU7pEZzr7MMSBLeWprp1e851JtwHT4YCvEzs4vzamAVCfj", + "CCgthPmrL6fsPRtVn5DJAkGs3wnYy8HUSNmJ4PCgDw2beZAKb", + "HEEvCX7Af3TPBAJ9KLji1fVfjHKH2ZJwVsV1BnzVKoSR8Xs7C", + "QwUfCXBeTiPL3Rv51CxT6BhDw1GkDbQovnQAWzp7sT5FH5a9J", + "a7d5UaCCbdW86qszpNc6WSow2a6RbNMALTLZwkjddk6WXfWEC", + "bV2La8TYp38PZZVHLcdf62dBxyshP5QdmxoM6AXwWwck6Bj5w", + "fr1W1wLpVup55hsC7wap8Ry2TThMxbQYFmV1s8h7RDMTm6m2B", + "iDTh19j3bYnSSkQ2zhpKYPFuep8hHZoRo6pKkWDotQU1CJzJF", + "iuaz5BC3icH5f8y6koA9DUpnA34hvUDB1UALnBYednBeztpqC", + "pUgAh6Qik6Q1zgK6iHRkPnW3KHQ4htPJVUQK4SNRFvN3bwvaT" ], "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp": [ - "21JL6NSfcwJWCtKqAV5fEzvcjXiDFbPJBqtNgWVmRphHQmp3K2", - "26ARTBTnBpALjtK4VcWbqE8GDwasYuHaCrpa4RBjrnxxurjaks", - "29yzKYLoKaDDbhTa4ugM91Q8fN2FWFXHwjFC4XhgFfPunc7xfA", - "2CTwkS8TRfNK91mRDV2Mtdm3vpCYWMSuTG6M6rS55M3MKrL3x", - "2Dm1gkhRHzc4VFDDFnPPc7SmbUngx9wEuDzrnx9nTXjB61oeDY", - "2KpmUTDDnrC7CS3dBZcD93gjrESwBiGQNw8ghgi6dQpcZvL7gX", - "2KwiBuGqgTpp5WFbYZgmEQsj37i8eEEyMNdrcwQCNzdWN34iUY", - "2QuQiJETyN82sicpwNVzoRNvs3eX7sQCiFE4XPHUCm5oVHoYYt", - "2Ts7VC5VUyJ6ug6KkzB7UdS5bPofkJAwscJNsH1KkiZzhdRXhm", - "2VD38bY9Mv17HhpbSGmvuXBCMuS85Fio4bk9uE5dktPtCjomJa", - "2cTVk64L5Ewbmz2xEjd2Yu9UznptZ3MW9EhELJvZYYi5XxCCgc", - "2jagCcJ1AtDZ3ksqbEs6F9TEXRn3YfSNNeGQsZwb8Wdzn24V81", - "2osF1mZCzHBn4kwfSi4hgDvcSDoB5X2yLFs7Cs3nikXQzd11un", - "2rnF1eYbGkFtm188NAqmAjGFS5Chn7wfDW4cmSerotZ3v7xhv6", - "59PZZ1DKTgCJza1xjgvKekfx3P61eypedPwWSsLTUmifppVZk", - "5EvUT2oCwMq33k1owWySBRbEWEXMbiKugZgNXUTgQUsjxyTPu", - "63JVNPfXguA6998RSH43eMdo6TrCLCd99ds8v5Ujmwp9pUacP", - "Esd2dUPSeKZvbFkJpeYxuDwL21HmWVtZ2bQc2d1XdpWVcmkuT", - "FpNdqmJfv3Lrct7UhieXaXYpAKyVmVuSbchJxUeBtpWaCqtm4", - "HJGuD27nX4RQnddgEMfpLtoiWEwjGYTqNMVcmrciZFTTCsDyj", - "JEde81vDS4Rvj9wbyDsAnRQ7N8YnxbXQojJaHTJk2i4dZqsbw", - "KmkaqscUQAZaWwvsawoMcHerGYZCJeE73wWSGhPV3GfsyYPMZ", - "NpeZvNuau3tgZY6b8qtsX8PFqbnFMesmHEy2GCAEq2k9KtWtV", - "ahtk5oCozDQDq9mkrJXDEtrSnc8gtCnEnqKb3aRKaVBcN58rK", - "hUqmvoNFTtArkS5n3PWeXUFoYdAFbMyxo545KE6uPtbQZ5H6F", - "jJwCiWtk3e3MxwjE4J5APR86Fgxkct9QDG38tBpvMc6LSk2dS", - "kB61R92fKJUxxSQPj5nMH5SMrHFBSbs7WgCVSF5Ha4WR69DhB", - "mka4V1BeCAUmLVki5YGLXSqXFZH5kzL2xGcueN64yVP8wmFB3", - "vad1jee6EYvjDKPgdQGW8dQ8C4CMqaefUPEbyE1yxfrjbQa2z", - "xD43ndAQFfo1RmRi3cHH6TDfGNPkR6bZR716NgB9mQx5eBXg9" + "24oHHzQ31BsSnjJWW3etryAcjZxPSDCCmvKxDGhDoh32wz2WgS", + "29Pvnpsk7dsyiUNz54N8QeVqFoZfBQwbomEgM456sNr9hPvA7h", + "2Ea9P8ewiCJeaUMtRheXcDUCPhoeBoDUHVqmeFxQa2BbV235h9", + "2LrW1m2ZfnNRRSRit7XGNAHACoa6m9HX5bmxx1WMNXefpCrzDq", + "2MtxhboDRKRTAk5e1gWnvq4T79g6f5KXfbGSGruz3pkHHEBzup", + "2PUFvRQp3c1gdey3L7ZKo6Z4MrmYwkn66xtRKoDiiGGiWDkkwC", + "2ZgS99T8Prxe7H5N6294VEj572CdTFM5QJ8pBfqhDTPL6yJVJq", + "2csX3osi3bqW3QJpDTTaKxGSqAHNKQpatBjCK6WkGdmAzzoYqS", + "2to9JmAAemySQRyYdkSmtU3b2kLCr3kf7oZafxbfrQRMRkfHDk", + "C3gGVaxvCRCTT1NEtTxD7stp6bq5mL5h8f1H4E7fUWPLTu9FZ", + "DBKAunfGhpueh7NxFdgTFYLesHTVUko9S6JxSGMkVDp4YwvpN", + "DVbAaRP98iuo5rT2RPSCD8UcmbjcwNBZRjMkpuSrbWLTNuB13", + "GocGoWcjGgTA5KpYaxF3zct7j8ArVDCjDprqV9M2Xsyh2qKSg", + "JNVs4LwY6TtmcNXTStXtiLEdd3arofcmKjiVy6BZrJxjdHE6M", + "NhoFHDoCBHcABEki4ye5GY5tQhDYc9EapvgwyjgAbw1KY6R3K", + "SaCfseHdFRLhNMHkxvNxjhFwzfUykNQdQapC5P8y3LNMHcksr", + "qizRThCQ227VPGEXfEnT9h6RzVPx5vKYEKX2PFeHrmkqkVJgr", + "sTiUYRycE2YqVECcy5zVG4PQhJ3bbDV43m5YjUG93WbcG4riY", + "swEd63Sn9V4sxkXjZgMZaxY5w3aGdcJV9i5ng8pg5Q5PozNbM" ] }, "mainnet": { "11111111111111111111111111111111LpoYY": [ - "2GF21ZWpvqaC1u1REKeDeaRHopLRiHvNN7nGrFzZwAyXVMnQtt", - "2PdY2BgLwvSk8jpuyVn2j1rwDqKbUATQGDpqxuwgdpziHUPPdt", - "2TpCtdtrMdQQSeUxbSoS7jp8EbmRhwDPuR71jLYkc6y7r5LPN", - "2dR4yFxErqppuhWGfZD1SHjryN6A8ajR7B8DJ2b26X7Z4qTHyY", - "2kLaFPNUZBcgxv7Agff2VaxwEmCeZwf1Zr99rVPU7BXc4mLzbZ", - "2o5CQWZY1uViNW3ejoTc6bhtoacDhH2TcEZdk1k3gqew7qtAq8", - "2oTyxikDac4xpCdzmSBHZAgfxRhYt98NENpUqriQKJPHek6pdv", - "2pE1vB9HxPVhxgR2WS98jvcGygQzg9kaTkxyZ5E9BiTG9a5FG4", - "2u1ccTx2BD8mrTf5dcLifCxGhUm82GD7qvW786V76S3dqe4Q9q", - "2ute95hYkTBrcNRQW7oVbhTP8t3HqqbRfrxAt7BT8Thf48c2RD", - "7HzrVujhGqLG8tJANXtNr8brT6ByyEutN6d1eTN3ixrC7jRcS", - "9HTMRKfXuzq3KVrKF7EEzXouDcB1M3asCexNqtJDg8CCGdMd4", - "9bhZfjd4jo2pgJS3sVtvwRiQzx7k4gFiabskD1Gka1Z6F4huh", - "AZz8jyYj3pfTT7TsTPBKiKB5ByxfUZu2ZsNFUYobAKyN5eFQ5", - "BP6HSddREevAhZ1axVWS33kAJvz3gk1pjL2zkY548xRBvEpAg", - "JAykub6SHtfsAxpeCsQfkujLYwVsAm1N6wnKeMn8Dxykys7dP", - "X9X4kPTriRrNb1Hui9nT7XnQAN5RdMjoBVwaWsKdM2mLpjqmk", - "XBeyojZENqRmjWbWiMYRZJmpeZdCEryL6iLPDzs9Bp3jaQ6g6", - "eZpu3i8otKKBEt1DRcM2cwJ1b6NeZV7QRsHbG17rjmjYjERwU", - "nTXX6XCNeRA7RqAY658a91tf5NjwsgZyhDshvWsjDooik6w3o", - "s8u9dvLEXQSjvhvo5Lp5qgDH8CiMnfimVEkjjKrLiiLgDBNB4", - "tEPEYtZkM4A47xxyZRNDRAQrHN4a2Y5j65rfzDTTKdW2ovnjw", - "vKBoQUUGnbQoHtHqxg7RVwBZxbBkPrQqrSamSevcsZKRif3Ad" + "28dGi9aKqLv4PxShLdtH3SMcrJQ29rYFZBux2N75yqZnwp2tSG", + "2EJQYgLNCy4UvmcRHxjM9Jmiedaz8zRPKMsATeAPRXgu1TL6NZ", + "2MTALukNfX7F4kb1bdmifKYNYun3cZvYrTbxi5rxcVJzrVFhTt", + "2PcPtUgRjhvNztbFWZyjn8CSV2LEM7tSmyF74YLHqwpWtHK9Tg", + "2WA6E6F4n9GBcUySrpmwkRoEaj3Dg5eeQiMiuxAr3sYz21y8Lp", + "2WQmtk8nd3YRMEu755TJpjyUrqXRYG5B2FvspEzU6BbCkeJN32", + "2ZNpSCqAsMMW7jfkzm4yn8mLexRhiKTww6EkLcBtB6TTRFFU62", + "2ZvwU2XKskNJ7Yr8CeMAFtQ5LWDuNVaL6zA6hyjz4pc5xHiDX", + "2iJuyWqd8AxbR2rTrS49REENAeqWGnUKt3wegqteE2mPEGoTsD", + "2pAywJdJFu4Crz59u75Lo5fzpQwmP2GHuuS1omp2z7VmAygQfC", + "DKMfVHKPF2GA1gmoKLBxJwNbrZGU9J8fnfs2vDntUXHWa1Qbz", + "PbnP2Gjr8qHgNriKRBp9gr3b1CWYBxjqheHFPXGDbca1Mwms7", + "S5KxF6sNcwKUhR2dMC9wCsdY8zFcPEGS9XYTNiiXhQnP63Evi", + "UsAALF2bfvxwnykySvrpTXQCwanQRS5Zy1LuR1M3aJYM7zfSE", + "VHRVMDeZRm85zPw9y6Z5JRx7HEnZ3hf5wp3H1KXxNb4hskSVh", + "XXKhAbeLeG9JYEmbjVjgNmYWFt3Hs7iso3hgWfjAQkrhP2HxU", + "kVU2k7YkeeTegtunQHhoRpzKrXffTVaTNM4TSXDFkP8BkHRtv", + "rk2VNXsSuR8WxureE9xpNuVVonmEJ32rixtzaFpbTMK7M8DNG", + "vPRhn3zforT9idV3GZNupvkfoeH84fdjwqqxExV8qadpQMCKP" ], "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM": [ - "25V23ZbFXr6qmZkmGaNGppRpRHqsUc5NXd7ack8aBPLiV7tRNF", - "25g4kcd6N7sv3NNkgrkujCAf2riouW4JA8LpjUg6qvzxDL9Tsd", - "2Mrm9TNbJhrMUzxwDtitH8LGTSfhjZVbVNsFMugddtAdAsaqFe", - "2Qny7y4zUEaEPghMg9axqfiFjWfEGx9ok4FzCumRGzN3eTrb33", - "2RioJaHRz883cJP87uaBQtnXMLesJorUP3yBw3AnDXBEy9jkSF", - "2d7hQSDVrMXEWwM65g4g7vC7SFYEhiRU8DRVcwR79Rdyy4LWJA", - "2umyLtWu9HKcKLFfHvPJ4Cw6Fh2P7ngbPMkqVK6EdAKa6JN9b6", - "7anFSrdJvD3dkRwJciEZXiuzjUtpt5NpRaAM6RuHEyQxJh7TU", - "DVXavgfkgeQpKh7BgGazfiiYC9frsdx7mipc2DJ8yy7cwhEPV", - "KzkUEjrBkGHgCgPqNv43dFWZBHN8J6cLTfvoAbPy97zHcdLyj", - "eNisZEUqAyeeNLXVUn1wfLqFf1D5a3AELz8KnoR3tj1kcrMTr", - "k54VutZaDA35VeCi9yAegWcfU9qVcnABJeax3BQM7bCrSQUD2", - "qkcnLHCgtJkFLcANQNRE7gdzG1UzBGhhek8ZJrVbAQDGuYMGt", - "tQHZwERneSsvkrgx3d8b22991SaSamxdARCcQzd2mZMbr2KrJ" + "26XHYKSUVPHYW4kxdyTTHsq5TUpJjJ1CiuG7wx987ZZvb6jq25", + "2ASoynxpeeNJHLPBt1hnnFebgGNYjmgg2gRDL1TFWUVmyrqvUv", + "2FXaca8JETKg37Zyxcjt7qnunSidMtu7esreSmLP3dkw265rxd", + "2QFbxT1EzUqp5Pz21TbE5c6ycAXuJEVZcdPJVFcXdk61at4zbk", + "2UheKUo59ocm6ziMSd34MhjR8vVndVRY3fY7mcWfa1dfVm5npF", + "2dBVRK8obttmY9MJ6qHJF6rUTxSoGDXjpDcBXFPch2VCFmY28M", + "2kgw6QPds6jRRp1hKEQXnRcpVtDDK8ACRByZPmpZXM7jDwWW6G", + "CmNBZXe3ftxsUnzAe9maTkWDfhTwyJTmHNB7U6tTdobdM2Zra", + "E5ybD9WaQEerLdMWV95x9i4synu32fih1tp8sbfd4mVKux9bv", + "Ff7fQTynJt2FKBvu25VfdwLKc52oWKLmuZWYgGVBV4twDFFgj", + "V4wNqSUz6a5P1DmdBXjmAvuXsn9bNnUUiQE1wCwZhAoQKf8hm", + "cYUfY7t3mPiArvHTStCpysnYhp7DB8NC6RT4J5THD65SpDUb9", + "dEeXZpwpWx26N5xa21XrLDtNQWUho65QSGq3y9KYZg1b4dF9i", + "dSKAYrvokjFCTUg8QSW6Hy77drj1bh7Wd17MG9qYFR2Zmqpr6", + "gK9Yo8Sapf2FTy1utHgJdepHQjuLQFwg9wooxHQqCYXdABJw2", + "vh88AVj7hkpQGHRXTzNGsrd7xSQPPy1kEChkzbaoyCy3UvEmL", + "vhTHvg9RecciepKJcYT2sHHuAjDPhUT7tNikEPHwHckv5CSrQ", + "z5tLKeF9H8V3Xu4VFSyCDLme1XS7M7L8MuPTTJM3H6jayopTV", + "zQtgyGJoAWzRYKAhFEPKSBkGdCTRx5ZZ5dMuG6NJUVeZVh7hF" ], "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5": [ - "25XhJmnidUnsWFGhrsgPhnwVV74vYNsRmPtr65xg7Spy6bqU6e", - "26nQJbkaALi5wZF6fKgcUbip5rK6DqKkuDu2rprUWAzGATP3mo", - "2HTKTdMGHTyUacDfzmEDs2fKVdzuumBkTFY2Rgkjt1yZPJhoCp", - "2JS1SKHSFNZnfVcyRCRXYmAsL4WMUc4TskwzY9w3r2t5GapDoN", - "2LZzxHPxKAkauVPf7Pn43SBQT46xDrbPTUBwnDwicaVSy1WgzL", - "2NpqFckbrnbZgGzw8sh1a9F1EAB6VLjFhPcnjTLoPdR26wWoq9", - "2XojhYy1mNkdmFZoCNvycB9QgXDHmFK53Qvc5iGk6e11kQbY6Q", - "2dwqBWd3P1h5Bzm3dhhqUiNizmHfYekAQK8qNVgpNooArjhfhG", - "2fXeVYeAFqSrBnKjQ2ubVvdxSTePDNpUbURjKwvHP4gs9RtoUu", - "2jupSbpuugeUd3Q9BAp7G7inHqBtjhh4mY7hi491bGXcp6V4fY", - "2suYWABBH4yE4UjMc1TzrZcgsNrQMy1rJcG6p7ckSQLk6e1ubq", - "2v45JaLJXdA1t2WPDYFxiieuX5cQ8oKF7pn9TqHJpoaBRkRNPG", - "A2bq6adFZmnizLXFS6yvLRXA74RfhrqJWAXZAJ4CzA8YtS5ot", - "NcaZhSi2DF9nhXsmaHRmHZQp7DaNdk54gLsa1w39bfZGUCkNN", - "NtbdHLdfQWeWqSdM1ZYQNfeFy39RoEzyfDZcdFTQpTYtf2S2o", - "PgHyVD222KcxHkBeoc41PH64dHRykyUo9fLT171VGMBh6xJy3", - "YW7BB7uo9wQwfC6kJ6JgGzarbtYm9s9a4mgUy9qrmwUCjq1KU", - "gTjiLnQCWjK4jWMbY2Do2VBoAERc2QuCqoghAVfhPceaKCysa", - "hLikKEdcco5VdxGpLyHW7PWw2X2rc7QBVpivuKtnDzLid73X4", - "hMkwsrAepCYKMc54s9b2pbGEf9wMQMND8Ek1dANNLEEwQAaQb" + "24SqsryHJRV8Q7qyPEruzXcj3yJfvgv5qequ2skJrEWoohpwm6", + "28BXQw5qfdwTHyV5p2pN9d6VzEahT2JWHT1Dd9RoHPLgC67gWS", + "2En3SNxo49Vdkx58J7UWvR5cwdXzbpt8cU6MS6dTgVdsYZBdHC", + "2K8tQm3BURGo8917v5nKm14yau8HzRHSvRYNSbHuebavaTy17i", + "2P4dyKpq25wGRokyCbidSKYXkhLJ8cpe7hUCp69aXwGr5rA5Jj", + "2PJpy8yqFWVm3Ew4qcuEe1rdnr5Uznq5X538G69YXuYAtY3gUS", + "2PzygucFpemhAAR53Jy34C3kgrUgAfGSbbj2UkUKn6AkAmTstz", + "2ahXAJ9teQE4nrExSt9J3r6oa9tCwLsP8fVsrLa7RnKHv8La9u", + "2hCKNRDwZSe9UhXcYUwaa6wHQzzyh4egQEexXncHKAnvXYdnTG", + "2rFR5KuqSo1dJtpYsNNrnWTYhmDN26s3zxSfBQphP61Xrzg5wr", + "2sdVixbBNZiAGnSska1m5YzokGPC9WP2arKWEidWZCCAF7BZYF", + "2uvUX23JiaNH8ZJnug75n3ummrxnjR7TWJPfvZ5goQDNY2TTH3", + "7v8FtNmL63T4U68cXutRABDRDWBFTLtGh7q5UuFtqouSMjn5j", + "KNTZTo5oE9npWbpGC3xYXcAN6sdS9hZ5wV6DVbZHyx4RY477G", + "KXVRT9rDVzRzvJz5ybuc4ogox8amHni9k7i61rGBztp9SYKEj", + "bNFYzR4XpAdvRHFAQxk7kPvCNUAFRThHdAeRUnZACmVfMfi3u", + "dCwyTrXC89Mcg6EkD77ERgCRnEdAjcad8c4SJGEvKkHQhN2zf", + "jhbWmPAWw6cuoJi7Z74B92wu4Cty17q3iR5hRv9KmEcFaUn4i", + "qE4UJDByJ1jPnbdx8j9z4QYa9xhD5DKZDvwJxFVQjm1QLt1zw", + "udtBGipZjvhWZkDxGkMceBzoRz3mrbc2eK6Acf81knaKmfTUk" ] } } \ No newline at end of file diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go index b645beb32f61..128c25699877 100644 --- a/genesis/generate/checkpoints/main.go +++ b/genesis/generate/checkpoints/main.go @@ -19,6 +19,8 @@ import ( const ( fujiURI = "http://localhost:9650" mainnetURI = "http://localhost:9660" + + maxNumCheckpoints = 20 ) var ( @@ -36,28 +38,28 @@ var ( func main() { ctx := context.Background() - fujiPChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "P", 10_000) + fujiPChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "P") if err != nil { log.Fatalf("failed to fetch Fuji P-chain checkpoints: %v", err) } - fujiXChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "X", 10_000) + fujiXChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "X") if err != nil { log.Fatalf("failed to fetch Fuji X-chain checkpoints: %v", err) } - fujiCChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "C", 1_000_000) + fujiCChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "C") if err != nil { log.Fatalf("failed to fetch Fuji C-chain checkpoints: %v", err) } - mainnetPChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "P", 500_000) + mainnetPChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "P") if err != nil { log.Fatalf("failed to fetch Mainnet P-chain checkpoints: %v", err) } - mainnetXChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "X", 20_000) + mainnetXChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "X") if err != nil { log.Fatalf("failed to fetch Mainnet X-chain checkpoints: %v", err) } - mainnetCChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "C", 2_000_000) + mainnetCChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "C") if err != nil { log.Fatalf("failed to fetch Mainnet C-chain checkpoints: %v", err) } @@ -89,19 +91,25 @@ func getCheckpoints( ctx context.Context, uri string, chainAlias string, - interval uint64, ) (set.Set[ids.ID], error) { var ( chainURI = fmt.Sprintf("%s/ext/index/%s/block", uri, chainAlias) client = indexer.NewClient(chainURI) ) + // If there haven't been any blocks accepted, this will return an error. _, lastIndex, err := client.GetLastAccepted(ctx) if err != nil { return nil, err } - var checkpoints set.Set[ids.ID] + var ( + numAccepted = lastIndex + 1 + // interval is rounded up to ensure that the number of checkpoints + // fetched is at most maxNumCheckpoints. + interval = (numAccepted + maxNumCheckpoints - 1) / maxNumCheckpoints + checkpoints set.Set[ids.ID] + ) for index := interval - 1; index <= lastIndex; index += interval { container, err := client.GetContainerByIndex(ctx, index) if err != nil { From baec0cc08fbc360c2fcb0491268e81fcde1d3359 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 12:03:48 -0400 Subject: [PATCH 68/85] fix merge --- snow/engine/snowman/bootstrap/context.go | 29 ------------------------ 1 file changed, 29 deletions(-) delete mode 100644 snow/engine/snowman/bootstrap/context.go diff --git a/snow/engine/snowman/bootstrap/context.go b/snow/engine/snowman/bootstrap/context.go deleted file mode 100644 index 3aa14bef5e98..000000000000 --- a/snow/engine/snowman/bootstrap/context.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package bootstrap - -import ( - "context" - "errors" - - "github.com/ava-labs/avalanchego/snow/engine/common" -) - -var ( - _ context.Context = (*haltableContext)(nil) - - errHalted = errors.New("halted") -) - -type haltableContext struct { - context.Context - common.Haltable -} - -func (c *haltableContext) Err() error { - if c.Halted() { - return errHalted - } - return c.Context.Err() -} From 5ab0a6efa0a1ac74f4ba5d9dcdef73b28740250b Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 12:13:33 -0400 Subject: [PATCH 69/85] update validators --- genesis/validators.json | 903 +++++++++++++++++++++------------------- 1 file changed, 481 insertions(+), 422 deletions(-) diff --git a/genesis/validators.json b/genesis/validators.json index a6a79e2a2b7d..4d3c616ab90e 100644 --- a/genesis/validators.json +++ b/genesis/validators.json @@ -1,45 +1,46 @@ { "fuji": [ - "NodeID-11114JmSuQh3uKVcgTTSfTDw1FkPQhg3", - "NodeID-11114UC8HucRiRbUuV4dq1VL5WQmM2fk", - "NodeID-1111SJCR5o7pRK817ZBY4tEeYRZEbhq", - "NodeID-1111ZgWnsrSvMjwG1DppPRFvcdQgwbk", - "NodeID-12BFLTEPWCwrWuK8PNf2Pui9N1MVXDwGw", - "NodeID-13yohiYMSFxpqnXiTDGRjGyhEPds8rLJr", + "NodeID-11112jHXqNowaUzgEwjMAdiKRm57b5cM", "NodeID-15uUYVJH5xM396PKH5d9GTjGErkciLdBx", "NodeID-1REAt4C9SQUo17pseGmHL2oNUdpkBkrB", + "NodeID-22hnv3WsLkax27PmQdYJrVRDJVm17XCCX", "NodeID-23GCcht221hDaKdtH8BhSLpUrugsfRAY6", "NodeID-24WK7qiKXAumya1kKEktwj2ubBbRyq5UW", "NodeID-24nupT8dLucgRn2HuYGzqUZEbkfKRaUnX", "NodeID-26yNpVkHNGxboUshTXtFAy76yYLmWa7bU", + "NodeID-27n6vtWe35N6JmbpVQKfeVqy7KJ874tFU", "NodeID-29tGiEe2rxuoHJgjEZ4sDytQAivwjJmaC", "NodeID-2Bxm4MQUKqq7yMtHLWsfYpKqRAfSterR2", "NodeID-2CDAbZAYzHv4imG3sC9hBx9WGMzJdAJeX", "NodeID-2CVgPTjtmaxSSjKuZXUwrgG4cPapmEgmD", + "NodeID-2D9EnSs4qEtZVPB2kxUX2xEATUUgXX3Nh", "NodeID-2GKxWMGx19NvTSorxibapih9DcuRx6WzV", "NodeID-2GXYggxghp56hz5zkdSvtVXEQ3AZB1gGM", "NodeID-2Gp8ZuzK92tZDzLknZxmsm48RvppFYSqc", "NodeID-2JGdGihFqGFcKEZEUswXDSWwaBJcU797P", + "NodeID-2MrvT4zf7GNN32eeGizM34s6UaX9SuZsx", + "NodeID-2PPDjKZvz1RTRiKQaojA4vsrno6N8mWuh", "NodeID-2PfNAhAG7nypsyDRHzPwZaZsDcj1jA6rU", "NodeID-2Pvoq8Stniirtie17djAh3ys7rUxn21F5", - "NodeID-2TXd5wd2Bf6pFG9C13fAtC65G7pnzo33x", "NodeID-2Ty5YxnuVTUkPX8SPMcS1b1qfE3sMbcRV", "NodeID-2bRcmz6BF39s7bMoG7wWPWST73LWcaAUp", "NodeID-2cU7F76JcCHXcsY6L8pMeHQBxwXqMumNC", "NodeID-2cu2JVaQDucg81tff1W4PBeZ5oMUG3vj6", "NodeID-2ebMFnGycbMsnxJ3VV2WLhJSQPLQUSJgk", - "NodeID-2j78EmuBiyV9CBfVHgA1juLJHZZp9qu98", "NodeID-2kwc3kKwtfgTQ7aPahndbHAer236maSBH", "NodeID-2m38qc95mhHXtrhjyGbe7r2NhniqHHJRB", - "NodeID-2mcgvk2tEnhaXseBy6BPyXivsVvSvSg8n", + "NodeID-2mMkmzYVHw4YWojaAuAHpNoEz3mqyEbBJ", "NodeID-2n8rK9kL8N7y1P6hyKu5ZwrMFUX1NEXG8", - "NodeID-2wQ6p4vgDiKFkeCR2MzZQ5aWQ3dCq6QfD", - "NodeID-2x51r8aE1QxG2Vs4vGXKeB1hi7bvTERPg", - "NodeID-2z5K9uUhQdVfAQjqfQSWAgCrjt2f1sFtm", + "NodeID-2pV9ukRgk7eBJR9Ab5DSZqU3uZSfA9TvM", + "NodeID-2vtBaWPqDCi1rzQWdmcSXG3R2hJbnpMvg", + "NodeID-2wejWSTCbLboLdsgu9YAUeT2h5bnpzcNc", + "NodeID-2ywA5crdZzPPV41rXRPkPktyRKHHSCdEZ", "NodeID-31NFpxN7VniDZbDDNkvvZaFuuNhDJyYro", "NodeID-33PdW8ge5VAHD98Bmxy6kYhm992Mhnu8x", + "NodeID-345wyACGatmkic8wWga8Tr4qxoeuoiZvQ", "NodeID-34qTBTrvhsF3MQDuwdNUDHBvj982Wm6NV", "NodeID-34sJYzSaqAD8GSoK1WVguqLgdg9uVotGH", + "NodeID-36e7GjwMCYr1d9tDUgUyz9swewgNhKArs", "NodeID-36ktMvm5GFTkfTAd5pPw7zpAXZG174Fvo", "NodeID-37fc7hgUGsXKxPx3rMYyBdHatNpKRb8z2", "NodeID-3932bao9oUnjfwGwWgsBk96M8rBhgQdeG", @@ -53,44 +54,54 @@ "NodeID-3KSEXMHijPpZbUHHgpqubFvjA2N4GJ6MC", "NodeID-3KixTZkLBUqrDDeaaEpXaTTiU4Qan9xdC", "NodeID-3M7L6w9a1G7o6ywAuY47HTnuGaMPZKQWx", + "NodeID-3M8ZqnsX6DDFkxVUnBzcKgVxce8vFLf68", + "NodeID-3NghhwXzgEMZNnjpJGiYrrpfCMNYCtbsf", "NodeID-3PjPmpuCghoVT7AJRb8qTjyZ6DtCPuURp", "NodeID-3QKhsmp2cj4eJ1hYecqQ6UAPYGTfZhWfr", + "NodeID-3RGiNDT55RwAQARCjrKgFc1hjdjVVchDR", + "NodeID-3RaFvh85MNRXdUmsjMPjvfNHmdbrSn9kx", "NodeID-3U18hPBaGyELh3ZFEBPsvidFv5gP2Pv38", "NodeID-3UhYTVhNbwBBALPyvwhRiGmgJts3obFvr", "NodeID-3VWnZNViBP2b56QBY7pNJSLzN2rkTyqnK", - "NodeID-3VteqBi7XCUxezhkqgoJ5ZejfRKWaLcvR", - "NodeID-3XynFeRRXjz7gKPWWdyfi7ymxFWi8LEyc", - "NodeID-3ZCAFhahev1RL1t1pt7cmL13mjCykhMLr", + "NodeID-3Z6K13A3BogE9oMPg81vWgfitgvN1kCRh", + "NodeID-3bqNW8gEe1uwQus6dr8uux2g227tnXB5A", "NodeID-3d2VDPUTpXd97ukrx9Faepmb79wzFicQZ", "NodeID-3dahoBAqDyB1vskabnMHPy47zg8gJ9tD4", - "NodeID-3e9afsN2qNVzgz7mCac8mcjDXgxpjMiWi", + "NodeID-3hdUZJo43ZTmFe6KdYxaPS92tqbR9woqw", "NodeID-3jFnB85bDiJ8f1G8EgptsZMENJfGCeBVD", "NodeID-3jbJ1eh1i8iqQKsrMjcG5WzAmPhkFU1Ds", "NodeID-3kuuAaJKZWFYp4dy8rcrBWVkV4LDb86hE", "NodeID-3nhpqPqAz8og2A2DBeVjb4fmFK1d2rRvQ", "NodeID-3oFxfDPzWo4YhvYzswCMzLrcJwx2UKkwV", "NodeID-3ry1arUtntKBQ4shFYgF9VB6AbGRHnPwe", + "NodeID-3tJhpEC14rjctSoh7ZN6TXAijmrMvjRNf", "NodeID-3uK65P4yQGns5wVB9Bv955dHP2rRiXzFF", "NodeID-3uRhwbfSajPyvWGaNSJyjhDKGPACGqHz4", + "NodeID-3um9mPx53CkfV1KSDdYkdrv6tEVR2E8vg", + "NodeID-3uq87hQvpuXWoqpmPhLRWavFpqzGDZbn1", "NodeID-3vtMDZ9Eqs3AzwNbqudMoxuUXyi97MKut", "NodeID-41cr9VeX852rtHrELWnHthUV4Bbm75WBY", "NodeID-468yx2KFJV9M7uNiTXJrbqyFGeQxgiBfh", "NodeID-4B4rc5vdD1758JSBYL1xyvE5NHGzz6xzH", - "NodeID-4CWTbdvgXHY1CLXqQNAp22nJDo5nAmts6", "NodeID-4DDjS32CM5oK7tbba8iNnXv7VWJsrynDu", - "NodeID-4FB6KKULLKMss9cAdfgabKqpEfDtaGPXd", + "NodeID-4H2NGT5zSc5Tt5KHTciLXVHW3CVofDmuG", "NodeID-4JwxRwRY8LgeSdDLNargL9NBEBUuvTk9v", "NodeID-4KKUrWvuKKEwNQWvZj7x6NDhUEan1m44C", - "NodeID-4P3c2QGazSpTXeb1WoPaD55hCiGUkKxSD", - "NodeID-4QBwET5o8kUhvt9xArhir4d3R25CtmZho", + "NodeID-4KXitMCoE9p2BHA6VzXtaTxLoEjNDo2Pt", + "NodeID-4LJNqmxdSigcw9wnGcd8nRP7Z4XZrEMyt", "NodeID-4RApHGzbpwtrUEbL9BpkV8AfdCzr1ciCj", "NodeID-4SdtN4zCP8h3ZEymEfGxJRocAu5hrwphC", "NodeID-4TJyt2f7zGuusjc1yXcBJnkNvDMAJ9py4", "NodeID-4WP36nX46eS27wcRsW1agg7bzpNDonEf6", "NodeID-4ZrTre1sS8qxndZvsMNzBGm3MxxWBpbJb", + "NodeID-4aAK5LmtRsrAGnZgHTWXcK8EwrtxEk26Q", + "NodeID-4aQfCERvSk5sn9SJfzGZtb4ea6UQtxXNf", + "NodeID-4aa1L1AKqdG76yQ7Y3eGYV1wProfTVjc9", "NodeID-4bPd6dgavJ9sggrbTMou3jkjcJ6Ng9L43", - "NodeID-4cJyBoufFfiMShtRhcd6WGTYdvUCE3Ai4", + "NodeID-4bo3ptnJcE25b9YSZvzUYxkXipqptKGer", + "NodeID-4dNvbt8gNJWXtTMA8BARk8haL8agc8emC", "NodeID-4eruhJFiLfkgmeKrG9udZthPCvGpyyw9d", + "NodeID-4jkdfkuyACE6K5YV3YtbCieZazm6Gjjat", "NodeID-4kMv27g3A6x2RMkiJjiK73zmAxvPDmbct", "NodeID-4kSPhc76z8Nxfta8gjxHDCHcNx7TrNSLX", "NodeID-4syxSZ2LPcCeE96VL1HsY3fx3AYnnGfsi", @@ -107,20 +118,25 @@ "NodeID-54RagM4VF5VNeKWoVV5UNHJfM6ccHtBob", "NodeID-54WkEbocc1ACvV6N6Qu4NVDGHGfpFhBzr", "NodeID-59HRzrFCmhEmUJAncPdXZ5H1NrreBQR6e", - "NodeID-5Duaym34R1PzdVKEeQNtqVKmoEvP8dfL8", + "NodeID-5KtwUENNLTnfjAeVWpED9jq2TeCPZjTxU", + "NodeID-5LtxGcaXocgCfx5qn2uMKiLnoJZi8Q11P", + "NodeID-5M11QQFMk3iqV8g6QoRiDNSDwR2XsQSe7", "NodeID-5RHueEiTPCFb2T8YuDid94rJtr31UvnYW", + "NodeID-5T4381mMgVqnW1b6y9ddyHBfYAqaB8C8b", "NodeID-5TcM4MkRoE7Vhnv9kcawSwpVSiTPDDBKw", "NodeID-5UVT7fNKF22XkWXMxCDvGHZW2auLgxprr", "NodeID-5Vd1XuN87ZgjBzpGL5NDhVPbmaqzd4YfU", - "NodeID-5Vpuk2sJiHhYjELfcRzYEws1iN64isPbD", + "NodeID-5WPHvkgxcwSE3XhuLf3rVNU3crqoF1BJ2", + "NodeID-5XgY2PdtB5DdELR3CzSt4U5gpC7XEUNVp", + "NodeID-5ZKjaekNVNoi6xaEEuKLQ6ZbYMQk4wA2u", + "NodeID-5aXqEaEkJH58WjMzuw6h8i7b16SNHq5uD", "NodeID-5aqkYoNRpwJ3EhBvc8uF3626mzfiUsxdG", "NodeID-5bGeKYsDjDfMwPAipVDPk5rYX5b8vc1aN", - "NodeID-5dCr6Szbv9p1RpUQWatYgNJb9wEBmhgAi", + "NodeID-5d7oCjzEfhVhRVtyR2FPEB7HVJ78N6dx7", "NodeID-5ewkSj3RxqMG7shRumy4USF5ibHMaFAJY", "NodeID-5fvPxB3edzXX3Eb5x5r7tbknoxqKyELtf", "NodeID-5ivzLGz96pAJWd3o83x4JWHTpWZoHJvc9", - "NodeID-5kJjV8Xa6RrkiwascxHUrpFQnPLcav3NS", - "NodeID-5mb46qkSBj81k9g9e4VFjGGSbaaSLFRzD", + "NodeID-5kGqjBKnQ9gEm6gBXieWvP9oGZoFXPA8e", "NodeID-5naAivQLhjbpVw35YGaD4HJwXTwuDufXA", "NodeID-5oRZWHEqipzXDnScB5UgPP5cUqfgPa9GR", "NodeID-5q6drRMuNYp3hfZokxgB2m5NxBoFZXc6X", @@ -128,88 +144,103 @@ "NodeID-5rZ6LbEm6o3baUxVyV4GV21sPD4QqjPk1", "NodeID-5tqDUvtVzpChaPgXcrXjuRRS5EJU648en", "NodeID-5vCs6XJWRNTLpAkQP2HK8fwprGb1v86Q9", - "NodeID-5wgChqKt5SksEAZtUDYcaUG41Y1v7KbDv", - "NodeID-5xyc9328PKgo98C2DvveTZ4Zqp237kN8h", + "NodeID-5ztQ9vcGysCVPY56bfht1GsxV6Xce6tJ2", "NodeID-653BnnF1HfEQY9APtAu7V23FNEmRMBGDW", + "NodeID-678Z9gkWVfFoAAnRJBEtgSm6Th6TUhsMa", "NodeID-67tGW3yXGqnDVnEwEAwVv84yZtm1AiZPA", "NodeID-6DjE25mD9X5AXWf8xpfgJ5tK94SFq11Vw", "NodeID-6DxE723urFNy3H7SyMMs76ZLRYx6bDJdz", "NodeID-6FgfGS3McpD27X8hdC7ZgQVhs6DoKvBzq", - "NodeID-6J3LY7ojkK7WCZzmArvxEozaESDMb42hX", "NodeID-6Kgqv9SV42oRBk2KNSRwFfJwsLBia49De", + "NodeID-6KtZFnJUHfu92NNRdgdea9ZA5mjbADDBR", "NodeID-6LZ6k2VRSdaF4qLHgfjER6gjVjrjDEAmm", "NodeID-6MnjianNNDMpLNhCnirZsw47aGGkkfCZd", + "NodeID-6N15qNZphbUdxRSfThfDbbFpgDdJvoHrR", + "NodeID-6NHaJnvJtHSbdtJHzdDesKdj3Wu9mAuNh", "NodeID-6Powgn3qZ8HZGmHUeQ7b1acypxzXhA9Lq", + "NodeID-6Pq5DKB1kzJjvnc8KPNSDYfMCsUGJxCyZ", "NodeID-6TrmPJiRneiG2ztDxBPWQAxAqv976ZJmU", "NodeID-6Uh985Lx96QQZ6LmbqJF1j4CxLu4ZCcd7", + "NodeID-6W4LCoXP8T2QYRGWcAcpNftMYyHcVuKCF", "NodeID-6YPFxT3358wbWFW6zHTnVtUYYedASEnVu", "NodeID-6ZmBHXTqjknJoZtXbnJ6x7af863rXDTwx", - "NodeID-6dfJg4Ttv3nEPJTakzmYwqv4Qny6fUjgA", + "NodeID-6edspGWTTSWm3N7Zot3kGrEMHPtLrK3VW", "NodeID-6f4T9BgmXJVJBNTwAj2giidTU7WiomG8G", "NodeID-6gVjCexoCvwXqApW3YVLnQSjsCUjbSDYx", - "NodeID-6jRufzNELpUH7jeTz71PhiKJvyjzWNjuf", + "NodeID-6iky1tgQsZupgN75GcSjFyJxC7a3rUc3D", "NodeID-6pMsJc16h9YF2mMY5VkZu8rDS5Qco23fC", + "NodeID-6qzz3HV9nEmVLrDKGo9L5k94BZksKgwXL", "NodeID-6tWHHU9uVWAf46qTYTsnTnVZJeL65hwgR", + "NodeID-6tkEtqzyUzqkPZ1KGH8XS9ZTasYGk68iq", "NodeID-6uRAYA8LDmiD4se1Ve9fBSRrjNi5TZjw7", "NodeID-6uicgS3fAizqshZgZPrNqm66YieUeZkbj", + "NodeID-6voVgdj8tVSWrgprYtrQYyidN8myXQUXj", "NodeID-6xEvEA7hcEAnqaXW7R9RFZSkdsAniHPad", - "NodeID-6xFbRUP8AZCCGDMYtu1P3g6zK9weKbQKT", + "NodeID-6z161fCLZDJjvLNSPXCK1bAxkK6gjiDXc", + "NodeID-6z3AiSaoYsmFgjqsc1w8rPx4vGaA3Bni3", "NodeID-77ebv49H9yRLLiUC46Hm9H371wXYNZNjL", "NodeID-79idCdyu498QoEFzvqKBbWFsXECKSYbpb", "NodeID-79u7mCRHvc9q5piSciiTphM8H1TDEq4Ab", "NodeID-7A8w1M4GpWHy8UMwQkARRoB9a67Rod7yR", "NodeID-7BPqDUFt9F5Vs9eqZiBYXmnaeC5UtZ2U", "NodeID-7DYhQRawvQ3hoDTfytAa5KHeMTUM7buBN", - "NodeID-7EP7QhMfQsBYa7CgwzCb82Fq4D39FvsjY", + "NodeID-7EexMiaXNY1HYVV7gWdXtsiKh8j9gW1Fy", "NodeID-7FXaqpRJgAPGWAUPs1UunagASkxPZps2D", "NodeID-7GM3ww9CL3uXtZuK6nSpdKJmEbiiyYgu2", - "NodeID-7GvViHLjftpvgZLD7RNo1YHZzt5iUihCf", "NodeID-7H5yeX5kkfdUBFCHLbDfDRxqWCDoFrCcL", "NodeID-7HvCZsgMXsCTjddz7cYNpKrGxK1i1SxMr", "NodeID-7L9oKJx6AsgGfG2GR8qQ7ndbKBVxqV9At", "NodeID-7NenT29nACMVLj8K685mBLodfp6GehVy7", - "NodeID-7QTLwAtcwhLPNFkmwyaXmC2tUW5CsgaS8", "NodeID-7QjQJHgVxMFBZzNG6n7ULTeaa7dAbd1U9", - "NodeID-7TwAjiRpTbNcqUx6F9EoyXRBLAfeoQXRq", + "NodeID-7SKSvUU5xyRiTJxsKsoeXnLa6idNEtZ19", + "NodeID-7Uq7GYJHYNh6LxFinWQpyB4ZitqDkUC6E", "NodeID-7XRaRs6shZG5VVVoaKeUxdJfbPmuVU4CB", "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", - "NodeID-7Z2Ca8HDwrD2QxWqGSR4F76xRp5Po4dhP", + "NodeID-7YJB8mcHCRmzsrrkxxpvqjyQH4cCEBXQq", + "NodeID-7b3i18ygt1A2gPpXKeEfAuC3ekHB5J4DP", "NodeID-7cukmtqdCLDWG6N8BJswwKidxe5iGyVvm", "NodeID-7dCZydYmPM846KqjhL9b4gRT1C7MDFFxG", "NodeID-7dZ86Yv4Md2dwhHPpJNyuh83LjKNKvw44", "NodeID-7eR9d4bjMsTgpwCbvXz4ynETmbXiQrJ1X", - "NodeID-7hwpMxuv6Q3yB4F19zXuk9n7n4oioiKZo", + "NodeID-7epJ8SkPeY9rL49JY8ELYJSduMt6eEnAk", + "NodeID-7fi9HdQSPQbnDrSjiVBUAAy5YfisSweEk", "NodeID-7kVsskXDhAQ2grucq8sUwJARmtqsTmw9a", "NodeID-7kfKeW5gRRVj7XgsssdWaKNU4AvC8dLiG", "NodeID-7peBGoPt8rGfPUEeH1VCqnKyMFJg9y6z", - "NodeID-7q4hAGaEeRrzWdCDQADFBdpXnJzv3bWuf", - "NodeID-7rWB8y7nQQSmSmmEBeaAWQKKZYG6SXpQv", - "NodeID-7smHERiKttWGYmBwxnpGJ8QBHA92eNtvC", + "NodeID-7rxhbsWmUqQ74N3FqoeUo1jpEspkEPeuL", "NodeID-7uXxUx1VAs3NUs2J472MdQ4V9xVNKZHxN", "NodeID-7yTMMzMTd1Fuct5tTeCB34HoZ9kLdKCpF", "NodeID-7zbpDafC5Rxm6ZMXqSrz9D28ZdC4WV7Hp", + "NodeID-83qSEo3NEDrRoNYzJJY4RUBM79cSz4zVR", "NodeID-84KbQHSDnojrmyuZjWM6hrM2vgPtMWt3", - "NodeID-84KbQHSDnojroCVY7vQ7u9Tx7pUonPaS", "NodeID-89GQ3qi4bif58ovQnQAehtccU8Jbynozk", "NodeID-89UCR1CsPzzEHuknxhJHKxuFPNCyPz7Bu", + "NodeID-8Bh3X1LH6uW1q2USKQeu11PAozaSMgEjr", + "NodeID-8CgGmdahNXvmuhyK7NziR9zTEMiArgrrr", "NodeID-8DLjsnc2R3mm64NJ5puhrgisrLXHXihKc", "NodeID-8F62HdqXVhqGTySVZ7HyQbEyFDMo33iKd", "NodeID-8JC2wNQkExELqhtzoGnyBcC7b5Su1C9ju", "NodeID-8JtmUUx6NHGVACFTReQbFxx1mWMJTdsWb", "NodeID-8JvHG2u3R6DLSBpv55rHhNvj7MCbeWRGL", + "NodeID-8L6pLG9PQ3XUhsWHT7E2VGuW1S5mgs6LG", + "NodeID-8Lf1apT2CuoLpsqF3sHd5DQCRQ4cs8oYX", "NodeID-8LjNUkzYVge7UvJkrJmaCYyWvmRb4oxoA", + "NodeID-8MXE4VNHGfx5d5NM7zVeU4KU8kZVs17VG", "NodeID-8PvUVsNyrXj2SpTyrfxM7AcgjWU4xCufs", "NodeID-8WJr4wGhcXChCXKXQpSidvTW5RiCQzX64", "NodeID-8XhZkWckQGKgzhv3XSmUeM3NSrskD4bew", "NodeID-8YHqGprPt4vva7TqVbzTtVFRv38BmpDUD", - "NodeID-8ZD8eAZmNvwtfuRC7uLj7PLqWgTK962iX", - "NodeID-8ZFQww8ESvtRDufva6uRbHpKW4D3ARvhU", - "NodeID-8Zf1gnqD7KuNhL5Ho13KB4QT5r86q3c19", "NodeID-8bVFU3U2PpHCwavsvzfMTE54cir79cmPr", - "NodeID-8eH3T4H9fwcgn1o4oNCxULXiiFHwiqy6W", + "NodeID-8boFLW2GXq6DxBRTxAguJ9N6dBYmBd2Ld", + "NodeID-8byCCMYn6aaNs4sQmwemcQfMwrnxBDA7U", "NodeID-8eZ8eW3Q2Kf6YV1wEVCaFpEsRMm2vfmqy", + "NodeID-8efhLH97RLg7fodqvk16qQbscnGQtV5CP", + "NodeID-8ftKdL6NkAz7K2yUJwNuhZJVLrNiz5qjN", + "NodeID-8gYpz72F1GBoTwufD9FfjESwKAnRRYnwt", "NodeID-8hqGf72EsTsRTWpP1kxGJkbzeJjnosiDM", "NodeID-8i9eqbVxzf2KtQkBPiX2BvZujYza6fDe9", + "NodeID-8jUnxLxkowHFhDrEZ1FmucLDC62c3xJVi", + "NodeID-8miY3PqR6f9C6GDr6WFqAwpqqVFheJhrP", "NodeID-8nCutCx3GgDYrNL1ancH4ZsE5tXHRYj2Z", "NodeID-8nXdZLTjc3FLaPGbS41WXt3Qwa3JvKaHF", "NodeID-8pDV7WK6kEp4mw2kupK1bSXTsShiZamE4", @@ -227,69 +258,68 @@ "NodeID-9B3HLkYWERnM5daHNb6XaX8on8WP3XiGE", "NodeID-9DQ6UMDYYWZccC5MRmT2xqE5TaMZUDbLN", "NodeID-9DnRjykQ4ZdyebJ3FeoqKBBjJcbMC4nsV", - "NodeID-9ENGXxXDAEdGcRNZ7UU4Cu1FSZssJQto3", + "NodeID-9FKZ4X9iEb3aBqmqzBHsu9kXmhn6aUhzd", "NodeID-9HUatTvqyEsDD4bUaocsDGpVeePh7KEdE", "NodeID-9KhiEguiCdK9KGCsfwkWY7M4VLvM5dbuo", "NodeID-9NsPTteByFVHbn26rvU9NjjLjRKKCR84g", - "NodeID-9PsQNVrDQB8PvyRKjCiK1x4pkGSNHnDtK", "NodeID-9QhM9oKKXbAV5xtfARnyKXM97L7nwvGSu", "NodeID-9TCq8np31pHjjhGaHtLjs6ptYYPEt3LGb", - "NodeID-9TrHs373qdrNrt1axAFCL4YX976pgfBUk", "NodeID-9X4SMAESCQz8H32PMq4wrSafx6sAUv6oN", "NodeID-9Xp5yzoLDUuCzUdaU6uFxXTjUYjwoCvPp", - "NodeID-9Y2jEfz3E452jT6QGSpJ5Kd7NLPbVPinz", "NodeID-9YzkgDFxmnRQxV4M8E7cuWPd5HukCaQkt", - "NodeID-9aqgQwSS5HsfP52YvvVKoB3E5ZTfQZxqj", "NodeID-9bk3GQD8qBvHfFTFaBCBURupAKLQEYg6", "NodeID-9c5whzpb1QstunxbQ9PGqKQLanAU32Wnu", "NodeID-9cQwDnPkD4Km3rQFvyJuWD5GUCMYrPHkk", - "NodeID-9hW5Lb3t5JMgP945DB8wHUJP73uLuDLAZ", + "NodeID-9dqCQXBAv1AdbNPrR4HCbRDgDjMebHk61", "NodeID-9j9p75hBtn6rMES3TuWrGc7Q7tQZrfWf5", - "NodeID-9nP42bsqJ3HkqLUwNnnCtTgDQ51QfPDgG", - "NodeID-9quZArokFFqk7EPAMJFYxa6KCcGWsbqj5", + "NodeID-9jTrqaVKZpevKsGoiixjVSAc8b2Md18RA", + "NodeID-9jpUT6Zjmsi2MjU8xBh5MWWR2rmTHuurM", "NodeID-9yrLEmUoyFvZ6MVwrtsXr82LpFExgsfim", "NodeID-A1SAHmXVC3D7dn67LPmWgd8bMvoNKgqTj", "NodeID-A1YeC21gHYrEf4HBdRvxFheviXct4MUQ", "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", "NodeID-A2Z8m7egVLhKf1Qj14uvXadhExM5zrB7p", + "NodeID-A3Y24F5vNuDy3L2pLwmvZG8s976nCQ5Mj", "NodeID-A7az7ffBywSGhgSGvwC2WbUgNxcQSiJD8", "NodeID-A8VrzZuMjMGkFce5zqSQ4nbSwUMwNmnHt", "NodeID-AAvXsy99V6dtcjwvweVC6FRWRk4fxwhjZ", "NodeID-ABCBD3w6GosyujRHjEAXfbRkU14YxX1Af", - "NodeID-AByPv1JZTACocLTLXzpqeWgDKkCkKqZvM", - "NodeID-AGxsF8rtNeZgsEFkK4urDff5PE2odBT5c", + "NodeID-ACQt5KkctKfdLSNB6bfu7dVzmsyqpm3z2", "NodeID-AHnXYg7f19R1MMmtt8D2yNejuBwha5i8Y", - "NodeID-ALEsCNXhMUCtphtQcxFQB6Q1bg6wXtXDX", + "NodeID-ANZVxnoYnsWdzBUQePUsXHC1pVSdsGNca", "NodeID-APKTqeD7UsfjYqfYBtDGaDCwLpr3ECVBN", "NodeID-APhFyzYExri3n5GtDz7ytXCgbt8x5NAud", - "NodeID-AQYxySZDaBzqEojxps2crnAf79UJYcCbU", "NodeID-AUFGUsjF8DR9cPfh4kLWCjtwdKyop1Y6H", + "NodeID-AYWEvPkJB7nePGujP9zWkHjrL76ppQqYK", "NodeID-AZsVs7FHdKmNfjDDesfRY5w9J3bJd2e9j", - "NodeID-AcDXsx3uYnVkZs5BJy496WfHe1NC3uaXk", + "NodeID-AeQY8TMBdDVVUgvsgRtZjFkArRybvbANS", "NodeID-Ahtb1pwX6ugZfmb8ioJrBRWkPqg762Ed4", + "NodeID-Amf3N6UZZ5Q4PukDPttqqMDrkjYyu7Qfq", "NodeID-AnJkYoj9mvGqv1A7WBujia17Hq1rDZp4Y", "NodeID-AnZdc4zkKTSkYUDUByvX6u3HJP2MU53Pq", "NodeID-AohNLSFbhRMHRdF9CPe72epbRtYPeZwjB", "NodeID-AqXr2RXWtX9FcPndqPZmEDHqfd8Rm5cxq", - "NodeID-AveomWdS99JgszXcmvcUn62EzoWGbu1We", + "NodeID-Ar9txpfoVW1LxzfYpQ1itPWpjq8b3c3s2", + "NodeID-AuyddbmFnAXCgeN388tMWzvAYu3nMzi4m", "NodeID-B1SoG2eCceT7YhdRq8EdcuVZgcXeWB5VD", "NodeID-B1jRRwEACvv92YJWyZrWwQn8DaAhEQA8K", "NodeID-B3KbeQXjwDat2ySJrVppBxRrTxb7RwRjy", "NodeID-B3si8iQ5MxJDRnwMBJyVt6puzici5tufY", - "NodeID-B4t2yBUNfc3fUg1639NSLoy39ui2aYtC2", + "NodeID-B5EdUCfcqnnHKgYzZfoVE3BBabQt165y", "NodeID-B6GaYh7RRopBAkQJGiMeMZAsAbHXyYi6e", + "NodeID-B7R5mup1BGypqosat4fvCxWXGgziRaZgB", "NodeID-B8SLANqFYZnUqfnWMuJjsjfzcN8Fxs9rp", + "NodeID-B8vH6dfELDJgPjYVMK5hjrRQkUMFFW7i2", "NodeID-BBt17ZXGPvov135835zT6BBAa6uTwriQi", - "NodeID-BFa1padLXBj7VHa2JYvYGzcTBPQGjPhUy", - "NodeID-BGrjjjfPCWR6pGWNTN7YcW1XtUKofMQsL", + "NodeID-BHM9wtsHVPmqKbfmqqHTvTCiM4YXoRSvs", "NodeID-BJjQb2PFLPiHsvejL2Q3yX28nqRxGxEqA", + "NodeID-BNYwWBYAidDqYiJYKhRahibQxPuG6hGvp", + "NodeID-BQTWT6W3Ke4PUweoYHThhuQgerhuAFVZH", "NodeID-BSE4qod6VYM7Xxeausg2UzgxZqMmTTWnU", - "NodeID-BSa2KH8iHJPibpJvNKEkswp8FDNub5v1f", - "NodeID-BTATPxEmZ5HoetuSpGDnPMzs6J6KuTEA1", "NodeID-BVXicWEU3ULP9aBsmRT82PLJMCXfdXDMp", - "NodeID-BWNtQCsbVKauhUwXik3iKZ5ibTCXQGPp4", - "NodeID-BXTBUqX8gitUDtVam4fhRWGD1SfeHGoBx", + "NodeID-BWhTVK8YDrRmK6NeoLDn8oSk7pGu9386L", "NodeID-BZq3oJcE1Unw1rYTB86B1q56x2VYQ7PwD", + "NodeID-Ba4X4hJ4bz51Hm1L6M4rRhu9JwniJgyUx", "NodeID-BbDHoP1Th9LSr8iEuoHktCF38MQ6Wx5Ws", "NodeID-Bd7EUL6WhVm1wF5bVNefWxHYsg8q2ttuh", "NodeID-BdhYSwf3LW3bBqt3235WS6Cw7P5GYDFSV", @@ -297,62 +327,76 @@ "NodeID-BemmZ7Y5HLGHSz2kUjmPUDD7bbJDebVd4", "NodeID-Bevezp7VTbNs4wGiiB115f8NrBwuRa79F", "NodeID-BffXkmzM8EwrBZgpqFp9pwgE9DbDgYKG2", - "NodeID-Bfg5ZtbEdFYJx8iVFGMxtS5YQoCZRCo87", "NodeID-Bgskmf8PocRPgtHgnAYKUgyifo9qD3Y5g", "NodeID-Bh1NKhN5t6MBcHvY7XuGhLK14q7FwQjmf", "NodeID-BhmBgAcV8WiNyrVUdDYJ9CVi7TvjPfJV", - "NodeID-BiRB38NNFxPXDbYbBp3oFJffJvDfC3fzr", "NodeID-Bk8Etvn1q5cEbZcn4y9QjbXoEAPwsHxB", "NodeID-BmkswdTypyATT3xP9as8BeUCyq2sGScBD", - "NodeID-Bqqf3VLNgeaFCRHevXVzZriYB3hLdW72A", "NodeID-BrYXghQSu6KKGjuzhs3nrkcB46Wc2yYHy", - "NodeID-BroSWTprybJuNtDcJ2hjHbsGzrvLkKAo3", + "NodeID-Bvr4dL7pK3FHqXvPs3X21y6QaZS86g4z4", "NodeID-C2Yoi9vTGPppDhpFMx8J1XvKJv3CY2x8n", + "NodeID-C34t8rtehJ2BXMkok68K7ZuUZEk9ryJrA", + "NodeID-C7E4ym1BsDbraGxymND3zGYHmo8SJfMRb", "NodeID-CA74JxFwV5BeRMCesYQruxjiKw4ofkEKQ", "NodeID-CBy6ZLEwBBuYFtVDDvz8Wra2AfeAd96fs", + "NodeID-CCDSFhaQAuXWpiLviESSUPJmWUUTVxdGj", + "NodeID-CCPjVQc87Ka7nbXVBN5cVtGTfTzPVnEyb", "NodeID-CET8PwdAu6Q2Cx7iqHrfdSyo4WEnkoxFr", "NodeID-CEzYD3rFjsGtKFu7JLGpD7rMcGRNJFLGB", + "NodeID-CKZg819tz5CXMxMtrRfKS8XxVURFDuHVB", "NodeID-CMSgVPNXC5R1kL19KHCNgbbRTeStUWPJA", + "NodeID-CMaW3TiXtNHzPGm7xzjkJvE8fthGibhAv", "NodeID-CNK8vDPGbKfS3YSptRPPN4VYUEpoNH4Vz", + "NodeID-CNp6HLV3F1RnbBF977E93KReTXTkZ4t32", "NodeID-CT2Fqk6d8eYAx627aYB8HAr7VjWHZYPQc", - "NodeID-CTL3MEW1JDE4iNayXgMjaoamy7i7TEyCq", "NodeID-CTtkcXvVdhpNp6f97LEUXPwsRD3A2ZHqP", + "NodeID-CU8Tq3pP9QniPeYWagh3TKDFccbvfwDkw", + "NodeID-CYKruAjwH1BmV3m37sXNuprbr7dGQuJwG", "NodeID-CZP8JG4BKdDyiktxg3D2ZYgREHtFhqzjH", - "NodeID-CZmZ9xpCzkWqjAyS7L4htzh5Lg6kf1k18", + "NodeID-CaHFWxHNLv1R4R9oGHMQR7n2vKy95LTei", "NodeID-CafHoeCqCjg8fWufaorRqFe3iX8s7z6A8", "NodeID-CcS3n2j4CEaQCEnY39qaBDZajeZaXkRGU", - "NodeID-Cdm8CPSJiHkZdWWZsPQ9iycBrCZ5CaGtN", "NodeID-CduWdu3Gv7bsqAxnsdTCWuuMEyLYQqchX", "NodeID-CehvZ1zrpo5HAb7K2sDiQcrks1Cn4d5Ew", + "NodeID-CfN57fb8f1jS3NWKsYSxfsHf2Lo8HUFSY", + "NodeID-CfdN2fVKKjDBRjqMLsxZNSaSKFdBgpMmr", + "NodeID-Ch8GJYTFsdPRzMVyWgVJTVV8MsHvbS4h6", + "NodeID-CipRaLt4Ym8yKegs45dpeEscA2x5w29Q9", "NodeID-CkS5zL9rUsJkYHgSMtoYF7yBwBCV6Gn3X", + "NodeID-CkWijvSj2dEenuJeXu5fyJcxc5Wtg1feo", "NodeID-CoKgGkWBUGouNZTqKCYLBNJ9dw4yJXUEW", "NodeID-CpLDjTHrAuB8p3G42uRtGhnGKJ5YzGkFa", "NodeID-Cq8kbEVqteYEqfNNW1CJSkrG7S16GiZ3u", "NodeID-CqDq4nGVYJoSgKVpZpyutzkZPfcugTdjG", "NodeID-CqGy1ZUkq4ZTznvsvzwwXtQiu8gBT3eYW", "NodeID-CvFCEpXymDz9A2EftqnJmCNi8qVHxwKXq", + "NodeID-CwcD65rnKwedLNcsc98MZK6RghPMptEyo", "NodeID-CyQc7xjJ2gJtCQNL6RVMEJf1KysJXG6QF", "NodeID-CyS27tGGmcmxeKhCuCwhT4GwiZGBE8QEb", "NodeID-CzBZTXGcxZqfB7UiN9ALzssfyHMWbMKH6", "NodeID-D3BkKn3N6chukRSZN3yr6zQvu4DgCSvp2", - "NodeID-D7WZhpVMpyCMtSenB5peUHuaQkokXZST7", + "NodeID-D3x6QzTaTdXxkMXYFx1MDc3T224H2Pmh6", + "NodeID-D6MxfVN4395J9jSmuPHDueQJue4Gitwns", "NodeID-D7jdvPnW8XX3Yz1k4YYKCZxaY1FF7x6at", "NodeID-D8bHw3BUjyGycV3dDTknNp1p6w8LHkNhh", - "NodeID-DDSorcx8EXWLLV5kECjjo9nFMUTA3kEUy", - "NodeID-DFzso5PTUHWDPe4qL64Ec5mnhGQ6LFhhp", + "NodeID-DE5iNyHAPisnXpaf8e16diJWL5y33VB7u", "NodeID-DJHKfhFKe4QjX6AY7tyj2VTjZrpxUWUyQ", "NodeID-DMbbEVaCyas1EXR5ubg2naKgEBmVerPne", - "NodeID-DQEFtYhQ3WUKQoVSTi6fH3MXhuBAPjKv1", + "NodeID-DQ4PJvysogwgzru7R8oDiRLv6qoF7Wwxc", + "NodeID-DSCwZSNFHcZFg5kbWrbbMHJNdpLUAuWB5", "NodeID-DUNsbAcHScpFE2uwBQ2o3SPZ46C2svMqq", + "NodeID-DV4fFyxuvwUUUQbTKuc9bYnRibVixtSDs", + "NodeID-DVQevoevYh5pYSNCwoGpn3QnqewfibCJP", "NodeID-DVZ7ffBkVkXDbpjGPEqwyYQgvcHhuTynj", + "NodeID-Da1yBnfJmUsS366wMN9b2Kzw3EL3WMdkC", "NodeID-DdhG9cNQmDpPwWSpEW9u6T7PNCc9GKv2S", "NodeID-DeeVioFXeoXx718FkbAk2unyikBN8iLJo", "NodeID-DfWyvyBF7XF33B9kkSiXYcJyzxRBATXN", "NodeID-Dh1JnVoEMU5zEQtvR6LHPVsyw6AGqbLuG", "NodeID-DhQSUszPR4zHoxF2Cicx3pCUnjrfsewnp", - "NodeID-DjUwAHNXgKWFRLJPN9LiMEGLtnFromVnb", "NodeID-DnyNinbTZWYSyoekJ1xMmh8TxQCw9kHdz", "NodeID-DonmTGabi4TZjWH1ue6W9GnHB9ZSjTrqG", + "NodeID-DpwRt5xkd3rKici9ikuo9aEH4AMfzsT7E", "NodeID-DqogihFFxTyKaUTqmjDt1Fh82hWwkeq9v", "NodeID-Dr3k3Xb2uFHqztcbVtAbbfhtrwYjsRysu", "NodeID-Drb1UM6uo69KiAy8tyD2QXv3JUGU9exaz", @@ -362,24 +406,28 @@ "NodeID-Dyd6GY1EnBTGi9WEMvFo7kkjsZBWWRDo7", "NodeID-DzyJouyxaQRYYyfYEvTaWrB4uaPTTKn2V", "NodeID-E1tni7wFcu9CizXdckfgxo9dhUwR3243v", + "NodeID-E24tDGQ6uRbTZaFCpqnUgZdWq2Y9YX4qy", "NodeID-E6CBZzykpEJSqKyNjDdFeLvDN1AmZccWY", "NodeID-E7Cm2d6wVhaA4Q7AnuRg2S3sD6noReX91", "NodeID-E7e5wZQb8QYEKYd1BrRrszjPxUaAQNaY7", "NodeID-E8dfbZCzX8VXgXYmjnA58GorajNrNcpFL", "NodeID-ECmPviPvgqFc4iXFi3soN1xpXnUUDHjoG", - "NodeID-EDESh4DfZFC15i613pMtWniQ9arbBZRnL", + "NodeID-EEuQumHSHr2hV4C5S2FNL8LVofD2Wvqyi", "NodeID-EGzKzc9RU6HGCzBe8nK2qY6mVs6WqroBg", "NodeID-EHV8d1ezFyoA8DMzTU3WZXfVR95R7v1cv", - "NodeID-EJ8BPX5xG4WDPAtcpTWWKVL9PCNJErsa8", "NodeID-ENMu41b1avXe4yRxmF1uzymNJP9Xf4jcy", + "NodeID-ER95YbfDrVih5Ja8F81ac1RZ3Bk8h6dTj", + "NodeID-ESYYcZZMJkLzC9raPoRvH4rUeErh6YF7P", + "NodeID-EThtNJN89zd1cGjVPyThdEwHknvV6XeML", "NodeID-EXuaP8HAE4anxXGR4QJX2em2nfEiTR9tz", "NodeID-EYEsr6Srmjn4XM8DijPFLFT3Hf7fsDMHA", - "NodeID-EZ38CcWHoSyoEfAkDN9zaieJ5Yq64YePY", "NodeID-EdSG1Dy4kqqaDJRn3kSAdM7RVSdW5eyyz", + "NodeID-EdbD6AHYPYNqv4X9KMUA4RBkuHnd54E9a", "NodeID-EfGKSr1JxRXofvpSo1kABnyjuyJWLr19K", "NodeID-Ej578hCdtGtaSQUMQFkPkoXVHHByJJzZM", + "NodeID-Ej5WQFmSCm27bZuRPoK6PeFe5tMURCgdG", + "NodeID-EjSCX6FJvzVA1gaja4cWqfaXEkZeAgnQb", "NodeID-EjvGBJ65yHcJMwV5RhDJBEcKb1QP4Du1L", - "NodeID-Enfkqb6z3yyuL9c9FGhWUmzMYp4kFE2np", "NodeID-EqJ1JGnx7zPAEvGy9JRgytDDTrsPtZUet", "NodeID-Et4ic8Ew2HhDqKzb4Zx68SMbC8mCLUWzi", "NodeID-EtBgBdH22chVR1fzZZPky3jzUZDTigCbV", @@ -387,92 +435,107 @@ "NodeID-EuQ17UhJAMCCPKo6qhEkeiEgeyNQk3vLt", "NodeID-EzGaipqomyK9UKx9DBHV6Ky3y68hoknrF", "NodeID-EzN4q9mU6TVFkND6oghbdLAUqDacE9Czp", - "NodeID-Ezs3eF4YftR5XQKvyN8NzRs5bzQC1QVm8", "NodeID-F19vhTXhznYNp6pAvaUmUpj4VWq7qjUyP", "NodeID-F3c4DfFS8crrJUyExRhgaMiXtZrn3TuP", "NodeID-F6AdvbZj7E2JZDfG9WhafyQeFAqiU3geT", "NodeID-F9kHeXw8eoxEMpKVCi7yCUwYGry5zPURy", "NodeID-FDXS1jxwngimMxWwdysC5N1dNZVPZ9GQ2", - "NodeID-FKxCgNYHFdfrwJUTyEvZx6vknoiywzcvL", - "NodeID-FMjQwTYbygN4dMc5csXuHkttP73SqFn5S", + "NodeID-FGA3erWUCbD9rUBXy1Ea2rzp4xas5zLgW", "NodeID-FPZ87ZH95TeFm1su82QJRX8PCJi4oBAoJ", - "NodeID-FPwz77ux26d2dyQji9ZrcLieVGUS7KFay", - "NodeID-FT1FE1i1J2t8QnnvbaxMqdyGy31N7MnfS", + "NodeID-FQ4TUmX7RFf84qxGPBdmPkrUCzCVoWuVR", + "NodeID-FQuy4XRiNwdHunxKvAEsSG7N2oTFvcKiJ", + "NodeID-FSDQT7qCdqgxZZq4AnFDcMpxukPrXUoyL", "NodeID-FT27zhjAL6HYVkfBHoWk8FQ3pCt4xyVsA", "NodeID-FTtpSNGEGH4HiQbi99qcgwGsgHthwMUGZ", + "NodeID-FXLBpf4W1QenLua7FMGTKqvk2Anobbi4m", + "NodeID-FYBQVFbWhaazHHXnr2gaVXdSqdGN5PBTo", "NodeID-FYD28utCsypYL6THXnyT8bTW9syP4WQrm", "NodeID-FaADDvJH51EAP4vhJEKCEfCtgpUUnTNX6", + "NodeID-FamFBmBfwGwjn7fKpbaWjzcnTiGNfmgWN", "NodeID-Fc8JvkNuUmo9oSy8jXiNXUczUM2q3jWrS", + "NodeID-FcG6viphauzUYhxsCtbaJUKqirYqp8YbK", "NodeID-Fcz43yNkFRu3jL97vjLi3ZkpmeAcVR8La", "NodeID-FdcqnJ1bwv976Ft4RibXmD5DTeWSnMzS5", "NodeID-FehvGhfc73qH6s4zTdiKrNA4WmSMbCW4X", - "NodeID-FesGqwKq7z5nPFHa5iwZctHE5EZV9Lpdq", "NodeID-FfiosnkKYLrMKoUpNTuFZz6gY5kb9cPb2", "NodeID-Ffr1YgeWw3h2Ct9dY7V3u79ScrAbhSUUz", "NodeID-FfxNCp6tZxTpj1JxA8GGVTtJWowqKDmvY", "NodeID-FgvaeMrL2GqxSBV9R2hkLL7jH29vhBeao", "NodeID-FkbkPTVMLbZZJKFHYUKZTt1Z3quNUurV", - "NodeID-FnWP36cM3Sgw351JmpbzJSScnDoaANehz", - "NodeID-FnaPiXmmbc79HUCCuzN7FF86vsJizdfa", + "NodeID-FnQRH8p5JrhLRUT9wK2rtEc17EtN8Tcb1", "NodeID-FnsrF37UrgFtzoEKNxyAV7wN516SwqFVN", "NodeID-FqAXbqQUVaXS6z6jTaLPZGivbLnHf3G7q", "NodeID-FsBU6yEVf9ZVEhuFy5sRixYwio3LRN9Ey", - "NodeID-FxHNunDVymBHtATSVZc9BusCtFL2B4Gcv", + "NodeID-FvMWujr57hToQPSfGsd2exqaFBdZzJBTk", "NodeID-FxgVB4Wwgg4dZ5WTkkBp9EbwJhAgwZgWd", + "NodeID-FynRLYTNZroGso229UyxpxsjqmQqJgAQF", "NodeID-G1MJv3mVMjo2SueWzr6rvn1gWyAvgTXrQ", - "NodeID-G46UpgR7qUjbM8U52MStLHuQonVAHQ7ui", + "NodeID-G3axaqp4Grtc2S6LD3qhFR3wN1NEZRuGx", + "NodeID-G3h4X9o4Rk71ijtpEdsQpjWCM46GNCXPk", "NodeID-G4Za1ZuLLinkM5skf1LZqAWqKs3P5xs7F", + "NodeID-G5p6Hn8XFSQJKH1YzA5iS53rgDfCCE7a6", + "NodeID-G6g8fYiCrp6ZNryP3Ni2fJKysDxHbaafU", "NodeID-G7fjDTJ9DH2P3ckC4VqKvH9q9Zqsv9b6b", "NodeID-GDZpG8cVCndUcnoHiub4XPM5WR2hF7tmk", "NodeID-GEC1zVazREQmLUpj1fF2qvuATpRvMgf62", + "NodeID-GHvQsCAUehhZi5psMeBxDfKHuoVGfRoDt", + "NodeID-GJsdSRahtgdsTBjr3jbew5uqTXLcjJkG9", "NodeID-GK8GSuLrw6jk9CVZ7ryAjSTm3pFEmeVF8", + "NodeID-GNJqrL7nMYPaYXcrSSfsY7ffe5JAzTRGh", "NodeID-GPc1Si7SQ6oAEfP8MzQ3cFN3fsAtkwC6i", + "NodeID-GQTbQ8qJYwBEhQEa92V1yjHzeVyjTDKFP", "NodeID-GR5Hc9oEi2AvNBAoUaQDZtWEYz73jP6jq", - "NodeID-GRG3yvkpJJ1zAxxjpHYuvXaNSgPoWwiaW", - "NodeID-GRTQxKr1NMbxPZTBWkHKUg72jCgtwd37y", "NodeID-GTgPUiVqjBX1UAFmdDmBoyHuiRhTPrZen", "NodeID-GTx2HdjpdzYuQEpjrKnuuvXDzd8XPBxBG", - "NodeID-GUUNt9rB66P2HE2Nmke3Bq6Hw7K2pe2Uy", - "NodeID-GUkLRudNfaCjrKSbmAgG4TDVanAixyrG1", "NodeID-GWRSuAdKF4LjKSgEYFXR1crtjov8vnW4a", "NodeID-GXtJyspnxHxzLWWyUqJ3xgXNidoxwAtdw", "NodeID-GYXpBJh1SYjG9heFSV51NVhJHh5LindGx", + "NodeID-Ga88DP7f7F12ePN3LEYUGge9kjKi3qHP5", + "NodeID-GbUcqW9qSUuKZPMJ89qL5YJWDfAuUjdq5", "NodeID-GgDJXjd35ewugJyG9tonbjBEKVZambFAb", "NodeID-GhLyXd9aVH4xujx9SzC9oy2JcQQ5amXuC", "NodeID-GhsAAVi8nXhvLS1Xv4ast3EbcL4BDU8NK", "NodeID-GiAS7J8Aiuj2iBAnKT2wmnxWWqp1QLd2v", - "NodeID-GiQ2h9z9qok5FKJV49hitcyWiu7RLwR67", "NodeID-GkiKRa6ww4zJqXKQUcqHXnGaRKD6JNoYx", - "NodeID-GmQXASjUEx7pRPkJEMeYD23PsxTrStRGw", "NodeID-GoVFrxwF41mzpVyt6Pb8K83ynj3q2U1CV", "NodeID-Gohrw1ApuWhwFwUbCLKjS6hbijukerjuo", - "NodeID-GqqRC1EFp63nGjHHuwNZu6NqqqyyihS5Q", "NodeID-GrL2hD5CdKU4CE8fbN97kVH5DpztHMLPX", "NodeID-GsGzZFRypbZdhosjortCTbGCHiMGAifhw", "NodeID-GsoJqaJe9SBrouxVCtSriYE64e2cQB4NP", "NodeID-GsufzM4GKTutEFEAkDunS2wkhjdUPUvCu", "NodeID-GtJaZR21ZmzB8CcPYXVA2Ks6Qgb26upj5", - "NodeID-GxKwZRuXEtYMgd2JbXZS1iCeh18NhGnaK", - "NodeID-H4UuVAHhJGARXDJc11NP6Rdejh5chhACW", "NodeID-H5Kcdpnye7iumF8ad4EHEFxvYzPAg4o89", + "NodeID-H5yv8taAdDWeCGNSLzdM1u2FA9cavk8ka", + "NodeID-H6FuMzUuGxjcko4hoBhPaZ56F4pheS2Sj", + "NodeID-H6Y7aEKkKz5HeWp4nE7nKHR4PUksjBuke", "NodeID-H7Wq3A1RJsb5skBd9iy8zY37yW72zrNLy", + "NodeID-HB5cY5e67mzjNwrcqucGAxh7SyNMWLY2z", "NodeID-HBkBmNgoiab6dDBZ3d7Atiq8ja9achxwV", + "NodeID-HD9qhGtz18TdEbLeuMhn4ZXNCxvdvQTwy", "NodeID-HDcjsGMHLaLgJFoQYmi4CBsbjMKPacuP6", + "NodeID-HEdbAzR9GLht5p6b47J214UhdshCDX9TP", "NodeID-HFEef35BkgqRBYiQ2ou5JhsyB8LHRtyuo", - "NodeID-HGZ8ae74J3odT8ESreAdCtdnvWG1J4X5n", "NodeID-HHXxANboEXufRMuSFBHgc5dbpk67L7XPV", + "NodeID-HHcVpHweLyANYAB3UoDYrBQLDznFeS42j", "NodeID-HM73QztvPuGikaADwnjpaJ1iKWAABuQon", + "NodeID-HME2ASYZmCcpRRpKQRsCLPJ83ZkWDBkQ5", "NodeID-HPpKmAyrXsouQTaxMJR2YFgSDVV8BA5xP", "NodeID-HQ4mk1kjeNvfsan5qrmynaMhQLCsQ4pYv", "NodeID-HThbCMfRbs6nVRR1ySihYtWLraLZw8x16", "NodeID-HTkPf7hwzrLyDDjAZAqMNQh9oF4B9iebY", - "NodeID-HTkhG7jLgNvjmLv7uaLzihgofmfKdEsS", "NodeID-HVYnT9MUfcK8sFV9tRirmkppWiNmFWQya", + "NodeID-HXdPaFvKy2oaDKcd1ufP7cjUuRLk4T3cQ", "NodeID-HYDf2HUkHFDiUKYmort7tjUFLq3253dHc", + "NodeID-HbH45yH52gVWeFe91A873QBG8a1uGBD3S", + "NodeID-Hcg9iX24FKp1zumDpJbXF4vPzkbcHBDhw", + "NodeID-HcrXuRruPjFEdc3snCR9wqxbh87sNCJWj", "NodeID-HeWWhU8g5KQBNFaVdwnj2TZLvBVuke7kB", "NodeID-Hfm8gpD4DpCz4KTzt2osJPfFvu7az3qiD", + "NodeID-HiX1MqbbJLeV96jrYH6uTkuWr7ofbiAHy", "NodeID-HkyME9tYN3G6DR9bvrha6XWNB3kYaDJbq", - "NodeID-Hu4Ap79XGvJrRtLcWikAN7fqorC5cjwzb", + "NodeID-Hm1uax9QMFjwNrrAmriWVQVcChyfmrqFB", + "NodeID-Hn6ji4ie91SEhmpgs7PZzDajaMZoH3eZg", + "NodeID-HnZNJY2KscixbVi58em86faLMY1BbT5Zf", "NodeID-HwYioQttyXRmGzdGAfNcZ8cAkrhfCqSuj", "NodeID-HyWNPsQZyve88fbwmxgUzq8FnNfE6wR9E", "NodeID-J3s61uikXhXGVxC8ffsgbctVLV1Mbvxz6", @@ -481,103 +544,125 @@ "NodeID-JAyKNPqtqsmjizdEWgTy8C8dM1tgZ7XNz", "NodeID-JBWVRVMqqTR9sYFQqESA1V9YQNoi8oa1b", "NodeID-JBiRdFNc9he8ivyGkdAzH9WaL4GKHoQG4", - "NodeID-JDR81pYzZNZ9Dm4EfFVQsRoopBCi8YRSL", "NodeID-JHQyndxosLrdixA6TjB6bexisQxCuQkgR", "NodeID-JHVmPLfE3YrKdBozJM5MEn1BzgMJzUyPz", + "NodeID-JLw6tbjnhJZLhEq5jnWsrxRgP3AEbxAtT", + "NodeID-JMoiLcTY2t9P94nTXfm68pYq7LMQ4fdFt", "NodeID-JNRTA7Q6t5azWZrT3qaVeeXnT4vH73zDF", + "NodeID-JPvPvJLYDc89thb7UhqrqhndNCHGggxbM", "NodeID-JQGMqAo4i7uXuS49vgaZDeJedDRp6oyuH", + "NodeID-JSNDtZdthVnHjSt7NY3HWd1ub4gw1pKez", + "NodeID-JXw6V9Bwidgc7c2aCZEebHDRT2FuWzBLu", "NodeID-JYJRG5ZYgd6kuQ6RvqHMs9CGh8RkyEpvv", - "NodeID-JbeonHKqomERomXgCiXr9oC9vfynkBupj", - "NodeID-JeAa13owysmBVL3CU4qToAP4qbvnQ1kGq", "NodeID-JgQWdp2K5yq7Bj2Z3TfGDP8GYAmeqtUQX", "NodeID-JhWkuVZGeJ42FLktoMVoiGuoaepWjxyqx", "NodeID-JjvzhxnLHLUQ5HjVRkvG827ivbLXPwA9u", "NodeID-JkadBNex6QYkFN6MRMjrRq8LHn6jp6qKk", + "NodeID-JnVy96b53CKBAPiqJTRTK7FnPxRk15gZ", "NodeID-Jni7c9DhGu4aMvU4axvH8jfnKLmi5iaCo", - "NodeID-Jov5q3HSj2somCAaZkhj3m8VfxpW9TZeg", "NodeID-JqPCvrvnKgNEKdsKfCnhVcaP9KJ3GWPq8", "NodeID-JrKGcbdnCzXUijeLiwzJZQNX48Cyrs9Yx", + "NodeID-JtgzXwsBLsJh6HWQGWfszrCCxpCnnzdwc", "NodeID-JvyHfY99GqXXWUsSaoeEEZZ64LQpMCUMU", - "NodeID-Jx97Z1v4Zz6DDG8JKuxfEPvjhfVG18yB4", - "NodeID-JyE4P8f4cTryNV8DCz2M81bMtGhFFHexG", "NodeID-JyRud4d7Sp77cjoXiuaThBsUVrSFEHgMQ", - "NodeID-JyhVgztS2ZmF3dcYiG62J1owhVLkUU5W8", + "NodeID-JzcJLa8bXBPBg75VVXUHh4fqgmhx8N83h", "NodeID-K2tnczAaPNak4WDoHs7thRxztKDc3LgoH", "NodeID-K7X83JX64HEzj4xSLF8MZWNNtUbQmwnn7", + "NodeID-KEkCHDs3iiF5U9xaKSVg6xzDU27oe6bBp", "NodeID-KEkeqcndUcaWVXNjNCXUUbX3gUepXqvCm", - "NodeID-KFmFFLE7HCvT4MjaDxLV2ZsNeF5XZcgTH", + "NodeID-KFerpW79qQ1whckFbjUvuP7eLwtXEHndV", "NodeID-KGfpnGi2LiRyTFfeq866B4skCpo5xuwFp", - "NodeID-KHU8AsLkZweFTA6vMie7E159rbDrWdvUN", - "NodeID-KHbuVifm5BFUNaaSKnqbFHw1npqegLMY4", "NodeID-KKMxwJXjz4iB6G1VopYYst5W9VJ7dE5RH", + "NodeID-KNGEydgzXRZzNcibfSDGfQwZBUHaA91ij", + "NodeID-KPi6dGARXc6A8vMjKuA8troteNsArT2nB", "NodeID-KRibmCkicP8FkeGM5Xm9yykNcrED2sjaK", "NodeID-KRvfLaiAUDLBEixkmdTDf43nNppas96Mg", "NodeID-KTnhPkucgchw74sGCrkpuCUmv5y2Nwnnz", - "NodeID-KVTtBgVLRs8umzWJS9gLQX6L4hgvEPUew", + "NodeID-KUVib5Ye7nrnA7RdKWz9nv8q7gZuCZwp6", "NodeID-KYr2Ldd1YHibJx38nkQ1vfqzRmsc41Gzu", "NodeID-KcC4UA5WXJtgRBdhtEnECqxyNcxh6bsno", + "NodeID-KeNHPP5bXbGV25Ujjp6cYfExVzQrmCfkq", + "NodeID-Ked7WpBzVYe4DthczsGV3CCYpEvj2F2bD", "NodeID-KerQSdj93DReMZFcDxqCVqs37jwEQb1Ji", - "NodeID-KiYKTPc1Kz9tCGSy8tYceHs8zLZs8rUEJ", + "NodeID-KfWrRxNQACEGRqPw7RNkpn2AYh5kPbCFt", "NodeID-KjKVvgJ71tiwHGwqBmhQLKGqrNeQBpqeR", "NodeID-KmzXj1CfPzG2WoTJiXr2DACTksgeQARJp", "NodeID-Kn1JzoTMNzKS67fuEtcLU73dUTCdjoomR", - "NodeID-KnV3Bcb8A6Yrbhwwzj9XUGpqJRN4ygnk7", "NodeID-KpdyakxPD8mdLHV7XDYjrtUZ6BG4rXRKu", "NodeID-KrZPkFHQnZWqdSC76pXRvnPVXBC7PyWWZ", - "NodeID-KvSUP1BJ6rUh32FNrXZdXfJBjiYz3n1A8", - "NodeID-KxPfHCXWXAe9LiP13K5fkKKSoHAzG8z2j", + "NodeID-Kskhj6CSMxyA3Y6VsjrjGUDGZdMXTMjjv", + "NodeID-Ksmvwp6BpSszz917AjDWG9mHqi2cdXVW2", + "NodeID-KuvxfizxywPLkup6RtzmaJcCECjBrSACL", + "NodeID-KyP1LyscPyThYCEbN1KXekaeNgCtUgFhq", + "NodeID-Kzj2Jr4XWUdVhLkRsaYC5WH3tKVKyqX8x", + "NodeID-L1UD9fwiT1VtFUVX7en9Pnz4EcLTwAvwP", + "NodeID-L2LTo1cbHtyqkZfgKpPdo861Lgz8WmJzj", "NodeID-L2kZ947yAuzugQaduZPJdysWRqxxsT2Ak", "NodeID-L3eNEFiZPrdiToXvDvcR2Yepk9p23NK7X", - "NodeID-L5ABr7mT84CLoKUePv19PyZBa3d3Xp2GA", "NodeID-L5SLiTDbpJAgt4VFJ7CtVscaYcLk4L8jT", - "NodeID-LADSSEtszTR1nvUXc87ZaRrNLzhCTbykS", + "NodeID-L9Md43FWvJz6gQJ2eAS1QVigXSecSM7LC", "NodeID-LCXfgTWLmmxazX8C3JuRbvpzmzqjzT3xe", "NodeID-LDKGrAwCoz5Tdhu4tVDjqFFQsR7nKqNHz", "NodeID-LE9q4y22nKHCv1gHSJfUyYY1qXcziLkFx", - "NodeID-LF6k1axP5xwxhBenLMHb7hwSokxRsFiCh", "NodeID-LGGrrgqBdzT3smcojPh7nTKiPRu4Q8G9g", "NodeID-LJH9JffagSPthZ4adGRjHByXFytPdrmmc", + "NodeID-LLH3HuzG4eaxJYYMiZTpQPVJNuEAZEaa4", + "NodeID-LQE7F5TjyfGV3HqrzAwYYAjdeUZzp4Fzh", + "NodeID-LQwRLm4cbJ7T2kxcxp4uXCU5XD8DFrE1C", + "NodeID-LRPi25wApvsNUuUFwwQtUMyuUNgrhmZPG", "NodeID-LRZMF1NjDo4neYWtbA1vRD6P7rmLKu3RL", "NodeID-LSsApoxv5refjrydswTevcdtddK4LU392", "NodeID-LUMxSYFmov1nDn7KZE1Z4RmT1EYgTCu3v", - "NodeID-LUTHJ9cdMxmsTbN6kztgbhSv3U9iGmq4", "NodeID-LVSzcr2TXAjTTNbEi8Nxfjwk3GQyZo2s9", "NodeID-LX75T9BwhW85T9Vz9mxvUEQhFqR1688Qn", "NodeID-LZMzeFFuZvg2fL3JYoAGd8sChmBncgPA2", + "NodeID-LZYJZxAqgn28K3g2crJtGgr5mW9mo7NFc", "NodeID-La8YHdyQZHuaaoEb6ww2BznRa1N4c54J3", "NodeID-LaidvDiaEiYSxKhqPsJx3ST2PQKFidmY8", "NodeID-Lb7Ez9LWTXUeKRUMgHX4JJtg4WNh31JUS", "NodeID-LbijL9cqXkmq2Q8oQYYGs8LmcSRhnrDWJ", "NodeID-Le4BWsZM3dAuMXTDL4rkcRZBTyHpC9zzq", - "NodeID-LegbVf6qaMKcsXPnLStkdc1JVktmmiDxy", "NodeID-Lf75GiFUq2psqfd3e6GkMNuVEYx9BUuuT", + "NodeID-Li2RswwproDXoFXPtrc4LvVWLxC1osx1C", "NodeID-LkER3oCznkUE1mTaRsugitboTtBSxNF7o", + "NodeID-LkcSuyM6DZa1ZMWDpybe6VJVD1RjNF3JW", "NodeID-LkdxkfYhg6nSw1EEUxDUSYPXPwmr2cUet", + "NodeID-LmzaWSmdA8jM4hfYjsEZ9QJnHZP9K7nET", + "NodeID-Lpb442HkX5sNFDeKcf5zXZJ349cuqiWdg", "NodeID-LsgAS4nCNrjL4gxPmTSDmNu2ywWrPwvVK", "NodeID-LtUqKXZBqZj37HCNQGqjaor6TZVBVF51x", + "NodeID-LtmsxApSVQQ68HiczFYmweUUFFLG85CBr", "NodeID-LyaNgPqgHTrKSiLdEpp1JPF3Qkv1k6n1B", "NodeID-M1745j4YUixszHoRfPq52DpyQ4TSiM8pL", - "NodeID-M97sgMKR1gLqZxy83MXhjusNB2rS3YLet", + "NodeID-MEEDgr35ZZm61jCzguAYDqFipBGrEnMtP", "NodeID-MEe8K9JFZHtovv515bNciv3YGC3jci3yN", "NodeID-MGkAX1DhKPPUudKPgP9qu2bCh3h2KY2ea", - "NodeID-MKXBMesCpDp9u2GCPXLhBWXaCKr5LifqM", + "NodeID-MKaR86DivZF1UA77gwUtRjHp6ddUHBr6T", + "NodeID-MLHMrE994WwHxKqF6tf6E6DF4SuQyeP2Q", + "NodeID-MMiSVwiACfxkyURcAYV2EXUShAYpmpkWJ", + "NodeID-MMsdXcGMAN1RgytS3EfsEFzF9opLeEryY", "NodeID-MPw5DtJq8yeFFuEj9LrhiM6p6hhdTXBsd", - "NodeID-MS5HLVJTZt1qW3BHmymnFhRaDoMMrD2g", "NodeID-MSF7z6rWEhimnDUJwwaGTiuWxkQEjT1Di", "NodeID-MT8bs75x9ZZYTCC2G3FdBfSiSPmW5nste", "NodeID-MViNUVT7MHKe7jS91EtfJixZG1nDowv9y", - "NodeID-MVsWL9MCUvzXMe17w9d3cdeWJwj6yzvrK", + "NodeID-MXwySzKc2JDDg2GLR8NsmHXDQ3XJcWFtT", "NodeID-MZxyHcXmSRh6uLruUmgBEhXRxYge4rooz", + "NodeID-MbibpFmGwGXAL1yPQVDvJfjL5GgbGqDEJ", "NodeID-McsVE9skuHHM3ebcFwWLhzXvhpT2Dc8Z8", + "NodeID-Md59LZThQ9xsihEFmbgv4SVktSuQkXnN6", "NodeID-MeDZKLP7y9ydHRVixZ54yxZQzWqS8YvG", "NodeID-MeZyN4H2yUfvu3KuiTFDh7KLctHWni9tF", + "NodeID-MiMhJNePYcQNGrAVsXRYEKXQ8AA85Nhb9", "NodeID-Mj7LRrnqPK2UPrAKYHY3aNSDpshsM9tXP", + "NodeID-MjFgGwGpHSsvyJPk7d5XRhWWyihttVLNU", "NodeID-Mn5pQf8vkLQtic9W6beXzE592Gyctr4qo", + "NodeID-Mn9484xnB1NnnrfPfeJ9UrdakNXdD1B85", "NodeID-MnAL4QmHAqYihdL8Ad61AY5NuKAtYjz9j", "NodeID-MnBVormBXdmpzuFUVFX7XVdwoMHEbH2bV", "NodeID-MnNiFH3NJLWYsH1MU7C4U6fXdzhqtZW6a", "NodeID-MoW5hERQWaaaZDvy2g3LDHqUNqkf7Bjo6", "NodeID-MtR3HLYP88Xmsd8whwWHRvijdAuWsPsBA", + "NodeID-MucxfzaqiKNQCznykW8XPPM7JZFPVEbhF", "NodeID-MvxNcbGGUifjjh41nnrm7RRsTqmU75mH1", "NodeID-Mw9wURaGBAXkgbpX5fkipsmoqnWXXxzdF", "NodeID-MwBo6z1rpGZqbD9xuo3ByvcKTw55D4393", @@ -591,44 +676,51 @@ "NodeID-N5gc5soT3Gpr98NKpqvQQG2SgGrVPL64w", "NodeID-NEeaczgsLrh5DKparo914eAz4SHCNrCSn", "NodeID-NF3dhwiiGHc1MoT85T7MwWk2xLF9zpgeh", + "NodeID-NGCgVZpeUaJXdjVq2moRRha8tM8tfYEcc", + "NodeID-NHkrKzwkkva75HTqd1RDWBdH7tRe9FAFo", "NodeID-NHv8CEWXzT8z8A4xDU9qDVp9yGfM9SZVo", "NodeID-NK38Y3Y1gg3duKmwEmPURY5ngYLYb1yAq", "NodeID-NL8ivcdpDokN2c2XB36iBbqTP2dmtDN2z", - "NodeID-NMqMW67zt1QwWhyJhxa7nqtir6n6hqze", "NodeID-NQxiZFkiHvPMdFnVQer5K3mPJPxctBefD", "NodeID-NRhg5SrvPn8CvtisAdgFXA1QkLoPsqRdp", "NodeID-NTELjonQCqJzT1QFvRdvMSDtJ2qwnqXGR", "NodeID-NTvmKq2wmTvqoccqpxW7fQd1iGCiGhAsj", + "NodeID-NYrHxv8EfFjM2wnsvXSickbq6XEqwwB34", "NodeID-NZeTWb3Ri5eR3tim5hAntmiwEWoLVdkDE", + "NodeID-NZfe5jh36pdgmAN4yX3MgafwUFmvMTCXW", + "NodeID-NctFDTRfjWrT5cfC831NNBA12XCLmoLTC", "NodeID-NhqNSzgKY5HahcosTxbcB887htZgzcrjS", "NodeID-NjPTsac32vTLnYBmz95TLBmMZZyy68Y8t", "NodeID-NmGx6qD19PwiQRPwJq5fxfoKc4QUaSYPc", "NodeID-NmUiTVDryDrut41qnwaNrBref4FMfn9Wg", - "NodeID-NnvANHHBKof7x3k5JFY1qhDiwfkqixzh5", + "NodeID-NpagUxt6KQiwPch9Sd4osv8kD1TZnkjdk", "NodeID-NtyTVeUSdkNrAEQo3vPLzrqhQfrYg8f7Q", - "NodeID-P8uDYREb61uhJV316geKEMZuUYvkrDBxy", + "NodeID-NwkffS9VYtwYH1pDJ3xMD5ZKKt3ZAqCW2", "NodeID-PA9LANCKQbk9Un8Wv4SbBXoDCW4bP9yLk", "NodeID-PB6nGgZqX8ccEvyEutDiasS8ndhnrakdf", - "NodeID-PBDjgkEC6S7Y4mRB6j7ffWFmkjCv1S4iq", "NodeID-PCuSoYTWTcZwQUZW41HpW3VaU5ogsAGER", "NodeID-PEdsT2FKxpXiemSctvHry8gbZJC6bJrF7", + "NodeID-PEsmPuBRtjpBRnaV6gTrTxTFehVUtjDf7", "NodeID-PGhVwQYM5eidnACK7jQ5ZkL1CnFpKTAm3", "NodeID-PHiFH2SQRhBFnaNsLVZX179np4y8gjmk5", "NodeID-PKSwUUGdADabw5br1MosKrSPyyeYdRKAu", "NodeID-PMYYkxDpE7RPrtmACDaHi6RESLwhoHcYw", "NodeID-PNXWeCUduveVZYuHRf9Mi6b4suVMJsxSK", "NodeID-PPCdQBpQ5THZzWrbKAHTdwj5fcx2x3wBs", - "NodeID-PPhqhyAvf9a6XukC5wSTTBQ2VmXoDHamN", - "NodeID-PPoRxaftnXBv7Egx2f4ts7GFNRv4J1vwQ", "NodeID-PQRNvZxSZi598GNxbH6joNaUPgxaD5Yaa", - "NodeID-PUNwng1LNJ22Fp93S8WHt7MjmeZKbHBxB", - "NodeID-PVrXwPVn24111jS3rS69ufseedz5uvoZ5", "NodeID-PWko2VpWPb748ARPENzdAfak6NZ6pYG1D", "NodeID-PWnPrE1Sckzuoj4Di5zBwrRc5q8UYGm7j", "NodeID-PWxEYBRBbKai9U3t8jgfb2SA8uAECKvju", "NodeID-PYXgapX8Yi28W2Xib9oNDxuaaLkZ1gZ42", + "NodeID-PZATpKoYGFhHosyUfecJXUAzbXiMVEWcr", + "NodeID-PZCSrsorCsvyTxkt2aq1yCMXPxEUm5PGF", + "NodeID-PcZGZ4CzwJ8NEGsL7ccQEgAGZ7AU6jtBc", + "NodeID-Pd7rHrBk8hJyD5uCRcG3uWC3ZwPGtTohm", "NodeID-PgBvqpbMQzJk61yoN346xxrnrHad8y8LB", + "NodeID-PgheFFDtZftKj9mNpEvH27zeQ6c6qvoep", + "NodeID-Pm3TC3M1pWDFhwa79YRqHGzG9Sjvgcdtd", "NodeID-Pn9jFroHyLVfDmsEruHABa73mpbnSU5RN", + "NodeID-PnZAZuzfg7xchQ3qbCMAtg4bAW9XSx1Jx", "NodeID-PoyWPaU4f25ev8h5KQYWrnTdGMiN9scHK", "NodeID-PpR5kKTZTpF2VstAXn4BwNKHeNEvo3LiA", "NodeID-PqKQwU5B1hzz11kW9BE4G642BMB6xrdnz", @@ -636,17 +728,19 @@ "NodeID-Pr6ZsMxfFr6uyMyZeN95ZJ1yHqGrDhqRP", "NodeID-PrZZEFnhrsgdbWr7hZYBw1vTpLpkntFLv", "NodeID-PtHsgZydMzwYNT3GcUXmaKptmScFwJkZY", - "NodeID-PwWYr47hP18fedky9LpuN4iNsjWxHHjdP", - "NodeID-Py6qdStyPBTqcLxpiLVWAz4CmJ3oHZLHd", + "NodeID-PvST69voCJeusKj2UGoFvK1UJxuZYWjmZ", "NodeID-PzPoTUQaErAzPd5EBdRzJeNSFr1kVMX3h", "NodeID-Q2J1vGj5FvVz5rDST2nC2saG1BeDofUbY", "NodeID-Q5Jk89SmFTSnxonorozufMhqnyY1RiUQx", "NodeID-Q5XuPs5dhsQRuGJebnzStvyF7GKWt9JVp", + "NodeID-Q6uYpvGDEJUUqgN1eiiKNkDCfbPCjB11s", + "NodeID-Q7e8iAC8sdAhnhPuegkFchun2yHo7UAC7", + "NodeID-Q7y45kPeb692xEHNUXA5rCdZgDqvQtHtF", "NodeID-QAnYYbuWU1PfEqVFgZQz9EHKEWd8fky9z", + "NodeID-QBtEYnbWGX5PtbsD1cd37Jx4eATeJoDuA", "NodeID-QE8ipEQ1Sc56Fa15G6HdCfUFk9SpFRBjM", "NodeID-QFG9ZiXr7boyFonB2D5B4MLfPHRgQDwLd", "NodeID-QGGJXjdsv7EKVKy1EG5Hq9GzeFcNFMbMh", - "NodeID-QKHoaJm3tfMjTcknMuCtx4HheAYHpQ1iP", "NodeID-QKheyKgFVkDyMxLcnoUHregsKHFuzuR6h", "NodeID-SCtrKtb5k75f8KUnTPj2gBsq6yrxpmk3", "NodeID-SvkCVFNKhd5VEo8Hgdky2TyxZ4J18NpV", @@ -654,54 +748,62 @@ "NodeID-UCaJK1qXng91C24jExSCkRhqE8hSCXWW", "NodeID-UujvYYJGbxFXh357EMppUFsXzPKvU3sN", "NodeID-WqHQbG5MYQAYBRzjJV3qqy263mbz6iko", - "NodeID-XHq85YsvM6SKvSQJiBsEZuZ9Zcg1NHqn", + "NodeID-ZYrkX7KzmDHfRzUhtVu7B1EYy1dCbbQZ", "NodeID-a4kVGB6zfhfHgz3JpoLY7Yqr6aXM9BRv", "NodeID-bQd33gr3fvRae95TLYkF6LcuyqrJeKK2", "NodeID-bpSs3H78Q6kdMPHyy1WAYGdVXhVMmuWg", "NodeID-c6NmA1sCyFvKV6NeKBndEykD3a5Y3Svc", "NodeID-cCZxQ6nBdNcPMpKdKHHxm5kjwfR3caTk", + "NodeID-dFaWdTjZH3FryPCs2MTiivJuia52711h", "NodeID-ei9CM9pS3ePsg2UYUrdRRALKr61jyJav", "NodeID-fJcYnNFYcnf9Tn4sLVPSyKnpFr7yivMH", "NodeID-ftRqiSfcMstsADKTtMnHGX8svv95tPXn", - "NodeID-fwEVgpiS2sV9LjEou9N9dd86Ud1x2Qyq", "NodeID-hArafGhY2HFTbwaaVh1CSCUCUCiJ2Vfb", + "NodeID-hpZLLFfwLit3Az5SDfXAtgCsErQfdQ9A", "NodeID-jRBYRTWyowM2FUvfyZkg8cmhtKwqRYb3", "NodeID-kCqLujZC9JuZp7sqe3vhffxgMgVwq7bu", "NodeID-mce4CCkKp1Vx9ck6FwtjQVbTyUSvKe1V", + "NodeID-mwGVBwDPG11rSWCjYwYyqBJJxM3ZEoPj", "NodeID-oRUBcQ7Lsrxi2S5bmWGD5CF69e2x8mct", - "NodeID-sd3N4YhnSr74bwpzbBU6ADqRAt3XxiPw", + "NodeID-pQCdCxnzPybSowJ8aNuu3o1w7e7QCVNH", "NodeID-tFgE4qqgLiivtexeoojvJgSk7eHv1HRU", - "NodeID-tVTPo39FS8aTyQ7DYrzFpCNdWjMNegwh", "NodeID-tkLPZudEk3RpVG2DLq5jfZS4KHLJf27E", - "NodeID-uoYEe3FynohdxKEaHpvPeQbLajgNGery", + "NodeID-vDc7LhjzpkqnPoFNMisr4BvijCQKe2oQ", + "NodeID-vZMp41xfebyKTCjNNT8wq6bm2u2xo46B", "NodeID-wvLAxGEDoLcPaTWzEkmV1n7ipXFiWAA1", - "NodeID-xkyMHEuJMHTSngLzm5GQY7r7GmoDoFRr", + "NodeID-yJAXXBzvB3sTVciXpoyku7uWuvhPnnqa", "NodeID-z7b2btT1NfrouM5xCJPescQW1QxWLq2v" ], "mainnet": [ "NodeID-12dyQ7nhRzsNSiFzEoW1RWK819Zkssf5g", "NodeID-13XrVPjS5dVxBKaweeG94SjY1Q6yeM4EJ", + "NodeID-1431VdHCWJgM15Wcg3zaSBYbpXGTSd7Hu", + "NodeID-158YgSNVidjeFx76vtQ5SxWq8B1F3ai1E", "NodeID-15AuPME9h4AS8CAEDsokNE5KMjLovnphr", - "NodeID-15ngGTze32Rsr3WgHyLHVgcdqnY2eyFo", - "NodeID-168kTGVaSDD9CsPQzbqMpQg6zUvKatqr6", "NodeID-1A1GTyMcDcassSiTBZFVuoXs7AS5HcHu", "NodeID-1Z67stQzn6v2hi1wD1Zd7nooPoqJE4es", "NodeID-1aA7BtLfTX4SRXaWR8HttP4z2UapE1R9", + "NodeID-21TUfex3GmhmusTHmp5SDUQTEaCkaXwH9", "NodeID-22jB4hF45iUrVhqiHvbDETRgpHKJdirY3", "NodeID-22k7HZj3D9DSAD7ujyvvuYn8XzWuwA1Hi", "NodeID-22wjev1roSt8jieZ4SW8rJLG3YiWyvbV3", + "NodeID-23NsVPT7XuxbAmisVH2LFwXAN1JsGvCjb", + "NodeID-23Po1dKrXFmpQaRafo1ZEdv8qbHC7i1yi", "NodeID-23Xaok4Hr7SgTcCjjMnVsYJaN5cSZLR3Z", "NodeID-23jyZenUu8Fm26ebdyXEEVH6PDoEXJ9j2", "NodeID-24gzuDUUhGEsAGbxhMZNJJ2x5G1wDVHEo", "NodeID-25GWqcvqc8m2ZT5ULNWfan5SEJNFBZMcw", + "NodeID-25RzatyYmpsm3QbYj9QdSWqdFQLKxdMR3", + "NodeID-25vUwC2XTURgqbtYripLhP7V6HPrkji96", "NodeID-26VN5FUvCmFWEhHm2k85hHn4rDqyKsV3W", - "NodeID-26jY6nu8uyVyQLQpi3SMdvSTbMTZeajHD", "NodeID-28wbL4a2ozWTgYXt7NekGT12h5wp6UyKg", + "NodeID-2A2CytyzFR1r5m81cfUPL4BR2MAAp5U3g", "NodeID-2BSvxuZFVVSpjrezuABMPvC6cLMwH8TT8", + "NodeID-2Bct3bqbgyNctwUahjFDCF3siViyVBiuJ", + "NodeID-2BjnggzgeiPAgrSmpzf3Hd1r4DTan3Rdo", "NodeID-2Bq98e7Q94vVWipc5tv9jCL4aMxL7pjxr", "NodeID-2EH9c6NwjHLZLWC2Ah3vekv3XUwcup62L", "NodeID-2F2gRAyyVkaNC7jtPzJ4zgcQh64QyMkvx", - "NodeID-2FNBUKXo8ShvqRgGhEUF1FxYC95Rk5qtY", "NodeID-2HvkjoRiMzEcZgpWKNAruLKNv9r7Lb2pv", "NodeID-2HwdM25EpGSt2M2BDaYREmGJrbYNudMma", "NodeID-2KSietvSEq4mX2C8p1DAT83RTJPykxUqN", @@ -709,16 +811,16 @@ "NodeID-2L2wFDTAv9Ti1wpqbFzqLbTa87dMw7QQM", "NodeID-2PZiqgTALZcdU1TUvQeypFARYEgjkQZPg", "NodeID-2Q8DS1hgPgsaMB1y8VqmxeworYJ2h2Ubt", - "NodeID-2QKRkQ1A9DTdXPAuwVC2DYWPBNmBpgZaS", "NodeID-2THa3uLP7oEvBj19k4E4jm1tCpT4muhYi", "NodeID-2UXMFjdXTw96iQHNL23PxH2hcLJUxnWic", "NodeID-2VJfSPqaevBmiJKSVDnw7GBwsdfgA1XuM", "NodeID-2WfvcQumS36rdyubDSioc8B5YinToKAaf", "NodeID-2ZtHY1RPNrq1y5YuJLaCShK617g6CjRsU", "NodeID-2aCXkeemxpBXiFui8BX1tVpyVsvhoZCU8", + "NodeID-2aSKmf99roSwDq7MChQ5pvmCKoS1qbcHS", "NodeID-2bRK9nCjngVig5fMFjLhVgqf18L7dbTj6", "NodeID-2cH1ggEZ8Z6CoKoQsEeZudUy5kEihW4T2", - "NodeID-2d3ZJcLUXLyZE11hw7FUi2YM3nUkMvvdP", + "NodeID-2dsDfPgPdjhqMfDHskgiwDcqkqhhG6f7H", "NodeID-2eBu8RjbvCFTZMcxu1oh2oKtfHT7V4zyM", "NodeID-2eJ2XJDpUagguhE9wKFR9JUxYNaBk49Ko", "NodeID-2eraCsE3WijaEnkcFX77hbK494TneHXkY", @@ -727,16 +829,15 @@ "NodeID-2iVvryG4GyPR5XBQebYMMVTFYfsNKy9oB", "NodeID-2iWqUM3VWvrcTLyXi2KgBLVhunMvFW7vY", "NodeID-2iY9tRvYLGjeGtjnUGyGbMz7uoaBdZR58", + "NodeID-2itoUKTyTyhGLyN1sYKNiyKHG2UkDGjgk", "NodeID-2jnJ9jJrW2EULmCCNnZz88HHCAQYo1Bja", "NodeID-2mWa8ytKEtviCNwmHfSPmDvkTGPLH3kf7", "NodeID-2nfH8Mmj5ZY6Tx5oD8ebst7prrEmbS4Ex", "NodeID-2pC9PZWbWLdaxTuXX3zvh4xZ4WobwiExr", - "NodeID-2pN3EtqAUKWvJedQvYfPSgKeonNmFn8bA", "NodeID-2pNQqfaBqMqwWgeJiqPbmHZk1cUtWcjqb", - "NodeID-2rpzBQ931ezzMPY8EKKivdZWfkiWtAyvZ", "NodeID-2sNYafYrpqSjsGspW2emjd6TqNTtWz74S", "NodeID-2sspVTzGYqTkeiQeBsdFKv57gWpLg6Efg", - "NodeID-2uA1cSeJhPtYgGtMUcnGgjesqAK7LzpQw", + "NodeID-2vPh5nJm68PNyauc2ot6LJgubxBaJbBkV", "NodeID-2vbdREFyZitz6LvSBca5gCe3eCPHZGq3b", "NodeID-2ves7JhkWUcLfPWWtKVgh7uvJogz8HLnR", "NodeID-2wWroHMggzJvKh6t3tdPtJTTP9DNmdc4K", @@ -745,34 +846,30 @@ "NodeID-2yZivvmC5XD2M6CwcVVBdPGGgU3MNta1o", "NodeID-2yrtwg1pRGi9jB6ayaXgpNbMTeGHUyofw", "NodeID-2zzp8nVwqw7ssQsMXniESwjwpZYMzeFsa", - "NodeID-313g6SGRoJXgCh4wVo8YpXyhDqkKVG2hs", - "NodeID-31xXC3YuXN5S9Bv9d63kH7ev1vuQKG3wR", - "NodeID-32EFwYSrpMmuxwDsgGf29ouKrcPquTQ5e", "NodeID-32JAXT6PVdHqpvDuXXHfWrFLXg8oZGqiv", "NodeID-32aVnE9HYv1FesKKbvvUh1ZvFU3ARNtR2", "NodeID-32dhPQyEQArm4ybXTxAvAAWAap7DkZAPh", "NodeID-33Ztk39cwheRHZbWLMyrNFUea7y7VoaWW", "NodeID-33miCHPn9eN8H9Yi4bCzEaL9Sc5BLeKMg", "NodeID-33sja4uJHmJ3fpDDu5byuG6V8icdSAke7", - "NodeID-34HkMQ1oU1vf7wNpzY9xWCiazE2tGhyJs", "NodeID-34QP8d17f1XjB778dCTCsBfjL3T4PeMAf", "NodeID-35rq6ZWsLWs3coxC38LACEayLh99jxMav", "NodeID-36Vywf4J2tu9gA8xJCxZjwi2JABWSF7qo", "NodeID-36i6jQQTfB6Z8NXFPQJsY3FVukaSGKTDp", "NodeID-37Aec6FfbDxVtjLNUv3bTsaXWaw5EGUrM", "NodeID-37ZMQ9ZZ4e7ZD1kmRg1WSTpRrEPSQ5LGT", + "NodeID-39ZN7XxaD4si7XdTrhiaPJfQqusjzLP9M", "NodeID-3A2diR9QLdWU77zW1sS39tAb1rSYexhSG", - "NodeID-3AMVspPXZimHQ3yqWizDf1bcW3GjL2B2e", "NodeID-3AUVAzMqQ66svzG1H7JVgURhUQHU8Y3r7", - "NodeID-3BVt7MvqaJ5jpoGecuNzzdz7cqGTKUjLb", "NodeID-3BmiiYjMNvspTqKKo4fXJWbjDbaaWRNXE", "NodeID-3CHc7PuHw5sGxtSVjujpHRxgiFDSFfucK", - "NodeID-3Cbz64Z4cvF1ykJ2vP1h2VmUFwgZHRDgj", "NodeID-3DwhPYMEQABuocceWDAZEpi8GMcLyvTYy", "NodeID-3DyUWkRptB3CRUVHk39Ni6Dpr6QvGWXwA", + "NodeID-3EzewMeb8MrVyWam8FhnHPHPoKsT7ERXM", "NodeID-3FhRFK6UxSfMED5EkK7jZT84pFZy9f17D", "NodeID-3HLAgdaA61zPrTx5yQ7Cc6waKWidsiqMT", "NodeID-3HvUXQy1siDNUBGWMYxwMfjufh8mxLtQY", + "NodeID-3JSPJv6xHFBekjausg4m8e5JP7UXSPWj4", "NodeID-3K3PUAqo3cKxRoQyYto1EsXtuTHoDZ2B6", "NodeID-3KAxYX7JeLQgm1fwzVqbzjow6eNzSS9Aa", "NodeID-3KX9tgCEQcTHbC8W9yY4zY32Cj3ET9MNQ", @@ -781,7 +878,6 @@ "NodeID-3MFu1eLpGRrRcWksHJLBuk516Vk5PoYgC", "NodeID-3NJgvio7B47MB7BZWm31LHzbPWVdkEiEP", "NodeID-3NXS6ZAzHeqV7w4saG4vXxAd4tcbpmxfk", - "NodeID-3PJY4Rpb5BRR3xSUvuU5Dj3cyHcAmzfjD", "NodeID-3QvnmD9KrJt7BcoYytWfCsCD83TmKo16d", "NodeID-3ShFK7JbJ2LN2gFT2W4iXp4N2NVuP4vZC", "NodeID-3TWEGuLyjvyKYLQqXNvQ7GQqSNoSQrviN", @@ -789,26 +885,25 @@ "NodeID-3U945Ju6EUzVaiA25ea2BvaapV111iqcW", "NodeID-3V8B3h9bS1cQerQMF47sw8Tr9jmJz4uHG", "NodeID-3ViTS5vVn4uLoQQ5d7Qs8mF5eYvgQcLQe", - "NodeID-3W61mLt8G9fVa3VNnNiStsbqmkeeSPQ5U", "NodeID-3WH62agC9m63q5SmAyPvhhLygsUjboQe3", "NodeID-3YkLrm1D9MqZ6K4YTwaQkt1NBb6wP9Ldx", "NodeID-3Zbddv2qkn6gWAfd12ysNN7N9EsDTjc9v", - "NodeID-3aBrvkLR4sqBEdeRoj1WsWDeWLuoiZzZw", "NodeID-3b2dLL4mSiGK2gx9pmML5n2Za4T9pLHe3", "NodeID-3bciNCJdZcW5k8jMtHujT6msFbGMotkSF", - "NodeID-3cqFtBUEe4LgkL94wHotgwtEMhboQqxr5", "NodeID-3dan8fxgCWWJZpNUkrBBEw1vhL8E85h4i", "NodeID-3douD9GDP69zSq1eMzRAYfKCUVtjEEUCt", "NodeID-3fntmpjeW5JhEgbVfKT9fy8xeaMg4tquo", - "NodeID-3hcHkkARQk8K3voT2NBHf79NFYonQkvPf", + "NodeID-3fuaS8gCD4cWtgZDCLrffU17gfHUNHX8Y", "NodeID-3iXKmHPAMgJa7z7pGcPpMC6pAmx8fjM1q", "NodeID-3iknBWGJowmNu2d63Qv7mRM52xoQ3mCoB", + "NodeID-3ir9ZQxz7rrTVDcfieFUHcaVNVhV4ysUR", "NodeID-3izZtcg2iecpF5rEkQF7Mwofd4puVGZwz", - "NodeID-3jYdfpPubNVyDqKkVrkLfDyy8RtZr4wBg", "NodeID-3kGMSCRnasr5CjsgNm1D8FbZnY4C5iNRE", "NodeID-3kTMjX1jJvdH2S94GHLi6Qxy1DKyLhuc3", "NodeID-3kUUeZB7umtaENekUfWxa1bxrAU2eq1AD", + "NodeID-3kpT5aLGx1dFdDY1Dfn3qPH3qYkoj9dWy", "NodeID-3mvtMQ554k7VbrbYFUaNZR4JmeCoggD5P", + "NodeID-3nuVL5JFrrumBeA3xqAk7BqTkRpu5mJsh", "NodeID-3oJ5XYknQTmDrwTkBxLx4DCuFgFKFP2h6", "NodeID-3oaegcGaKyncpiWQCzEVd7vN1Vcsue3Wc", "NodeID-3p3GjN8gxjGNpFCEKyErnWoXJGENDdj7W", @@ -822,11 +917,11 @@ "NodeID-3txc7u47G8EyCyD5aSZdTxeVdhAWSbpoa", "NodeID-3vkjzH23PgBPmHixW9xpdUD9vndf6ffBZ", "NodeID-3wd8cyGCDmhuoZYWmNDab2FhAVpnKYKJE", + "NodeID-3xmutK2VUntMTYcAL5F8A8AYuDcyeAZ4K", "NodeID-3xtitFQ6k29E476KCq7a6CoZtDmUgKqmQ", "NodeID-3yiw3g5Rer7repmzoJaATJpkf7GnWD5j9", + "NodeID-419QFcweSxfj2ZgxFMR619CkMNupjpAW4", "NodeID-41CFoAtQx8Bqivuq3tkg5oqnj6WpBz32S", - "NodeID-41G32TrnmUaVZUbWBSA6oyUZLCJoz3m2V", - "NodeID-41mvUJUdqhRjP7pX9BB7R89PXkDhC7f7i", "NodeID-42kmqmMDkmMyw2q6gS1uLi4wiXdC2NLwW", "NodeID-43AKDBv1R4hvnt9bjDFA4SEcwFMzZqpXX", "NodeID-43LKNkQ9avhKgVj7KrHXjq1bYi6mvxQ2C", @@ -834,15 +929,16 @@ "NodeID-45kFbHHYtgXEXEy53LCaLMBE8CA5XEdKL", "NodeID-45p6WjZk3E9Je9Sw4q4SvEaagbYF7Jsud", "NodeID-47pbycgGRRWtAB4FZ5fJZApoeG4nzv41U", - "NodeID-48tcs7C6Q7sBPrCMJbhWNAMj7bEnnDVNE", "NodeID-49LTjmBTcdjMyD33u7gKkfREPqEhhfPaj", "NodeID-49tGSAiEbwhRcTvnu2EaskxZPiPb9Lv2T", + "NodeID-4ALu7Jfcp5S7S4BXnQgGXMZ3rm3fQkxNR", "NodeID-4AW19ZAJMCyr64UKfFAUhZXuZDtVshQ36", "NodeID-4AWHc6b817tKesbKJ22EAEsJa4GkrDuNE", "NodeID-4BQYSFMqtFcjNgwS1bQgLnzvoKqqMx18E", "NodeID-4CJDfSDWT9X3hTosPsgui1ZRkBNRhX6jV", "NodeID-4CL8XnuYqfVVLxRre5C5A1dpRv3cZN2Zs", "NodeID-4DHwFAw2xZ8HuSu3jFzMU9cXvNhUHCkZ9", + "NodeID-4G6U36ehMMYjJ3C9gzLmYRzQFho8c4U4w", "NodeID-4GFFG65jrNUU3X6vsZKgUhmz5iCG21nyS", "NodeID-4GcMxoKhvXDebqgeZq2zKWPgQZF5aDPm4", "NodeID-4GkgAWZzSWHi3hZZLjLGes5HwuJ5FXDuj", @@ -852,53 +948,61 @@ "NodeID-4PKUhJMxeL5C7A5epar2X5TAAzXLqH44r", "NodeID-4PTYheMTMhPZvYhJJ1Hj2FwCZSR6rSWsr", "NodeID-4Q7EdeK1p9JkHULo5nZ9KVwgWYjDjDf9F", - "NodeID-4Q97SD75d14ikayvi4C21CkbdoaboGonV", + "NodeID-4QRHMt4aejVDLqY1VNmSXnLxaQiZoZbej", "NodeID-4R4zmBEWqY3dCtKHmvDd56Dupq97UAwtP", "NodeID-4RV8eRbw9andBLK2og4rtt3W7txBmSuxA", "NodeID-4RVd14QquiKdEXitdrnTuZiYpaBY1W6QM", "NodeID-4S2uvFvPmHh2Q4f2To1XznG2HMsyohuA1", "NodeID-4S5sLovGppHvP9uv4v6jZHV7JtASRpUUk", + "NodeID-4S6TMWiPdBW55NS9ZU95y4aHTBjUqr2eh", + "NodeID-4SkHqMZLGsjBmMXF7Dnpg7tYESgo9zAC8", "NodeID-4SvFyvJPHPYvkMnJqBaNcwr5yuU8sCsem", "NodeID-4TSV8FnyRHrVAmPALXfvLnGaHGspS5W2R", "NodeID-4TaEnGcWM77nvEityjYDxB4zYdLQ6LiZ1", "NodeID-4Ubqsj2vfwdGUUYNg1jtYpkYNNLugNBQ9", "NodeID-4V2KBeNd58jdBXej3ohL8E5d1bNTTp4tT", - "NodeID-4VpJH4PkkQmg7KrJ9z3czh2Uipg16PRYt", - "NodeID-4Vs1rw4jmL5QersqfLr3qB9HmyNtfeVeK", "NodeID-4WGNJ4vv6bH3FLCJgovqn3D7RCJ8rKBDR", "NodeID-4Wt44Y2AAuuD8iRvFfh1va5K7p7v697my", "NodeID-4Xw1ekhVqhHqzZ4pLTPtofbTZxpkvcQNi", + "NodeID-4YLHgpase4iRi6a4wH6c2jUMdWsKr74j6", "NodeID-4YYQc96D2kyeXh2z5Eb9U2owhPXKPJgS5", - "NodeID-4Zw4yFm9gJwULZHsgYuG7AbFKUJ7wuKMh", + "NodeID-4aLF7SfieaFRqFtLBKo6eeEbQbpVYVjoX", "NodeID-4abzhcVga2Mc1BJYEfypmRVtVctYwsvpx", "NodeID-4bKCgF7VcG9ZtcfMwAVFfBJoh2xDgvz1j", "NodeID-4bajtcpjERHRChiaYpovKU8XE5qAE4usY", "NodeID-4btZGj8TmrycK22kwgBK5wJEFighAFWiZ", - "NodeID-4c9S7HLgYom8eoa8So5ZrfmzZVvGQpLNX", "NodeID-4cJyBoufFfiMShtRhcd6WGTYdvUCE3Ai4", "NodeID-4cuTK1XYjm1VMTitd4MPBcwZ7LYyiqjfd", "NodeID-4cw926TqMXDNo7QyraCShjWMXNSCDZqMQ", "NodeID-4cwQT5hvhnhgYM7kJia4MK5kT8XLVZSNz", "NodeID-4dJTYbWkF82oeT3gYAjoVNNbaga2zXsy4", + "NodeID-4dNrRsASZXHs7XdZ1sPuj6kKWs5bdqHZ9", "NodeID-4e1C32U5TBUFuQpykL6rSw46RijbjdwRz", "NodeID-4eaj7e8pXaR1TSuCF5n7tKDCHPPemZGky", "NodeID-4edDKb3xKovZjTSuFbhNzJZ3Y9KTAzDaQ", "NodeID-4fK92LkTyEUzPoDW44Bo9b5YvL5kJ7369", + "NodeID-4fwq4Tcz2ERoDWDzcow2JNmT2KaxtJrjY", "NodeID-4gTwepTF5fcacXB7gdYZLTtfSFsYh4faj", "NodeID-4givb8yw6262YETrNnm4hTSRPeK4qEBfk", + "NodeID-4iabwkRVrx3KWgYgFuDAR23EZna6rjKxc", + "NodeID-4jvscnKzJyMUpbsZzfoaZVHd2ez6Vj5ad", "NodeID-4k9FLLYj63sJNrrGycj6MTRm6JqyacEav", "NodeID-4kCLS16Wy73nt1Zm54jFZsL7Msrv3UCeJ", "NodeID-4m1TLqY9ob5u23YrJx9zWDj11dz6DmV19", "NodeID-4nc9Pi32BZwWxcM21U95mVHsbExbPSmkq", - "NodeID-4ngWFEcMdBhXKj38YwJA29WS3mczGNrNd", + "NodeID-4o17gdHmyD1dWGxwez5KqKdyLDfiYmPX9", "NodeID-4oA58fddyvuKuRtqanZtp8V1Sz9mbr6sS", + "NodeID-4ocksMuoXQXnBH9XPRnH8j5x48cLLpFmC", "NodeID-4ofBXitDMQ6QZi83yvPjCYn5LG6HBwqSn", "NodeID-4pZqGB9JdyanFMVQEeq5VZ6YG9yZNsCF8", "NodeID-4ppYtgngzEnrgBZ7JUVw8bTbaBD76efcR", "NodeID-4qzj4sLxsLnmhhktyTyR3BWXu8nXTABnY", + "NodeID-4rqntan9eh1AmkCW7RNKwzVVB1r6hhnxc", "NodeID-4soc4KzELnfnTLLw4FTgpEefZpE6aSQbw", "NodeID-4ttQXnMSk443JHiMCRaoHBjjLArwEWbya", "NodeID-4uHXbHesQbAzcDBRqaFyJ5kpgovHpU576", + "NodeID-4ux8p7PdNGBzrcwYE9U3gHF8ehb882VGp", + "NodeID-519R4edrXr2qJBZnFX7X9dJvo2JjJcesT", "NodeID-51wXjrXuQkpHqgnyZ6pgQVbiBwTWgVQZi", "NodeID-5517ZjCrBhnLs1aqw2YVqRopDnAu5z8FT", "NodeID-56PBmfRBSmT2sYsPLiBPKVq2fQUVGEg9g", @@ -907,43 +1011,44 @@ "NodeID-57o8JLPG29tydZsDVGuD8iBZ3rVorYeoB", "NodeID-57vP1ZP91HztWSRTHurGdrMSw3TWHYumo", "NodeID-599kjqvHr1rEhyvT2mFA2whFJZS2Yoexg", + "NodeID-5A3vbPTyhDj14bLRCBs75HvsjMJ1h32FT", "NodeID-5AzNzec73Pth9Acw6jVd2BYZWyY5KjV6y", "NodeID-5B2Uyysf1nWcRbiCYdKwXzevVF5a7sN6T", + "NodeID-5C4VhhoWhTJ2LewfxQNvM6AKk1o5oHS3o", "NodeID-5C5QEUprYutWMbxYicmQd8dUFhc4eh6TW", "NodeID-5CDfrTrcGndVpY6qtuWsKWLm3j93GXyey", - "NodeID-5CjaXtU43Zar53KzzGHqZrmihayAdbFcb", "NodeID-5CwgaeHgQgWbeaMB2ERYZ1ntrhKCmSs5D", "NodeID-5EuG66om4jxQDK8hRFyq89SsMqfdvESew", "NodeID-5F6HiZ34F4oRtMX8PZoJcfvQiH7K9mGSs", - "NodeID-5GPPVZdPNj8bicXQQcYGCtksCSReksKaw", "NodeID-5HkCsXm4TQUb9uXxM6Cjy1WzvuDSspPui", + "NodeID-5KGMoDk3pwPz5LgQ8FTJ5jJXJFnJ9CuRc", "NodeID-5L14VfdhVJvi4GowA2zgqj78bGriVMLxr", "NodeID-5LGFWx2kfwMZXpyG52FkRtrfYfVRimjh5", "NodeID-5PMCtewYFfdxWmE5gcxuZeXAQAxHqMhu3", "NodeID-5PMGUqdapvGYEATmbQ48hMJTwcYyKFNDg", - "NodeID-5Pc2rnbGHgdmVtThh6fn8JqGVJavn9CrR", "NodeID-5PeQVPLrJH9xiSQZ8hcmeXWtUzhcArEhQ", "NodeID-5Pg156uQvovbZQ3F6JKUiyAg5MrdFseMP", "NodeID-5PvfcnfPd3MLnpq4MujxvBQHPwtdjYk8s", "NodeID-5PxpmHkfB3gNh3spZWuzEKis3DJ8WKxLt", "NodeID-5Q8GBt1GY6fUToWZ9txSGzWr8QTDUXKJF", - "NodeID-5QV9Tg6tKyGVWcEQM7vmAvac5w3f9wtp9", "NodeID-5QzeGmasNDHSxzxBqiUQ9TBPqkkwzJWGe", "NodeID-5RuEXmu7SJpf8bwuY17UpMpoEsGZRWnuj", "NodeID-5S729stbM7nFyWHdsoBeFzo5NMUXaTrjR", "NodeID-5SmDUGU8WwZkvxKMnjwKAYvfa9w2qEe1U", "NodeID-5UW1pHAXDJi1tRFfGSEgujuExMztq6sCc", - "NodeID-5Uf5RUZ89pWtYj4Sgc7pxf1mkq2f4EEMW", "NodeID-5WCpR3DKFt9665Wj9jDCTdncLNX7AbzfK", "NodeID-5YX9uqiPm6hmJEmDy2fUyvFEjvSvSbiWE", "NodeID-5ZXpg581dpjG8AdoJgTDeXXLnxrQc9Wtd", - "NodeID-5ZYfA8hgaSvUmXbsLjmu9aCy66Ha31obb", "NodeID-5aCHiSvLejirNRt8Xgw6SNzd1dDq3XviL", + "NodeID-5aQHgP4cTuyentoPz9KK3y2anCBYyG7tG", + "NodeID-5aiXb9CdCDJ6vRmJ6reLPehKFeKvdnHxy", "NodeID-5bJYpPDsUq3JpGJrFjVRtr1GybXQDP1M1", "NodeID-5bNomTz89SyKffJWnEZGXXdwvSnZanVTS", "NodeID-5cL4dSEdWWKnzZxvg1rqen4M31YeZhFkf", + "NodeID-5dP5pp3AQeD9GbRPbhuyXfFcNsU8RsgmM", "NodeID-5eFuL1vXb4NSxW4ZF16WZsJM3gyjS7i2Z", "NodeID-5eVCCzU5VQXhj2iqpqneRxTUNSD8aCJki", + "NodeID-5eogZcASu4bDhWxMuUF6h7VFK5SCt3msp", "NodeID-5gcdejFBQ3wMPFpo7qKUKBREJ8w3PRTM1", "NodeID-5gmMRqNob9UjcgroCKH67bQb9PVwtnoeD", "NodeID-5h3GjwRs4cndBMxxfRpuDMyrX9SF9dPoe", @@ -963,19 +1068,17 @@ "NodeID-5wQr9SafAyQ6BKMjtTomLB7Bc4tg8iYD4", "NodeID-5wUKLtxUEckPyuzLQSozcPmqVzMRx6v7j", "NodeID-5wf3A9TPUALDHaRhufq3Ry4jfH3cA9SEe", - "NodeID-5ww3vwysnrzVzMR7wMTohEYS69tX7sKAQ", "NodeID-5xEL4zcSuMjZCEzY3WhQ81Sb1Pw4E5VL8", "NodeID-5xhFgBpc99AjBEXqfzNAG3W8mX8vnmXWZ", "NodeID-5yYNsLs1TZoj93f27GD1CBr424tZJVpVh", - "NodeID-5yhiTAmJzTBpDLKdXSiZ7Puu5c6VSJtDc", "NodeID-5zENHPe3oP2SdU13oTAvxZA2cEupejYhD", "NodeID-5zP7p1nk2KnAL4SHvgFWcF9Xei3Q13CC3", "NodeID-5zWQQHoMSd29NfKUMziBuccvtt2aahnHH", "NodeID-5ztBWB4caxbw121xfsXc9JqsknrwxrRob", + "NodeID-61nHqrF65PzDx4SeUmaxrdbBLHNxGfv1z", "NodeID-61rJbupdhGqaumerueZFVVJT4Sbp4fciN", "NodeID-62XYpHtuv92hHhJJXVd4wxJqPFv9rbWA8", "NodeID-62hEBGiabBK34vV52kGT64T6S9QVcdMVN", - "NodeID-62hKwt6g9MMngpDLHapNFJmxXRcDoe2sc", "NodeID-63JGDZZtRyCMUiGmqQcL2rxXx4MrbNzNt", "NodeID-643Sjdbh4n7krQXPSNbSK491xfVbh3hqy", "NodeID-64Y4Dq4dwfnhTjNnZEFjCexmc2Wwi1fyM", @@ -986,8 +1089,9 @@ "NodeID-69vkfdsq14i5HZSd6m2kUwRAu59ePbeWw", "NodeID-6AKFYXuxWErAD6nqqFkPnbwHzXB1JC4VW", "NodeID-6AXAfsfvp25QX5Tff6Ag6ERLXQ577wurM", - "NodeID-6By1uWfbKV7Wzdvazj2Xe4Ncf1rTfqWAS", + "NodeID-6Aed6k5Zj6vffgNdvr29Z9VcdDxk5PoMq", "NodeID-6CGouDLcYyiuBY9xEi4rEaHCoBzH6UQrS", + "NodeID-6DX3ppjVpWsV8EUihpbRh73K5dGXBSmGr", "NodeID-6DqFjxDUK7nh68zrFDE7iHfVsXvoM5yzt", "NodeID-6ETncdUXndB43iT4LijRYLHF711gWeAgJ", "NodeID-6Ef219qf1xYjFL5SCFQo29ZYKDrcNi6xT", @@ -995,18 +1099,20 @@ "NodeID-6FSSZuuLEZ4sHJZGfpY4Wuz8M3qnK6ec5", "NodeID-6FWuMoDyCe1gsmeQj2RsGBmYv1hoGUbzs", "NodeID-6GEno5sempCQdCZvTEuPZpDLqVvpN2JEB", - "NodeID-6H4xWodWdcEbwJxbyFyz8ycHpKpAPF74W", + "NodeID-6GuJTV6P89ZgzzYM1CJbsuMuVTioUMmuv", "NodeID-6J3LY7ojkK7WCZzmArvxEozaESDMb42hX", "NodeID-6K9dR5Dx8YkPXzYeNvDRBionRmEo6HGE3", "NodeID-6KsZqkvobK4vUHJzo2VdwxWMsbHtXCZPb", "NodeID-6LHDq7hq3PS1xBj7cFQuvxozaM2hJXheF", "NodeID-6LRbs1K2iPGmhn1EBbX8u2udyPbUt5S5x", + "NodeID-6P9u3TyWn6jh381HSZP2uTyf1JdGBLqHP", "NodeID-6PS1ECxRbQ5x3wj31utVWecd9Xkgcp8sb", + "NodeID-6PabAb3cYifZm2i5Trr2BCaYyy9TvYYKJ", "NodeID-6QD1KNQkx6wj142Tv6demd3FYbghQvCM2", - "NodeID-6RsvR4PCfMrZN4u1fYdx2Xi6Lu9rUjBUT", - "NodeID-6S8zAjmFJ4JdZwPURyFGp8Q8tqQ5NcEbX", + "NodeID-6QpAUeTWNKyVo34r1LrCYpfNtUwUqXNMB", "NodeID-6SwnPJLH8cWfrJ162JjZekbmzaFpjPcf", "NodeID-6TG73ofz7EU4keEwv6jt2xLrpaFzqXnYR", + "NodeID-6TwryrqyRkE3evDcGCN1C95TaWzkXicQM", "NodeID-6TzpKmXTYp2f1ok4rEzEAgP5b87FSQ9G", "NodeID-6UMb71Emubx62ZEsNBPhhuEzZdqgGpKZY", "NodeID-6UpNHJdkRQM9TRX1m1wb1sfNX32Ze7ZhA", @@ -1016,26 +1122,28 @@ "NodeID-6YNW6QK3JDpCaEnVNsG5wsNA1SvxT1dhP", "NodeID-6aZ3KyGBPTcn6NF9K2jpvxTjhhDjks3Ev", "NodeID-6anRg13mVkUeZmpjf2Mm41sug56BH7Jof", - "NodeID-6biB22M9yY6jfRUeKHvLvz7dyVVZ2XYNy", "NodeID-6cRZQD9AsdBxSPSoHcBfqXeSAwzKNYsBe", "NodeID-6cem8uPoUwQ6o45VYS3D5mmFFzTuNC2M7", "NodeID-6eLQBH9yJUPLiZGXToPxQPj2gTWv15Lf7", "NodeID-6eS6iDVjh54ww1pGHmCAoKiDhkNGi6xTM", - "NodeID-6gAC5LaDoT9EWJezcQ7ijFjcsYa61Atdb", + "NodeID-6edspGWTTSWm3N7Zot3kGrEMHPtLrK3VW", + "NodeID-6ff9kZ7ct7e9PvGKBfbMHJ3MJaMPCmyTE", + "NodeID-6gBKuwn1xHG9SmLZKprpSjWACGDUp5k9r", "NodeID-6gFsNyzYU474fgL7t7x43Efjbak7Vx7Wp", "NodeID-6gRx5vFhuMTDtaRYP82ZSGuBq7eR5s3jw", "NodeID-6ghBh6yof5ouMCya2n9fHzhpWouiZFVVj", + "NodeID-6gi5JXkZSZyoZ28CHU6TDtJFVRy4e21W7", "NodeID-6iLoGX7rEPJW2GZMekiNPEDNZKmsbn3iU", - "NodeID-6izbDmxXdSqHwnBdWkGWuJtxVuTh7AZyA", - "NodeID-6kZ9aC6TPxRtXaWgDR7UHz1aWyfkU6o6h", - "NodeID-6mRmWBQmMyFzSD75SJzjx4VmToenpMt5u", "NodeID-6mSXCB3r7oeP8Suy1AWroDY2KEF9hT9Mi", "NodeID-6na5rkzi37wtt5piHV62y11XYfN2kTsTH", + "NodeID-6nssFkEQTjVRoWGdMfkkYJc6wMNYdRg9W", "NodeID-6o65ccWJmdcMSDkDphL2i9ajLCZRsvAfj", "NodeID-6oBNaAUr67MFY9Gtu4eis7bsGY1RswvAR", "NodeID-6p7pSJ2hoYnpRAXUt14cr1tsA5kEm9vXE", + "NodeID-6pCQAcsrwzFfT8sYZeT8cQ7f7aF8S87TM", "NodeID-6pShVkG6mZsinZNWZr48xvQSuSnmnyh5o", "NodeID-6pXaVajr1G1nj8Z4rEXisGUajXGcFPh14", + "NodeID-6pm7qiab6Vt5n47MdeNGuzKx5Jy3Pxwu7", "NodeID-6pzGb1VVyQT4RLChXUQYfhvjLrqEmWiNi", "NodeID-6qPNz3b5VZpMWkVNjmLmpBrL1sYxr38bs", "NodeID-6rJMJqgEbTGJCv3hBzDaY3axQ3Fq98yFX", @@ -1048,6 +1156,7 @@ "NodeID-6w8o4bbNdVLscimLv4X6BA7QuSqX37TFL", "NodeID-6xPTxaGM5hVHVKKFuC2MjpCL7ZD6xT3wN", "NodeID-6xQ5oYAQ348ntvsshCMMSd7uduReey2wC", + "NodeID-6xai7EXhzyxCUyHDrtLTYT6uRCNpUfRHB", "NodeID-6xjnXHhLrLDafewh5t69uRqtHea75RSGv", "NodeID-6yS1J9HFdHgdX2ruW6XMouQvECDF2Fta4", "NodeID-6yf4tK8VmAKhQHC7tdQwy5FTw39i9mXVV", @@ -1058,36 +1167,36 @@ "NodeID-71taHoSLZsm1Aqe4spXKJvNXw3o7982Hz", "NodeID-72D6UYvQjfgKuSrSFtMfyCtHq1jZZ2gN6", "NodeID-72ncx4NEgf4cziN5GPDRhn7i71rgwH1wV", - "NodeID-74Nra7czmjgHAtKCqDwheX79SDMgnddsa", "NodeID-74oLbJEptxh1cVzvh3QTwaykED3FXjPYK", + "NodeID-75PnenZJE9PQbQycTys2zonb1atGLsbX6", "NodeID-76GDFDnZW2ihXCsum843HEDmrvcVuMDZ5", "NodeID-76KcZZBhWfiWuFqrx21KyeBHdXxsaVyX2", "NodeID-76nqFaqDGakCDcm7kDsgP7GJn2VSM33xh", + "NodeID-77cf68EUcw4pSLJcvjBNNgxUtxNoTHjNX", "NodeID-77kWbGy45j1Scbvgh5z3zhoUBL1S3qjAi", "NodeID-7843EeyboY1mZSmdzjqdJodxHycNn7Kv2", "NodeID-793wJG3RHeLFVCXkNTQxsM1pSUHNyDyMv", "NodeID-799wg9bHu8gGe83SHdioqQ6hUg8QCYRv3", "NodeID-79NUUnbkpDfvGzGtq3Q9FArGK9D1Wzpgq", "NodeID-7AVurguoWJggFMe8WBEBuTzZjmN8AmN8y", + "NodeID-7AnPDxUDnyU4p5YgCpooC6xx1tCfrMHhf", "NodeID-7BvjRu2P26PSUXWzCSh8LLxLNdSpHEq8f", - "NodeID-7CK2DghfK6VgUpPr8vz3EHxBYhpfYGEpB", + "NodeID-7CQwXe5Vnm7hzSQeWDRXqUsGDc5vcPBfZ", "NodeID-7DR9yUKc8S5d9xwGoaT488hRn9LiHhKTz", "NodeID-7EEYbCpedmA4bgHnnvhx4zXgMUpKe5Gkd", "NodeID-7HgUf4o1UiEGh2Z2tWp2erbkn5JaXYYZG", "NodeID-7HsxnZQnGRWYG5jFVWDX2L26zEAYaUwAP", "NodeID-7JijGwmqUuditkaCwdcCAr4Xc6AAMy89A", - "NodeID-7KKSDmFVJ4YXsdcnxjDnV4girXR32yRni", "NodeID-7KvAj74Y1Aixv1CRWfNMGj73S6qsSGzhg", "NodeID-7P5SGZLFp95WbF2yv3A9WbQaQDzqfsAFF", "NodeID-7PUdh6Mzq4NfJR6wpng6cRAYDraESgWCe", "NodeID-7Pjqo8qr8Gd78Wmzgo5xqF85qcafKQ7W6", "NodeID-7PsjAayJQ4g5wiQ4QF3qokruC7aSUMqDn", - "NodeID-7Pt1CaFRMYN1azEC7SFoVjeXLmRF3s7EC", - "NodeID-7RBkUCXxXbZ8m1dAH76jFxABESmVnzT9H", - "NodeID-7SL1bpLt2gmSSppWDzmHcVwf5xSmrayXt", + "NodeID-7TepNNPHs1pGnMS994Pm77YFdSKvghvKm", "NodeID-7Tv2ubT5xnAXWNRf8X61Eyw7VcU9J1w5b", "NodeID-7ULxX37k6SSaTX3oF5RdrxL9r5aGZu75M", "NodeID-7UaxuvJw9C9FytVkUjRCQ3csmDiNzujGW", + "NodeID-7WDMJNKYqJ1yNbPLJrBZubqf6LQrtTw3E", "NodeID-7XrrK8iL25SJfWrrkyz3gZSo2t5iEadvL", "NodeID-7a1GnsoFxviSiL8gJyFqrkazv29xY48mr", "NodeID-7a5FbgWRUJeRWPzyidAyL3ENC8wQDJ1eK", @@ -1101,19 +1210,22 @@ "NodeID-7gLtM9D45daj6WJfqrT6uUje4muznwKwQ", "NodeID-7gqKK3aZ6m81v2138yfc4fsAdzFHsB3xb", "NodeID-7gu4gthY5YhpmpUpQvuAy5CDDvDs2yEVt", + "NodeID-7guwrZEeTwM8EZ4eULA3pw1f4ipfYFiLn", "NodeID-7hQFksPPW1Y5hZukNcQn6bTQjuTZPnj42", "NodeID-7haZar18iKUdnps7YZEYbJCSwnFw4KMY1", "NodeID-7hnK4EoWzm7V5qFPqJvpcRQti59au2BD8", "NodeID-7iFGXSHq1R8MvEM88EkS64rW5z7MwukYk", + "NodeID-7iHpsauHYyQoCjMSZsXJkqXodq7J5eXTR", "NodeID-7idSkp4X9MwUacdNn32NkE9SXo1XWveLj", "NodeID-7jqH9PXuyYhoTaaQDAF1eVzLtCVSgmSpz", "NodeID-7kfCqUsmvGEEfgas81FXNFx833U9xZtWL", "NodeID-7o1ubnZAYsiV5DUD5R5oDYXkQQvWo69i", - "NodeID-7oH51vMj4hQ6pUniSp6xGpyAFfvvU7JhM", "NodeID-7oHSQLPBV4EzZurguKU4a2FUvPxShuVzf", "NodeID-7oKBFksJjAcBCNEY3ZcRLQeXLX7iA9dNE", + "NodeID-7oaj9Yf8Uy6PRhqjHyv9oUyLzFMt8DgrM", "NodeID-7oyvSG1pLLp3zf2ouSAT6rUeehDuQcNtQ", "NodeID-7p8akVY9Z56XkLykaohLpNGp9sU9PLTvh", + "NodeID-7pDhCWQKNrpCjTL6tB7uNvBUnBQ5amgob", "NodeID-7qZBqVK1XAPXPqA6jPeDwimDqMTo1ZudW", "NodeID-7qrESfShxxqXfa35MfBC8D62t6enjm2RC", "NodeID-7rE4BjdFpwUk2igXEeauKaZT8mCjkt9Hs", @@ -1133,7 +1245,6 @@ "NodeID-7wyu3EXASVzsJpRPoqhssRWdmTWa6Fycd", "NodeID-7x5HbUJqp763SUw8Sz27yU3bKWCdQiqAk", "NodeID-7xCJtVM3wTprzgDBhXeXCXEUy4NEuqUvi", - "NodeID-7xcqn3xNHBxreF7mzRx7qEDbpJguaYg3i", "NodeID-7yBDXjCcqHCnfqC8LfQ1oL9Yyx1se2Rj9", "NodeID-7yUhoXtjqGABwMeSgQG42cWX56r1DkBwh", "NodeID-7ynNyRtZx8re55eU1CwJ1Ga5cEaRMPJ5s", @@ -1142,7 +1253,6 @@ "NodeID-7zVSqXr1f2wcEnMtMRBzMh1VczoEXsu2", "NodeID-7zeJ5VBLvTF7LvTn1VRZCJfdt5EsWUg3e", "NodeID-81U2wpq95De12KchbFhatf2fBt6KTFmAr", - "NodeID-82qNDEtRpFygtdH5AL4Fu5ZV12k6WCLqL", "NodeID-84RAL3MngQcrLpLgTgJwtLobhryyt6TiM", "NodeID-84XTAh1VM9QmfdewNnqFVhz2kbjrFvK4Y", "NodeID-85QtYSfGWxkvQjbiFJzv8R6ajAutwFS4F", @@ -1150,66 +1260,63 @@ "NodeID-86HV89ZFehy2HHmnkpgBuUn6vRxg25if4", "NodeID-86LjyKDK2eKVUpdesMPWJtvo9gadfW9m3", "NodeID-86oHZkq55eBsPNFwrFX7kV5w97BPHhtgD", + "NodeID-86rtyxneP9grH5wuqRcQMSZw5mS1vqrKm", "NodeID-88fsGoe69sPGtRjqe21SK72KrJNezzz5u", "NodeID-88ik4ovrpTx4dTExqhXhSQ4JwAQnHbuGA", "NodeID-89ucgJfiRvHtGXynRbta7VcaX6MEcJ7K6", "NodeID-89zA8HBgsSce4Ut5hzWgfMRKshqooJWdu", "NodeID-8ALyunjeYV85zBSrD2rjJdQ754z9jasvq", - "NodeID-8DLefLvLwgb6fkcghkLgj8w91MSrnPdjh", - "NodeID-8DVxsXms5opComNTHqFMgR9pRS99gt27r", + "NodeID-8DYmrGzmxDPogtQvPR4YjXhRyo2pNDBdT", "NodeID-8E3UaD6hjNK8aqK2BBUmqPXyrfB19WJJ2", "NodeID-8Fiuf4Uucg4x3ijMfkyVvYXdfgdBFvsFk", "NodeID-8Fn8YCu76VUHny7MHQTkm3mPSuGPkVeqn", - "NodeID-8GLed1n4Xtqh7RaYHWjm4BMxKT6AnhXbW", "NodeID-8Gct3pDyuCEY5xH1F9RdYjvk9ry23cTtX", "NodeID-8HHLzk7pF96soZ45bJ1tfHNcSp7moXiTB", "NodeID-8Hg2J3s2MQVf1GtFLcRpfWjvJZkMesX3z", "NodeID-8JYJVijgzBsSTK5EUsXitrMEYNGkqeba5", - "NodeID-8LVdUgSHBFouhLBef7orFrHTeHgmTW9r3", "NodeID-8Mk5Kpvp3oTpLbRSnwmCJmPbvRwsR48ra", "NodeID-8Nr7TDSiK215oiNDY17SaDgF5nfty4KUi", "NodeID-8PmuHd5fRb8VWpTTyNhytQuv3sy83P2jT", "NodeID-8Q1uX2BfyLbmCCor1t2h9qvn414WXfQ92", "NodeID-8QKheMcZ1jn5n9RVi5MFBkzGrKjFJNNAX", - "NodeID-8SJJiFHcGfH8KErq78txDKhNGARL1K9mp", + "NodeID-8RRm8QkFnJvyuNk9GtXCwniWfHs47b8ni", + "NodeID-8SHAaWWn5qoBCFynwzXdRtFCcMvEkTjAM", "NodeID-8ST5juiAQzVfXhNAgER1UapEpNowZyMoj", + "NodeID-8SbnHu41g4NFAk7aa8EXpgFSmQ8ZpvX56", "NodeID-8TArWpFgH3sazEH8qP4gUjtGtFMvjw1aR", - "NodeID-8TXq3f5WiXqZuyQWF3Sa7ncoW3YRRaevh", "NodeID-8TubANvEGU3Zkz6nKeRx3ShmHyULLjD89", "NodeID-8TviTXQLiqxcxkCikPTut9DwifYjFaMcT", "NodeID-8UynAEU8PuuGetmjiiPcbGmvD3EyycuN6", + "NodeID-8WowWhvPM6hwXBLGkuX7HvwApmXNDCyrH", "NodeID-8WvUBZyrk6XyF7pvcg3NJZk8jtJGi1W9G", "NodeID-8Xt57NiwBsGKt3CjYZ1ymKx5h3nHU3vcX", "NodeID-8Y4i7kpWyv3pvvwJSk4EsGx7frk5mU1Ah", - "NodeID-8YCf3nhXEnz8vthaxYRWR87ez2orwP7yW", "NodeID-8YNtmpa8fe2dt12PqDzhDCBtwcQDTXa9p", "NodeID-8YqEZ2ufMNUFPXyNpUAvLJWRXLKqC6D2H", "NodeID-8Zvnq1815CaYYegXmuyBD5BVtJnurtpC2", "NodeID-8byZLbVuVJbedEvsAjZxTTSqorsjz7ThK", "NodeID-8cKy5FzzP2CHV1rcwdKq62vuYP9yUzYuG", - "NodeID-8cmpcebMMbqJuUTqnz5hoHzqZkDduNttZ", "NodeID-8dCZ9beUGmAWyCZPwdM8YZ5FDBRPXUxFf", - "NodeID-8e5R9yoryWwUCYDxqKdV3PNPAFme4nZMX", + "NodeID-8dq5Vwc7PzWn5NYNFRkM8TfnYaJpLiPis", "NodeID-8f27M6Ju9Dnh7YU5pHqpkBLhCmBq9EBBD", "NodeID-8fLXgVYgby12VunVnSMrRrvcgEijVknbo", "NodeID-8fq1H8oStMi9BZrEk8qiE8QAV7AtqGnXt", - "NodeID-8gLyc1WmUgnTJh6TAjg1nbqsqdF6xGSeL", "NodeID-8gndDR9ULm3ywRNbh3FUveaSyo5g7V3ns", + "NodeID-8iQxXS1Zbm6tGzfp56kpSyUboE5kSNoH7", "NodeID-8ja1C24FM5FyQgUGjsm4qwpD6shiu71KH", - "NodeID-8nNsX4HqDV4UoewbWjcrQv4aDnsh9fCAe", + "NodeID-8mFFkAeyLkQ5Kgw85ZeAb5XFXjqsxPGUv", + "NodeID-8mHndwCShG4xau63f5FMJC5r1kDCZNpNi", + "NodeID-8oREeth2haQyVW7Bu1iGgiMe18h5Pqiwp", "NodeID-8qkeNyB3cbs7LqzP4AB7rHcrcHLAYVDEs", "NodeID-8rEmSGNj5VW2HUjGYMyynpWTYJuDrMpFE", - "NodeID-8sczBhZjP4BGoCqbn7SaRCnerh6cJ6jE8", - "NodeID-8uDtidG6poHRfZfZJXXSVBwivoMogXQ66", - "NodeID-8ugXJLrq8DW4m7m7vBTpkh9rCLn3sUmmc", + "NodeID-8su1eeSjb4emswAx453du7ya3Pp8p2wSe", + "NodeID-8t9KLSgmSQfW668sfoLjVrrur3nDwW7fC", "NodeID-8vuV1UF3KHF98EdqFyuFAMDJUzwkQWEA7", "NodeID-8z8rezdB9vXDxBurBeCYnNBfNcD1kVrJP", "NodeID-91W73TnEik6kseSpBHSAZzsNVRGk8Qfkm", - "NodeID-92aEQicro9Pht1HRiexK9ado2BToyi7fY", "NodeID-93LVjgmjMcBmcJSByxYiTuyPNbdVw9q3n", "NodeID-93bNuNqHUpmiZiT9bvcm4YdRU6ADQnESy", "NodeID-94CDXgCTFRPKPDmK55UcfG8KqVQfy4QsV", - "NodeID-954wbYhWNWY3mbqATFyrHostqC5EBwPHp", "NodeID-955GU1MqWL8yXAtoc8AsE7FNx4nGC9JyL", "NodeID-95rcDYyjGNKckKCF8PKuTyEV1wxkQvP3n", "NodeID-96tBuFHLkXJwyYug768fE2GDEFmebUUTy", @@ -1220,6 +1327,7 @@ "NodeID-99hQvpQKJi1y7gTjD2icHKYwk1pNMHFhg", "NodeID-99sqQME296SfcnyYWTmGrLXQJxaGUKAA7", "NodeID-9ANDYM7So3ZPNwbMMd9xBKUiyJirXN3vF", + "NodeID-9ATz2jx7Vh64A31CcD8PgJw7KLZy92fRT", "NodeID-9AjYPCvDWKnwzFgRiy7jeTEKmVxK42LSz", "NodeID-9BCUhY6Q2Eji4J1u6MV9XKnPspciWWdLR", "NodeID-9Bb6E7B6GMd1MnAuxYVVYF9CSf1XiBCEY", @@ -1231,11 +1339,12 @@ "NodeID-9DmoV3n9Sb1A2aLkYuv9wZV7uPJo5JhpG", "NodeID-9EMH1m2oZQsbSFvrMzx5YXZWFfqSwjuUx", "NodeID-9Ef44CXDWWfP63UaLr8XSCsmEWUFY5i2z", + "NodeID-9EizvTJhGPtcwRExBgYySaJMt6syztj2X", "NodeID-9FZQBRnW2jMU1PW99pqVTnxkPHF2Srfeb", "NodeID-9G5DhsoBgHjDA3j1FqFXKyEJH8AGPeB67", - "NodeID-9GEnATgHgKGpkf6nJdS1jcmXz19ekHWkc", "NodeID-9HT8KtMkcxP5aWjmxaVVGBCMZ1r6jGmgz", "NodeID-9Hp3rH2xzTzDoZj6JgYqhbmTFGVeS1BnL", + "NodeID-9JE3zL1Ud1x5RgSJvqRpyMG6F17dPwAdc", "NodeID-9KjtB2xC9aehpcYRuqJR4myLGJaq1tVse", "NodeID-9Lyd45k1mXNkksF2C3nwgCJRX9YY42FT6", "NodeID-9MCd77R8qxsNg1ajgHqFMsRYCaQ4KpGot", @@ -1245,7 +1354,6 @@ "NodeID-9PzVetjSSSY4Xtk3VnNcGzQdEjZSSkR4g", "NodeID-9S8duheEvrp7gKW4qLLrWVCnC2wvo39w8", "NodeID-9SQzWXUh9SF4b4qDmYy7p6LcqWSgxtu6o", - "NodeID-9SoQgX7kSvnBcYsajQNeDsp6KDkZ34vJN", "NodeID-9T7NXBFpp8LWCyc58YdKNoowDipdVKAWz", "NodeID-9TMnzP54UVfmYmYcxAzVuNC9rpVr8zvgB", "NodeID-9UWtBGvW7G2RVSwcR15MS8gesUvLk6f24", @@ -1254,14 +1362,15 @@ "NodeID-9W3QhxVhg9EncK9438UUepFBrCxdtFp2w", "NodeID-9W5RaY7LA6so9hGCPGfLezBXMnWNRQb8V", "NodeID-9YiwE69B2wcvXtEW986YcgQxGg9ctzmKZ", + "NodeID-9Yq2bF3B9p4Lg5czRpYoQULLuEn3nwuhm", "NodeID-9YqDsggitZTgCi2WnnrKBz3jAcD1S7oin", "NodeID-9Z7jK8jN5FsTXSqkG1fV2QNG7GktPU8az", "NodeID-9awX4ceeXavKKmccnAuDU7uvhqGfaEDSS", "NodeID-9azF97hpcwpzj3t7S9mD4VKY1S5eJDrcW", "NodeID-9bU9jwHLH6KxcTu8pBbqJQqkHYR4woY7L", - "NodeID-9bmxQyFJCrENbZgmMdy6xXorVN1RL5qWY", + "NodeID-9cEGqGSwjjX23qXbP4vEqva6TwJqH4hAH", "NodeID-9cazV2uY7efo1f9bjbixH87FFNG5wGyts", - "NodeID-9csVHpVMwxCY7G3bYvr6fMSinoHWGSsbR", + "NodeID-9czFqw5FRq7WhYyf9SBSfq8wsJ1f82m53", "NodeID-9dN9NU5XCr3WQGYnFjGudKRScQ1HKGmBn", "NodeID-9eH3Zu7LN7kNwvUy3Am8mkgvvekrkxD6d", "NodeID-9g6keiiMr9vXhaSNP3oqdxhu42LEZ3pWu", @@ -1270,29 +1379,28 @@ "NodeID-9hksERdA8ypkBykmHuch4mw24RR2sg5js", "NodeID-9iGXJ935QZWkp5j2v6KNSTr8b45a7Xbfs", "NodeID-9iiCATASsRcosMQ811KpxSMHsGdM38rPJ", - "NodeID-9ipN26YdR2YZFyz4hdoyMSXFYNFMDgDfy", "NodeID-9iuMMyL7LZyUxMK9s735hcRng58bSj3gw", "NodeID-9izFTRjPnyph3GJu1sp4Cf7zHiwaK7KbS", "NodeID-9kNp7yMjHnDg1QLQboms9ACgQ7BGu8zpS", "NodeID-9kgmvmU19mNsTxPS4f2F7ZiSZSwZ7dfGk", - "NodeID-9kq3kK1diyhu37xTwNHVxBkpVKHZhTEKj", - "NodeID-9m519rUcX9um2PdgG3h8tYSZzCRPZ3Dwr", "NodeID-9mtTuxamXQyiePCNyheFEyjr4cAQo4Wbg", "NodeID-9ntqrySGMSMwqYR8yFdChFdU2ABj5zSEp", - "NodeID-9oMGbzXR5wDWa1f1BjxmhvsjkPYcFMz89", "NodeID-9oP7KmQjtxi7rK5GKmRXFNuNpPmr2vzfw", "NodeID-9odH3Jbw7uPuRrbaVkVoYeitdzwX6o69A", "NodeID-9okkd3AwB3eurfQxdP46mcSM5sVhD9jxm", "NodeID-9opRroLX5zG47LVmyw8hGnQJx6dxmfGsf", "NodeID-9pBxdzsJRoGFdAjEJzcdWbzKEEkdzyGCr", + "NodeID-9pTnTcJZ714TcKA5ibKwjc4ztbxnt4YR4", "NodeID-9tAAt3ADXpmStdjfpUKsgKCBowaPjXueE", "NodeID-9tJaF6mjrwczuEZk3oQRJsB2AzPk7QFHn", "NodeID-9tLM44jzwQqnsLmQTfhv6Q2GaAEkCdev6", + "NodeID-9tWnniKF15vWEqJa6o2hjmL8p61jq4ZmW", "NodeID-9u5MGjm2Y2BvQSZBqwDkqjUrqFKffDund", "NodeID-9ucNhNpdx1QhUnivTY35AtNEVpjY8AAK4", "NodeID-9wCVwfdLGJe14xss2yjAT8ntowavfe6Cu", "NodeID-9xTBvp3kCUiUGu8aM8XpBWPf2co3vJTJN", - "NodeID-9zPtXnScuWRvoiTDe498ZtjgoTXwTwxr9", + "NodeID-9yFkNXGSAUgPu3hB4UxkWGhbp7cXBLaJN", + "NodeID-A1rgjFoH8JTHiHWoWYVcDDWC3WKnNFFi1", "NodeID-A21bAN3Nk96xfoAh8auwqP4uQRbk1xAPz", "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", "NodeID-A2aPfvr1t99Nm1K82U2XyWtxse3CNmZ64", @@ -1300,20 +1408,16 @@ "NodeID-A45ZieXX9VhAjrz2jhACBGYYypn2HEjaS", "NodeID-A49YH2FmGteFpSV46b9WDxZWDEebAnH4q", "NodeID-A4amNjJyWX5kd1wNhxZVqDFqWKomCndp2", - "NodeID-A4ebHxQGYx1fUuJWf3uWzSaQttx4VwKaA", "NodeID-A58AWZohmoEPEG2FDjqdT8m5XeUL63FZc", - "NodeID-A5CGvttTf2Bv3KvCeGwzUkxTd6Ux4MURA", "NodeID-A5SHWeGWKUiuvPZhRvNAXKyiEnyDhJzdh", - "NodeID-A5djhLPbKEsfiWZn9na9vFEHThJ6Ud6Hg", "NodeID-A5y781VL74i4yfFdcMLnjxr2qLbtjaAgi", "NodeID-A6onFGyJjA37EZ7kYHANMR1PFRT8NmXrF", "NodeID-A7GwTSd47AcDVqpTVj7YtxtjHREM33EJw", "NodeID-A8jypu63CWp76STwKdqP6e9hjL675kdiG", - "NodeID-A9vXzVChTULcBPwXnFoNTfQENgrYRUyMS", "NodeID-ABHKUic6BDS8Kg95tSWoYv71CXWeuS1Re", - "NodeID-ABaXv5WwxLamczWpE6o58Dm5FyngUbFrg", "NodeID-ACB5BBC2RNLSGZVEGkRRQdWg8hqXjnTpM", "NodeID-ACMpxS8rnwkAA4JfCUm4vNoWQaznNCqGV", + "NodeID-AE67987jikbcv1cjf612huYwFgx7RPAZG", "NodeID-AEtF29pZDpKEkZ625bg3reDrux4wyMjhh", "NodeID-AEtKZyYiqnWqzsrwSKEPWrciPHEAn2Q2T", "NodeID-AFWbdZEPvWxEq6A5SThDPVydUj9FSHjCQ", @@ -1326,13 +1430,12 @@ "NodeID-AHTFPmvMrQBt1hcoGS7HugNCuu15Q5gY6", "NodeID-AJR4Z9bAx8tom9ygqv3PkpQtdxDV8JeLD", "NodeID-AMMTYTe6uZR7yGL1AbEMuwYayd4N1J4bL", - "NodeID-ANQn6yF5HqoipSTWowYpMjyiHifhewv5y", "NodeID-ANeoZC7jBSmoDSYVLip5uASJW48GwWLLG", - "NodeID-APrWZpt6HP8qQjvLR9R64BcskxsCfJD6Y", "NodeID-AQT1i38PMJQxRqjpwrQ98QESW3EJzG3p7", + "NodeID-AQckPm8yWZiWwSAx4FQ44J41Tp4yF4qME", "NodeID-AR44a1cyPrD8cCNZgyhv7Tc2Lvw3ryhEu", + "NodeID-ARveB1Km8pUjtoTVQL6e27fMHfUyyrjjZ", "NodeID-ASgm7N2wwZKYc5dZPiHExfDdNcfyZQx3T", - "NodeID-ATZ8pFjm1rjV8o6Hp7icMqapoGycT8Pi5", "NodeID-AThE3ad1aiPLKsj1XfmhCsNbai8sMyPc", "NodeID-AU27Fz35YmQuM6d2pM9HsvLtgwGT5xwnd", "NodeID-AUeAjRR7q12Pps6Qckyy1PUzFwP34pFij", @@ -1344,23 +1447,21 @@ "NodeID-AWMoYmhjbfpWphJ3nmgxGAPpVFzQbdp1G", "NodeID-AWirVtsoiwvNdqhqQRwz7vQQEiEyvhq3y", "NodeID-AX9Fkm7jKPuY9Mit6AyZoS73tFKWvTMF2", - "NodeID-AYJX8inuAUYHEWMWn6V3x5w9sN5tSkFAT", + "NodeID-AXPrBC45azzYv7UKCwLYJhidPkKat2veF", "NodeID-AZPULN7CsYdfSq1zepSS3CZNhxJsU3a4n", "NodeID-AZfAXX6qyLxVXBUJZPwEgR1iJYwjwozm8", "NodeID-AZiGXCQ7UJvsVjmBpUMmXAQ12GRj1iaz9", - "NodeID-AZszYbUsVw7PhcssGJYM5274dwoe3gQem", "NodeID-Aa6HmCaYwZzNoNXRf2xd1aqgtaWdnnryn", + "NodeID-AaVVyiopFyWeLNfshG5eztnEGSUQRDmnn", "NodeID-AaxT2P4uuPAHb7vAD8mNvjQ3jgyaV7tu9", - "NodeID-AbfdkS6u8F8kxh2pPuK32KASNK4sSr4QR", "NodeID-Ac4RdT7r2vj7J8s68DB6mpoqPQ9sq6oro", "NodeID-AcUWiUhdsfAAD4gyVUfQNokZXpDD2SF5J", "NodeID-AcVHs6PgeipByAajqn3h7PHDk9cZXDZ2K", "NodeID-AcZuWDkVDZy32y8YSxMVU57sLtkyHbVFQ", "NodeID-Acigg3i7aU9j7coVrns9SEtyq9dox6cKz", "NodeID-AdSMHubbQcGeJYMcY9nufaieoYjh57uzp", - "NodeID-Adk8ovrBBu1dbaZ7c6Qy52EWMQuUr6WZ7", "NodeID-AejE54hVtRxSm2e8KW4zUHpBTgHz9fpEw", - "NodeID-Ag1ZLeovcUsR8V9C3EH6NQpGZoQBhT5Q6", + "NodeID-AgDYXBZcELb6jPp92Jk2p9qt2R2jbGweF", "NodeID-AgfJSHN4yaVjgxanEWMfQXKGDNScwrVZL", "NodeID-AhFT8H88EZjd7K1dhrRPfhatXKuz2iBiY", "NodeID-Ahq7qT8wG6ufLoM8MrvB5G65SbEfZC85B", @@ -1368,11 +1469,13 @@ "NodeID-AiVA6rmmPhouiy3ERwF7k1eoLTrPErd2p", "NodeID-Aix93q3XbWsEcoNuuWjYuQM49ZeCX7NLS", "NodeID-AkWM2duSrGSfWNEdN1pmWm9ZLrwZDg5MN", + "NodeID-AmFfzQQtUYm1RNuhkQuoG6hzaXpYYbYtE", "NodeID-AoGM9c6bKC46YpEecEe9tHG5HfcjqPxtb", - "NodeID-AoHdNKxXdndkKrbQegnB2TCaJF8JDEXLX", "NodeID-AoU4gTzEVKVmopKx7s9hKXBbQ14VYyAcc", - "NodeID-AqBVQzsBnqMjTuoMoCAQH7NgTz9vC5APv", + "NodeID-AoYvCZojkKKkDiUjY3Daq5z3FUPrhMAbB", + "NodeID-ApohQPUqvLAFGgH3XobyeDFBHEz7vbS5u", "NodeID-Aua1pVxQsWLvTTf8bNVw2ZCA2NfogNqiE", + "NodeID-AunfxeXeb5uh5FbxYMr4TtEpbVTPssmmv", "NodeID-AuqWFe8yzJxPgaZShBZpa3AhEnKT8SmEk", "NodeID-AvTYuKYvu8oB8dXCbAsLh7nTpCvih4fdd", "NodeID-AvYo16nRcdMuFmsEps6STb7faiRoCRgHx", @@ -1392,71 +1495,74 @@ "NodeID-B9dnZzwTmygKPxEP7GvyqDh1F6pQHkmmi", "NodeID-B9o1a3g4PFp4JWyMJxRv2nvnWHsq1rSvC", "NodeID-BAePtWtdsqk26YVfucEAJTA9spGpuLf9r", + "NodeID-BBJP3fsJ2sRRbB3umzz8UXAhzrUZJmWqH", "NodeID-BDFwWjNUNeLYrrfGmYqBMqZSGZQtmCcxx", "NodeID-BDnEyGooDS9w6bk2Ty7UncMyQ8t1iLLqh", - "NodeID-BE6YSS6Dw6tsEv4fj8smNNkHpqQvAf242", "NodeID-BFgsRa6TLCKcHZhN9iuufSqRengbXuxQy", "NodeID-BGEvsCNRi5gr4ga83cVx1E7PTSiBZjyhK", "NodeID-BHPTN8HM5xA9HNiwUPceNa314kh3YnDpp", "NodeID-BHsQhBq2NYN4YYB9t9VxoxcL2xkCD4zPj", + "NodeID-BJTip339hEcVzpgyNqzERhfjMc6sUFabj", + "NodeID-BLjWtGBQU3PxgBSMvhiGxHGZ6Scn1gyyB", "NodeID-BMaQ42mVapxbCcX2RLPRTeRW3th91XdaX", "NodeID-BPsD5nsuqTKR7ToqUMDFqanYioFnAVo8C", "NodeID-BQ6uwBhrSU3mwDpguw4rGPXa7kVkk6FyM", "NodeID-BQEo5Fy1FRKLbX51ejqDd14cuSXJKArH2", - "NodeID-BQjBjtF6gz6AXUqRbEvN1M5EnFL3Hcnv", "NodeID-BQpbmskmST3wkcSbypVuFZu7YULXG6pKR", "NodeID-BQsr3wEWirFH6C81M1LYsYagHXVxXRFSS", "NodeID-BR8ysKTDMKpwbgH9fsfCdVQWMsniMQBWp", - "NodeID-BRPKnug3F8vq9aV7VFU8YL7fASHF4L43J", "NodeID-BRRp1FdWN4PepbmQNUksWPsRJaZ1mFP7q", "NodeID-BRrFzQrJs8nnmeSZxWwr9yCRcq4U7resP", + "NodeID-BSTCzJUvn8jYqDtsV3aTjRycJHBJi98Zm", "NodeID-BSornzAY2Y4SmDcQw4Pgsf5zH4Wdv6d1S", "NodeID-BTUXn6xfxjtA8P4nXYHiwEJpso9Q9t8FZ", - "NodeID-BTjbJK42vkCLo8LnJfXHHtVeDrZJgfTbw", "NodeID-BTybEYu3y8aW54EK9SSivLUYn2fiCosjD", "NodeID-BURrZL8SidbaotZ1cNxvPxNH5DGvXS7gN", "NodeID-BVSFJU3T86CWXQxSTc2Y7cHo7nYJx1Jn8", - "NodeID-BVWu8imNSLAnVc2bz3LRKyKa8jfA6YgPR", "NodeID-BXTBUqX8gitUDtVam4fhRWGD1SfeHGoBx", "NodeID-BYGnq6ZKg5ncN419eBsxd2YQcxoewxfrQ", + "NodeID-BYSrjPkpQsN7YxR2v6ToGhmD6VnpEz9uR", "NodeID-BaPYDXQYeS9aCFHv76r38gUhYrtfpzq6A", "NodeID-BaTDuWRvZkEy8gg4FRYmNYXASWL4QKzFD", "NodeID-BaaUYiEUD9ogi7dDikVZAzaVu5yxAHjGs", + "NodeID-BagXwfWXPpzCt2utVf1P5MTwdQsPnxeaL", + "NodeID-Baof3ssuxMwMHxd3RXpNwiWmRdskL3hLD", "NodeID-BcfnNieXDpsvkMApb8FcCmGAoQdtyu8jH", "NodeID-BdD2fp6PXxbSdGshiVrHDzarWpgLFEMF9", - "NodeID-Bf6sxEpjBCbnoouk6sdrPNPfHfxfNumDB", "NodeID-BfeJfXUfFveZPbS5tFaJar7X2uQQ7S7so", + "NodeID-Bg5GpEVehBRU9HDf9e66vXmrRJ39BW1hG", "NodeID-Bh9vBw87fdqVzMzrFrPiTQqA4irjDP6G4", "NodeID-BhSpBoma36qXxym3XPxM2E9xisXh2hBmL", + "NodeID-BhbczAQnAARsn5Cwa1onMXLD6j4Uu847F", "NodeID-BjoNuhod6yNfMJJDJgyfNWWRBUG38ZPCs", "NodeID-BmKvEFG1hXNQ52rPBTXwQ3ZxEmcCmxXZx", "NodeID-BmmaSGfGKxQNMsaBSnxvhQdLCNchGEcUo", + "NodeID-BmtQcEcSHhUJzkjKQKJKdF3gQaVtud8s7", "NodeID-Bn4LPbETjf8D9pZE45abJgcCk5KSQCbo7", "NodeID-Bn8ZcnL352FHc4utgVPVDjD3o1HfYwtdA", "NodeID-BoN8r3MqeJiqVcvrQx1VubZMGDQE5pJi7", "NodeID-Bom5dUsayGwdagVLoNNxe1t1FFDZXGGK", "NodeID-Bp4nG1LrP7JCg9eSQpfBE91mBSd8biThQ", + "NodeID-BqCmioAapUYdqLL7AuWJqPeRrp4D5a1ag", "NodeID-BqtSwNPmkfSi5W3Zz7CRffeLmYrUYuEmJ", "NodeID-Br6QnUhtZGAC4CymYLPRSMCrsNyhLMmH7", "NodeID-BrexWemEB1Vgpbpnnriy3k8e2CyRvxsPR", - "NodeID-BtPauDeR52DaiZeBXuJSvRWaFnNhVFMSf", + "NodeID-Bsa6pnd8nUhHEQ4v68GJ6fDFwCpz1QSBj", + "NodeID-Bsgdx1HosAzQ5X1M7JmbYngULQ3xjkP2e", "NodeID-BtcHfm5o3A4WhAmkTm6YPWRhPCChDPLMM", "NodeID-Btr5hkRibMyYztC9jQg5T3fpKNeYf3Qdq", "NodeID-BvDJUkrDJotTxgZi96zsEe6iYQBLtz958", - "NodeID-BvHFTM6QMuaxmk1xXZAUS7N4amyNn3Fbu", "NodeID-BvpPGydG4inQCbkwRZ3nPMp1zAGToUTxz", "NodeID-Bw6s9DYKi2V9jRqNmaheGGg2Wz2Dv7DQo", "NodeID-BwCLnFCE3ipnmkT3V814hGsb6sCRFqScn", "NodeID-BwsGZ6YpSqF2j3QRRiQJDf9JC4FmCGXq5", - "NodeID-BxzE2rHWw4hBSTVqP17p9earG4qYKpCwv", "NodeID-C1oRu2mGfJHUD3UyNCWVJnJ4T6AWXhj5Q", "NodeID-C3aMR9tsKqTNQra8FbqpFkMgHV5DtuJGx", - "NodeID-C4UwtB1v86mBctdWgoQZGCCUk9EUtjHSh", "NodeID-C4emGUFHEeCEZgoeMDHZddr5nyZBgEUKf", - "NodeID-C5Gqdho8U8fTWHhBvymcyRVBU43D1WMpc", - "NodeID-C5VJTAsWjmjh4KU6DpR58X8QMYFZjc8di", + "NodeID-C68ijbc3Bz1cdoQv4Mh1TYxrzeGA3PnmG", "NodeID-C6b58cQGYSqm1FeQyvXKXUgZ3R7Q9D9es", "NodeID-C6fd6GFYMnbD44LpZR6AuddMDRXTvR5Nn", + "NodeID-C6poeYWySHhDuKWMbckvcny24gTGKEtEK", "NodeID-C6zVv1ab5JKn2j8DDCGWGai9jgWhmpLVA", "NodeID-C7VsWUVsE7uFmSgkRQpcjAJWB6gRdm9Pc", "NodeID-C7YyYDva6rvbpY5GEu2Su653eLBNt49TA", @@ -1464,14 +1570,12 @@ "NodeID-C8zmJazq2HwujDgsjKpmYJsvSuNMD1kwt", "NodeID-C9Bcji6rXUp22qyWhvYKm4v45hJAkzvpU", "NodeID-C9CJ3oVhdeLf2Db71JPuzvEUKjy3BdoAA", - "NodeID-C9FY2J7xE6f6sGSaThsmcWva6FU5y5Qi5", "NodeID-C9eHQ7iCCpW7zy7Vk5UJEXd1zwXEdFtS8", "NodeID-C9eewJtL6WMZi2ce8YoPxhHTCYemhvnKm", "NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg", "NodeID-CBPbPrYDbghbAP4RLSCQr7bHQqHWh1c9Y", "NodeID-CCBWkqmiTdwUCR9ExH1mNSLzvrt9JRKF2", "NodeID-CCPtDzjuJWjt1VuV3yiHPwQr35qh2rbJN", - "NodeID-CCh6Pin5Z4pVLfqyCsZqQfg7ZAZi8QZb9", "NodeID-CDjuct2YS1o4d14nHtszWmyVUmFjo6AHm", "NodeID-CEHgpbVVJh676muJTUNKzP3jmZ6Cs2zar", "NodeID-CF8WKgeNBHxWFmijN7tysmmRSHfJFEKD9", @@ -1487,8 +1591,6 @@ "NodeID-CPkJH4zTnyhERzo7H1usRiSmMVDeUszm", "NodeID-CSmSE2veuHYG3dJD9WuqobvsAdJ8iF5pF", "NodeID-CTry2Hj2aXeA1rfWq1s6pDL8SzaCFGLMC", - "NodeID-CU7T6w5aj2hPEtfHSf1GWXpXKLWnN8uWG", - "NodeID-CUTxQEQariSZiwv88qRoGtmUMWabjJoce", "NodeID-CVJCnaM2gVKr6WCmJxKSPjEA6GFtmBknY", "NodeID-CVXpUPtPZnsEM4mSnJbctBpL6Sgj1rCRt", "NodeID-CWTULAJzqphbmedDkRpcHuCvGiHARvodz", @@ -1499,33 +1601,32 @@ "NodeID-CZVcr8ZP7njdQynukR8B1RcCcG9qxSdD5", "NodeID-CaNQUnkzWJFcsYNhdx4iyRk31McfqtKhX", "NodeID-CadcH2YHzeVWDSBT2LR9bfqHvMVfH6bTs", - "NodeID-CbFmga7as6xEZXwhgCTmcvU8hix4Kf7ru", + "NodeID-CcNi1r9gNk8NtaNFKShCQdahthUEpZX6R", "NodeID-CciiJQMXRWQ5967qBS5XncuEiyor1Png1", "NodeID-Ccx7u3SwfPt52GxWbNc74kjVJvqktTkn8", "NodeID-CeaG1icxFWcMkTzsqQjpwt82nePJrk5gZ", "NodeID-CfM5DQx47iD6AWMsFdHGfWUnt97Sbt9n7", + "NodeID-CfT57H9QA59QT6s3QZGi2HZz8TH9i8V3y", "NodeID-CgXPRNG5FeVSz8qC31u5UDpZ51pJ2mN2X", "NodeID-CgbgB1UFpUESETV1CVGDM17bE9JA4tVHK", "NodeID-ChjgtCzFxwhCYQGsUzGHUUTi9nFYrLsXh", + "NodeID-Chk1hvm92LQPActavSVqoEYCmXfQZeFvE", + "NodeID-Chy78FPagNNU7oAj1QWzrdPFjJgZP3Scu", "NodeID-CiKdcSyNH27re2W17ygscpZ4xG7474E5U", "NodeID-CjX7mnJM1qasMtuyyxeuKoKy6b9fdSSbE", "NodeID-CjooWTHxne1o2w1hetMGgDL5Et8JzKMiw", "NodeID-Ck4VEAv4JTMgnijLQDeGCWST8Zdgxe9Q6", - "NodeID-CkMG3CThWnfAYCYE1MDsFqSU1n4NESoFt", - "NodeID-Cmp153iz82jTqJNoNFSvGr8wsaVyV93S2", "NodeID-Cn4ocmPe1Hqo29RyYCC1QXr8b763Wpw92", "NodeID-CoRQHCd3aSKe7FrhHSUnvNVZzW52xu2YA", "NodeID-Conr75BBUMBFNXD2VP6gvEbCRihCvjfej", "NodeID-CpAhCB1gu11mLxBZJfgGLExwwvKobprLQ", "NodeID-CpS69JexgMfH1sy7a77fiwQgN3c5QtrXa", - "NodeID-CqbkQ1txNkMjeroDyJpAtvUAbJf2VbV6x", "NodeID-Cqc4sovCY4ypZww5envqKgtrvd6zrRPTz", "NodeID-Crfqdz3qPavSYvQUWSXMawWjUXxnr3Gg5", "NodeID-CsGzEmegg1sVokBzrSKkMygKy9YCVEzkq", "NodeID-CskPetRMvtH5Xr6gLa5cwfY4hR34UgkM5", "NodeID-CuEMaXrtX3tdegH3BPJowHr7cMUyf7P19", "NodeID-CuF2PsXiuZESJWa5itRLmXWQ66qL1NSE4", - "NodeID-Cve7X2y1c9WG3AvnWrMGBLkorLdmQTrL4", "NodeID-CvzmyAWqVXtrEcJWfXDP742oE9PsnCyoB", "NodeID-CzW1jKjZwFXgkB2Ria2nNPvah4bMq85bH", "NodeID-D12qpTYhB3feogxvMBzS1QPvwyKyhRK8G", @@ -1535,9 +1636,9 @@ "NodeID-D2iAoisJf33uGaaKh9uCUMrEjN9HG5dib", "NodeID-D3onstuMsGRctDjbksXU6BV3rrCbWHkB9", "NodeID-D47UrYCDdkfrDrv9gUvYKLUyT44TXYCJZ", - "NodeID-D4fXiW66E7QQoTTaFjdNuhbim6RVK8f98", "NodeID-D5aUrNtb3vKUBKYpdapiaGEaBTmUz3Jr2", - "NodeID-D7JFYevRv4N7LXa8ihCwdzVtc5szT9Q7j", + "NodeID-D5wkgZDwkAQVpFNYtNZmGUJGnUYRB97RJ", + "NodeID-D5yA7HbEr8AJ4yzwVZXsDtb4xhKkTRz73", "NodeID-D8vyyYopHECxjFCQ2K4X1sttJjC1B7zva", "NodeID-D98ujhSFuA5pXc8bnKPPpbP1VNFnfESVk", "NodeID-D99fW2bCQpU6QCN1pu4UccDLZTQdVEwMj", @@ -1548,10 +1649,10 @@ "NodeID-DCUpFFgVWQBseGis77N45cBAZudSbaZyg", "NodeID-DDzbSLsiD9qMPr9eaUhxwrChfbbXW8Zu1", "NodeID-DEa3uaa1iztrxytaMqaP3PdydErzjWEgh", + "NodeID-DFDnfBmuJWqEeCxMviw2u93rK5thcetQo", "NodeID-DFH5SbPENeErMmeys9FcQTMvdKkYrdLU2", "NodeID-DFUyhAzXyYi3TUaQYBvm5cezyEaREeSYB", "NodeID-DFuM24ytt31NZquBMCS6X3EHmrbfJXMa8", - "NodeID-DHEd8i3AGxYG4irHHShuBuxztefU8QCxj", "NodeID-DHUX369UfTJb2vVuWSRdJr9s27owdMbkS", "NodeID-DHpKTzduyCvN3x2G4svUD2T7LZDD1T7nC", "NodeID-DJ6nZjHBeTwdQiikyuz1foaQ6dWLLYm4u", @@ -1560,10 +1661,12 @@ "NodeID-DKgP4pe8GtAwQ3oVgvHJFG3WexnLjkkSt", "NodeID-DKxvuUSqd8xtyWejxXC2JvQfP79SAsPvG", "NodeID-DLFjLpQupsWf5UdaKRFiGELdeY2ViJfwT", - "NodeID-DLwFM6gfY5wWfHHMf5tC1NjttQqxZq7gr", "NodeID-DMn1E4EyXZu8GZGKHV3p1naTmpKkpf4fM", "NodeID-DN3fqQmgTBvk5JDxKjCFzmbs2XSVXTKny", - "NodeID-DTpuMKcnryCN2VyDse3VdSiQjkspJu17P", + "NodeID-DQMJfc9ArkN1gohMBh4SQi4Cmu6EKAPo8", + "NodeID-DQVzByLn57iLrib1MVzoxVsnEksS9jbgb", + "NodeID-DT7ET1yHCTuNMydS4mGod99maQjBFS9MM", + "NodeID-DTzB9kesfKQNYuRBivWhK3iB2aWsuYu6Q", "NodeID-DUmZowZh6nxKskHUybupqNAhnXVA5yQ1r", "NodeID-DVh35F3R11HAAxzeSTbk3eR9w2BzPrJQt", "NodeID-DY2Tk5ZqUir1NpSiTwXVGdETCGGEV8wHe", @@ -1578,13 +1681,16 @@ "NodeID-DeT8Fw4Tp875GUQNxfcfKoBSPjKpGi6eR", "NodeID-DhNYzUwYHPF24Wfz9MmmVyqLBUF6tkEpb", "NodeID-DhuG2YhqQy26zabyLqTqNr85T9XscsWpY", + "NodeID-Dk754EMv2Tm1SP276G6sWuJgt1nWSNxXv", "NodeID-Do5ZUHCK8DHm194KGqdcwFc5wWE4fCQ6s", "NodeID-DoEC8uw9qRNi33EiYrPoK6Vu9pnsH2rnW", "NodeID-DoTTJmp8cmERizJdYQGFsPVFgZPJxfcis", "NodeID-DomnwLG65RUJM41RgCJ2tRdR4iZEkVCkk", "NodeID-Doy4qhTgun22byNDyHxNSRceygqwhwXCn", + "NodeID-DpXBTEP6ZCmm5bgBbv2rb6MzdRovARVhi", "NodeID-Dpba952dAUnayPmf52GJzQj1PLoqtXahS", "NodeID-DpwJ1uaLSpSqKu8ZTa7XpmFp5BuBYN4Ns", + "NodeID-DqE45ELtkEn4hSyU58oukvcPg1Ua5UdzV", "NodeID-DqqpR7tQ3goBbudggakvzYs2K9TzR7daR", "NodeID-DrijBGc9SonJrGUwex3vXtzzEGW3cB5DY", "NodeID-Drv1Qh7iJvW3zGBBeRnYfCzk56VCRM2GQ", @@ -1599,81 +1705,78 @@ "NodeID-DvCdC1yWp8a9NNLBR7agvTV4YNmJY7zb4", "NodeID-DvKgKdhkDk6CUf68iqA5Kwaa44RkBa4zN", "NodeID-DvMo3a7eJYQexjLrR1rykrc1jsNuVwnPn", - "NodeID-DvVgVUfihpm93kUJs381BdFcS6goazwUn", "NodeID-DvwWC5ed3j5iG6e4Y5yxAUacPkXvrxLFT", "NodeID-Dw7tuwxpAmcpvVGp9JzaHAR3REPoJ8f2R", + "NodeID-DwP4ATkTPn52orSSS1FbjjT21TXnXoEnX", + "NodeID-DxdedkGTUuVoRS4VJA1qYXuFU6MerKKyX", "NodeID-Dy47rtrYr4eiyRTSnbaFi8KZVnR56XrUC", "NodeID-DyXd5SxgwWWadT9PdEpieSPtjcKxYCMjE", "NodeID-E1c6FEFavQ1RiaNARpxGx4sWnXAGh2YHN", + "NodeID-E28yXasMLXFQM3f3mQtGWUGh2jEgJATi", "NodeID-E4KwVKcddwozth12cNvNYApyHhVbvnby6", - "NodeID-E4pVcU7hgYn962iz8sQRSf2R7jNKDQewK", "NodeID-E5DL2H2CxUUdxe6TcMW7uTHC5mFujF1eD", "NodeID-E6GJmPWBnGKad7hPfxCK9GRwsuAKc2MJQ", "NodeID-E6uwzybtqQ8H7aArfxxVJWVsEcaCPLT7t", "NodeID-E8rXzDkKySREDECoXPqaPPhQA7QuxL9M2", "NodeID-E9cBEoCDBGi6qFGcW6bfFoyhWpq6Vc57Q", "NodeID-EA7WyeKRdVx34ixXFCvfWbv5P9DSNsj1E", + "NodeID-EAdWoKJCXzi2jKAEoETCm89CB3dzyMdAy", "NodeID-EBF7imfP93Sc4cv3cUAK21maYDvaFMS5j", "NodeID-EBHJ9gHUbjtNQMnNNcJEsqojFpAbLrnVS", "NodeID-ECNKxnabxDwevTW7bLgP2Meaid1j8ztVn", "NodeID-ED4xkYFhZPNNj3WXDQiogcTULeBpDVjSY", + "NodeID-ED9nabFu9bXzdDizCeNytDisKqkdEk83Y", + "NodeID-EEQ4pJQ8FTsFmPi5qEiZDBkKsqCpBRZiT", "NodeID-EEipCNkeRgfvwiDHbaBdQ2WeRnsRVSH7P", + "NodeID-EFWjQ2CYsraxPFxWVJL87nfqKNsAP2T9q", "NodeID-EFd4jseGxHxQmYX1ATcJUSZoCnE7z6dFe", "NodeID-EG6gFe5McNc2EyFzARxuvTApN995FdBZj", "NodeID-EGKLqBNabvY52737RGARiuGgvu2vHRY6v", "NodeID-EHJoNS9sgSnjg5gkvKL4AF5vyi8c4qTvg", - "NodeID-EHpoaNccurjGvMCc4fFHKXvWKCzCeFsCw", - "NodeID-EJDb7Gfu7w4vJeBA5VGa4k6d2foKVE9P4", "NodeID-EKH5gkuABvZWiZGHvWuZLgGar4Zts6qX6", "NodeID-ELNdDSKVpamvTWSQvqqBWzuAKFiJLzoT7", - "NodeID-ELcEoPFQPwAQmnndhM7QXtVc6sQiJiTHu", "NodeID-ELjBQTBvaEAMk7Qx7qJNJsEh2DYC4nxUn", "NodeID-ELx4yRvGiDRcG8r8Tow1LUAhMXkVYVzHo", - "NodeID-ELxAoLLT4rkHwrAxxo6Ubkg11P4ye32kL", "NodeID-EM1NUe17RtPAJ4ofro1qPc8vEfcvEhjZM", "NodeID-EMETD23g2Bne8CuQKyR8HB15KWomaAuFe", "NodeID-EMq3MvHvWctiQ5CC2ioXpeyKPsHteXAeR", "NodeID-EN2aDGGjPAqm4Npzk9wCjCdGfg5hVrWgp", "NodeID-ENc7M77QRhgtpDojDQY5nqjndjiYCWR4i", "NodeID-EPqYJkZ7knGWY2TNe4rxRtNgkqc6spyDC", + "NodeID-EQtsYPVt3rHBSJdp2Sss3pm645cpTJkGp", + "NodeID-ERzoQo45TdZFeWHG7JpHVnHbn7ULpTRiV", "NodeID-ESRpVRqLwts8M93Ly9QPm4ZSdMF4wEpbt", "NodeID-ESVMWUoEkKz8uAEDfKcEpu5UUCkA6GeyC", "NodeID-ETwxZVMHXcikZmKsKfjiZuVG84KsZDdqz", - "NodeID-EVchqoADmKDHejumCGQDgZKc1RoqAWnFY", "NodeID-EWNvJxWq2UBBsn2UH35soQugQJn8CVKdS", + "NodeID-EWmdnUhsVGSfZPnbuSodLUTA6ReJcXz8v", "NodeID-EY4iiXyj2TfoHspEHBHFfBYrHxXESnSN5", "NodeID-EYDcoNgbX22og1oyEn5s7iH1BYSmR5yF1", "NodeID-EYgNPuFCT4Qy7YhvsM2s8WKTT74QECvTV", "NodeID-EZ38CcWHoSyoEfAkDN9zaieJ5Yq64YePY", - "NodeID-EZ7FxvAP8MCsQgCz36DMBUGA1tcHL2PG7", + "NodeID-EZrxYbBm2ZcoK13eTPf2sdtYuJuSHyaTF", "NodeID-EaEUnvUyfTr19uMW8g51bvFXfi7r9xL1W", "NodeID-EbwYUq8FZAK4jf65nZ4dcb5kk5WZ7RBgb", - "NodeID-EbzFVG1XWNeioXm9KKPCvidgkZELPrj86", - "NodeID-Ec6W7Mq2fnotBFoiD6rwQSsZq2XKVEyTF", - "NodeID-EcPEgrRgf6CDahJR7mJpPvHct2EHi7jNM", "NodeID-EcoA7iNFXhc2DwrmWxiEvjvsDvDmQrEKK", "NodeID-Ed7NMisAoxzWRjxQVrWnBvMShLNcydRa6", - "NodeID-Eeg2Huipo4K5oURLwd6EJNm286b1js6rL", + "NodeID-Ee6MdWL7mFKdPAXbJTWZGvwEUsi17869c", "NodeID-EekL2aJ7TdkbiXDzSsPo5PKyaaQuQqVg7", "NodeID-EfnXCVeLUtW24v8gwW1VYiNuqDeRPEVYC", - "NodeID-EgAUHBUiTj1QTvNmw7cdqWDe7W7P8B2PH", "NodeID-EgzctrMz5jVPbfUEWGufKxf9CXUMLBRGG", "NodeID-Eht1FjvmFncRbagWk1PGMyE7hVrCS9Acp", "NodeID-EibWFSUHeLNNjWZrEznmuxH7ZWNsavRgh", "NodeID-EiyGqDavdQ8dMUtN5wjAezDXAWwVBdSBK", - "NodeID-EjJCGURmZ76FsztnHPZMn7AvwSDZXZhsV", "NodeID-Ek1pare46s7nXPF9JtsoyM7PcaFnCBms5", "NodeID-EmPwabyobnM3jYDvQuxZdLBTut5V5pq2n", "NodeID-EmRTfxEKTLpzTyWJmYTXVxyGr79bsv4Bp", - "NodeID-EmVPjC4ePzg8perYoF3c3ut6fHHDDfAqF", - "NodeID-EmWrMTi9PcnYH3ZPCXky3FDDTatB7bfuk", "NodeID-EmhfRnDPSzpEMhGy3KSC4BWhPdtoxmqqV", "NodeID-EnANSJ3hrErv6v7ZGSi8p5RCHhdhbGrb", "NodeID-EnVDmm6dUgePaWbtBem6HcbzptaigBxDe", "NodeID-Eo31HyvvA1Madeagm6U8CM376cEfgS4Bj", - "NodeID-EoJirncHtvkCuiLac47FracheuCHmMxnL", "NodeID-EoNXC39QyT1eHFPXb5PgvDNigBN8tMeCC", + "NodeID-EooPQfxvcRG9XQpNmbDg85sNzaFDzux6G", "NodeID-EpU1DGKMMvDRtag9u9G7uwZHRsJF5NodL", + "NodeID-EqBR9F3QBBrTQTN7CDN7sDEUsDGDdMYps", "NodeID-EqauaQBwVXnpamJvLi84aeZLTQra4GDep", "NodeID-Ess2uf91CDTfKsLezaTLKqqsWcpEHGvJv", "NodeID-EtFG3SrbbudeFQCaWRxhwvv28wHpo8VRq", @@ -1682,43 +1785,42 @@ "NodeID-EvdPJG2AAVGCP2s3543KDx1LZ1g5SiH2Y", "NodeID-EzKkVMd9y6XqzQsvRDLuaaiXqXK8fFipU", "NodeID-Ezk1hTiN5bogETxygJ5NciRvHXgXvUVVM", + "NodeID-F1JWRVsJ3Wq9eSdNEHvoivQVCsW19r8gT", "NodeID-F1K4jks15y71PthvXVNks8pgutgBwdHZH", "NodeID-F1KpunDAMisiGKLX3R6k9uBoJoeLwzJoU", "NodeID-F1qvuNMn9XBXSjv9iWyyMGfV2PQ2Na7KM", - "NodeID-F3SZA2ZNdRjTBe3GYyRQFDaCXB3DyaZQQ", "NodeID-F3b5mj8PWnMP53hFbfGNxkiXpbK6tPyDU", "NodeID-F3r4EqguPQgupLCYrTG3SeJSCi5qtc3x4", "NodeID-F4Q66oFkqCmRnBjDUAh28iXvWx6WxbxJJ", "NodeID-F4SmFmnXuFBkW5fgFgh5RT2T5w8KseGRN", "NodeID-F4kKmjMhZJWkYwsWyPSLFxtNcj7BhELmY", "NodeID-F5sBP4yNA2YXHbD6FJUjsZJ5zhoMqMi6g", - "NodeID-F6QBpEsQZXXqtW8PxZRm3Znx4fVaAr5Sf", "NodeID-F8HvQKYDbonSeJ3x42Ynb6ibxiJa3FWVL", "NodeID-F8VWioW7dC64159mMhswhzpkHxnB34cjS", "NodeID-F8Yq4R4Mx1LHGbQ7g8s3beNB4LGnCUBpv", "NodeID-FBtCkPRmkfDry8GGpNenBW2fn3fD3qoKn", - "NodeID-FCnZCi7LDQH6Jx1L4ArW3jYZUxD9q4rqT", - "NodeID-FDMe6hokunP6wTY3GFQ9u2uVPMtrfXGFw", "NodeID-FDTRdm7eS7sBuzAnQqMrXUmNiuNHP7VM3", "NodeID-FDZXWAQeuMzZVq8tv53b1NdiwyJDUHGpB", + "NodeID-FE6WTTtg1FvtgQMZBjjZ1qhZpPq4WoM4m", "NodeID-FELjhENFRLHTgVrwiKTdL7aSQbU8mBd5Q", "NodeID-FEUSZzFmjF2JyrniKXksGfRjkQUH5R4eH", "NodeID-FEsoMJf2VjoRPdnm1Ux7CGg5RrHnAH3VX", "NodeID-FEtgjYGndfWGzLZELTJJoikpSobjVKTjk", - "NodeID-FF2Szx54cN5iys83j9H5xaEqHiz3RipkG", "NodeID-FFWS6gV9FrKecNWCYJQuyR67t7GY6UiVq", "NodeID-FGRoKnyYKFWYFMb6Xbocf4hKuyCBENgWM", "NodeID-FGt2J8WREPFbbTXgVU9YC5NjdERhoMa7E", "NodeID-FHGwnPLGdU3FBzbwnhayx1sDjxiiyb9sD", "NodeID-FHHEXLYRNrnQhKFneEwDPX8TZV8WtUpQY", "NodeID-FJ7WdKoGBkqb78mMGrr3r6kSL45R5Vspp", - "NodeID-FJfF4TPzajcf4QNHjHUi4ctGPq2AxkGJt", + "NodeID-FJu9WvWrxTucYcNzEVQj1pHbbS4LaFTnn", "NodeID-FKCbGm3jmceEEpfSdA4uQUVANpmqFLAty", "NodeID-FKGhEFYnHUdFadoR2ePvdTTM5Sz8tgjHp", "NodeID-FLQ8ifj1DwXuRWKShjck624SAgYXVpQzz", "NodeID-FNfrZNBD1bxGj1VmdgSrEKT8oMePC448e", "NodeID-FPwgrsmgeX4DSkG4abJ28zZQhjcqirPYi", + "NodeID-FPzqAmcWBR9RZdNggUMtuyWwvuG2RkqrZ", "NodeID-FQKJ8yATVmwGuy3LN2ExsURDEtZNWgr3v", + "NodeID-FR1WrbXocb3QKywNmjQABt3a159QqRMBe", "NodeID-FRTCPrh8YwxmR9L1XJWjLuMA1r9SjPrRu", "NodeID-FS8PXhYXxoo5GoTHoki5Y3Fqk5zzdMY6E", "NodeID-FUpfjb5sPRnT3XxMbtephYBc1MHZE2RYL", @@ -1729,7 +1831,6 @@ "NodeID-FXzsVMpT3ipDikUzabDtmeLrXW8JYyNZp", "NodeID-FYv1Lb29SqMpywYXH7yNkcFAzRF2jvm3K", "NodeID-FZHUwdFr4rndHpmSFXLK9dJwKVcijv4yW", - "NodeID-FaS5J4D4a2FE7GRG6SG5aTizazC1QNqWA", "NodeID-FapbxinG8eCCXzZQKCjxicKcXijmnKzD3", "NodeID-Fd4DMc88ELLiTHHSLVZ7L4MB3Z7jbDEAy", "NodeID-Fe3121hoArBshDTJEEeMeJTNW6HcLXxT1", @@ -1744,8 +1845,8 @@ "NodeID-FjPxKjpGqPNj8NyEVVdJgGT2bXFVkNyW5", "NodeID-Fjgs4ALe7yajXjZYmcRAvaQBGrFE61QME", "NodeID-FjpAr4XXwanzuhLMajEVdm6bwdcGgtZNv", + "NodeID-Fk1hBt9ZyaKiTPjq7MLyvL7Kgd2YMH4ie", "NodeID-FkHyxMuq6DGNLdQtMKiLzhQQuwjSCqwHj", - "NodeID-Fo9rQ4aPdfbA2TZbj3Ppcp4pkQGumuNTZ", "NodeID-FoVyB5QV1hmvAxsNunHRRzonCBJGkLvtj", "NodeID-FpA1n8w3xHmJ1QK3iDAS49vbLJokejfMA", "NodeID-FqiffXvatKSLPRhkkc5y2MkALrZ8EFN91", @@ -1755,7 +1856,7 @@ "NodeID-FrWaLbhUVQHEzXfeekv6MCbkmLfx74HrP", "NodeID-FrhMaTxsagqjYCetCyxLxpbcpkN3cjVLH", "NodeID-FroHhWhFsUAh3s6Y4hjh7mx3E79mBUZGj", - "NodeID-FsmksgteqNTPjyrwVV7xPgsC8SwEwKrgb", + "NodeID-FsqY7xFDE7Cvnxkc1BkpnRbiLXH2tAVha", "NodeID-FtJRoxeiXq4D4hsM9PCAZkoerJDTqPEW7", "NodeID-Fugfqxb9NKZ3h7vTe7XsjqqKqxYwSrTsh", "NodeID-Fv3t2shrpkmvLnvNzcv1rqRKbDAYFnUor", @@ -1766,19 +1867,17 @@ "NodeID-FyTHAQeNPFhoDetc7pznBMJ5BRj5s6FJr", "NodeID-FzJA5i97oBDNiKeePSfHc2t3zt5cRHnjJ", "NodeID-G1KHG6SL2B9jnfbzdTudhjRPa9hp5tuRQ", - "NodeID-G36WdNdkGY4aSh77e1DziUy9SXTgohYCE", "NodeID-G36seLQVfXnaUgaNobbSWg8anRta2WUwE", "NodeID-G4dtkvboFCTYpnLyHYMVPq8GLxns99NPq", + "NodeID-G5AGU54ib6jCTc9B3aUC6BVLyhEZUuqYE", "NodeID-G5QuntEfMZS7A1TPSHN4owEa81C6MAGC2", "NodeID-G6nXgtucmeKn4nkCp8YTDdM4btVSnW4ad", "NodeID-G6oS8Nbb74RyJatPe34iwhTUPDqJNtuwD", "NodeID-G7aPjXRfR2XtrB4PGATDS8NoqxmqZmryS", - "NodeID-G7kG9MRuLaJuMLopdfnWEKUPQp54qc2T3", "NodeID-G8uVCikgvakai25byQwYx1z56N33unmj", "NodeID-G8yv8mWQy8FLdFfAhJ4v294T5Z2DWDVEH", "NodeID-G9aa4VXB19wnUzrmVq2SheaxnKEieUW3S", "NodeID-G9ucCcZoHdXC6mrVpKVqKzHsMrnoVZLU8", - "NodeID-GAEZpCd2Lg5RSrPtQhGvxw6Kid5tAL6bw", "NodeID-GBvezLieTFYRqHsd8QzWqH1JUhuwD21mJ", "NodeID-GCL85wyq71aw2FMRTct2PJ2F4qGQL7WH8", "NodeID-GD3XH39S9feuK74XEh8AhhNEapSt2hqHo", @@ -1786,11 +1885,9 @@ "NodeID-GDp4P4Jo84yyVRkL3UTkJDuTNno81BBxN", "NodeID-GE2jerBVdHtvfKkqfNHwBr2MCkDf6tLir", "NodeID-GFbG2ARoztCgE1FxUekg5KjEaA1bwThjW", - "NodeID-GFw4C6SgNLkbVq5EeaGtZTjGKwZzmWbUz", "NodeID-GGHpri3tVbRgLUEFKqxNivRbegTKBAnyG", "NodeID-GGfhdfGbqenvgChEXpdngjkKYAByo9di7", "NodeID-GHBthsGgAzrPLXuXk7vbq4qsc9CvSbwXS", - "NodeID-GHY8D7pCGPY2qScDmtLp2PAvpbnAiVib7", "NodeID-GHZZWcg26qxY8K9uDLXu6Gc9Gh3P11dK4", "NodeID-GHd5dmrKvYkAbxii5V7wmJw8sRf4JqYAi", "NodeID-GHomCXMMRTSPRZrrxEULYPFHHXEhb7qvY", @@ -1798,31 +1895,31 @@ "NodeID-GL87o4Z7DghVRLf4z6befUxjDoWXZUDqg", "NodeID-GLSSsNA2oHSaebdYDBQ3u98kvHfH7zjYf", "NodeID-GMJcCQwhNFDGQy4NAkKM563BMudjmHpXb", - "NodeID-GMUutmiNAryEiuGU25DtGiUmdijYqzWH9", "NodeID-GMoxCucPFt2LPSpTh5hPbDPAp71fiV648", "NodeID-GNHgGvi7xri6CckDAzmQYL4YgR42WkVsX", "NodeID-GPYurKNwtkhJ7M7UQoDinFz5P7Rsu9yUo", + "NodeID-GQZBUwNZb7iSYWEyqpyrp6HXG7Z43uhWF", "NodeID-GR11oP3kLHf82Xbi3H2kewqoM7ydHF5ES", "NodeID-GRReUAPgHbGdXcv5Btpm4ByGvLrD1NgXG", "NodeID-GRrpJze5AEaBezaYp5QRtVcLAF6AzdJSy", "NodeID-GS68HENWev9AWcUrhLqxYvsv2opJBZ7km", "NodeID-GSgaA47umS1px2ohVjodW9621Ks63xDxD", - "NodeID-GTiNyt8W8giLsJbH6A8jXuLjDesZKwo6a", "NodeID-GTu4yYzFRv4QGXyyvcorGDUMWjzzMWuqN", "NodeID-GU7boimY7cxeqdDmnPRyYrwLiRmwiHxhn", "NodeID-GYAMwLv3XViragqqJUQyTNRcUtoRWbi5F", "NodeID-GYYGoe6y5TtL8vNBVkvTqk8sPTVVqbGaR", - "NodeID-GZpKzj11mC7eg52BWpL6x5YpQHBAhKPaD", + "NodeID-Gajvbi91pdURX1xzYQ7vzm1qUzNQJEfbG", "NodeID-GbhKbbABkTdzExgzbbsvCdc4gZe8eHpgP", + "NodeID-Gc1hRnfx1mvhgaUnmymNq9TKwvhFjhEkC", + "NodeID-Ge9DfHbtays3Yfsyr1C2Z6eHSLpmTXQ6H", "NodeID-Ges52zCMZimxqri3ia1J32mUAKyUsvcpV", "NodeID-Gey3HmUZyAXuvawThT1McvEjrofAwrGi6", - "NodeID-Gf2f3hWkqxbYtdwPHFRJXQwf6PFzvFigx", "NodeID-GfDdBdRqzEKK55gCKqThE2LVxLdLhJY3A", - "NodeID-GfRY31feBaTknS7uvpF7XHromUfckDeWh", "NodeID-Gfeb3fWPCSpA4g9edG68NS5aJcYpXn6T3", "NodeID-Gg8SEQhx4vU2KWzQS8ESCrSpcjzEqQ7kY", "NodeID-GhG3ac1x2g1Fc4xPWXxXRoTLmMuT2asMV", "NodeID-GhUSE8wcdouEgd3xeCvmYhmevkdNetfXk", + "NodeID-GiEUKDy7YfYRdxD5rA7t6CgEQxyrWP9sj", "NodeID-GjYkDpBkCueF4vTkZVdtq3yFiMJha2XpF", "NodeID-GjjemGsR2kXtPLSwv4oNV3JFt579oJUnn", "NodeID-GkiJ8CRTibePNf3Y2F7LbGTinHm71HvnF", @@ -1835,9 +1932,9 @@ "NodeID-Gq6cTyqtHRGHSHELPNdwXCjQJH6vwUkBc", "NodeID-GqRuMoELZus5EYMwBpiBVtWFDnvLmaJj7", "NodeID-Gr9xzzL6emX5jWv1LoMKLpCebYR2V2nYs", - "NodeID-GrUepNEsZ6CNa4MvP2r7XS96mywaWxvHP", + "NodeID-GrL4JXttpkikBorzFchuaGhnDTWc8nmEb", "NodeID-GrkiQsGvbv9PSqJf9r3eE79fUgbZqydmK", - "NodeID-GryC4h9okVKe5e9iZAWFxPWtbtMSMervo", + "NodeID-Gs4BSxTpRPxx1ioRz18VUB3kEYVBsDV5T", "NodeID-GsQoMs5GAL8inkh88XPVJWKMwmJqm5T8N", "NodeID-GuTDsR1tBFgQUbKqCf7J29yBo8ofudHEZ", "NodeID-GuWMRuFkQPvPjdnuegSQYDmTMbj3UtPBm", @@ -1848,49 +1945,35 @@ "NodeID-GwfPzhzby4Ur8mgdqPDjR3jSTevtmfmY", "NodeID-Gx4oY9nZmAzJrHUfobrmuK9LrJhwejykC", "NodeID-GxUaibkyR88sErviW2WK3ukDJsT3DFpoU", - "NodeID-GzSFF2tfNMc7YdJzGeNeNxfSWjDvENJUt", "NodeID-GzhNocnYWSCziBTP5Jj4xAKn29xDKW9Yr", "NodeID-H1R3mBHFDeBoQzVYyHzX6RGnVV4nMTrWZ", "NodeID-H1YSzbspeyANTzErprmBQgV2Crq5hXSW8", "NodeID-H4mD37NM384RtLGjz5aERQoNCrtGEjgK4", "NodeID-H94Q5zdkBByZVWvqrB5ByiX4dZdG1J45y", - "NodeID-HAYp8Bi1yZ4dy4JeBQRBydGC8NqPEURXC", - "NodeID-HCvPALEtcP4HX3HbPk4P4SQcrriBgsvCG", "NodeID-HCw7S2TVbFPDWNBo1GnFWqJ47f9rDJtt1", "NodeID-HDXjAjk4rG42HXey7gzQPx6dMBfpWeh5k", "NodeID-HDmmLUSLtok2sGQEruUsYSMjBeQbUrwpH", - "NodeID-HEXgWUqyRHf8KkRLMccJ7gNaDGZQAjDWF", "NodeID-HFFiNVtYmv2YF2WHCZWHSCigo25RxgnFz", - "NodeID-HGGdFL79J8hGBoMMoimh48CcKRpCxHcb", - "NodeID-HGtZapUapv9uNq2JyUA3njmdFCPJbjdqR", - "NodeID-HHQ4BFhNMVJwMz8b5tenWtkzdcSYvonmi", "NodeID-HHV1onrMrN68JdRoKfQGeZphebgRrcADT", - "NodeID-HHXrPaqfJVquBsJnCam9KRdNcQY35sPrG", "NodeID-HKskHZG5zu629RsEkScAaGrpfGQABqep7", "NodeID-HM1vYJWnjWhJkJi8dErcu4p5UDxwUKbp9", "NodeID-HMFqHmnsaeBGdeg83uXsraRJSH67DNsi6", - "NodeID-HQ4Nfe891SxSJ2FTx3e9AdabywKG2ufYF", - "NodeID-HRM3t2N67g9R4nWc1DhoL4GohVhHEbgFm", "NodeID-HRZAiPM3BaZJpAq9jy3UME2EGsrv1ZMaa", "NodeID-HRmKWRK8HjqqTKWvYMBNv9hcddSYrhqnF", - "NodeID-HRsnjv1s8VzZz8Ybuiyx9MgfDevUcPeYF", "NodeID-HS1PKAMjZczSb5ZQRastn1WG6eJeNmahd", - "NodeID-HTAhjx3CNb84CJUMsGj4SbpyvEsuehcWC", "NodeID-HTG7W4VHoGJBUTip1gKXzXGtEBhiW1DXT", - "NodeID-HUNYARt6cNSXgANtsSakokNpRCUKCFoVS", "NodeID-HWwYYkiTKnXgYycNN5gXQfxhhA8TZdBvs", "NodeID-HX7H9nBZX3nZRvLVUxCDBesVX6n8Uv4a", - "NodeID-HYBD7r66XFw2Kx5UydvFNAb3w3nnJVtY2", "NodeID-HYwzPrs3tDR6yyMtKZo22fq8grJsP1DVF", "NodeID-HZnBEWRUGocZ4HYX8EuMP2YEY94NtySWR", - "NodeID-HauVjq2twoqYvMdNe2dCqzSJoyvG3DJc1", + "NodeID-Ha5u99aoKUdNdTdomp8bQcWHUw8PSF7em", "NodeID-HaxdTdeEr1sWMRZvXwRN2iotd6RYd9XYM", "NodeID-Hbf2ZY1Zs1s8KMp3rA1zK36N7zt5fSLkz", "NodeID-HbmSiec8zTKiPWxaBwStg58a3N5KePhC9", - "NodeID-HcFuyTmh2wPEDBCQc7T7YqUS3N3qj4oRe", + "NodeID-Hby7B4s5wb697sM4XFN5VusKW7eNyDMg6", "NodeID-Hcq3gpdMqAEiVwq19E5DZhsjggbkxFx2L", + "NodeID-HdByRj5WVuR7REF2eJDndNyHA94hYhjMp", "NodeID-HdG8EdGWAy8LR8YPA8hndoa1uwwgGv1si", - "NodeID-HeWgNLFa4623i2Ha67tpjnA8RdDNpV32j", "NodeID-Hfa96c7a4xF9vYHuMh3cRsKUHa6YkDsYN", "NodeID-Hgs8rDmSTASnKigsVfz7k3yZ3DgXP5s1j", "NodeID-HhEvRMAeXAuXqULRysWKNLK2XZKzYwCnK", @@ -1903,7 +1986,6 @@ "NodeID-HnCFvKLXEVsT1fJtMxCnkNj5fs9ExEugv", "NodeID-HoC4UxP4UuJyda7MZs5jUkZRk8Rfj3pzD", "NodeID-Hp82btBefk1ffBD7d1qtoBL3DuuNUv6qa", - "NodeID-HpEw7munmgQtTNd8PWqp8T4GNU738Jvc2", "NodeID-HpMSfYT2ox1vkr1hFNMwmdWuq8QWhvH2u", "NodeID-Hq2aEQ2RYhEo7BkVR83c78n6wbVLPrbqJ", "NodeID-Hq5vdoGnZLMfasw4ykMzdM6PhUFDmp7FL", @@ -1916,19 +1998,18 @@ "NodeID-HuPCfRaLN2cXoXDYyi8GYvjATLDmNJMHs", "NodeID-HvmgHvMoe15ks8rbGXHyKHvJWDyN5yAGU", "NodeID-HvxZoKdC58RkD4ZVTYwjVZ3TsiQoTESEP", + "NodeID-Hw7wL2of6tnqntucHPpca6xnnTYZCvBRL", "NodeID-HwD5fu2NCooHXCPc2GMuNHrhfsThpsQYY", - "NodeID-HwQ8H4zxykyXmR9dZgxsiKiu2u6s8Mppw", + "NodeID-HwSpUzHSq3ZQC5H6sL9xyze8r9APmFunH", "NodeID-HwTU12fiGyZoyqaShTAFgTadY2w4DnazT", - "NodeID-Hwo6hDmWvSH3rQGrxCoujGvsDWzC9NgyG", "NodeID-Hxx8vTs8kH3stQWgPw1XdHKqpbuD2nMRi", "NodeID-Hy2aSw3vVNwwQhKas9ETUxtfZgcefsPZD", - "NodeID-Hyr1U8Tbw1Q9wgJYRfraYsEp9EzMugRte", "NodeID-HysvJteG6zyScbEu5WKiqAetFXHNrnJHA", + "NodeID-HzSHrBKrycaSu3FMCLwd4WfPrQF2n61tG", "NodeID-Hzfy8c2s9PyC7CPiUB1PmPckWYs7nj9Tm", "NodeID-Hzwoqn1Vmj46T1HZzEUNG9kb633SLLHxZ", "NodeID-J1CD2Nw1eX7iNUVw3iXjFJkUgrSm9qbm6", "NodeID-J2RTGUXRNDSx2kBU8w7Am6Y7k3LABR5iU", - "NodeID-J4NNvkEUScCLYG4aN7eW5RYx15vSCHrui", "NodeID-J7GwUKfHXhxTqgFbuQd4us6yKYdwahHHx", "NodeID-J7PV3mKZgSJRDy3atopJhh15Y1TqYsySk", "NodeID-J7PjfVJgpLL3mBMUwpicPqiqDFAmNWhKA", @@ -1939,11 +2020,10 @@ "NodeID-JAqrskRRwjmmU8fRp6RAf5wDoEtjXFyXu", "NodeID-JCT5WWZVaKqcMNDXuuYm3Gpgah9TpKevV", "NodeID-JDH5gzcB2DTfbEokaFU7EvpLN7E1RHzpH", - "NodeID-JDS6pq6tZxZxePaDc77TvrmNnY5HBUNX4", "NodeID-JDYxVGLrUb8SHwuu5jZBXNC9rqYWd29PG", - "NodeID-JE8JBF8Kb7xWQ4U59wKp3PcZMBfzvKo8h", "NodeID-JE8niwmtgpDARKNUqTEdXPQY41uHtb1PN", "NodeID-JFMBphfETbxfarEkQBHw1RSpfoFhdhUSR", + "NodeID-JGVF16zbVcXqH8ysCQdK2ap38DfHk8ie3", "NodeID-JH744d6NN5DbtYR3fwuonjNGqUNwhYG5V", "NodeID-JKCgdbWtCa8BreNP3xftfUuoWGXoy8hWX", "NodeID-JKxZwnEvK2MAsL9SQ46fyCnTo1ZDkz22D", @@ -1953,15 +2033,12 @@ "NodeID-JR96tvzbG8L6xdoGLUWUWhQiGkCfNFP7z", "NodeID-JR9oQgVHfNBybNVMm64AB2AGvHFCfaaxA", "NodeID-JRCLnbo62xRaNLhNeNd3HzSHK4dW5iMx4", - "NodeID-JRNiPWVdV7Vq7MzBmAQB4jekNTfvRAedj", + "NodeID-JReo9xxdEAX82pAt3berdoi59Pn9km8nV", "NodeID-JSKsSxV74dyp94CvBKqEKUcEEKBXyNbge", "NodeID-JUncQvtGY9EVfsfHNHrdsiv4kRfAQSsvu", - "NodeID-JVTZ5F1RvjDd4dA4Th7hiV3furipAaKTF", + "NodeID-JVRaZNCXjBjKqsmrd8grSR9LjFDr1zcgo", "NodeID-JWBfuYPeFXRkuL1AeW6p2fquqoQTVJsV2", - "NodeID-JWRFL3w3x2xjxYZGun74vRjNofTw4Gpd5", "NodeID-JWwGze2HXQq7THFQj5zWRmBa5XaMj55jZ", - "NodeID-JXT4uEeTEuFcEEgRZYFusfRm8c5iH3rqj", - "NodeID-JYRSy3bCaQMdn5792isxetF1m98urfFWq", "NodeID-JYoS8akGmcoeLq4kxpxfsPJxwi3UWeXu2", "NodeID-JZg54UPtzhHhXoVkX4r6WSTc74cAgdFjY", "NodeID-JZoTeECdroSJ8sDK3nwpeBz2cYCEPPjiu", @@ -1970,43 +2047,35 @@ "NodeID-JbsnKEwxa9J6arKtZ52j4obF7FwvH634k", "NodeID-JbyG4cewqSwjatqGtg7mDYbcvb299Cb8Z", "NodeID-JcVg17s5KwKNv2yJtYfBjEFfB6GdHDmXN", - "NodeID-JdwZvLUi1hnwuidkpJnR2ZfryBb3FbkGG", "NodeID-Je9mYMihjzv2oDF3ebvzDKs96zfaXDLHF", + "NodeID-JfXzxLA38XSz8EfYiWDUvsz6Tu8xwhdkF", "NodeID-Jfx9FcVMQuy1FXGd53EuigXnCEgRQUUMg", "NodeID-JgEayrUnvk1tvMFS5Qvr6LPNSE9wNYNik", "NodeID-JgdYonZgwW2LRYGMwcDcHywQ4GmvjJoe2", "NodeID-JgfyD94R76Wj1KBXWkGpnsSAXLM6f6dnN", - "NodeID-JgnwfnQC9MeT7Tba3i62KGhZiCpSNNQUe", "NodeID-JkjTJNKyJwjEfxdfgQhvrUuf9x3ovpQBs", - "NodeID-Jm1k2q2WAkH99w4ZBEgzrmm6Kte39qCWJ", "NodeID-Jmvu5u8svgTa716m6xBEcrB6wweP9tX5h", "NodeID-JnREhSP5nvBcrCY1L3it6odDaHKZDryA6", "NodeID-Jp4dLMTHd6huttS1jZhqNnBN9ZMNmTmWC", "NodeID-Jpad4xARtJKgtzo199VoEaGbmYdBYbN39", - "NodeID-JpgUnEssGrh9NBagctXHVP2cXhYZHxgwf", "NodeID-JqHkFFzz1tYoGHzPuTsueqF1yKifPiBEG", - "NodeID-JqVwhr995DJVkh8z6u79nRknt34pmdjNY", "NodeID-JqXD8Tsj1nKXCBEp65ESmFhBrEhPL4WCs", "NodeID-Jr2wjVqKeLpnyK23Y4EgDpCBf1HJ8XpJg", "NodeID-JrHvS97Avz8uqX3E1RgG6mCSaiedjWf5E", - "NodeID-Js3ahWihoTLJWTrWzpth9mttniJNuyoki", - "NodeID-JsNnvXMTu37NctoU7tHx8mt4f5oswJk93", "NodeID-JwiikR8FhmnYxxGjywAZeJMFjxfpfD3L3", "NodeID-JxJxzCNp5c2p447FF24jEDPdHkbB2mhJY", "NodeID-JxxUAnbxUYQXzTQ8eNeE4jWQt9fTzWd8o", - "NodeID-Jy9zeyBRu9XvAxXfSGQ7pdZ1opTHeERgq", "NodeID-JyCGTjJaPELmLZdtn5J1HwKHZzki6Ae9W", - "NodeID-Jym9FJcjAbqezV5HUbFT3eG3NraSQSLMZ", "NodeID-JyomXASU2NoPhoGGzQtiVKUAHFpm3NeU7", "NodeID-Jz2nuAFAfyvgni96rviZWsXxyYYBgSmXf", "NodeID-Jz9EUhGBC19bzUE7kurEPyoKTRjVMgi3v", "NodeID-K1E6w1DSaHzZky2aUM4qyQfPYMxF6Mixi", - "NodeID-K1JfVJnvPQ9ThN4FUqU2iyAQywjx1Gf5K", "NodeID-K2fyNZcrWA4DBUNyFme4pNshAgSw2YSSL", "NodeID-K3gyeR7GXuuf4coJXD4CxviWpRopysX4j", "NodeID-K3unRwiJFD4p6dXDHJcdeQn6CaoFiqo2", "NodeID-K3wvYyc46fLE7sSy3G81uta4wDKVkdKbZ", "NodeID-K484QXg69NxbC2BUsB7Bgc511t22E6MAs", + "NodeID-K5J2aanpMN3PJLmYT7amdzSGygetejuPQ", "NodeID-K5ecmXoCnxQPFTwrDxqL63kfdh8X4Z3oJ", "NodeID-K6qqr2J2JcYZnSMRSqpbVv5ysZfnwMreQ", "NodeID-K7ZsFPBybHPuD3YbzBpp1fe9QTj81WYSU", @@ -2015,14 +2084,15 @@ "NodeID-K8zr3RfHUQuupNJdPDKnbhFhwcD3TTbuD", "NodeID-KALbip9YkRerN81YxU32ySYk5PbGrkysz", "NodeID-KAjUQ36dNGmMpw35iavX7i8Cr5XGXwby7", + "NodeID-KB1wcvduXXXkTUw97gWchLs4oXbQK8Gwk", "NodeID-KB5e5rq9ioGR5uicmKdmgjR5hU7iRUFTz", "NodeID-KBcYcnQmw47qpb49rKtRr5tZgsxnsdkrZ", "NodeID-KBvpDcnJ9ztfqA4jiAoMwARqfDaS91xqx", + "NodeID-KC9tasJTftYR2SYdNcPRF6XJGng6gBYcw", "NodeID-KCQARVq1pjYw31EPSaW9571giKoFH498X", "NodeID-KCX4L5dr83TbmBnE4UeFtzGeE2NSLskt8", "NodeID-KDHVpdM7PeMtoVm2mmNNXjFfs93cABSut", "NodeID-KFhoZ7aZMtAReBrb8KgcKG322q27akhN4", - "NodeID-KGQWaR3xNXewSaQhp4zAu8ZkZv6DAdipn", "NodeID-KGYVGbz1pbyuJpujtJAkXhSY3AtLqBG2Z", "NodeID-KH8r5RoMBBpy4XHHb9DMrbMLc2a1WJKWC", "NodeID-KH9WnxfcrJLod4JWXHxESehVTAqE5DoLy", @@ -2036,19 +2106,18 @@ "NodeID-KLPimX5rN51nsSg9UQQahoRvKapDLD1pc", "NodeID-KLiUDfG672VocEHwbAwGxxFdCHovg1Zp5", "NodeID-KLsfWtM1cJLWNG21LdwPxaLk83pZo99oV", - "NodeID-KN84FZ7Bwp8y6tvNa52iwTGs4LwWgTU1v", "NodeID-KNLkh3KVKFFhBWujmcZ5P3p2fJc3BbdNA", "NodeID-KNPCT1vLFcbVsFvLzgQqrbCS2kvEyZKBz", "NodeID-KNm1ZqZXdAMJxggBGJkSs7A4tSwYLAjEb", "NodeID-KQfghSuT1CskYLvgrQAt6oxUQU7ask2QS", "NodeID-KQfmZVTmDMvuSEW2kts1rmVNmspyzUwVq", - "NodeID-KQocfzJn3D4V4gBGPYsUB9Es7nT28Atvq", "NodeID-KRhtytNVPjiSeZMJrqqE1vdHTCoMTHCer", + "NodeID-KU58LYgLuboacvuaNQ1T3VZMSdcTxzFfH", "NodeID-KUgJ4Tiwfx9di8h6oPCkTEcrBBDiDq4hg", "NodeID-KVB8F5Gy8adXA2zCg3i3m3qJ23NoCDDiA", "NodeID-KVF3A8uB916AuexeZWS6eeeMdK2ep2vi2", - "NodeID-KVXQMie2X9quytg2ZdRq8rsadxfQCvNHF", - "NodeID-KWnYciu66jjGTmiqs5U8hyeexiHEUa1eu", + "NodeID-KXKwcGbqgdKb5ksmyB13p4oP1r8jmsPTW", + "NodeID-KXizASmXqFZsywyF2n41NEs5y6MBbJaa6", "NodeID-KXuvoHe9KgzW6KfVNHXW4CUNunzWDDC4M", "NodeID-KZLSjb8umvkj4nUVdARnY55NBKQcYfVV8", "NodeID-KZiZi4sS44KZjmGtkeF6r1vs2MNN7p2kZ", @@ -2057,50 +2126,49 @@ "NodeID-KdEdrTAZpr9rdfqcpXjJxEbHC1oSWnvZP", "NodeID-KdxMzeB5ubHBCbk8SqgesC4BAUx7fCT6q", "NodeID-Keh97V9b6k4QvYt4JewbkabSmGoQ4sA3Q", - "NodeID-KeyQeQwf1D4bzdcHVP34xXXWhJzFjVTSj", "NodeID-KfPXTUa3haWHCr1z91ULmY9Pit4VwUQ9C", "NodeID-Kfqu9wo9FhcXG1jK9nVwbTrBV3d3kzmKR", "NodeID-KhvVVixdSrBD6u9q25YYNbayxBnNsw9h", "NodeID-Kk1UZNLJiyf57AL7vYPHntjPYLBdmTyu6", "NodeID-KkCG4Sktn8zxkaFRV9bi5RaJxZNu1XyMq", "NodeID-KkZX7xaSAUZ2sGBwpGWLSfLRER4pzR8Fs", - "NodeID-KnSegLyDRx7V29WU6PgTAy5FnWwQwdz2x", "NodeID-KqKMF5JYhxjkMVpYWQz8zTiv1N1qm2nSf", "NodeID-KqmFvyCFfsaTcs2XDquCerCfWx3S6Zhj9", + "NodeID-KriCxu39kfZ99PrLwzX2pDUf2Uh8V796m", "NodeID-KsSwTshRyF2xV75YDNXcEB5psLaBFHKfr", "NodeID-KsUkk3D4hSKJGM1WBmeu1yj8Ab7h512X1", "NodeID-KtJJDa5PVQYChXaNd1fKVmF5LSsBB8NHP", "NodeID-KtJLagoYnWfw2oBnRki63NcguiGjuA2Cr", "NodeID-KtKf9AuKyBvofsQE7Jn4eAzAndKHu1f4M", "NodeID-KtSsjRubDzNuGP6FsXphHmtjWx62KCqvf", + "NodeID-KuGgrUTz4ki5oYkE91wHSdXgGL2Gb5fju", "NodeID-KuStLqzCMZmLv3NigAtKPt2BEE12q71wQ", "NodeID-KvBcQpCDXbb3w8x7ktMhsx6rCq8eSYcd3", "NodeID-KvN79EtxbHdT86o7w9GBQEVeRWZ5woAJx", - "NodeID-KwWsJneoQZaVzUaUjjkKDj44BxJqoXT7D", - "NodeID-KwqhQAGTv8eemSuH4yEv3x3jE8VJQPZ5D", + "NodeID-KxLfzAQyjR1At4rPWmWYGueRUkxSfbVBF", + "NodeID-KzbTvxZgKCWpKcL62Y2HbB54uuDVNTCSo", "NodeID-L1RcwxtQjb72GiCABuonnV3PWFZKPTV4P", "NodeID-L1u2bQdMywnBLHVkrMiAoTSCYJTGSwE9k", + "NodeID-L2zTrwT5JitNvBTbC8L8N8i3ANQ1KyNd7", "NodeID-L3JrbBLmihsqtaXAPXg7acKQbGa9tjhEc", "NodeID-L3SyWrZH6uorqgExkkmGuXPx9neqELqXA", - "NodeID-L6MwdnCDs69eZBXJJZ4jw4ZHW3CyZahyK", "NodeID-L9D4FZhAGu8xGd6LL6Kn4ZqfpXuXSxTXJ", "NodeID-L9HsJPQ9TF5aXjdx3KnQrh1eWaHJaNXNj", - "NodeID-L9eaKWJQNkywXWVg7FKMZNWFno52oh3J6", - "NodeID-LAk2MapcDFFxS7HZ9KeuwxPhdCD3YtZDm", "NodeID-LBA1YYYBbxwYMMAA9odGhR69d9SCbyq8v", "NodeID-LCQBGoE9MtECsDjNLohwAP6L4rXDbSooL", "NodeID-LCRMLuFKUYvcdAemtKiudy1XNM9oMN5Wv", "NodeID-LCVUCE4bvtPopRuYvoWwTopRScmpLHTcg", "NodeID-LCvxVSwts7BQAS5mVuXH8XYGuVJZSRtCn", "NodeID-LDgwboNU4iVyy5MQgArg2rcDPssiAe6jT", + "NodeID-LDv41AQj1469CJsYDux9cLZepfaAWKzCr", "NodeID-LF7ktpNDXo1fjHYN6MYHnitMPrHwN3pup", "NodeID-LFNBojkAbg1az3ys8htBJHmyQ96hYhFzP", - "NodeID-LG2NYC4RxxzCG4zFGWoAwSo4U8mjMux1f", + "NodeID-LFg6CHJ6gQKNjcCMoz97BdDwqTH9JDUbG", + "NodeID-LGPn5jkr3MueEHLLt71wCRire43N5rp5u", "NodeID-LGrCunBRJPWSqZLEw2QTHruuQtZai5P64", - "NodeID-LJ5SMSqLy1x6NRLdz7FC7y57QZMfR4W4r", "NodeID-LJBZ5j8beyjdcnVdNk5fwtThNn4LokYpV", - "NodeID-LKPvVELtRehiZPQo3aSWuch123JpA7H48", "NodeID-LKbxWKUAE7s5dtGWhm4Cr8hsosDxLsNzu", + "NodeID-LL3tKdbQ9qCDRMm4cif2pGsxGDXsNNzBp", "NodeID-LLVMxBRYjgvczhD9u9RJDSmZ48bbXdWx5", "NodeID-LN7tsaTsJaPDTJHjUPUX4ePk2HFBWZVh9", "NodeID-LP9FxV6iBCayBiupHa4QiPxtqDWNoBoVx", @@ -2108,53 +2176,55 @@ "NodeID-LQP4aci528q8z4KMe8Ug3Gh1aHj4yojPX", "NodeID-LQhwkBnuj2vjE786WcgsGneFVWcjiH6KA", "NodeID-LRBqzoj2mB8eD4AHE2oCTBziNdssTfxuf", - "NodeID-LS7NEp4LEVzAsjFRaRm6RFKDDL5tWARVo", "NodeID-LTM3DRAzRtWoWHVtB58s5CohXKYexiqVp", "NodeID-LUFJGzAfqkmUaTDBVScjvdWtrruDkbFvr", "NodeID-LUhB7mVaTMnkYLQsqf2RV2PUerJfsq2wW", "NodeID-LUqMj414dv39Z5SNRXRb3bz9YhLJ2oWrS", "NodeID-LVqsakFrQLyqNiChxcYqsBzKaKFRMiBsN", - "NodeID-LXBLi3qaqXWjkawWZLtvpYCK2LzcPutRc", + "NodeID-LXCSfcmd7p7LroJzJtYoSAhbsawe47CNk", "NodeID-LXVb4LZEU53c7XCk2v4bU2qacG7ux5dUB", "NodeID-LXpULpbU1A4AobEzCSBy6wYLEbogwsMK1", + "NodeID-LYXB7GQj7vd4Ju3y6fMnX43wkAKJoEN9b", "NodeID-LZMN1BDS3u6pe7T5Umjuhg1Z1MahXkK9C", "NodeID-Lai2VTTYk897ae9uq6cGk9FbhKD1KHvFS", "NodeID-Lb2X2hJpi6krux6aRpYSG7xcNvCXNg6M7", "NodeID-LbAkNKxyv3kCs1C2ngkb91STbKpYHKs1q", "NodeID-LcBGn2kscipZRgqhKqDCA5dq4WmHuuvai", + "NodeID-LcG4rUqdBPdrnBuNQ543C2pHVwfknyMJJ", "NodeID-LcNseW1dfEL8FnXQB5HidFpzNu452vuGc", "NodeID-Le5rVEBBPdgYEcEJpvYeKo36hRs75WE5S", "NodeID-LeZUTECdpTLux94oAXKruxYgz5ppx7tfr", "NodeID-LeesBWnR4x3zWaDmYTPQHmNhsMwm6KqWK", - "NodeID-LeyuRqXk3UxoDMZWjgqSY8gR9wDVg4ht6", - "NodeID-Lg6HaVBjndKUjyXiq8ZjHookjqzkDxH6Y", + "NodeID-Lf7b2RCtkb9mYi2Y5kZ3mJvJNc6MEjVnC", "NodeID-Lga7mB6EfqgSJv4VTPaUwDjEtq6utiNQH", "NodeID-Lgjda988AdujVYMYdwuEM4Tc8aopF6DRk", + "NodeID-LhLiUsJSSSpW8SrXCT319enhrYDybuG3H", "NodeID-LhjS7bvahdBn2BomUUBHHFNbnzLRjri6D", "NodeID-LhkzuEyUkHR9SW4cMxB55QQRbbGF83zzc", "NodeID-LjxLvskdhxQ5jAhBKSzKrxU9NQD1DPuKR", "NodeID-LkDLSLrAW1E7Sga1zng17L1AqrtkyWTGg", + "NodeID-LkTbz4orQbSz9hQsjyY743JUA2v1vPjAf", "NodeID-LmZ33PJKkQqueDDzPnmVSyHMgFFmaADrb", + "NodeID-LmvNsnX956Es8bWDXqaVm4UTQ5wHC3uf7", + "NodeID-Ln3NxH8SbGS4CukCp9Hs3q7ijKfGqneXz", "NodeID-LnR5bqTLkmeGjsDKiPdJNSbRPr4pjAURR", - "NodeID-Lp887ddQT84DG8ub2kfu19RuzAJKzriSu", "NodeID-LqLgyDEyMbd1uXfRa6kf8EPjnRhpF4KCF", - "NodeID-LqUHsZZeoCvhiwunLtAJMSXx1GxYpozzq", + "NodeID-LqqUzQs77BPhtbXR7jFBsaNRxdLdfLSnT", "NodeID-Ltq93eHazD1AtdGNuWb739t4fyvnRLryC", - "NodeID-LuAPt3GG24RsuzmjPL5neGBwca7r1h31E", - "NodeID-Luoxf3Y7sPVwS6xjZTTHR7yJANwG9C9No", + "NodeID-LvKMfPzfWT1VfAPLef6denZ8hTwSAFMGY", "NodeID-LvWcDhi9d75T8dwerYcQRoVWD6yDtywFN", - "NodeID-LvioWzV19k7FxhFZC4Z2Xq4qxnswkL46C", "NodeID-LvpYyT4UY4UAgP4quynTFzffYmjoxqZtR", "NodeID-LwiNyRJeqRfAGS5phAQvvKhX9xj8LbQ86", "NodeID-LxrJtyQXpdweZH7LR3ujcEQZJ9VDTW3tC", "NodeID-LydNf31SmNLztbKL7iNsHXPhnKxz7g3Cw", + "NodeID-LzEWm3dhVaGJeHA3ZzzjaRaAVWVeL4Bi3", "NodeID-M17yakji8RzPBFJNPXnksjoeabg7BXUJH", "NodeID-M1SrBrn1szYR6jQJkyrJzd6YXsbAeWSnj", "NodeID-M1Zsz7o9AiDgUqA6KFE8hrCkvybN6EqcP", "NodeID-M33qUGE35HbVRppTTMY1qyyfK5T52id2a", "NodeID-M3VrNcHHd3LGpwm6U6Gw1vfuJHoJzfG7g", "NodeID-M4AhBqhjwLxGixtjxaLvenUpTe8mxNfhg", - "NodeID-M4Yxuz5MrQd5K6dxhnVaCYPe4Y56w3pE8", + "NodeID-M4FXQatkpbrCWRwdf381tfifDzXz34XUS", "NodeID-M4ojoWJoEmsVD3vf7KxZ2BnfR5Ue2wr41", "NodeID-M4psvzu2dS7hQ8gHgCUzXfipVKuFEsoFU", "NodeID-M51d2sDyE92NjgRaiTnSjSLaG3U9eJ3BD", @@ -2164,18 +2234,19 @@ "NodeID-M77VJM2GfeAzueJ6DjumoM5enZma86Zop", "NodeID-M7GC8ZPn3JACK7sxBXqzeoNW6Q2XZeCpM", "NodeID-M96ypSznK7ECF4EGd5KfxcxCiboyAZnAQ", + "NodeID-M9LeDgEaTfEN1qnEtLw3CXBwjh2VcGbeG", "NodeID-M9Q4Fc2StCtFCofjppsy6DC7JDGmtRfUA", + "NodeID-MAg11ijmoZunT94rEdvxhmQToJzgH4bYj", "NodeID-MBuKQwYxNAttaiugN4eMt1aV7vhLUo7Qh", "NodeID-MBucJmfSNuMy7CiXWb9Zzd1Gf1yCoKwGy", + "NodeID-MBy2Rde5LJyWunzffJ9FfBj3BVNg1haib", "NodeID-MEnWKkj5iUC3Z2rNhKuDTm5EVDu2ZUZZo", "NodeID-MFp5wwuKzSfCNESpdD3avbZBkZ3KMkEeK", - "NodeID-MFxpZAcCZZagmDn9LtJoidGktKPpoZoBt", "NodeID-MGJcpxBEXDn2Yk94uTXQwxgmYtuX6Ky99", "NodeID-MHBrAomZpJhaYjqWKWXSS3YusVo7afBn6", "NodeID-MJvk5Su2t8dFhcGe6z58Fx8A2QAAZTMGd", "NodeID-MK6HYMwXj3k3HZfzjdegdnd9p9LQ1dk8x", "NodeID-MKfE4StupLg6ts5v7u6Drs7HhFf1rHjEj", - "NodeID-MLDFMQwHyrvXrYtJvhuXDkHAS3kRxydrU", "NodeID-MLRgfkWbezKNtcH2ghSyE5J3C4Rcxg5Sy", "NodeID-MLkE5eQrTGa4BoQSR9QLEZKQB9yPJEnuN", "NodeID-MMemzZih83vtU6TRK5oiJt6bJpNSWm1uE", @@ -2183,7 +2254,6 @@ "NodeID-MNm7zKhCHwqQ3a3oqqEqDSXM9uVFMcEA7", "NodeID-MP8NsoqJxPMUfCbw1izND6n4i5pTJJkhS", "NodeID-MPLzWkWAbT3937j7U1uWfxdTMg3iw3BqY", - "NodeID-MR5cJw9vYb2cA6TExPE4ZXioGV11zErUq", "NodeID-MSbDAksgjGPoKE4azGEgvrDj1EK2GG8T7", "NodeID-MSrtdRQ9bEWLhi5d8YLQtnB9E2biVkkrJ", "NodeID-MTEbgxTNBdL6GWh8SdQMfMXvEU1jC9aws", @@ -2195,23 +2265,27 @@ "NodeID-MVUMPzSBAtrHwTD5SZSNPRVTLkYnDPDz4", "NodeID-MVayMsZd2VrMvEwFMDreTrauJHGBZu3Xa", "NodeID-MWqZRLNFJzDPKnEuUHJSpEg56ejrzY56V", + "NodeID-MWwstjwXDrzkd3Zqnfaoa9vWtCpb32Fhd", + "NodeID-MXNBsr8xSHE9CKfmyzvBYyEzxAbLuHTAn", "NodeID-MXxYFnzdP24DpJmdtUKqzMEN7nh69aYqD", - "NodeID-MXzyYAXy4JPVDjmXapcJXW6HUq9Yxmnr1", "NodeID-MZV1PpqVuFPa56t7TmfA8VVdXxDSHnQW7", "NodeID-MZxjrRvxrjvAdaz6pDS82v65xLwckmiti", "NodeID-Ma3Ztm2A48bCVjfiSmoZS5MKNzKVTRN7j", + "NodeID-Mb528V8a2cdddEYWmxh7ThDGQoQWhMt73", + "NodeID-McTi7BY4csWEnBAb5B9Z2ojNSk21Nt4NK", "NodeID-MdQZNCCZN5gTEMVaJkSekNYCZkvp5xp4L", "NodeID-Mdpo4kYtg8eqn61AhjTrZ51exnHLJmcpA", "NodeID-Mf3rZ5w3aEtM1bzRBwFqhZYZMwks6FYF5", "NodeID-MfVDQRZ6jSUmke5aofBuNXruEQunxZ5F7", + "NodeID-MgLEPkYaWQD6XqbvRRMk6CfMWe3Zw3P7S", "NodeID-MikkG849wcdpBdeUJ2HTV2gTEDfeXWseg", "NodeID-Mm8qGQPb5tHF96ENH1MuYsYwhA5Nj2DHj", "NodeID-MmTfUacXsPdKryR3WkVteMqoFvyxEdYf4", "NodeID-Mn2isVXFR85bfjMHPM1DT8EY8wig7YhTW", "NodeID-MnQoJXMCgPk3zxKQ7kkYdmoZwj2dcDcmb", + "NodeID-Moej2WBv9BCw1pnPGsm31GYvfyY5BHZCD", "NodeID-Moz5Jcjj2JoDgay9ScwcRDQReSqX8sjyz", "NodeID-Mq7hjS5ySKApHMKCGw16YFo1tW7xA5DXm", - "NodeID-MrGm83LnY7pRQCQz9mG5TTpRWSBgNhDr", "NodeID-Mrh4UKAifNZtd8RJXqokDzajQnAsZuw8Q", "NodeID-Mss1z2VZYsNSa4LyqD99vXeNd8h3hUMDA", "NodeID-MtJWp4WidtWe1jzPf5u8hFtxMy6TCmaRX", @@ -2219,8 +2293,8 @@ "NodeID-Mu35k31HAXFbEp1SqJr1uUrue9nwqVFe6", "NodeID-MuEFvXvbZ964sk1rdQKWNtUc5PJAGkWeL", "NodeID-MvfTRb81PAx9AHYxbz5xACaoG84PM7YQe", + "NodeID-MwZ3XEbAdDciHW65MpvfPjiyS9D68hiKz", "NodeID-MyaTMxwSKbtrFRRypqr1nWKJ3EK6di3dF", - "NodeID-MydZ4Ju3KA959gXeERXvqxN88EtUrAaGc", "NodeID-MyeSQZnEZDzTfFFQvxZ5qqfqVDwg15NPB", "NodeID-N1aFXom4C5ALmH33bXHuRpPBo7Nwqeu8t", "NodeID-N21EWyi4Y5D8MNapwZ5tXs9D5A3rrfPi1", @@ -2229,30 +2303,34 @@ "NodeID-N35BjCN6ARikprxERf4WiMeUnh2ZsfwJJ", "NodeID-N3WnyXmV89jbtQgmjqpoxBxpi5Rah86az", "NodeID-N3e9W3EngjabGnTZVqyZwunVcbCdrY5Qy", - "NodeID-N46bdSibDXA2hx5pFFTuVG117Khi8j8db", "NodeID-N4eXezpVzti1ssWvyQKqkuGB15dJNJsp5", "NodeID-N4r8sLfeDVa2c9eDFpE4wuxJccUku3LKu", + "NodeID-N4vaumNTt2kixxUTtWEBgy4vwsxnuahc2", "NodeID-N5FWBAn5j1UVxb3nH45N9DyXEAaeZiU4q", - "NodeID-N6p8Do6bVJi9xHtCkgxdP3x6wQBZHDoy4", + "NodeID-N6c8ZxrQwMWWMGn3GVbZvW3GwC6PyWYMz", "NodeID-N6z9WSBMoSxLSRtdPDz8jZvasAskYcCrd", + "NodeID-N7FjoUy3LrDi1kSYeaBwZjja6H2Y2NLsN", "NodeID-N7WPJ9DXvEx8xLJdtDswNh1JdNmCKejSq", "NodeID-N7iZFQdtUfPRcWGs8DB3JQRZt3Pq33eoZ", + "NodeID-N8MfE7gFMQUdH3wirj6HXkYZeeKd13xAx", "NodeID-N8tijV4qwWMep4STmLzWJEkqbg6bSdCmn", "NodeID-N95GoeyiprvxNj6E3G8QvYg3gpQ7x8NKE", "NodeID-N9S6JJT2VKRZ48vA5vtWgboDnfzXXycQn", "NodeID-N9c2YTRzGpRNp2J6qyPEEiAvyrViL4cGH", + "NodeID-N9qur4q5HCDb7xK6b89peZ5dKJxEWPdFm", + "NodeID-NAFCCsFtU8WXbgpgbciz6zUzwnRZAE99L", "NodeID-NBjvikZcadcyCJ2hEJsUn9EcCjys5hav9", "NodeID-NCVrEpmYjJBHqj9vx9r5usFiMd1PooCfZ", "NodeID-NDMPc8h9L6keJw8F82NBobc874zZ6bDa6", - "NodeID-NG15fF5qJuD737tg4u3PUw2hyZ8RZYNNU", - "NodeID-NGFHFagkdYNsjJ94n2nZwLhiDZtV3gwbT", + "NodeID-NEeK7hrVjQUHCwFQVMTmUaVDr33EH6WAw", "NodeID-NGspMWkA7FgT6DnDghg4B95pQ468j7DK8", "NodeID-NGxhFFwufwUSXGHjxdCUZW1hNpodfTrmj", "NodeID-NHBv1LqcCdrcwatzQ9pGbGXPZQTi462Ur", "NodeID-NHEESrJJNnyCPn5c5Uyp9EZYHCCkZwzuW", "NodeID-NJZWC8HxGtLkxjQk5F9KSG44WC3gCm8a9", + "NodeID-NJaSwZPtuiN9TxaFLVF2sk3eNNHGm2UC9", + "NodeID-NKStfwoiZwBnZEFka1rqT54AiZ4CN3ksi", "NodeID-NLBgQfsmCGFzXDehvwvmzjyfmkWQndx9L", - "NodeID-NM6RqsshepCVojpp7R8747TGBLRvYpLLB", "NodeID-NMfBW4PDVkVZhJzJa6SiCDZ4M7wAkXbAc", "NodeID-NN5j35c8DsuMydM5icoxhKePqc7AjwH1K", "NodeID-NN6iut3SAWZqM56kbg8EhtpTU2NkMJgWV", @@ -2260,16 +2338,13 @@ "NodeID-NNrbnhLBjgzBvhi3JXK48ckVFcg6FXVnn", "NodeID-NNyxDSovcVYmXHacSM8aK2pg67oPjkRrE", "NodeID-NPexpo2AXQ7RZC3wCKugj9q4y599pSfrb", - "NodeID-NQWgSd85RNm2um4AywRNozgczjAwpmzbp", "NodeID-NSAi8z5XtoagdADeMNAPuWxfZpzUxacYB", - "NodeID-NSNWfQTGX38pRWaky2MGe4ShCSkuLnqip", + "NodeID-NSHmxWXYXAvHLdHqNyKZjP8MgSSu1dNnW", "NodeID-NST51yBNtgVkXWuofyacbR1MbqYJEYdor", "NodeID-NSUM9tzmeZ1DujarhTwjXAcnCeAH273v3", - "NodeID-NSa8Z4kZo8KnHzKHsVUkV9gW83NoNc6uR", "NodeID-NSngpSyxjXz3ErfjsFoc6CpfVPLxApJen", "NodeID-NTTNYBYdkf3n5U4zrZknt1nst9rHzpuCj", "NodeID-NTvJb2gZdvYU2kaMUrMbtu79KUMgyJNPW", - "NodeID-NUgiF4juieHZmcR6ekc9EDaRyG8qHUyjC", "NodeID-NUur4HBKXj8GS5TX11jZhtPHLH6zMa6L5", "NodeID-NVSSRYMjjYyMkUpt7AHXWnKNTTJCd8UbS", "NodeID-NVkHd9WCbVAr79r3gtA7AmKBkVkNL9EXb", @@ -2277,25 +2352,22 @@ "NodeID-NYjgvA2mJy4kTCQeEHnSuycnu5Kgo9gEq", "NodeID-NZEnXQpa55wAhwpcUZFgSAREXW1FLdkzQ", "NodeID-NZGsXrgoEuExZdJn8WxmyrLt4Cxb7LFyD", - "NodeID-NZYwtzqeQFeNZHjYgdukRvsZb4xQ43Fdj", "NodeID-NaGEfmLttvK5r93aqaoxLKoADVcs2HASy", - "NodeID-NbYMJFDrhNhubNus3qsw3kJBy6HNEV9UU", "NodeID-NcPHhZ4wgGywviLVxEQ6s2q5NZm6Wgrqb", "NodeID-NcSLm9skkUrfA9mKGjdtmT163iDjqAw6H", "NodeID-NcZtrWEjPY7XDT5PHgZbwXLCW3LGBjxui", - "NodeID-NfJFVKNj7kCUUWCRYFJULe1AR82f8a5ox", + "NodeID-NdpTU44ZgiACprPmr9evdh4NS6Knz1PfR", "NodeID-NfgHajZM47C3CaAXFa1B2YrwZmc4EdSgk", "NodeID-Nfz4ZGQ8ZPvNQ3yHoRNMT7aTCiFYjMnSA", "NodeID-NgkksDCWH73BnfgN2ALUBykc2kftsquff", "NodeID-NhL9H8VSfhrktdjmQQ3P47wYXzRfQwBiy", "NodeID-NiW2qTm2fSKHGuMqeo1twtM8j7LoAGzHR", - "NodeID-NkXpMv916WuB4Np5P31BZmByna2poFAby", + "NodeID-NkYLNRp4S6exbWamVvMzUUpXvHeVEzLR6", "NodeID-Nom39tjDi1Vf51VxuaZvJiDeQHwbyg6MU", "NodeID-NovHTxGVasNU2y33YPwmQ39DbYDkXiEfe", "NodeID-Nr584bLpGgbCUbZFSBaBz3Xum5wpca9Ym", "NodeID-NrVSfY4zCbPjYTe4XPjmQB7qLJhYW3V6h", "NodeID-Nrs246dXUZmALw7a2HRTANx6U1LeawsKq", - "NodeID-Ns1eDN3K9HTnavgiBQhtpzRxUCxJ55Xhc", "NodeID-NsVdtyjprgWXLsvmuWvYe749tx3tdbY55", "NodeID-Nsdn6eemD7KUpKEaGYjYFuJjxC36c3qXC", "NodeID-NtDMBzQGPnp7suCbyCMcdE2CFU4JXcvwX", @@ -2305,10 +2377,8 @@ "NodeID-NuXW8S95Hvv2eq6JoY1qCDmK1h8yuAAt3", "NodeID-NudTZgq7DKGQsY1Gkt1v3ZG7pgaWbbBuj", "NodeID-NvsbNmirter6SLhta1kkvoEjcgvaHxEt9", - "NodeID-NwZ4wmDE8DrbaDY7V2nZscmLBKdRUtUyN", "NodeID-Nwr26Q5CPcRfSHQKgQ5y3ayVPgjziWkkT", "NodeID-NxgyyDw6YGHprTJjZv7qh9X1yoj3yZN7u", - "NodeID-NxzZe138M8B3MQh7N9u4qetqMS5ViAgqV", "NodeID-Nz93c8UB78eEVVtfxpcecxHmiy2gZ4iAi", "NodeID-NzQnRDwTYZJPwYMcDkyNGCnhH7S1HQZgy", "NodeID-Nza7rHanhSFgJ6m9D8fFWgrx7fqbxp7q9", @@ -2321,14 +2391,9 @@ "NodeID-P4tSY1ZLb4q2xTdYGXCkgwXWeQN7mUUWq", "NodeID-P5hTsAQgfSLJumMDVDK2773U4gjyPtYnr", "NodeID-P5q5numCvCNo6GmD8vhDqq1tU25Yok4Ky", - "NodeID-P5zxQ1Y22ztxzjunvJU1y8BiSjdP4RUwY", - "NodeID-P6Gv97A5P1rFfm3NrAskXWKZKA1immX3K", "NodeID-P6M41urqadxF7NBcxEHNFxKkGPkHjC95v", - "NodeID-P6pnhwbrATbNUU2GXcEYCkfryyoBNHyoW", - "NodeID-P8pP9viiCuazxFMPmgkai4v3j9WNEKj1x", "NodeID-P9FGdfCp7sHRcUwHERp2hzo98ifUaCZ5x", "NodeID-P9kf9VSRrgD8B1MQKMsjravHvMHVxvoaZ", - "NodeID-PD54wi24ENhbBnKKhoD68MGXCDc3A3iA8", "NodeID-PDZYy4rfhPZWskL32EMt45zuLD2rWjDLs", "NodeID-PERaNX2PDtAr8zkXgbZvwXHfjq4VKtbew", "NodeID-PF9fY3h6ZMMqPmTZZUwc7wyLnZ1rSoz5u", @@ -2337,29 +2402,28 @@ "NodeID-PJA7yH2ZVtccSj4RrB94a8MtHboS9xozZ", "NodeID-PKiUH3xw8SmVNVJsAqFV1mXwDXToFVATi", "NodeID-PL7xq98yQ9kTYyGDvVQg3efowKeHug3HN", - "NodeID-PLTGkonfx3iubqTEpwsiDCMmRmwmh2HuZ", "NodeID-PLs2JZXeTtfZvYx4DJqkA3sKXz8ynvKLM", - "NodeID-PMGyPdRXPKRPRiWXAqR3XqbAHke2gNDUe", "NodeID-PPH8k8RGmrTuc6Dun92atkbDkgs3sj6ws", "NodeID-PPYetyVA4dk3bYdNtvTsy5Cqg4L31EUze", "NodeID-PPoo9VFqdSWsrZZHrnrBBfi3uE2cw9JgW", "NodeID-PRxbx3LZSnwvLqFa5audJBsSqAJe9rmsP", "NodeID-PT45awwLjTTiEqvFufS4nCkVN7wtEsDmf", "NodeID-PUw5p37RZKVjpK8kxBa12TBtZZdhykGUP", - "NodeID-PXZcW18N1BcYiDy7iWgHLGKwiQMQuBSyg", + "NodeID-PVm9UudEC7N6HJ3jus5KJ1Rufck88g1Dt", "NodeID-PY3QRSGTdYzmPTQEwrH2AmYUMBnrcge9Y", + "NodeID-PY5kT7pHUEZPmh2QK5k6w3H6pKhFGUfq1", "NodeID-PYFkkThWT79Sc7QqHijAc1yZjSqfXu6Eb", + "NodeID-PYJbbkTHqyuowa3EKkkxeYxRcXUhxehkF", "NodeID-PYecKsWbPTayLsHDdopKjB1Mw5NP3kDUJ", "NodeID-PYmftFnrKf6y9k6kXXuB5GWwjLtkP7sLB", "NodeID-PYwMEam56vM4Nix3AG1vufHZbMvdv8zwy", "NodeID-PZ66baswBL8xsSHaFVG2Yx7qH8MkBfXSK", "NodeID-PZvapthv5iRB7txuVNTrKCo2fWovBExLh", "NodeID-PaSvEqWq5ZESHSuNGTZeQL6sybzsQzoZ5", - "NodeID-PaYLWdJGvpxC63eK3RWXLLS8w37442aV8", "NodeID-PcDGg5a4P3XK1E7PXS5YedYL7vi8vSXvB", + "NodeID-PcN5Zh5GNvUJnoiaqkvRvMYBo4oAMDvTs", "NodeID-PczCXQXPxNgeKy3P4jtAt1ycvrjvghVw1", "NodeID-Pd7Hexv94PQNVnEbYXWUttEAAybG34Yiy", - "NodeID-PdsZ7ZyzUrcW5BxgRBKdH2hcR3wAdWEAS", "NodeID-Pe1pUMoFAts11s2kA3F7EPmzLyZwj6Msv", "NodeID-Pe5xmD9DhTrSCDykMqFdG8CazG3QyJxos", "NodeID-PfY5X2GWsSaj8y6usEji4HZmokHHdWsqi", @@ -2367,27 +2431,24 @@ "NodeID-PhB7iV3nDxiotJnAMetF6puzg6fxTqZCP", "NodeID-PhDmCZH4R8VFjVzQLRBquKMVss5sKukw3", "NodeID-Phds7RN13xWBmpe9MTPhJde3hajVpUB38", - "NodeID-PiaUvMvdFCWXwhRcrb2K1iPn4h7NugKjk", "NodeID-PmH5X1xavW8PjgvkW1u4K9qTHAbMx36hq", "NodeID-PmJQ7UjZo5db9XL494EbbEufAbYxqWswU", "NodeID-PnuVZDXvdSNRbC92ibq5w1FtPvbTFvwmM", - "NodeID-PpYToPR9XKswScUX1ypXKjDUP7G7utRDz", - "NodeID-PqL7ZLMh4fFQNxKrKt9uWuZKa3UGsdcdQ", "NodeID-PqPwxtYAt6AmikigAwkRzTQCaeMqPvpff", - "NodeID-PrPRAipDzRmPYPSDhm1dKnomZNR1YjLwu", + "NodeID-PtG5NyNK2mGku7fSkRDAUyaZwtj5hcbFV", "NodeID-PuF1sG8hh4CLLznER6vf4d1o6bWZc5Vof", "NodeID-PuYX3u6gfLje9bt6fCDFHkSwqaL8VSpv6", "NodeID-Puv7ksUTmwsxqEx7XLikRicKtKss6QNNi", "NodeID-Pv5X1dBk1wfZJwRqm8Aj9QecxvA87r31j", - "NodeID-PvZnYX1Nz8jp1GjQFixs1TAX9C9QXwrwL", + "NodeID-PvssbRjYWsCmvck5umz9V2qMRXMHPpz9W", + "NodeID-PxXndSoasDvvx9ax2h9bWGb9iF3LcR11h", "NodeID-PxmdCJV62VecySivang3vVymEBwjPQeTm", "NodeID-PzEsAB7RCHTFwHszw3yfs99GshYm6Qs5b", "NodeID-PzQafFPgbCLkvMgrP7nh7aCG1eKypdNi2", - "NodeID-Q3iFBGVU6gka1yX9EMjpNuezkocDTq1MB", + "NodeID-Q2NiN9VSKEYK11GMMFZm1r9vYQ2D7srq1", "NodeID-Q44XVjVEhgxacoq2ETj7yLBuUra9ru2BA", "NodeID-Q4mUNVKvwEHF3tkxQcCYbrQA8XWdybLzv", "NodeID-Q5rNbr5yFwotdbeRPGeTagHP1hbHYuaJg", - "NodeID-Q5wrexzsrQ94xJcXsqRQmyvRHCuYbrZof", "NodeID-Q5xvrPQSjHhJX8eLKbBnZMWbS648NqnsZ", "NodeID-Q6ZLZ1EifMyNd6evH83FJrVGyauaUSP9S", "NodeID-QBowbP1jz8zA86CtSzRwsFsxr5q1rY6pB", @@ -2396,31 +2457,29 @@ "NodeID-QDLrtBngMA6mFveLNZTXxKQVEYx518fG8", "NodeID-QDfLjUuR9D5a6G5ZAQdPPbggJxtLnbPj3", "NodeID-QHX9w6oLs8zjHdBvbzx1ZadHvy9aUNLr5", + "NodeID-QHa12bzXnupukwvFdWkRrRzRkC1Cz9nXd", "NodeID-QJMNxwTLjdg9C1vY2BKNtapWUuoeCgHFj", "NodeID-QKGoUvqcgormCoMj6yPw9isY7DX9H4mdd", "NodeID-QKdEYKG21HJ5DCQQaotjG4rJmcTgjno7f", "NodeID-QKfhLAkwYPwAZNKTanfuNfmm7cYRTzfYo", "NodeID-QKn4ujiEcP1n8iFbEJqNsKZUYbUG4fHAc", - "NodeID-QisfDcwSCUGaw6CwsBLA4mjJmTDto3he", + "NodeID-QL7j3UxnxJz2HUn6jNdqH7gqcGX5XcPug", + "NodeID-QLC3sD3RU2SkeWhSrzM8tfb5QF3XYgDgr", "NodeID-QmTPCR33deSWVwZ4Ri2jUw6cDAhoUwZP", - "NodeID-RSzGBBq5w69Gh14hRTVUQ3AR2WnErtGq", - "NodeID-TJ6G6FU4QtQFVNjzdjhjknqek5SZZGcy", - "NodeID-TzsHrNrY8qaAkg9MPAmJd7LfzCUDjvzi", + "NodeID-SWPRmNkYP7vP1y1EKnuH78QZNyJ2ZpZM", + "NodeID-TgaMGAEpkXKAisumnnmzzRzVkexbSkB7", "NodeID-UC1qmKMoMcfShU6idcreEAsxSHs3BDBj", "NodeID-V3fYZv2vHtLB5gQF548JRnSyk4tZfZ2o", "NodeID-V5R4XjWDtjs8Zi2g3TRNzngnGJiXm2ic", - "NodeID-VT3YhgFaWEzy4Ap937qMeNEDscCammzG", + "NodeID-VEhPJXs67q8rs8hifAfBxYUgE1s8YKfz", "NodeID-WAHX8MXekynX6xZSFiSewY9Qxnhq5HZh", "NodeID-WRz6mTt6LCdSSvuHdqsrBYxi4hdfecTW", - "NodeID-WrL5pKhhp8e2YLp6h1e62NBUPhuR6pGa", "NodeID-XYAkZN1GfMwcYRRyGLiZsGV2thZbqDGT", "NodeID-YdCKQdXecSPWqABWcRtPZvBaLd3MPPR8", "NodeID-ZVLPagHUUrQ2vB7mjsWQ44wNGf5SVKKW", "NodeID-ZwShn4JT1Bg91QphD3VBLryA88GFnAg5", "NodeID-aFRSyUykQjScZiWASVqmdTGzBfV9KKj1", - "NodeID-bTSBn4p38MofpJvhDgfNxuKAQkKxdqEi", "NodeID-bx2UN8z5nfLMTFphQqnYeyngQnccL6tN", - "NodeID-cmcBnV62GZxrLLmebZdeofd3AesueXac", "NodeID-cme6KToKFLCwqj27F7a7Ys9iC4cLrqMz", "NodeID-duaNgYtghtCRzj2rkiRDDs51BPX8CCjn", "NodeID-fr4FFtJ5PF5UZpyA3RyoxhNks6Yfhu7u", @@ -2434,22 +2493,22 @@ "NodeID-kZNuQMHhydefgnwjYX1fhHMpRNAs9my1", "NodeID-krdJFoXmC68zd4pSFCwMnCM4dhiR8gnq", "NodeID-mEbcN58z2esHFnnXHeR3T2UTfsR5H6WJ", - "NodeID-mRrTBjdn3s4oSyxjKEzLG2ibWU6V6Vzm", "NodeID-mfUNFSM9ak3NuCvaiFCtcmEcHF9ptfrU", "NodeID-mwty8tviuGBvDEG8e6vTQByDZN2MKnNo", "NodeID-mzhghLeMzv8qrRrK76wABwrf3LrL6mP1", "NodeID-nJm8Ltnf7MDCiuP3PzU4hv3RqXXKmeqd", - "NodeID-nT4KHRTgD9Lq44epZo7GPhjQTEFcGbT7", "NodeID-oZyu1tEJrBeFkquoqZ5rYpvsEAkfFiwD", - "NodeID-rA57yc1JzDdo6Fc4gND6Mwz8hQ4RBxJM", "NodeID-rKCpkJKNAZeE8sKEHduq8Co7GwrAdTJb", "NodeID-rS4TWt8iuAbQTsg6ez6u5tXvUzicRzuq", "NodeID-rU9hLEWJCxRksiPuEYm2qqof6uwWEDeo", "NodeID-rroLHLixQkZMTsTnePdWhDrGpWenYX7t", "NodeID-sAyLfHTC8ZQRn5HtfjNKxXDbnZTaJUqa", "NodeID-tHkVEqdhWPdX2vJGbqDWebw2VPrho4Aq", + "NodeID-uhGb1JoQ5sv9oJaECWYN7H5PabwxehN2", "NodeID-vV5S1LUtAxCWq9ASiDSjZpX88y2WcFGM", + "NodeID-vrzTEabKUgCBXYg3oHFwJFkR1Np6Avh5", "NodeID-w6kJAMpdT4hB9jE4NnEfBm47PzD1UXfW", + "NodeID-xHLKdNkbh94JMSFp2vU7fbwEA712vub7", "NodeID-xQU1Ntg4uYkkSgXivV2ELwr8s8FovRCS", "NodeID-xVVbmFL3eww4dmBkgQ2akBxcnEy4VyLh", "NodeID-z3Z8s8xoYQhN8A1fmNZcQx9CyXN6zxJz", From 348cb0f4cb0769c67464ab0264414edfa3cf19b3 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 12:14:18 -0400 Subject: [PATCH 70/85] Manually track recent validators --- network/ip_tracker.go | 10 +++++----- network/ip_tracker_test.go | 2 +- network/network.go | 5 +++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/network/ip_tracker.go b/network/ip_tracker.go index 0737c993954c..8bca76d7d755 100644 --- a/network/ip_tracker.go +++ b/network/ip_tracker.go @@ -27,9 +27,9 @@ const ( minCountEstimate = 128 targetFalsePositiveProbability = .001 maxFalsePositiveProbability = .01 - // By setting maxIPEntriesPerValidator > 1, we allow validators to update - // their IP at least once per bloom filter reset. - maxIPEntriesPerValidator = 2 + // By setting maxIPEntriesPerNode > 1, we allow nodes to update their IP at + // least once per bloom filter reset. + maxIPEntriesPerNode = 2 untrackedTimestamp = -2 olderTimestamp = -1 @@ -329,7 +329,7 @@ func (i *ipTracker) updateMostRecentTrackedIP(ip *ips.ClaimedIPPort) { i.numTrackedIPs.Set(float64(len(i.mostRecentTrackedIPs))) oldCount := i.bloomAdditions[ip.NodeID] - if oldCount >= maxIPEntriesPerValidator { + if oldCount >= maxIPEntriesPerNode { return } @@ -446,7 +446,7 @@ func (i *ipTracker) resetBloom() error { return err } - count := max(maxIPEntriesPerValidator*i.gossipableIDs.Len(), minCountEstimate) + count := max(maxIPEntriesPerNode*i.trackedIDs.Len(), minCountEstimate) numHashes, numEntries := bloom.OptimalParameters( count, targetFalsePositiveProbability, diff --git a/network/ip_tracker_test.go b/network/ip_tracker_test.go index e60213ef86fc..233fd7f20c3a 100644 --- a/network/ip_tracker_test.go +++ b/network/ip_tracker_test.go @@ -875,7 +875,7 @@ func TestIPTracker_PreventBloomFilterAddition(t *testing.T) { require.True(tracker.AddIP(ip)) require.True(tracker.AddIP(newerIP)) require.True(tracker.AddIP(newestIP)) - require.Equal(maxIPEntriesPerValidator, tracker.bloomAdditions[ip.NodeID]) + require.Equal(maxIPEntriesPerNode, tracker.bloomAdditions[ip.NodeID]) requireMetricsConsistent(t, tracker) } diff --git a/network/network.go b/network/network.go index 1ff6057069e1..4e462e933a42 100644 --- a/network/network.go +++ b/network/network.go @@ -246,6 +246,11 @@ func NewNetwork( for _, bootstrapper := range genesis.GetBootstrappers(config.NetworkID) { ipTracker.ManuallyGossip(bootstrapper.ID) } + // Track all recent validators to optimistically connect to them before the + // P-chain has finished syncing. + for nodeID := range genesis.GetValidators(config.NetworkID) { + ipTracker.ManuallyTrack(nodeID) + } peerConfig := &peer.Config{ ReadBufferSize: config.PeerReadBufferSize, From a8ff0a124d98352d57a3ebed5f6a635b54b59988 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 13:09:31 -0400 Subject: [PATCH 71/85] parallel --- chains/manager.go | 14 + genesis/checkpoints.json | 673 +++++++++++++++--- genesis/generate/checkpoints/main.go | 2 +- snow/engine/snowman/bootstrap/bootstrapper.go | 70 +- snow/networking/handler/handler.go | 54 +- 5 files changed, 642 insertions(+), 171 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index a5bd84d0d5cb..b8b051c0a058 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -786,6 +786,7 @@ func (m *manager) createAvalancheChain( validators.UnhandledSubnetConnector, // avalanche chains don't use subnet connector sb, connectedValidators, + peerTracker, ) if err != nil { return nil, fmt.Errorf("error initializing network handler: %w", err) @@ -1108,6 +1109,17 @@ func (m *manager) createSnowmanChain( } vdrs.RegisterCallbackListener(ctx.SubnetID, connectedValidators) + peerTracker, err := p2p.NewPeerTracker( + ctx.Log, + "peer_tracker", + ctx.Registerer, + set.Of(ctx.NodeID), + nil, + ) + if err != nil { + return nil, fmt.Errorf("error creating peer tracker: %w", err) + } + // Asynchronously passes messages from the network to the consensus engine h, err := handler.New( ctx, @@ -1119,6 +1131,7 @@ func (m *manager) createSnowmanChain( subnetConnector, sb, connectedValidators, + peerTracker, ) if err != nil { return nil, fmt.Errorf("couldn't initialize message handler: %w", err) @@ -1178,6 +1191,7 @@ func (m *manager) createSnowmanChain( Sender: messageSender, BootstrapTracker: sb, Timer: h, + PeerTracker: peerTracker, AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, DB: bootstrappingDB, VM: vm, diff --git a/genesis/checkpoints.json b/genesis/checkpoints.json index f5bc4de13206..4973c3daf12e 100644 --- a/genesis/checkpoints.json +++ b/genesis/checkpoints.json @@ -1,133 +1,612 @@ { "fuji": { "11111111111111111111111111111111LpoYY": [ - "29tNQN5Q32bctp1utmDYtEQy3HDR1osWSjT6enzPCPu7aZgbfU", - "2ARQJfUoWxLrrdj95fWz5je5UAENyMkNtshxzojbAWLcTJ2Qix", - "2Nmy919z6GipCHTquUAsYbwuqpsPBcmtQPUgdoBDNxHz1wcv5", - "2Vt3MxgZcS9FdADU3EQ23ZDJLyhBLH2vrvvzk83WkFfXUFbCff", - "2WBWBSem499WVH7TLjmJ6eHNMUE97eHPumoQsW3G4Kvaza9bFR", - "2aW19sCe23hHV3U6vdqzBazt1rr5i7eiZwbyzV6BjJA2WTcC6s", - "2ecYzYceek6FAX9DsbryLy6eZKe7Z59DYUjQPhSpSwwza9EPV3", - "2nLRH3B3AFBrMe4nP2GTcnUSbW68agmEJ8G2M1NkcLfJySbQNu", - "2s1ba1qw9WYv87biWumt4A2MatbKhLpqqqCHcFR12en85dGNwv", - "2sy9iEarGLeQKMJiyBaSRDDBeqPJtXqoT2VJBYfZQBxVz3JBH6", - "9oYNsiaLXNAnH1wU5zNzNGYTKr5sBTGMHfBiCwCFmntMwuqPn", - "BKmKYwvvFszxoYaeKHfBikjWfL9fTnmbvcL4UAdhRkni1kF4n", - "DcMURdU3yZVgpqZHZhpsk6dXRpBt9gnhMfrfVGKMGUy15yr9Y", - "XBQLmGiD1oPGURQHp7aVfJJwftB3znK7zZuUGwiJcxp9RtgAz", - "druBcLhhqTyxkGTyieQNcnaBkJ8Z6VCMjbzzvWmXSoVazVdCt", - "g66txMyz1SmTYr8MR4VMCYvcaBD3Uq7hgvA8hZfpho2MnioqN", - "iqf8fdw8vN5wWsNhPTqwUfWdcxZD4ru3yvR7TKaLBtRNSB8n3", - "ue2e6kxrR4ZvgJcmmrQU9FsYkkfYVPBKYDtBK8bNSY1iNWJKv", - "viMudAudCxdqzJNJHpKG5P2Qc12Jna9jBLBeBsxhCCaCxVTVx" + "223opwBisPqPFJYMGbHvmvNaBb3EVjHqDbaCD2k4DWmBErychP", + "22QytoWHKDyqoSHzEg2jcnpy2K1ocGhfLVvV5eUL8M5WGQyDUo", + "22eMTpCKswsDmHzxC3rq1foxecqX27DveEJD1octSqzu8dLGSH", + "23xcXTT2TBGqos4qsNmfhH9UdvEo6SSgG3K8tHzZSHgqRpuqF1", + "26mZvbGt9PVowp86TZkX5y8AxX66qgcQg48f8m6PGaGyyiMRxt", + "27jmo6kXpEHD4QsPNiXDZvN2mauaMjQdPdfQ6yqjZZTgd5fopi", + "27sYpucSURKu6AbWSKNLz37kjhXVzdkAiWmWyxBef1MaLNXyKr", + "27uCd85pvFdjGsnP5H3WKei9W7DBJ1exsG8ySKzLZ24ffryds4", + "292ig1WtzAxvwfdC5RoqvMHVcyQk9jwJeKPUXmnJMNUBmubjTW", + "29oddG7fursmoQNLHANS6h2WNftczJivnx9srxPLhqyv8yUG89", + "2AAxNFWkm1TEYuCmZP9aaP4MAX4nKuRk6HBGwPAyBsjVSpDait", + "2ArnZkyEykgEYvPBUnDQoeT5hvp2djc5chhPMiBddC3MWTXume", + "2BKC5Rw5guhbtq5ZzPBPA6tB7p6KT3uyqJmL5HJpnJoMCTLJcc", + "2BtVqL41rwv1EpLHbLhGGH7qmbp8CS4iBVbchy4XyDjXpdw9VF", + "2C5hHCqoRLh8VrVVAAPJXXsMd6gTWF7y7T6Zw8cFTWhNBPF959", + "2EALbD88Aa3jG9tyJ1EeTuNrMQEripPgT45ENoWa6kCBey4fj1", + "2F3nmzZ4zJwhDHpXyCp7qHipiL5x3vZ4E7U5GbdMioML28eGYW", + "2FasL7vS1W7KYydt2SRexThpeRc2mj1mdwYQGFVJudXgtNxbK", + "2GGCrHkhqYFsmZzEHGXBKTT1MYicZMUkXENLsxwCJEJnbLds2X", + "2GvUnbuw1Tzat9ANiBe8VKTCqCKqRJhUYbU2ydMHzhacdVjs7d", + "2MyJWUpCj5sEEfocM2QK1yHikmsmUYj1ohy5qpuBTV6kBV7SLV", + "2N3FEhJwqa7yQj4yiEUQWmiUjPXrwbwUdhyjmTWG4RY16dstBG", + "2NdCscMk9ptgb6rNSNN2z9jbAVS8xrHMiXQ14nfs1ZtAebfmrJ", + "2NtjDcF7768wapKgGCP2QMtkviypLQ9PRbEQzVNGHUDKoAFe9r", + "2Q5ME4Qu9tXheNCbbvE9ARYTBwcyeSBsQQQAcvoyX9cfqCzVqi", + "2QGPPTEQn8iyDcQEyMrMH4NnFoeYgKCrfcYd3rBBkvu4YG2FwP", + "2Qya51sKi6kBH4AYAMQLcHpMT5uDsuVZgtounj7GqqqWVvHW8Y", + "2SqsMUwbdGp583RTpewTnVwn16kUQon7N1GpiHJAScE9sw9dwt", + "2T57a4UW8HPRagb6dBftpVEUWCBzwP2ZeLrjL3hJeusDTXB9no", + "2VzjdKN5CuPQbZnP1AmqTnk4zesvpLd1mnbS3Nga4T71Xx6nkH", + "2XSRDfkA8vyd4EEwntPbULegRsV4ZuNkREXnBpdoEw2Fma1KjG", + "2Y3oAtgb3KtxmCEcF4qm7piGFuRX17abzv8dEDGNXeVX9iaJwK", + "2Y61SGxffumcVCkUYw4ycGe4BXYtc94Xm68XPp4hSCYDFZTess", + "2ZbZUZWqvNNe2W2FtdKiXcUCPBrm5bmX3SiaanQREFAxg4ev3Y", + "2aYuGkvExCVfptTid4oqKAeQGYrKZsxwuaLot8tU48KjPQBJK8", + "2dbfhBpFjL5VM4uzbX6npNbWMKPxWF5DhunzEi1Hj5hxDp6hK4", + "2igtVfGcQsSiADeKuRLW39RRZLewkTwhCGRvfMSY7v7y4AD8h5", + "2ipN93J1esuG4e4AYc7ASZBUugNP3x4zNbKahSavkrxinigJu5", + "2j3RXzmGYkyjkqJSXBmZChEuq2d159XAq1dijjWsWRSYi7hmv8", + "2jtrFph9tduRQnrwrKx4qVmfPeZAWzPGTzW8FvRnzRVYhdTYHn", + "2kSoQFdwQiZ7cnH1mVV2pAYBh4M8BcKHHo4HuuVhs3XyRbmBYJ", + "2kXf6mnse3hpoY531Xdoo6fv2vNJdT8y7V4Ud9pjNzEpMREBzo", + "2m797oeWLxKj9UMYfmwZajEjG21PzEd5RHBsb14pmB7mWEbM1J", + "2mzCA32ZmnoCfSGVhqtdrKtXBg16edtoFQJAqqJvy3Be5r2m7N", + "2qnJE1DDHmk4K3R2LrvoJMiMhJh5PymmrtfWjwfVpyPHtUGqK7", + "2qxgRBRKWKNGaBQEyxc81MwyY822vL3EBh28xCVDY7jA2m2Tis", + "2r3JH3so16Sm2wR6DoEW9mztToDm4cotAJkQRxX23J8NrmTKUb", + "2rB1a6pzf9Bk7JaLBfDYUUJbznDCjHVbJdcNzxR2oCMzgqk5gy", + "2rXgjQJgtHsQX1ijwj1XvDULkqkFziDT7oqfYo2gxAe6HAtPd2", + "2tHb5NapTuTEzQNFearDkh2bFTNgk4Bv85vEuwVAxDaESRYGxH", + "2ubwFU7pYNw2EPNsVmb8mLAEp2xfUBnwAACjKVHuzeApEPaZVn", + "3v4Rs8kT4Hr7fr5p3K4Yc5GmvBDieZv96CQH1fEG1QShPLX7q", + "61EZVNqCY4Lu7kzWS7Y2rihXaiRX1jT1o3QZPwhrDFqyQ2ymZ", + "6kqdpwBMmo4YaJs79p2XbuGnH7KTwWSye8c2Sqjc8jfERYuGN", + "8x8PagWMhJDDaya6oTmxbSXC2cfubqkqcKeXRvXkEqPnHwTHn", + "9VEBvpL5jEHxA8bnicvTqkQyapdjrMdp4PQyANp8D3GLGSYxy", + "AFFTGZQmL1GWeucQ89GFNKvjXprQbEzUBthzwjeVmybKgWNbX", + "Ag8rmvXryhZfxGte4sQccqJ3ibKvmdLnYYxwxFZpsiiuadxW6", + "C2jR7wmNuAhqn4y5XAGMFTJJGoxtc6QhX9Td2Bmc2T32DxuSE", + "CPw6ptdo67PWvHhZi1axonjFZP9GyCcZnjSWaAcunU4FPVSdn", + "CeNMWvAE9yUsbAap7u6dquJ6NGrUbPfF6i2UWGRKTkneU29XJ", + "CyyG6WwyVLP8zj5jDCVyaXH11auzRaasikoWbyWRqWfE67YfM", + "DPeEFcS4MvCWEqj6s3MQyGRi8vjc3SKySD56piTZBeWjzRsu4", + "F5QoLN7bJWJsLv6RgG6JWfAe2XWj67wvN7crQnoAdHYiDjark", + "FkqGhwHZLWaAjTEWPpLwvSf9zNWnER4XhhuunqsjuTfNRWyZG", + "GDcvEKFfDbFpdRmUwCBmHdSF12SxxMjzL2PNK6EXGMVWYPPDp", + "GNd8AChiLADLnqTmypEhS86vre6QKYpcPKUKZUhFnyB8gftyF", + "Jjp1kBE4tPMmHqQq8XeopNMREWQa8RxfLtv41VhpUT6jxupCt", + "KKYswxetFUrEcDHgGv86R9TcAegkA454RSFVVFGnnGd4f45qJ", + "LQ71p9PjkYBVWTUz9GbKPaFxA69V5pv4KQkVWNChKbCpKghiN", + "LrxumguWFXGaXty4nPzSzkogUQ8WBUufC2JGQAQ7D7KqgupQd", + "P2PzegHfs769nr5nEz2fFhbnPEBpEWWr6cmD8cahvvkAL7SED", + "TmwsnFjxo1jFsBr5rPH8XHLm3AtimbF26xBaxdmw9SYcHGNax", + "V6oXi4fXSV5Q5tvGYquWfdaZBBzUWQDS5iepyzsUtXg1yB6NB", + "WWfS2sqozxfHD2z3AJ5vgkyNbyYD8nwkJJJEut4xgjstb6JKj", + "X6LFRvgSX4rP9A8Fswtus91fQbxhQm1GFYDgTBktiZxTDkj64", + "XUE6WNfCKmHTcaNEsZQ2KftvnXXfPTKnZi5YBw3pLWXjTYZzu", + "awbBnaBnjKBc79RzRPn4LXHMTxoYL8C97toXVvbKPZf81iUp1", + "e3zK4rU88osx7rB9Nq35uBXJrfShm7f3eqVk3T3CHCJD1SrGg", + "fDLU1xyDSihqWErnm62UeMXZ7HNe2atawSicdWamFGTQbLv5z", + "ffHAHY1qvDLcL3u48VHNEXtzqKgTvoi56vKDMcinoEHyy2FTQ", + "gT5RrrsG2bAephkx3bUT9VZGAGVoosGj9Yn6ZgVwbFVWJVv4x", + "hHQYrV9wu2S7hzkewJpotYymvjYpPb6RBeH1oUHPir1EZwyJc", + "iD2h4Qw88P4ce7rbKGJaxXwJLsPeRt4h3kcThDEXJ82HF84uz", + "jB3N7Rd1HCJeP9wLmrDy3NMFT9fkVJ1B5G5KBoFVVRQxc6fpQ", + "jGSYaQZQjieWrt9yq3yUWkW54RYYKfoHxHaRqo9fEBKZ9zAu8", + "mcAyTfg1i71Y7DXjTggfnWrfdjnSWqtg6uHrH3y51AHTi4Tjc", + "pSLCmmTDhnxHFiY3FX4fqCSii65EhWXaRPef2rTHjcp63nVYS", + "qHaV2XmsBRdXA1YDLn8nCYvRAfQue3CdZM3YBWYvvkcW2gMkQ", + "rghpCpaeyY6PVnWCQ9GnBDGtCsRLsdNS9z3tDCSTobsDCNUeM", + "rq7F6LXvXNioXQQyk7qVgMwoHWWAK2UGQrGyJJjbqYH1CYaVk", + "uLPzkqsPd78pLTUVuuXz257nfJmJcamQdAFjXYCoKDuM8FbTz", + "uUGfX6pZNS7jXJW4uF25xntf27AAZMT91NLRppMZhWw2x2aEu", + "uxDeD1vay1vbN24j7Rs5h4kV5q1oDYBmwj3iUvh2h5meCKacP", + "w9djCKT2Em3S6URCHXooEiDWwjeahf66sAL4tBeSa4ihJofLb", + "wZC4y3LB4SPbYZt1NbqrbTJtEo3iB1VyR1vTPm3UknSdsbA5y", + "wt7gkf58s9uiiapcC5DL3Y3iunfWnewQu2woS7FAQx5yDBL3B", + "yXKPp5iLD5mMZp9cV83yD9Yomm4o9nEPy11hU1aPFvRJhTqwa", + "zoe37ZDDigm6owSYNyEgRe6Dj7EiusjxrsnFzPpHLw7EzSDPP" ], "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm": [ + "1GBo9WQ1SyRFZse5xhiMXQgptnzhepqnajzpdCvAJ9TNSJT5t", + "21xHKbCFFxmo5EdGCqR24Wvind1LR2hMWkHztqRxuu2ezRhE6b", + "23zbXVVjaix7VcFcU3jxJpGiW6TFxaEV29ZixDDtoGTkPF3eUC", + "25H3WwoqYUApdSF5eugBWEwqfpbmDtdeFLKFDwQqMD9aKHSBAD", + "25HTUEFnmPc193wW4LZUFjcyya3jy3Ws4psiWp7EU8X6WhAHn", + "26NADDbcCqF2xx5yaKTA28nQYcPCs1gcda7WwH3Q7sznPXZ71u", + "28SHVtdhn9MvJzMuzzGC8odjvBNcYvyAbtV6qBBricfP65NjJU", + "28co43WdBgJP6pi9CnqkspSvqeujm8oTK4GoGroi5ZZZqPnSQF", + "294ofGLtC3h62jc8aYpbnnsKJ1ufAEmp19rViEC8senqk8iKWS", + "2FGfG9MqLzwq9jjHAfx1QGtss5xKH6p4cZr2KQkrjE1Tin9B1X", + "2Gmqc72MXrXT65hxkDjuGS7cAJmwY3habQcr5HmXLDAFzyVJMJ", + "2HCLX89frJuqbauSLFreHFQ1t6yJSPb213hn8gpDUJW4ABsr8q", + "2HgkU9sT1oN6pUNt7CGonaTrcgQJtTpY1yHMjj4BYoqfECcJT7", + "2KGfWNfFrcc2qYw4s9oMiS29buB52h3UPoz5WDarhs4Kcey6H1", + "2L7ZfaHezUSQKoKNotq481hAsqafuCMX6DjZjvaktRjRfprjw6", + "2MctCP1iN6hskg6iY2EeGJRKJWbficY35UgoUMRd5PoaE9aagz", + "2PDa7wqNYoAHr3oB89weNFZujVdcR8fpjMPmr6MbUsWDsFQ64p", + "2PKwDA8c8BpibsyHim7n152C48viUt4wtccoWy5qiLiKvZHUVR", + "2RydwjCt1qipkTUXtjdxdQzwVCDjPLE6eNVzSxzUHhjBHko6vR", + "2SssQkgDtWc7dTnY4DSw56ZrCXBvL8uLZjj16hS5C3piNqactA", "2UFZQKZ1gLuzqeEqX2sHLtZNL3Bxmv1NQL7GdqS6ZvSPMjkftT", "2V3QXva1iArd88hVB7JsEK8tHn12a5qgifcPBkhpZGWc7fRRis", + "2VvgwD21RGHpEJeUTxhEVyuTdMDQN2Di8L37xPtmirYW4r22d", + "2W6MYE4TJZV43hjj5cMBHG1rEeStNQLXE25VMydkecAorZNPRF", + "2WRmUjiKn4xtGyw33s9qtyhzLvYPBByRoP9vWr4H5Hy5WKYr5J", + "2ZX42ozafD1DaWAKK5Nfsh9FUEKiukFKYfSFtwpwBxU5VLpBHV", + "2ZfNzhvVrgMLy5jX3ztgZXxyfvvt5ng9fjqqmkEPBq1Ds39yCp", + "2b9au7DpArhJPXDJCSFR2cMczAacLT9Xi2umZG9MYXLprkm4iU", "2bKoipmXErGTPCZedKDwPFKR8v6X7yGmtgZr5r3esN9cRZNxud", + "2bLQd8omCjWuUik2LLPKaRo2AQ78BNjTvYbDsANhFgGjLBcEeW", "2d9azyeuYybkt25YBwSSVukSdWko2EB8Q1ii2TdvjuNoRwigJj", + "2dUUsFXPnytJjnPmX1pQufNUaBh96MFQuPZ92vMa3XcdGCg6pg", + "2fw1AN9jJHGTEuvNBxqbtejWukHRfxNJSqfVpsFYXJY4Vbw2c3", + "2gbWojYtNF8YZmpJUuq17vxRMDreTTHoD2dUXspDN2rtucHmT1", "2hLra7rDjb77NNF3U9LHMAZ9MqnJzkAY5xEG8ebMjs2DGR1KQD", "2hNwDNBFeaHZ93VicpE74a5PuLDbQYb71WHQUVdrHyy5ExXPLv", "2pCJ9gCnbCFC8e1xQNYgu63XQzCLqp9uupk7ePgDX3vWvwoPGb", "2pWxqGSc8vPJQheXoJNaRRSA2NZKQ6wSdCvdhWXjuKS4VPdDCX", + "2qDzuN2ooKLnEYc5ULhNMEKFTcWu5cSKyipCeJuVjwfu7mVKvy", + "2qTfSXsWBbmuai5iJFhUE4AdpPbwDNR6QWUgjsBPGKdc3R53xw", + "2sE3rjLpaNnu8HAa49hTjYJ3y5dDQwz8TzPphVcJkcihwPqi8q", + "2sTSDCaRduH2oAtCA6cihuDKRbF8b9N3r8bkLYur8dHiYStkQj", + "2tFh16Z6eTzzzUQYDMtMcW7vCYVnZJgNFmvcXKdKueqJeHduLo", + "2vf1B4QJwuhGNUVHitAggar9iZ6GMP6fvkNBBNFxmrwn78Xxqe", "2wfMYUvLzxtHK5b8PE938LrMLpzL7pMkoFfVZ2P1wb65FVSMDt", "3oxSU7pEZzr7MMSBLeWprp1e851JtwHT4YCvEzs4vzamAVCfj", + "3srNc7xjafT7pkXDawHisjRyEhdedyEaxpCVdeeSF2eFFFsp5", + "53CPVeV8Jr6amsGVWiB9SVNZVN9vFk7i6omyCrNZxer5mfWqZ", + "6G2qUWZCW2MvgxpWrnR1azuTEu5Gnv6C66eafJsEXbQbV2yRr", + "7qxMYH7p8QsHw5u6pE381gDFESwBHrzbYXK6BhQ9kMp9dmKe5", + "8khD5WmMbwDadv17WNPhsd6Cxu2XLun4n9Pc88Apmd1nNYK7S", + "988Sk4hRBN6V4GQk2rMzKhTXQ8xPy2p7bQBXyiFHknHSLeSdC", "CCgthPmrL6fsPRtVn5DJAkGs3wnYy8HUSNmJ4PCgDw2beZAKb", + "DKYASkaDm9HyVskLiw9foxUf2exWhWqzgBmnwx5yncX1jDJW4", + "DYdaBt3C2QS1qDoktpFsUQCb43F9a3RzNPefpCQ2csbLjr224", + "DsBjgvFW4AA3GkRav9VCDSnAFYZxvT6CEYAmJvgKaXHkpFNYg", + "DvkrWrKpM86FggT6Yzu4wM63Yw8MPWrNGBa4tujPm9NSR94vf", + "FWXEYzxYxoEQojLLsw9GhFrHA7NxYfrsiFHozt2xV419ih98P", + "FjL4WreWPpTFxCDa3mp2KSxuTDin2yeUfNDiHtMRhnZ7uXWaf", + "GFVDQyM6LiDbYnLQBjYUZQixk2fDLcEf1zSDb7KFLbTwJJfik", + "GaFX7JQGTVQgKuGHZL6fcRqHiKBioCJpYDQ7w4cijaUMQXnut", "HEEvCX7Af3TPBAJ9KLji1fVfjHKH2ZJwVsV1BnzVKoSR8Xs7C", + "HNgxTBLk1Wa2mTNeYkYYptQLANDTyT5mZHpMdaBjb2axziyAp", + "HqtaYoyEE92oMZaFzdh71Y6zNBs6T8FR6zHJUd3c7cyuhJVGT", + "L82zC58X8yvm8JgfyxtSBUU2GRUAdVbYhWYKbYu7B46ctgNBg", + "M1necnfahQee39ogPGbv7kkokYnUsM6P8npqegLV6GqiAXF1h", + "MEj3pMhy6aNowXkzgTDsnHoJf7E3zKf5sJi5vuxqf4AsdgTjs", + "NbJg4zwzKdc8S77BgoHyYknMrSXzdtWgj98tnPekbQ2z2NTis", + "PD5ZjG1cwFHDjyeWSWYoAhLkDfFmc7ucEmQGZkLPfygXLc4XG", "QwUfCXBeTiPL3Rv51CxT6BhDw1GkDbQovnQAWzp7sT5FH5a9J", + "Stp9k2uteisQPNwUG9A7RQmW6yHaFz95WbLDRWu6QukoDTpD6", + "X23yYJTmGHgMdAYc2joMAzPc8U6d3crwrTemDNRyWYvTfuUT1", + "XETk5x8XPHkX9tAuJa5LvkAc5BXCzCUeMtwc74gfxauH55mkV", + "XUR1jFfmi3G3CK8e6ckwDis3WJMXGowJH9KRTAs3HaNuCFemR", + "ZhxYDBMMLeDwcbzjmM1uybVcx6Ea5pW6gZ75FMxG2p1gAypPk", "a7d5UaCCbdW86qszpNc6WSow2a6RbNMALTLZwkjddk6WXfWEC", + "a7yqQ6WwRiJkyxmcFjQ7P6c6HD9ggMzw5RhxCkciBpoeEtwKQ", + "aBARTG3jtQcqY4iBu6ysCYfgv5qxNZ7tRgyc4vfKr42kbtzDo", "bV2La8TYp38PZZVHLcdf62dBxyshP5QdmxoM6AXwWwck6Bj5w", + "ezDVeSFwtsKVj2TKJgnfFk2Ron7XBAnSHkXQaCxg26kyFKKNY", + "fb2EBwXSKdfVMSANF4suB2gYgPZTTFHEgK31Be7Yduh8aUPwo", "fr1W1wLpVup55hsC7wap8Ry2TThMxbQYFmV1s8h7RDMTm6m2B", "iDTh19j3bYnSSkQ2zhpKYPFuep8hHZoRo6pKkWDotQU1CJzJF", + "iZpg4RdbgzWHJLD8fx9SvCTBJMcFRzBbsobSZj6YAYz671gs6", + "ifoWGTKercg2y3gdugrmzh3hZ4NyDm6xq2yGAXGngRLVRHU7S", "iuaz5BC3icH5f8y6koA9DUpnA34hvUDB1UALnBYednBeztpqC", - "pUgAh6Qik6Q1zgK6iHRkPnW3KHQ4htPJVUQK4SNRFvN3bwvaT" + "jhzhmCBQRwZZrw7pTt1S9Tx9FdJ9VjHq39z9yCadSk31ab9Hr", + "mbHxp14KyQwjvyaKjP2jErwK3Za6iwXvi5N49dRyzUhgTi8r6", + "mobi3yL3zSq9WwC764pihrR4ZUZyLfD4LTS7C5uosXdC7sQaH", + "nCA3JEEwcSfdwV9aCoG5VApSLHmBqaCBKSXT64KSuDSEix88n", + "odgEc4y2JaqMeoXnRoh78EL6jnQJjdhfeVFabmk8BKqeYhbvu", + "pUgAh6Qik6Q1zgK6iHRkPnW3KHQ4htPJVUQK4SNRFvN3bwvaT", + "pauQnSkSBdq1we7935UxwyPBaVE3ygnLeKk9AMZvy2nFPgtde", + "qTg4ng5mihJsLnuxedfn8pXggCoDEVZ8K4zKbebbCmnLYeST1", + "qx3w3KKVhVPD9hJsDxaVRoy9k8z1iWnQNXxM193T4zwJvJnY2", + "siTgYyVSBf4rFpKzZrW2KRKteSZRjvaPz3qudqQiZfCKFfQqs", + "xfjYyMgV6RU882WBsWoK17D1TmAbUDgsgyVqmmtPVpU8mr1iw", + "ybukLCCdJvShHUs4b5AzLK4J7tJ2R6teio7d2ty5uJcEd65a9", + "zL9t4UtcRCPa2LikAW2Rejdohe1B5zhuUZfaEnk7rpoxmuoxV" ], "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp": [ - "24oHHzQ31BsSnjJWW3etryAcjZxPSDCCmvKxDGhDoh32wz2WgS", - "29Pvnpsk7dsyiUNz54N8QeVqFoZfBQwbomEgM456sNr9hPvA7h", - "2Ea9P8ewiCJeaUMtRheXcDUCPhoeBoDUHVqmeFxQa2BbV235h9", - "2LrW1m2ZfnNRRSRit7XGNAHACoa6m9HX5bmxx1WMNXefpCrzDq", - "2MtxhboDRKRTAk5e1gWnvq4T79g6f5KXfbGSGruz3pkHHEBzup", - "2PUFvRQp3c1gdey3L7ZKo6Z4MrmYwkn66xtRKoDiiGGiWDkkwC", - "2ZgS99T8Prxe7H5N6294VEj572CdTFM5QJ8pBfqhDTPL6yJVJq", - "2csX3osi3bqW3QJpDTTaKxGSqAHNKQpatBjCK6WkGdmAzzoYqS", - "2to9JmAAemySQRyYdkSmtU3b2kLCr3kf7oZafxbfrQRMRkfHDk", - "C3gGVaxvCRCTT1NEtTxD7stp6bq5mL5h8f1H4E7fUWPLTu9FZ", - "DBKAunfGhpueh7NxFdgTFYLesHTVUko9S6JxSGMkVDp4YwvpN", - "DVbAaRP98iuo5rT2RPSCD8UcmbjcwNBZRjMkpuSrbWLTNuB13", - "GocGoWcjGgTA5KpYaxF3zct7j8ArVDCjDprqV9M2Xsyh2qKSg", - "JNVs4LwY6TtmcNXTStXtiLEdd3arofcmKjiVy6BZrJxjdHE6M", - "NhoFHDoCBHcABEki4ye5GY5tQhDYc9EapvgwyjgAbw1KY6R3K", - "SaCfseHdFRLhNMHkxvNxjhFwzfUykNQdQapC5P8y3LNMHcksr", - "qizRThCQ227VPGEXfEnT9h6RzVPx5vKYEKX2PFeHrmkqkVJgr", - "sTiUYRycE2YqVECcy5zVG4PQhJ3bbDV43m5YjUG93WbcG4riY", - "swEd63Sn9V4sxkXjZgMZaxY5w3aGdcJV9i5ng8pg5Q5PozNbM" + "1KWV9WNrDP6kz6YUwuD2HqgaJCcpw72LDsM93Qi5ZG5ijMxu9", + "22vN6KcPZYXhjovkMgZcAyLAEewn5yNdyZuPkhkJrLfhoJFuTJ", + "26XuN3sKgaughQTGsPjRtgYWU7MJvXKK7XLNKP3yyCJw9rhvLM", + "27U5xgvBqiZrmYqiMTA8uWgKkEjtR8Phvj8fYduqePhN6ogBBo", + "28U5USEqtabqMDrg3GmoA9JBURm2iAAEZCrt9qiioJ6WX1MpsM", + "29FMtTUJSMw5mKxkN9H8jzU8LL3qt4mNSBuQsX52NRNfo7mKXP", + "29gErA293yVQTywZZSjBX8RzrtzJ7WYXqC4oo7RDb9T4Rh4mEt", + "2AqwCasWT5PZ8HizcBXFSzJMqkumcw9fZhdZZanfQq4GLs4sTc", + "2BZvxBaBjM1VrUbUbwyrUgHzGz7XB3Lcn7XLTcBVEXp1Bt6Hi8", + "2DjZAG9mx1ZX86d7YBQCdJgqWh2hN2d6rCS7pcAFzB4Twud3ah", + "2F6x6zPbeFpNBCpvsTDMoMdiED8c1XjhgViqpPyofYYKbW31ob", + "2FYcJRnxesn5vBZfhD7nhcA1q88U9RbLJvgw4DEhG3WQ2Tagb", + "2FpbCEAUR9qUHBNc2vJZvd3QPKcSv5ppq6SvJSEdP7gcPiiw1z", + "2J3sNMVPuToh8RURxaEyAH1UXJeFi85HyazTbK1s1AhqDKmR4r", + "2K26B3wBbMvA5MRH6x3ux4AAJAL8nAMLdQX1Z7kbCZ5nNk1bFg", + "2LS8kMM5763MqwpSnvzm9BP8q9K4dfKpKzPkSth2QFySDYq62s", + "2N6Sh17ZVm2Tu2y37RVZoLnq151uFZ1QbGkfxiYx9eWKAmqTKk", + "2NDTTiXJWtQQPMkMubVScTsKGx8YQDqH5Eiz4JeK1hWBn9MssA", + "2PVUHSGFMmjPtdoe8TDd25keTyab2Skuv1NfL8aXbrktLUnunn", + "2Pg2sJtejpHcNWayT1wYVRFh5TzfXffpwuVtEiYp4WAoNBvrw6", + "2Poto5skwyXNDTcKQBJ4oBAQM8wKP91QbMKRAyxESNWn15Rwi", + "2SDV5pC9LXFBejEvzpgfjLt6QiGLWugyPsoHTena8aeBXtJePr", + "2T8uMVdubBmxXLaF4GNjAcvDbHkmJKMgWcw3GGx5cwvKYTyiK7", + "2UUzJgjrEiGXjdDKJzJCoCdng4d94fv141bt3XxLV4MvNS6f6W", + "2VEuYLumihzFzb7vxzteJihBmujhy7MYcEjfBo1PpHqE6LsY6X", + "2VWvgipoHfZRa7v4DyhZ2Pg1s8hiE3ZeWFpiADcsvbNf6RhZWD", + "2VoYpYz9EjMPCg4sQSHV1db9FUdrk6C2jgfkhY489HfiGMFRms", + "2W9YoH9ovWbR21keSb9cxpCpUnxpvUmQR4ae8NCe6ZS6hYwcEF", + "2Z2CSK29hudGxmQq1a9zmcFMPsQdzxFD8BhFuzZ9YWdvNrG2hz", + "2Z7ynRiP5NrjYWJyPAT7QZvzYWDH3koypckoiect6G1WnkzNkd", + "2bVpQvmCSxuCpCYdNMABhparTf4omeZ6aWJ1PQNqnn7u53cf2K", + "2d1ZcYMQseYY1wDV1cTDQE569zV7aFwL4JD4nWCytqRwNPgPQG", + "2dVNpBGQB15sDBBSSKDSFjkgGKnxi1YcJwYhikYqcBcNxz6uTP", + "2fCTmsjpLmeZVrZ72PEwR54UNRFQRVxDR9KW7nPe1zocV9Lrx8", + "2ffQNKo4MYUdeNfC5C8VF7skk5JDBg2rWzoZK7nUvk2xwid477", + "2g1Eeb4wiVX6wTT78Z6Hsts7oMW73Y9nowGz46i7s6ExiATcCw", + "2jvBqz9bSXRFirZFmSJV85CzKmL3VoAYnLPSQGrWQhQ2xhXjao", + "2kZRT5XN4EavQNQuEsanx72AiRHyjVnvonoBpcCRQQn3tFNhK2", + "2khH9gYHqSvCXq9s2SSGUPM3f4M83bg2BJ3SZax7G8eqHovrVr", + "2nAaqqDvkhBcqfzXgqp3FmnGK6GEze5aAy7PTQFeNXqJcE4Soo", + "2oB5St5UsELdmmtNjnjvXM4BAyop5gf49Mt4WEE5EHgmRQReL5", + "2pEJEtUuUH166yeubSAXkNPGtUJwhncwRmKpY3sze4WuRNXjZS", + "2pjaqmDc64z9R1AV7oZGvXh7TJnBfgWtetUmHkW12xUf5kMyHh", + "2pm6NsXbJaHvWXGr6nAm2PjfZSWyueeEVFLh54XPdcWkxhWLnb", + "2q17ZzgTkVGzWL9tn8VvJyyaoExt37GJTgP37v5iqVJBApGyVm", + "2qiHXSRExXE8sZtxdBoeVbyRrFb1vyUrHRhoQJ14JEL7zQF2pL", + "2rjuAzC65ABoaFDYP4WeLYCABZLHJZDyZgnQ2AeaCpj1YSjHJR", + "2rkKSGBNNqsWfKFyGyxRNpNcTjn1p884anWyHKpzmp95cwJpXH", + "2rnRJZ79AqJ5r8kWx823HTHH4eGbj4myg3QYLKHQpznyU7UUSH", + "2sEZqbt7SeACMF8y8Z1sgisrxXwiUaQVTZ1QAVPaARndfskSUk", + "2samdSpAwG79oHbNxt8fS4Cm2PaSFZEY8rxCcSwYWQicfcLWBS", + "2th4bbVdBDjMYFoMx9ecWeCVAva7R2UahvwR2u9TnfPbHrkYni", + "2tq3K37fUW76epQ2A7JzTFHZ4FpSteLgf6qt2dns6QoHENDr7i", + "2uHjP8Rs9Ls9bc68VeKgBDCuw5ajatrkETg6q9inotJzFy3qcm", + "2w4xDyqCM75R5KfUGTf6ZBUEevFwViAxLdmsoB7m7notQPk93L", + "3E7ufDTHLhy4diVjn9C5da11ERPQV8JMs4vyxV6ibRpm6eZmx", + "4ZQ7sPbzyRa2gC6MsMKEEAWQhHinaax5tmxfZx5Mp1TQPLMYG", + "4qpg7eBaVWpCBMR9KD2sgcPs7GReFvsdNVhXRWJhVEFuzeZS5", + "6Be5He1koaSUTxcWgjD9fziZNamkwjhYassbcvjUbhbEn4R9H", + "82j4aV5V9Sq51pYopwqDfZ351Gwkm55FGkg7HeRK3Ke22KLU7", + "95U1Zo3qBuAXc3DyC7Q6ugocSy4yZ1R5yFJYyQjjoH1ken9uH", + "9Hdjpq4oG5qA4jEk4AHNdCYrhvE1QehcMR9n9XchcAShnXeVZ", + "9fJn4QTNTrW4FPmAYtHDQCYaENk2Lc9p37gWJJnvmmq5QSxa4", + "BZsEEekrc8qfw5R6i89wCmS81TqkrY55uAt28sq4z46FYxw3c", + "D4J1TfmgNiSzfUW46mNE3tAnCiVGvEY7XREHrMLW4fHMZoix7", + "GDuVQZuNdVmSdSrPXRTv1q4F8ryEZ4bfo7PLEqE1Nc7a2TsMv", + "KpGYaFWH3ieLiuntop3rjqU3ex6BHtcCsjmxXnBZHLARcQz2n", + "LHdTiXWE5MrpNnJ4vhx4oQ2Jm4o6zFCKma3WhaRDuYXCo7Xfo", + "Lw9b7jptgwZya31sEwZhrMPUtk9qLWgTu2hAfnsngxNGNasb4", + "MatBuKxzGvDR5SpEUtZDa3M8snvchqWp7CHjWZvqugz3nXwq3", + "N4aKbwME9NcKUzp97naU7VvTCH8PL3UEDnkyPWh9XAWZR1c98", + "PMN87cq5QHkAqX65RUE1ujh3mDXBjHJXpZubWYeZCRHLkGwUa", + "PZeWmD69WoCPChRjKXFxXgGectDVYU5g3xr9iCQycrW8iSA9U", + "RZqgD5chcU1K5aeENsBnLGJoYpF1H6KLxSKFC5hpvLj7uUFeP", + "S2mxC6Xutp6MwgUp1VEpHbSucGEFBtEfkS5yfDEHV6Ymof6fL", + "SKv45ux34W8LCPTbMXpXMVbfEkat7uGQFdNEMruS2Ei6FvFJ5", + "T2E5avovLexcckZmDk7pxE6xg89g796pb8MXBJXwMxyrcSCRz", + "VLVwUXYLMApV3zgu2L54Bit1jcqjxccpYrTVRv42ZThNUJMc5", + "VUNwEkRsCPG3vXn1yG15YJmCELTg7dcxvAnrL2WZTkS1RaRGF", + "VwqWvs1zcKoJETKctVe2UBKM2b3NMYL388MkY7vPVeamJwMLu", + "XTvDGrQTRiPt67rN4BieVt7id3fE2MNzoW2x3yFumMPGbS9wC", + "Xd5UmxVAor46ThCACws7rq4W9WMRuTQYkicmTtjmeFXNEEDey", + "Y7JzNwUouybw93xrLtWdLiddCeUKp3nXW7kSWVBrfExoszHBA", + "YUgQtFjbuRx5qVf4kfATL2r8u6N7Txh9Tjiarc3i25S6hSfvR", + "djecm5zmaXUttbysXFDy2VaFqhf7JUPh5yWkNqLsaNgQEJkon", + "emvHnDxyWoR6r2QZnrEHJPr5js7SGUDzndEDKMryUbaAFeaEq", + "gtzSKqZYfexnE2dK3cbtqYQrUs6w9FokxtTWHzGfw7MQhgLrm", + "iQXHMnEyNG2VYCXazn7GKnVULeAcYEVNERPbAwaxvJZvogWvE", + "ikQChBiPFrQEgbyixBGNyoc3CFXuYAuMwdmPH96bxnHxzHAGp", + "kAMsxWMVntYrjR4Emc59NbaieK4WMBuSRtVk8Bd8Kt7VVEV7b", + "kfzBpfuuEzVPFoRVKki6xznjJ1cQFC1Np2YkVP9N28qDmUG2u", + "kzKtBfUWVh2RxeeEbEusz4kW5yLUNCpeShMjzMw1bvde6MZkv", + "q6ATtkYbFMKPJG1Re8EkwG3LcnwTUr4yMV7arXjowaTvgs98J", + "qGNsBqQfj95Wyth9b3UBhzCGjayRWjmkk66by2WYvJUt5FkkK", + "tPhg8Rru1NH57taGgDfmjx57s3VHRFzJ6jCPyarg1aXknLwNK", + "tvAydg5xMADWoKQKtopCURMGcdQyptNxVZqtFTyAMGStXZj9b", + "wrdKkYgFZJGqgA8cjXHJ2rX79zDZoV6FFoyPXxV6TUJ7sUzAF", + "yHtw6unDu9c5ttbtPPcE59akMRPnws7YiZrQbySiuQVBzXEXe", + "zdtLm5Rn5mVJHRoVBJXPZNMJ1jpDZqqHq42GkYKyLuvAFpntB" ] }, "mainnet": { "11111111111111111111111111111111LpoYY": [ - "28dGi9aKqLv4PxShLdtH3SMcrJQ29rYFZBux2N75yqZnwp2tSG", - "2EJQYgLNCy4UvmcRHxjM9Jmiedaz8zRPKMsATeAPRXgu1TL6NZ", - "2MTALukNfX7F4kb1bdmifKYNYun3cZvYrTbxi5rxcVJzrVFhTt", - "2PcPtUgRjhvNztbFWZyjn8CSV2LEM7tSmyF74YLHqwpWtHK9Tg", - "2WA6E6F4n9GBcUySrpmwkRoEaj3Dg5eeQiMiuxAr3sYz21y8Lp", - "2WQmtk8nd3YRMEu755TJpjyUrqXRYG5B2FvspEzU6BbCkeJN32", - "2ZNpSCqAsMMW7jfkzm4yn8mLexRhiKTww6EkLcBtB6TTRFFU62", - "2ZvwU2XKskNJ7Yr8CeMAFtQ5LWDuNVaL6zA6hyjz4pc5xHiDX", - "2iJuyWqd8AxbR2rTrS49REENAeqWGnUKt3wegqteE2mPEGoTsD", - "2pAywJdJFu4Crz59u75Lo5fzpQwmP2GHuuS1omp2z7VmAygQfC", - "DKMfVHKPF2GA1gmoKLBxJwNbrZGU9J8fnfs2vDntUXHWa1Qbz", - "PbnP2Gjr8qHgNriKRBp9gr3b1CWYBxjqheHFPXGDbca1Mwms7", - "S5KxF6sNcwKUhR2dMC9wCsdY8zFcPEGS9XYTNiiXhQnP63Evi", - "UsAALF2bfvxwnykySvrpTXQCwanQRS5Zy1LuR1M3aJYM7zfSE", - "VHRVMDeZRm85zPw9y6Z5JRx7HEnZ3hf5wp3H1KXxNb4hskSVh", - "XXKhAbeLeG9JYEmbjVjgNmYWFt3Hs7iso3hgWfjAQkrhP2HxU", - "kVU2k7YkeeTegtunQHhoRpzKrXffTVaTNM4TSXDFkP8BkHRtv", - "rk2VNXsSuR8WxureE9xpNuVVonmEJ32rixtzaFpbTMK7M8DNG", - "vPRhn3zforT9idV3GZNupvkfoeH84fdjwqqxExV8qadpQMCKP" + "1B5E6QJG8krWQUgWepyt8E8pgaqJMqMSEmT2UyvPexkkb2wMc", + "216EBD8XMdcsG3qbfAXeuYXpyPV3BBD9VqpYyxWXBjAR8FJoDg", + "21EgREZEARGLVevhbmEKSKTn2vdzCfkYBAKHu4Wdpvete8wXek", + "23Ue75GBM1U47YsoFcopBD1fUFNDWSNnxfF3zn1SQviPS5Dtxj", + "2458mNNypg5TDhihkxovhPgJdS8pxCt7fScP7Y97cjEqfqY1o8", + "257ugtvszdB89PBFy55WBDY6qUfwb9TDfjRRqEzyM2iCMBpxPr", + "27agGp4mUkukwHY9xQncGiTkmZvVked8gjKuF4gdGaSuocrwjk", + "284patz8aHGYZmedRF2BWd3bkd5UBYCsdRrDAjq8DKqLU3yJWs", + "28s5c6WMU5fhHScwxUA1LeQ7k8VDkfQsU5PZYdVg93HDQhTicv", + "2CboCm8ESqLHL9uc5rLwrrDvHSL9LYBUhcN3UuDGfyoFkAKWrZ", + "2ChzkFC68QxvogYMgsL4w8nNZwxijXDrYAzkxE9c1LZaLBXfQJ", + "2CiRj4o32nNTFCQ7kJtGkZLAdrgNrxAUhtSR1QErnGvXUFeXHs", + "2DPVnGZxkfhFweWgux5PQPS4BieA1hRxYHCX9MMQAiEQqMHseq", + "2ES37jRwnEFVdcQC96yFjBM9egq2vvzoWC1CodLZ3JQLuQN8b3", + "2FsZaB9CFCXHZGaTtwonpFrJjQtjQJ7kagANppAx6YtBKvQFmy", + "2HYagm4zUUqjCiJxatVgoPQ5YoRTwb115prmn4fb1fWHtYqnjN", + "2J75xTj6JYdDqWMsuWAzef1sQ9M125qNvndkdnjMLCDWLUdHP3", + "2Mazmq7iUqBsCddykcwS2iVbD7hpP662PsZi8yMrynn7pv1CUh", + "2NGNixxskQ55KWNmcJX67QAG4rtJnovZ9NBi2s8yS4WQABzJrS", + "2NnSg46yjVax6XbvAKUn2C7Xf4FTSG5Vs6DSxqSUiuBWdTRuJU", + "2Nuwv6wzV9G2tfkJduHZX1Xt1HvgBG7UsiDWMA519tqh3DS2vW", + "2PvJUPZ2ixw5T5EGLkyA3Pqbc8dnYFjVrknfCqReVQdeCgiw4z", + "2Q891ub1rhnnEZ3DyxHt5Dy67i3158jrXNg3onUdhGmCH3156T", + "2QSULGkaPRQj8xp51QDyuJQmYBaxm3HTJ6LRtmo665j6onbkPv", + "2QueuD6F6U3qjDQ7L8Skkkq43ik5sCeCbcDFUdjZubyTGMMtdQ", + "2R6gaLK3CVbQv6KdJ5a2apnufM5scnKLdw772vkMJ7JQGZoYKd", + "2VvnV6H22zA6jwGSTcsnS5NrP2yLL4sWWmmYRCktvDHCwUysLG", + "2YZTnhsjKTNhYLtzrCTJdX9yM6e5sb5wBrLxYujbysCoAMji5U", + "2YvU5Qsae3rzWoZuZTrNbbdnMonqPr846ypKmiQbJtkyYFnCkZ", + "2aQG9LLB5aeTUpP8j8WbsxZWpFLWrdCR5qvDg9cTPXKYgRDzbM", + "2b8Amx1SWkq7NAq3BuNTMWmQLdoM9QpUJoEXa4SPguQ5Bsfspv", + "2bfD6RXczkn848sErk8GuHynHSMGMsZLtuLmShJVanxfcme4pG", + "2bivnbDYJp4h1S8iQEa4Bd9JHKMdFnxzjDkCUTdXiFDCFnsFVV", + "2btiQJ3DYqkRMhjxzMEnzxB9tdjWb59rVQLQ1NyvwyY5VhptVJ", + "2d87gMu8KNdd71y55fQxrLrA7xmgxRPX9b2J89Q3v8eA6sG6ih", + "2db71Fs6RTqXXFLWSiazdgQEkzVsNahtQLRUbLN6XSxdT1Vr77", + "2fQJs1QhDXWiAAMTiN6kQDo4ENyz3bFQpPcQW5x8qWYKacYMxP", + "2iLxkZLBw1M34R5XcwT8wJyzZUEubKNEW8M1hwNKpyRm14cguX", + "2j6bG1bwvQYSNA4UqVh7Ty8XbkW7EANXtXDzvWwd2BQ9jYZ5ML", + "2oeRV2fASwAtAoVpYDspRXwkUfSNqaHoFTDKqGaf5jiYkAxue9", + "2sCcCnd1XsA1imsMSsvC413TFtjgfpBHAtw7TN3HFrJLxYqHmu", + "2vJTSMNJ5Hfmysjz5taXo2HCbG5CkEqbyJZkDVVYirgbL3c9NC", + "2vUFxa9YJGYzURETT8FM2KMW2S8qRVq7Jg2HpwRzjHQ225hY3A", + "3NGMMRrgmi6M8t4HbhJQDM4od4ZrSSJjGa648wPyFd3EQwKhm", + "47EXXL3VeKqbY31LmFLowjuvsjuDtT1K89auyZTfdBYLsq21e", + "59xi9sRmBP6atqwgimUb3RYEqb1iw3CTTesX5hHZd7722TMof", + "5fpDvLcqpCXfiP1PWqUg3MMUkN6vbaWiQY9aWr3g6yxKm4RhB", + "7mHi58ZtfXLsn4PedamHFkgdMRM3TRz2K7ovvxQ2Tci3QT9be", + "9kn4GBBhSVLHka9BxhXsEDHuNtD4fKuJFNthYDYjdZcP1b7dj", + "9rnaKHusnJVsNSejUzknoiT7j1AMMQ6WL7U2YmbPoTGJAn7Nj", + "BRuntV1HAFdgrG4fzeFGtpCRP26ZEkd8hTqPFLs8vfn6ob29b", + "CDLZaajCDCNEzeLhgGNNwrHQmnL2vhJ1r1EpkUDbp8nRqHRAN", + "CHSDMBergSGoDov8pSq4AVXsC8oUKJPgRQgn2r8fj5p9Z1JFB", + "DNra4ocoWiggxvUv4vi9tkVufeKmyhMEVcK6zUpkfWjpYEz2C", + "FgHPpc4m5uhR3hvcuGEsTJXoMRUK6snQKXE7a1jNgi7pkRi1e", + "GcLiwTxX4GYD9u1fz7WZPwqFnQay7RDsNnHRKx9JLzjg7p1VH", + "HSQLGpksQsXDgax1wrvLQsnibFBBhihj3CXwUaRyZ6RykZDEd", + "HtSF13P38ts3TS6rN72ikABkWHp2e6zsoZpkC1j9m16qicdQQ", + "JeGy4Pp66rSXCfFzaMbpzQuJkDwrAp4oxdCgeUzztbiULxjie", + "KKWgmdPef59z8wBgzcWjWcQci3MNToZ4mK2Hq6NHFdaHFo8xz", + "KrPfWhzKouLCcSsr64x9ocqEgxFeRzpQP5EiKmB588oNfRUnR", + "NMXfCc87czhn7QaJQV1cmM3KRafvkNW8Lxxj4mk65NScfrVEJ", + "NqMU87mHva4QqaVA2h3nAGfkkCGyxWFkoTKDpkmuv27CmcZk8", + "QXsKk4bEAhJkk1sCbQJ6knz482Nik5p8jeBBtYEZShGGSe36Y", + "QbxcMxDiMgGbTFrLyNssMVBGkoMETSTSFCNXVaU44zDKRvhJu", + "QgxmNGZFK4kvxkeWbY8sEA5eE69QRGvpj32ptFhSHT7KZxW1f", + "TH7jgMrZwozAX9Ae1hK8bFGZY6k2KgiJpMWNqyRLqtnvmE3oT", + "U1TeMELwQtPgCFfZa3ueiR8kXFYbcLWjqEF3DZQXrF6d8gQRb", + "UALKWgfm4YHMAyoto5ZxSp7Qa75Sf7LTBmpdJzPQTu44YtseZ", + "UNkDbZaJUZZW7TZv5YG7Qd8BBY5t1hRRNj7KHZYx4GRgN3vQQ", + "WHeN1jp2XUetgYJeiX7LzKJcvVvycX8sxodVy3vncSwyTdybA", + "Y5L55ekoJF6CmBLMougyxR7NtmeyQkgdwqDt8jCQW7fSM4erE", + "YxhbASNGuSRUVYGrZqMKF8UVT48NyxJLZdb6nzRTUN8voYjuY", + "atYynkSXtQVgMNhmengPRkUNnf3vgUtTxEQB8PfidMFHCUSkA", + "b9E9wuiLUJc4SUPRSMHrap9KBQzrJFTo9SPAEUbdhBatQU1zi", + "cuXpQSKjARZMBH84fZtjMaJ4C2Sj6M9jvnrKqiWFTFohLhQSr", + "dF4GALvqziT8bPZs45Rm71bPRMUx6fd4CQE4VFRnJNXh2ztWC", + "dRJoo91U6hjpTzArqT74fRggpkNPtTsRUb9TgLENHLLtCYP1F", + "dgXdjC3TH6nj4eoQNCH55nEfMQYebNB7yUuZD5JS34HYCCTeK", + "dxmkXKgjJDxFHgy6rYo6v6dx8kPoitGY3KJ2MeXRCjy93zNqM", + "ewog7cnWqu8Ep3hQXTtzm5wNKekZD5SzzyML8UnTEfvBT9YX5", + "f2ENwrf7oYoCyTLGkwEGSWDbhVArvmFqtU4p9zZTwcWKAYM9F", + "gqeypYBAtebhpP5rNT37fA6jj6yF5sSH6x4cphYkMcg1ctTph", + "jdrPfgims5SUTHHMucQPZCaaHGzot5k34BtbBha6ZGEvzzqC8", + "johENG9LroaomPakRjjhdcPJwX3QNsShoptVuKU7YyxohhQXA", + "ojQ26TYBrByyiLYvHf2ecy7y2tADcH4qBA3esQpqSnBL3w89k", + "pM25U7SYU5LthtajhrzXPLz9g1vwLXknsRJ1EJY25QoCHtGE3", + "qcejTh5svhzBgeTQPpQ48N821LSVj1W9JGjr8sUJm1uzH9nwD", + "rXHYTHFFAorpNG1UM5NHCpE7U8dFhbYJUanGRpd4dHah1VPyn", + "rd7g67SkHtcUZQnWcq7eyViMhDZ6HeTUGQjADHB2C8KQ9Cxam", + "rzPRVPkVJCTwgcPNRcyQNPHwgSJsirCN1YPXUPE3Q3qjLYb1A", + "sBpbsXZZce4bCu1pnftXvB4atrx5qCdB3Vwgb4EXhzZmpphPu", + "u4455vccKvx9FqGk9NSKAkdVAvNx57iL8PCRDMJ35Wpymwgf5", + "uDNP7jJ8Ruygz2zR3U17h5mLYX45t67Rd8LHmk8oYdGQ3KAAc", + "vGqFd63hJMSwkiKHqsFEBd2HCCTNmktCr2HyPxaVkGwCzZTjV", + "w7fgyu1U9vc8acU4t5JBQgaKTCuXPVs5ExV3ha3CEKa7CZmih", + "x26U3zcgJGLgVCKuAPEfjhuUwAymDpeR1TEha7L7XeLjdf1bV", + "yNPHiSQADpmMF6H4XC37rRXMfXqozX2cg9Hb5u2skhw7VP3rv", + "yjx1bhsKZZG8HYYBn3TbyQ6snjFJKDBi3NFjcg1ycXH6ANShc" ], "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM": [ - "26XHYKSUVPHYW4kxdyTTHsq5TUpJjJ1CiuG7wx987ZZvb6jq25", - "2ASoynxpeeNJHLPBt1hnnFebgGNYjmgg2gRDL1TFWUVmyrqvUv", - "2FXaca8JETKg37Zyxcjt7qnunSidMtu7esreSmLP3dkw265rxd", - "2QFbxT1EzUqp5Pz21TbE5c6ycAXuJEVZcdPJVFcXdk61at4zbk", - "2UheKUo59ocm6ziMSd34MhjR8vVndVRY3fY7mcWfa1dfVm5npF", - "2dBVRK8obttmY9MJ6qHJF6rUTxSoGDXjpDcBXFPch2VCFmY28M", - "2kgw6QPds6jRRp1hKEQXnRcpVtDDK8ACRByZPmpZXM7jDwWW6G", - "CmNBZXe3ftxsUnzAe9maTkWDfhTwyJTmHNB7U6tTdobdM2Zra", - "E5ybD9WaQEerLdMWV95x9i4synu32fih1tp8sbfd4mVKux9bv", - "Ff7fQTynJt2FKBvu25VfdwLKc52oWKLmuZWYgGVBV4twDFFgj", - "V4wNqSUz6a5P1DmdBXjmAvuXsn9bNnUUiQE1wCwZhAoQKf8hm", - "cYUfY7t3mPiArvHTStCpysnYhp7DB8NC6RT4J5THD65SpDUb9", - "dEeXZpwpWx26N5xa21XrLDtNQWUho65QSGq3y9KYZg1b4dF9i", - "dSKAYrvokjFCTUg8QSW6Hy77drj1bh7Wd17MG9qYFR2Zmqpr6", - "gK9Yo8Sapf2FTy1utHgJdepHQjuLQFwg9wooxHQqCYXdABJw2", - "vh88AVj7hkpQGHRXTzNGsrd7xSQPPy1kEChkzbaoyCy3UvEmL", - "vhTHvg9RecciepKJcYT2sHHuAjDPhUT7tNikEPHwHckv5CSrQ", - "z5tLKeF9H8V3Xu4VFSyCDLme1XS7M7L8MuPTTJM3H6jayopTV", - "zQtgyGJoAWzRYKAhFEPKSBkGdCTRx5ZZ5dMuG6NJUVeZVh7hF" + "1Ae9hQEWAS9m2M2hFCBwfLGmau2U5tXSi6TQk4GETeaTixkBr", + "23kpwHyGxiqTMqpNptCMcBznTM2tNsP6CcPT49GiJLyEeJqERE", + "247Z3hLKURTnEDYHnPuEcvxeoGWruEmcbT3eYW37orzppKf51S", + "24dJRAmswgfvaQp8AnLwwKL4a8xPqMpRy1sHgPYdFZLcWJR5tt", + "24pBrgmP6eA8sEmcagTgfyuabQpVH8qZXSeZwLwtVQEqFCV7n4", + "24zEDcob44JLkPsqxTUVn8nb1rhp9Fb48gz81WozjnJtUTtzFD", + "25145uqXstk2NDbFtKAfDZLV5HWj2gkkzcYgB5kL6S92NqXvoG", + "25HNUza6krmGgUjDSdeB17zziX6MUAtmQPK8PGgPB4gqJ3Q5uY", + "26RCSnJXJuLLBURxaHyobVem8ZtAmvtDiCrQEZgx5TUNywPQzM", + "27oerofvay1CZG1aEdr5Ta9QdqTuuPQbYxJqMo6Q2jFERjE2at", + "2CF5ahFCyoqraDkvqWL4wMN7ujNtw2DC1tAnNGtWYo2HMjm9qj", + "2DVSFnMbeGKs6622bnta6A7AYMQPxViQcCukLp9L3naV5CjyNr", + "2DhiH4LabbAmNvrJqvepRj8cae9uQanELUt5Jsso6qTJtwFXz3", + "2GBcz4FMxRKaZuU7wFh5o2jv4Wzs4Wt2c9i3EzmS72PYj2ArXL", + "2JPNWm9r3kNhEn1G6Bd4cK1YXF8TZBesiq83rJo8mwuJVeNGNk", + "2K5VpwKTi7ReYsNaGwkmYi4CHYMLdS4sYBo5rJRP75MbbVrWhx", + "2MVr3MkzwhxXiRCZkNiiH6yuyWYtaWiU7DAKYNru5RassNtCu3", + "2Np4vReQ16ZbQFek5hvLZDEo5XF6XjR9PpQdHtm1KyYPpqwbh4", + "2Pgqbr62GbariHWucWhYr2eR26bVWcY9rr6hRvBnCFEqMEHKsc", + "2QdxyJS9wQDjWXzcofAAkkQmrhJfrwna9ENCuZLXBGB7amonmr", + "2SrGrZaB98Yfixx6mTqtmLH9TU73r5qbUmDPn6872JRUz3dnhq", + "2SzBpTiFj6nSbV2efQkQkkvVHE5pEj9SXxzr99iLkpAttsoany", + "2W79XdUH1WS39HKbTnJfqgcfKoJGx7Z2r5JGPaCfMTxcUgcjus", + "2X2DCHJsxS6TGd3fr5M8xUXvWRtFC6BSELfvGGL7KLg2PQke5y", + "2XPAn4gMbh7yGSHFoiYD15Xh56t188Lktr7Vh18VJns2HVdqv5", + "2YMWHBJ4iSEQe15f1vMpdZE7CgPx4igojavwRgHHuR1RE7uH8h", + "2YsP1aBkUaRQa8wAya4DYiCJrhRnFPJsNevDjypUTehAsPF23P", + "2ZNX6yBhjVWsMyZeBKunhxnpG6w3uvVDAKtAp6eRVQTtNZmNQ2", + "2a1nuFW6TfxFAHw6vU3smvKtnsnWSEMq4xfFz4cB4Pud1GfM3d", + "2aBHA43HzA9ZzxPgXHEMUtpYb1zT97KCkzcmxWfiDu9t2kFsSt", + "2cABtHSTFkgV7ZSo7w4fKr8hVGrhFV9xUdCYT1Qn1fumCSPzTQ", + "2eEEM6zvWcGy9rSHH5eUJeeJSuS3nkJ3KnaB39hycfyCmZqm3W", + "2efGgSbva1ZPMy8ECXWixMvh5nbxgwCkwqiBdsikeZnC3nAifY", + "2eqhdPabKa2dHB8xcxG4WE4ZMj36LhAFkV1NvuzLyAucavW9ft", + "2gPcJ7ajCASRYdAnvvY7usqZoWwBeNQFSXqVnUu44zbpgoHmAe", + "2iZ69h77wEoxYW88qtTqaWjc1fy3EUSD1Lf9uGCZDgZ7wMZYs5", + "2k5zYpTXiLyYekphdJCtxPADv7JXs4fUfHGeATcxymzknqGRxt", + "2nHTwrqTFz74xWnm6HkmPbzTXgvtMkRMiLAAmr5pkL26QMRSVW", + "2ntey1XxkcNJn9JfWBaxmp3qcSQeVLTJ259Zs7oDQ3yh6cycdA", + "2owRT6U1jiMBVFPhCKqfRrgcA1C9YYbcUyvY8omJtJNBK92wmh", + "2qHoLoS6iiiW17KddB6qVnorZaMnWw3p6T8vKJnp4TTgeor82j", + "2qRCKTWC2kSPnD7P87mNJEeorifZNvrUqNaWmwYHbVaUXhu4VD", + "2quwYoLxkLBAs1wyr97WtTtuqtP9tVnDBxEc79v6Q7MfcpLPgk", + "2qyu8FSYiyF75x4Vj2UrKV7w4krtf5XuRjvcAh8Q1XkiJa8d2e", + "2rA7Tzu48FLVqyWxYnQt8XjEtJpg3EWQz3Su7AitniJXrECt9p", + "2sftDbonhmXovtG1zEmDGDRaQgaRsxfz5Hx17rTcwwDpC1BgDb", + "2t8eQkJua7Z7wHcCdTx5VHGakAwuKXKfeWWnoQpYpNgwE2yx33", + "38EXWWu3ykrfF9SuAAJFpqLfPWhqk2KFTMUDVjFCxKqzCF4fR", + "3ioeyo4aMd5p47wfAVqy6u1K8U7ZMnXGyufZqnpHPTWhNPdU3", + "3mK3RtxvaUHK5cDDKZjGXZ5Y7GpQAuxXtfXcRGqbTD5qmhFgD", + "422rsGSzod3km15HthYpZwSrwgmzJS1iUcr18w332suVdifFj", + "5jtdzWfCPCjnnfAJ4QjvkFtEkTpvBUoA6Wgcz3qdA9bQDZmnD", + "9K7CkmGzSsRDQ7nP3gT4mc2FU8ASqU3UMnNXgaVVk8WWhpTxi", + "9qM4pGcXKQ2LjpgnDEo7d3JoZRFrFoQVSWBVfDvhFPerr948Z", + "ALYHdonQ61xQASoYNE2SeK8pTHUbr3wBc8n4LM8NWQnbvNzFp", + "CNy9seGsWFnXBadGyoGcxXCByp1k6GXjtogfdQCXRMZzeXQX3", + "EWPGekKDHx5gfeSg1YnS8Wupcb4nyKSiK7ci6RVGieQPyENi2", + "EtTvUtiy31wirL2RGr4eS3iuKBg737EVxF9JZPVQvpH9Bgzum", + "FZyUJdnnajK2tZGfTf5G6dMuAasQiTSmaQPpF538Q5xbuGEiB", + "HkZoiRHc7xc9ybdJZRdaBPNCHtydWNSaRWcD2TNhLT28yopcj", + "HrQTKM7d5MNz4g1hLsDp24i9mTAehY577UiTUJZZZYdn5ytdU", + "KQdjsbisZVPStfgQ5gSzNU6M4xWFbyjBBy5BHeev1VSQ1UTqK", + "KpW4KjCHsUkAgbJoozdw3PrH7UkMNW9QXxTR31so5pdZnmRdW", + "KwNWQtyGLYhHJx2UEx5JYhHLH3rfcVZ6PaceXQwYMNrpbm8Ab", + "KyREJFuGnuiGJp9zdGZsNnzzyMkNGScpDjBqoNknm2XcWaPsN", + "NP3Hhz11SzkYViPfhe3ko4w29QrLYuyXc5dEPVoCJuzibGXay", + "NYQ6mvjnuBdYLygezRAL4xEz1sfeLs2W1YXoXM3apwKnk5gUV", + "PDg5pepL2aV1nrX2wGWDemd4xjQeQwWEiH9Kx9fucKRJgjzQr", + "PHWQg87eXXbd24AELVJyFL9W8f3wrx7cLcudyDk6pqfC4mDUF", + "R35AbpPUZk5Xt8bXDUEzXgEbjXafonaz1CtBM9KYmFW2qeTDi", + "R6Ma3fJkRQfaNh3S5BaPCZ7VcmVoqDuTAfW658KQMrFK2qrVn", + "SewiN8U2kdNMR6zWXuAoaTtCpmLToh5ByaJkKhhdCNS1PEJ2w", + "Sgq62VTCWHwnwrPnwvZdPaBdyEyryHPwVMhcY8Si1nd75vyz4", + "SojnEYnHDU4brMQfN1tAHt4EAJoWH2N1EphEsxpRjNo6oxT2x", + "TCqtwpMiNeo81RorwX5RQNJQaGCGFdhfgUquXzQaVe5xhxqNq", + "UZH1H1oMotkYhqDMDQnFmTaDJDiJhNkS3di6buqVNgrhzCBr4", + "VXwKVnctnS6yNcWmtreFY6Y5G6zvVGgiTPydo6x2LhFAkAArr", + "WCdmNK5uudVG5juxhG1rxHrWzqJ43YCFu8fiW5jiuMwEWLHwJ", + "WHJqcrdA72xgCHmdyQzFP5nhBqF8FtXwU4hwTYHVYDxj3YEMr", + "Wnta9VHvYutQFZAZue8Z3rJYhMhiSg9EGFHeS1YwJfTB1QnWJ", + "bZNXEYqPZZMADRRgvmRpnb53P2EB9GXbbNJeQYkhQFD4UTrja", + "bfvu2GH74yBUdTH7GFigHcrdaiva9vfnrZjJ4Mhf3PYeBVPr", + "cgkcHF8ahGkdJPjhjSSXPZaov4YdhXob8iHnj76xb4g2vSKR8", + "dYBvJsLeGdNZxmwRo52NXQidBhhk5g8KMwzUjirZH1wafj3XJ", + "e9wawVmGBCf8MXcQPQAfcukJPWzZirTJYLmsygiBACJUCbher", + "ga8t7mq68p1J27b6DeE25cuejDtniYgN8nwRo6ez3PNMH3X4D", + "hw8cL25a6diCFeMEt4wHYKEvn4NzoWA1LVQ6mc8n2ANEdoyuA", + "iA2nRx155NFFiHkjQqApYmBVu5vZeFdEhky9QtCXvu7f99cfB", + "jYssi5iwGqnkmu1h54NwwqmH1ioGjbU4199ZbJfDVwic42s1g", + "jbK86vDpB2YTagzP1cLvjnW8g2uUtNghDXHLnu7rayxmPAwgy", + "ktoDP64jphphRbsEfRUTL2S6cX1JDNMcGszD2yfWsTLJrRTB7", + "ofqmdHJwoHG4RS1bD8SVhGw8dJjLGsrPRLXvXDK8p3Dv5Juzv", + "p2AtkzpSt4p3arxPZsNhkPKXtRpCZYh7FcB9wAqLadPRFfm8n", + "peZXGdHx3RTFcsFApy3euc6zBGvtP7xuXvV1AtXC53iwjwyzt", + "sZgtCtdoWKivMyG3dV4VXyx4bgmFGR3F48fKhxomThU7RGtpV", + "tYumUMgfSTYrj67oGZLoJKD885EuWdUniytQgddcj7cjS5aqN", + "thWe7H4NKFmVmTR3L8Z9QuqAe5PKkg7WecDW7Znp5vDfeR4HC", + "vgmjpXZFjqbhQF6jDUsjVfFsQEpEHokTDm4dhz6LiVwmy5M6r", + "w8oNyLfx11yyFhUCr5G3g9GhdJvevMzJuE2y76bwxsMzBv2sw" ], "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5": [ - "24SqsryHJRV8Q7qyPEruzXcj3yJfvgv5qequ2skJrEWoohpwm6", - "28BXQw5qfdwTHyV5p2pN9d6VzEahT2JWHT1Dd9RoHPLgC67gWS", - "2En3SNxo49Vdkx58J7UWvR5cwdXzbpt8cU6MS6dTgVdsYZBdHC", - "2K8tQm3BURGo8917v5nKm14yau8HzRHSvRYNSbHuebavaTy17i", - "2P4dyKpq25wGRokyCbidSKYXkhLJ8cpe7hUCp69aXwGr5rA5Jj", - "2PJpy8yqFWVm3Ew4qcuEe1rdnr5Uznq5X538G69YXuYAtY3gUS", - "2PzygucFpemhAAR53Jy34C3kgrUgAfGSbbj2UkUKn6AkAmTstz", - "2ahXAJ9teQE4nrExSt9J3r6oa9tCwLsP8fVsrLa7RnKHv8La9u", - "2hCKNRDwZSe9UhXcYUwaa6wHQzzyh4egQEexXncHKAnvXYdnTG", - "2rFR5KuqSo1dJtpYsNNrnWTYhmDN26s3zxSfBQphP61Xrzg5wr", - "2sdVixbBNZiAGnSska1m5YzokGPC9WP2arKWEidWZCCAF7BZYF", - "2uvUX23JiaNH8ZJnug75n3ummrxnjR7TWJPfvZ5goQDNY2TTH3", - "7v8FtNmL63T4U68cXutRABDRDWBFTLtGh7q5UuFtqouSMjn5j", - "KNTZTo5oE9npWbpGC3xYXcAN6sdS9hZ5wV6DVbZHyx4RY477G", - "KXVRT9rDVzRzvJz5ybuc4ogox8amHni9k7i61rGBztp9SYKEj", - "bNFYzR4XpAdvRHFAQxk7kPvCNUAFRThHdAeRUnZACmVfMfi3u", - "dCwyTrXC89Mcg6EkD77ERgCRnEdAjcad8c4SJGEvKkHQhN2zf", - "jhbWmPAWw6cuoJi7Z74B92wu4Cty17q3iR5hRv9KmEcFaUn4i", - "qE4UJDByJ1jPnbdx8j9z4QYa9xhD5DKZDvwJxFVQjm1QLt1zw", - "udtBGipZjvhWZkDxGkMceBzoRz3mrbc2eK6Acf81knaKmfTUk" + "1BzdwpbZKUesxrx236tWjpXKc2zPHv79bxL9mCtxMh4pUUUkC", + "21HZGcyTyeQPqFJCF4C55FQqkaGkE4g4RgvHJ7mPE8J3Wi9f5g", + "22j5UbQro6Q2fcMNPjmnG6rkEP3eKpPHM6u6rwGTgcZ4r9xp8A", + "23ek8kAZ5cw98zdZcsZcsdkN5ZKJXRaedJbiPcor9y36VmD51K", + "24VDn1zvbkPcoqeJTNLEo8GVXN1kbxwyXV9LtD5uPquinj74eG", + "24kxTyaF5wJo8P6orWnNUmUnAEEJuQ5EFDtbGEc3CpMSCE7Znr", + "2579faBLAxrCoQ3nfXmXZDa8ywSgtfEpqwo8Cf4Su8jBa8JDEu", + "26Bj3DLWNZYhT15cAP4ZHWa2bZxCY2iJrP4aHpoUVMeALKN2to", + "27Wh7KoskusBQCpF2u4LrzcLXQHSrNnwTtVd7mBEaRvVBDWnuw", + "291n3t6QRQQJh5Nz9TEEAqP7CSYdwB6RU4jDZgfCQXQgqzvdr9", + "29GNhM5F2qAidYAV5S9kwdwkrCif5udQiZWujUFutcuDbpQp9w", + "2AancWJ7dXvbALanrR2TyyD5qPnqpC4eAYukA7EaogvUQb1GLH", + "2BRovpvuU9arVMMmgUR6mieiT6M5uNoN2BbKJXJGdvLB6DUVmB", + "2BykimsMG3Tfca6PMBbfj7eRAJWz2d46LKobaZsGqC2E1Guceb", + "2C1gRw6WQEpDQqcdqoPCxbVRLoe4HkvN1Bu51t8LreadFkxfCq", + "2C4AiKNJbC52pdjpZuQxgbuu4fZ1YHj6rB3fQeTJtcWboden6f", + "2ChNUQTeeyry5bL81cuYhNWWioxqNxf1yA5cQ5ErrmcBfVazCj", + "2DVycjXSnmobMqn7Jo188365NqU9enXLRFcjfw7mrXSJxbqnfg", + "2JeJSDozjyZRawoiG8JuUNzZppMzi9a264SRCEAxRny5a7U8u", + "2KfnE651SpSDBuUHZVhCcPkMC7pK69LCySpFbN5Ut9mutRuYCF", + "2Q2mkrBCYnM6fL9hydBgiX22DFtGfze5dbtsExoD9PfQ8kHa5o", + "2QHpvbvPKrMEDaj9LHtaLkN1EN1mnPGY9FAwmqciyFtQnEH87A", + "2RDWfWBzsMfGSiA17xVUdTE6dckFJt4ZU8rthKZUjXZMi3Bysr", + "2RiZD17DZy7s6p5wP2M27VUB3fP2k5hd8EL1GBiYoXQmG3AiET", + "2SA9bWRf8Uyk3LWA2HK9bRcYcRkRoj4sJviyjH6KpxcLMomgmn", + "2TWNBd1Fy4NaPdP9ZuMC7mvjRXsNqrEYRjZJmpAP3Dx68a5KPS", + "2UR7USVAJPMgg9p2176cDhLQvAhj6uZrpqzUJiL7rxUYbaxyeQ", + "2WJi7kJxeY3wdrsNgGx9fpeFJVxnXxByh2RtSZEZ4QDdJ8etjX", + "2WShd5ScedW2gh4Rq955C9Ks9DMh6AhyDk6igHdHeLP468ULtF", + "2WxCnn9HqaFeqbTbGsQkuLsEvyG54Su2gEochTwmEiRe41TMxA", + "2XCaDzta1iR8TAZGotbEpifKkKZxVX7DuTzkgjpGMtWUAfAfQR", + "2XFsgQCtNPbw6j4dYqnLKaQiA4mkq8VpsXJaG3hvEBPTiYZaUM", + "2XuuXcVkXo1fmsuSiA4DXgAVN9BaF79aHDNXFxR2htMLJ2nx3N", + "2ZJsLzo46RU3JGTuWPwEkzgQvwHneVQN15mqGKVvza65jSva1V", + "2ZaD3udbmzeqNnfsdsX4qkaj1ufPZbD4xkS4ouCchkUFqsGrAx", + "2ZcJccmo4yN7BoNta2gRysjmCPiiaiZgc9PMHF4MBfcn796sgr", + "2dT9aPGoUqsUhRwRFp9oicE7thmpd1doXZEwvqdAGUarimcqkf", + "2e5wcMqexjUDs4uk3zfx4igNicAckz99tyXMCaHSaabMtsB3A3", + "2g8PDhSPZ9mwhkHEKv8F9Z3frNnUwRaGPtvYpevseHouY3jxMH", + "2gF3DbjqzM6TE6q7x3bojDykFRomJ8VGWAEs5BK2TBYS9Qm9tv", + "2gxQ11RzPXugyuChNXaDeGYVkG9Wpw2cf3Sp3NPHbA4mZ6Uwz3", + "2jBfNQejwQryJJKCeATfknYXKy7akwtqWBWk2e3yxZveAZCwdr", + "2jBg8tiDhkbdCnJYj8QiPC5iSh6QND3kwUK8tFZB8eqZ2abSSj", + "2jCoUw1J9jFBLdPch456KV8j2cvJtMncTXdFzZzCdJvVFg5Cjc", + "2jHfWvgAZhcF74kotXVmhEs81i2VFVnLFH8ZgzwCm85KZsvy1k", + "2k3m2FMzqhvS1xbFhXD3qb6p9jKxvpG7SHMCjncP74rjvJxnEC", + "2kPe8FZYbHxmEs9eUoofHvzB7JE4RBxzfjAxs397kaayAmgdPo", + "2ndWTwvSSNq9g8uDEvHZYupR8NHWwRMuwpwstm6UXn7KqP8Ny8", + "2oa5RVvBwpxupAmx4Ney9H9M5LVpfT9LrLKv2LfLjLToGfR3Hz", + "2ofby52VZVUR6heTxa1kDQND12rnvTc6mviY5diVkSoC9otFrD", + "2pZpMxqrsRZXo6VCC64TZRGPEVKqWzhr6WrFiYAfiHxTXisc68", + "2qLWDz8Y6rUWsJhnr2Mx9WLgZGR8tqKq9xedGbaqRYmDGuL7d7", + "2qonD7uEKiati9MFjF7ajaQ5uTTW5TLLSA63YbJW7CviTR3UgG", + "2tgMBsLAkz84uKPrJiQ6FdizGkRVDafAL2xtdwBxcm3ut1UjaR", + "2ubrhDQ5o99ZecuLxLA39VMaRDru2tJeBDaevuZQkcSNy3MXaf", + "36e9fDaeNptGwM6hPWyC3pozobY2rscjXojdBeJWasqh1AGrh", + "3cqmmgjQPvZ96ZhX4srEiRKyS32iEpA6C8PZDVFqUfycHPUSu", + "3v7thkmDPdpJb29S7TFBVvQpj6hmCcL283aUHa8SmFqzYQAAi", + "44XagP7PAE8iFxKNbHGBkBeYxbTKnz8n5RntcFtLAevnNi4pm", + "4mhZqjPD7e9gkgfKxJg5zCu247nzgknCsuztcX69mEyjd21Uz", + "BjjASLGE6WU4XZeLZ1wWj9FvZ3QaAh9QyL6oHsaV1qop8RNmN", + "Cs2rBDhgoq4dzjb4uRW9Hnf1Jfqmq1QwVdCXYXR7jKDzFtbX2", + "F2mcJ9VTrp55zPMSdZBwF3aRWs2pHMxL2pi3ZjrUM18uduZ5W", + "GWeQ5npjHLidwZWpwvXXtirEtuSTFxTRvP92sKnK7mMSTdiwv", + "JXHJbLGorRRNqeB7aCkq36yXF9X55T7WAQfDhFLrkWXGbinp5", + "JcfdA56T4PKqA4JTE9gTRgdtbGYeZqYggscDE9dVG9J3rC3rw", + "KFtfXKdt2LEvTjc9pHfJK9DuS6mVJHqY1HktrXDGP9noyiNjV", + "KxS9jDJdFtY71Y3Ecb5xDMkLG6d9KpzcbaGTq2XKAKgcihtCA", + "LJvUJ6NpKfrGHqB8UQR7HvKHAiMmTddDnKMJeHTUpPQ97CLpu", + "R757pQTxQ5GbspJizUPKvFD6MNAshEmoZJaivNrpbaCr2uD3A", + "RvWMixsyDoX81fbSCMggz8Bx2pG5AmVgtaQWgGUJqykL5p5fy", + "Sk7HihG4YrTtszuEA6Vsq8f7aG7ZfYcEFyBXwnj12ebrEn1sf", + "TK7xNZJ1tEXP7JNify5YjfQajkgSkrGD6Y2swBnw4XWzitgtU", + "V3bkjxQ6he2g96DjHKAUBXqjP5M1fzPrroqLeVx2RWnuUk2dL", + "VWBZCfXRMdXCQRRwRWez9JqrnMrvCNghxzPpBV1UsFcnSJny", + "VyQX4W4xQVXrjJWs5abvRgzXvoBA4ZVEAyKgw2jCTshnoo6SN", + "WN6AXcnC4zVD2aY5HqcrGcFLuLnCtEc2Am66TYxZHojgpsXrn", + "WnsutixgfL4oAev3mLGp9rj4ZpfBBr4mGcX26Yt2Tpyc2EmuA", + "XcPsrKbJivgxGsBJEtzHZTnxPciZqW2uGQsoFtX7k841rXMU3", + "e9yzwPve5jZsVJ3xC4MytsmnWUm8z1ebPKgD3ZMfNemaKmC2n", + "fBedioFvXoBhVoBEHyAvu39ssZL7MR2EJY8Q78t94W7Z6af2N", + "gVJzF5MAsmxhzXUANN8Yxjqz6Fb5hhFBBWKHxVdQevXsTXBof", + "jMKRPEGtaWhF9t5LohZBKFJn1Rd7ja3YuZpvHV5tYiBUYnAyL", + "m9gRuDwLKSUsgdw3U5H96vHCRqbPGkiUGbzLVDmggBuoG6vMC", + "nRWpyWoNetdRTMg2ypT2WSFnAqTc5cemgQcMW68iLZbx2Y47N", + "ohqFAG9PjwLhDZ6Z1gSm2L8VAJXnsVoTzeLn9155HqPdka88g", + "rYbSTMtCfFUZuJjKF6aYHYC7h357AFWSwuKknDSdqsJa5ydT4", + "riNHNAuVxJTpqa7WJwvFLKtpkMBcK2JTUqms8Rup1Zi6siJQG", + "sHymkefCnHGHNfHYJR655S2WpcorWof8RozeL7X7Y1C2Lp3hL", + "u3LBfdRmqvgaVaLmP4Ecy5avPqBhh2gUDdWuu4fAYZsTvGRvJ", + "utq2dwQcjG9bStN4JshvrjkQbiQSE1Pq2mawu8mbMZs2K23Pe", + "w3k8PVpd5DMXszpgrhZAafFH4SXjUEcaWphS1vg5nyDjmq8d9", + "wWacMnmWpmA4BVagSwjeNYUjq7KdjJScBKJN7o8TG5pTni8KR", + "wXAP57DYynVdYBZYDkm7p1BVSzZmagbFthVh1g6nLbkpV9SpN", + "wXVsv7Uy61CmuxaxTuZw9hFqZo2sAXiRsdnD6XNzvfD12pjks", + "xbtCy9DTPo7Szsdn6E3pu1nS16Dr8n7kUGrpsxvCLJeS8hWDZ", + "yWAvFXy21oceM5hRxnNPhuPZyqFKAu3v9N3FJivZvvkXZFKfP", + "z8b4iXgcse6Ey7PqLpm8x3SKdFtR1B73dgqUMMnJwcabqE4Rn", + "zjZErccB4zaDaQstHUdMB97mWNngP1wYbz6hUiK5bGScBUQn6" ] } } \ No newline at end of file diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go index 128c25699877..b3e79cf4d660 100644 --- a/genesis/generate/checkpoints/main.go +++ b/genesis/generate/checkpoints/main.go @@ -20,7 +20,7 @@ const ( fujiURI = "http://localhost:9650" mainnetURI = "http://localhost:9660" - maxNumCheckpoints = 20 + maxNumCheckpoints = 100 ) var ( diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index f0db03e0a0af..0cdc4a92a55c 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -97,15 +97,6 @@ type Bootstrapper struct { // tracks which validators were asked for which containers in which requests outstandingRequests *bimap.BiMap[common.Request, ids.ID] - // fetchFrom is the set of nodes that we can fetch the next container from. - // When a container is fetched, the nodeID is removed from [fetchFrom] to - // attempt to limit a single request to a peer at any given time. When the - // response is received, either and Ancestors or an AncestorsFailed, the - // nodeID will be added back to [fetchFrom] unless the Ancestors message is - // empty. This is to attempt to prevent requesting containers from that peer - // again. - fetchFrom set.Set[ids.NodeID] - // number of state transitions executed executedStateTransitions uint64 awaitingTimeout bool @@ -199,10 +190,6 @@ func (b *Bootstrapper) Connected(ctx context.Context, nodeID ids.NodeID, nodeVer if err := b.StartupTracker.Connected(ctx, nodeID, nodeVersion); err != nil { return err } - // Ensure fetchFrom reflects proper validator list - if _, ok := b.Beacons.GetValidator(b.Ctx.SubnetID, nodeID); ok { - b.fetchFrom.Add(nodeID) - } return b.tryStartBootstrapping(ctx) } @@ -211,13 +198,7 @@ func (b *Bootstrapper) Disconnected(ctx context.Context, nodeID ids.NodeID) erro if err := b.VM.Disconnected(ctx, nodeID); err != nil { return err } - - if err := b.StartupTracker.Disconnected(ctx, nodeID); err != nil { - return err - } - - b.markUnavailable(nodeID) - return nil + return b.StartupTracker.Disconnected(ctx, nodeID) } // tryStartBootstrapping will start bootstrapping the first time it is called @@ -375,9 +356,6 @@ func (b *Bootstrapper) GetAcceptedFailed(ctx context.Context, nodeID ids.NodeID, } func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedBlockIDs []ids.ID) error { - // Initialize the fetch from set to the currently preferred peers - b.fetchFrom = b.StartupTracker.PreferredPeers() - knownBlockIDs := genesis.GetCheckpoints(b.Ctx.NetworkID, b.Ctx.ChainID) b.missingBlockIDs.Union(knownBlockIDs) b.missingBlockIDs.Add(acceptedBlockIDs...) @@ -427,24 +405,24 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { return nil } - validatorID, ok := b.fetchFrom.Peek() + nodeID, ok := b.PeerTracker.SelectPeer() if !ok { - return fmt.Errorf("dropping request for %s as there are no validators", blkID) + // TODO: FIXME + nodeID = b.Ctx.NodeID } - // We only allow one outbound request at a time from a node - b.markUnavailable(validatorID) + b.PeerTracker.RegisterRequest(nodeID) b.requestID++ b.outstandingRequests.Put( common.Request{ - NodeID: validatorID, + NodeID: nodeID, RequestID: b.requestID, }, blkID, ) - b.Config.Sender.SendGetAncestors(ctx, validatorID, b.requestID, blkID) // request block and ancestors + b.Config.Sender.SendGetAncestors(ctx, nodeID, b.requestID, blkID) // request block and ancestors return nil } @@ -471,15 +449,12 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request zap.Uint32("requestID", requestID), ) - b.markUnavailable(nodeID) + b.PeerTracker.RegisterFailure(nodeID) // Send another request for this return b.fetch(ctx, wantedBlkID) } - // This node has responded - so add it back into the set - b.fetchFrom.Add(nodeID) - if lenBlks > b.Config.AncestorsMaxContainersReceived { blks = blks[:b.Config.AncestorsMaxContainersReceived] b.Ctx.Log.Debug("ignoring containers in Ancestors", @@ -496,6 +471,7 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request zap.Uint32("requestID", requestID), zap.Error(err), ) + b.PeerTracker.RegisterFailure(nodeID) return b.fetch(ctx, wantedBlkID) } @@ -504,6 +480,7 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), ) + b.PeerTracker.RegisterFailure(nodeID) return b.fetch(ctx, wantedBlkID) } @@ -513,13 +490,21 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request zap.Stringer("expectedBlkID", wantedBlkID), zap.Stringer("blkID", actualID), ) + b.PeerTracker.RegisterFailure(nodeID) return b.fetch(ctx, wantedBlkID) } - blockSet := make(map[ids.ID]snowman.Block, len(blocks)) + var ( + numBytes = len(requestedBlock.Bytes()) + blockSet = make(map[ids.ID]snowman.Block, len(blocks)) + ) for _, block := range blocks[1:] { + numBytes += len(block.Bytes()) blockSet[block.ID()] = block } + + b.PeerTracker.RegisterResponse(nodeID, float64(numBytes)) + if err := b.process(ctx, requestedBlock, blockSet); err != nil { return err } @@ -540,26 +525,13 @@ func (b *Bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID return nil } - // This node timed out their request, so we can add them back to [fetchFrom] - b.fetchFrom.Add(nodeID) + // This node timed out their request. + b.PeerTracker.RegisterFailure(nodeID) // Send another request for this return b.fetch(ctx, blkID) } -// markUnavailable removes [nodeID] from the set of peers used to fetch -// ancestors. If the set becomes empty, it is reset to the currently preferred -// peers so bootstrapping can continue. -func (b *Bootstrapper) markUnavailable(nodeID ids.NodeID) { - b.fetchFrom.Remove(nodeID) - - // if [fetchFrom] has become empty, reset it to the currently preferred - // peers - if b.fetchFrom.Len() == 0 { - b.fetchFrom = b.StartupTracker.PreferredPeers() - } -} - // process a series of consecutive blocks starting at [blk]. // // - blk is a block that is assumed to have been marked as acceptable by the diff --git a/snow/networking/handler/handler.go b/snow/networking/handler/handler.go index 1f5a30d839c0..f75c4cc3c9a2 100644 --- a/snow/networking/handler/handler.go +++ b/snow/networking/handler/handler.go @@ -20,7 +20,7 @@ import ( "github.com/ava-labs/avalanchego/api/health" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/networking/tracker" @@ -30,6 +30,7 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer/mockable" + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" commontracker "github.com/ava-labs/avalanchego/snow/engine/common/tracker" ) @@ -123,6 +124,7 @@ type handler struct { // Tracks the peers that are currently connected to this subnet peerTracker commontracker.Peers + p2pTracker *p2p.PeerTracker } // Initialize this consensus handler @@ -137,6 +139,7 @@ func New( subnetConnector validators.SubnetConnector, subnet subnets.Subnet, peerTracker commontracker.Peers, + p2pTracker *p2p.PeerTracker, ) (Handler, error) { h := &handler{ ctx: ctx, @@ -151,6 +154,7 @@ func New( subnetConnector: subnetConnector, subnet: subnet, peerTracker: peerTracker, + p2pTracker: p2pTracker, } h.asyncMessagePool.SetLimit(threadPoolSize) @@ -493,8 +497,8 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { // We will attempt to pass the message to the requested type for the state // we are currently in. currentState := h.ctx.State.Get() - if msg.EngineType == p2p.EngineType_ENGINE_TYPE_SNOWMAN && - currentState.Type == p2p.EngineType_ENGINE_TYPE_AVALANCHE { + if msg.EngineType == p2ppb.EngineType_ENGINE_TYPE_SNOWMAN && + currentState.Type == p2ppb.EngineType_ENGINE_TYPE_AVALANCHE { // The peer is requesting an engine type that hasn't been initialized // yet. This means we know that this isn't a response, so we can safely // drop the message. @@ -507,9 +511,9 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { return nil } - var engineType p2p.EngineType + var engineType p2ppb.EngineType switch msg.EngineType { - case p2p.EngineType_ENGINE_TYPE_AVALANCHE, p2p.EngineType_ENGINE_TYPE_SNOWMAN: + case p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, p2ppb.EngineType_ENGINE_TYPE_SNOWMAN: // The peer is requesting an engine type that has been initialized, so // we should attempt to honor the request. engineType = msg.EngineType @@ -544,16 +548,16 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { // response fails. switch msg := body.(type) { // State messages should always be sent to the snowman engine - case *p2p.GetStateSummaryFrontier: + case *p2ppb.GetStateSummaryFrontier: return engine.GetStateSummaryFrontier(ctx, nodeID, msg.RequestId) - case *p2p.StateSummaryFrontier: + case *p2ppb.StateSummaryFrontier: return engine.StateSummaryFrontier(ctx, nodeID, msg.RequestId, msg.Summary) case *message.GetStateSummaryFrontierFailed: return engine.GetStateSummaryFrontierFailed(ctx, nodeID, msg.RequestID) - case *p2p.GetAcceptedStateSummary: + case *p2ppb.GetAcceptedStateSummary: return engine.GetAcceptedStateSummary( ctx, nodeID, @@ -561,7 +565,7 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { set.Of(msg.Heights...), ) - case *p2p.AcceptedStateSummary: + case *p2ppb.AcceptedStateSummary: summaryIDs, err := getIDs(msg.SummaryIds) if err != nil { h.ctx.Log.Debug("message with invalid field", @@ -581,10 +585,10 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { // Bootstrapping messages may be forwarded to either avalanche or snowman // engines, depending on the EngineType field - case *p2p.GetAcceptedFrontier: + case *p2ppb.GetAcceptedFrontier: return engine.GetAcceptedFrontier(ctx, nodeID, msg.RequestId) - case *p2p.AcceptedFrontier: + case *p2ppb.AcceptedFrontier: containerID, err := ids.ToID(msg.ContainerId) if err != nil { h.ctx.Log.Debug("message with invalid field", @@ -602,7 +606,7 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { case *message.GetAcceptedFrontierFailed: return engine.GetAcceptedFrontierFailed(ctx, nodeID, msg.RequestID) - case *p2p.GetAccepted: + case *p2ppb.GetAccepted: containerIDs, err := getIDs(msg.ContainerIds) if err != nil { h.ctx.Log.Debug("message with invalid field", @@ -617,7 +621,7 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { return engine.GetAccepted(ctx, nodeID, msg.RequestId, containerIDs) - case *p2p.Accepted: + case *p2ppb.Accepted: containerIDs, err := getIDs(msg.ContainerIds) if err != nil { h.ctx.Log.Debug("message with invalid field", @@ -635,7 +639,7 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { case *message.GetAcceptedFailed: return engine.GetAcceptedFailed(ctx, nodeID, msg.RequestID) - case *p2p.GetAncestors: + case *p2ppb.GetAncestors: containerID, err := ids.ToID(msg.ContainerId) if err != nil { h.ctx.Log.Debug("dropping message with invalid field", @@ -653,10 +657,10 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { case *message.GetAncestorsFailed: return engine.GetAncestorsFailed(ctx, nodeID, msg.RequestID) - case *p2p.Ancestors: + case *p2ppb.Ancestors: return engine.Ancestors(ctx, nodeID, msg.RequestId, msg.Containers) - case *p2p.Get: + case *p2ppb.Get: containerID, err := ids.ToID(msg.ContainerId) if err != nil { h.ctx.Log.Debug("dropping message with invalid field", @@ -674,13 +678,13 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { case *message.GetFailed: return engine.GetFailed(ctx, nodeID, msg.RequestID) - case *p2p.Put: + case *p2ppb.Put: return engine.Put(ctx, nodeID, msg.RequestId, msg.Container) - case *p2p.PushQuery: + case *p2ppb.PushQuery: return engine.PushQuery(ctx, nodeID, msg.RequestId, msg.Container, msg.RequestedHeight) - case *p2p.PullQuery: + case *p2ppb.PullQuery: containerID, err := ids.ToID(msg.ContainerId) if err != nil { h.ctx.Log.Debug("dropping message with invalid field", @@ -695,7 +699,7 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { return engine.PullQuery(ctx, nodeID, msg.RequestId, containerID, msg.RequestedHeight) - case *p2p.Chits: + case *p2ppb.Chits: preferredID, err := ids.ToID(msg.PreferredId) if err != nil { h.ctx.Log.Debug("message with invalid field", @@ -743,6 +747,7 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { if err != nil { return err } + h.p2pTracker.Connected(nodeID, msg.NodeVersion) return engine.Connected(ctx, nodeID, msg.NodeVersion) case *message.ConnectedSubnet: @@ -753,6 +758,7 @@ func (h *handler) handleSyncMsg(ctx context.Context, msg Message) error { if err != nil { return err } + h.p2pTracker.Disconnected(nodeID) return engine.Disconnected(ctx, nodeID) default: @@ -826,7 +832,7 @@ func (h *handler) executeAsyncMsg(ctx context.Context, msg Message) error { } switch m := body.(type) { - case *p2p.AppRequest: + case *p2ppb.AppRequest: return engine.AppRequest( ctx, nodeID, @@ -835,10 +841,10 @@ func (h *handler) executeAsyncMsg(ctx context.Context, msg Message) error { m.AppBytes, ) - case *p2p.AppResponse: + case *p2ppb.AppResponse: return engine.AppResponse(ctx, nodeID, m.RequestId, m.AppBytes) - case *p2p.AppError: + case *p2ppb.AppError: err := &common.AppError{ Code: m.ErrorCode, Message: m.ErrorMessage, @@ -851,7 +857,7 @@ func (h *handler) executeAsyncMsg(ctx context.Context, msg Message) error { err, ) - case *p2p.AppGossip: + case *p2ppb.AppGossip: return engine.AppGossip(ctx, nodeID, m.AppBytes) case *message.CrossChainAppRequest: From 667372cfdd8e3110bdeaae0b92b8aad57d50dc41 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 13:37:29 -0400 Subject: [PATCH 72/85] increase number of checkpoints --- genesis/checkpoints.json | 673 +++++++++++++++++++++++---- genesis/generate/checkpoints/main.go | 2 +- 2 files changed, 577 insertions(+), 98 deletions(-) diff --git a/genesis/checkpoints.json b/genesis/checkpoints.json index f5bc4de13206..298c488c3483 100644 --- a/genesis/checkpoints.json +++ b/genesis/checkpoints.json @@ -1,133 +1,612 @@ { "fuji": { "11111111111111111111111111111111LpoYY": [ - "29tNQN5Q32bctp1utmDYtEQy3HDR1osWSjT6enzPCPu7aZgbfU", - "2ARQJfUoWxLrrdj95fWz5je5UAENyMkNtshxzojbAWLcTJ2Qix", - "2Nmy919z6GipCHTquUAsYbwuqpsPBcmtQPUgdoBDNxHz1wcv5", - "2Vt3MxgZcS9FdADU3EQ23ZDJLyhBLH2vrvvzk83WkFfXUFbCff", - "2WBWBSem499WVH7TLjmJ6eHNMUE97eHPumoQsW3G4Kvaza9bFR", - "2aW19sCe23hHV3U6vdqzBazt1rr5i7eiZwbyzV6BjJA2WTcC6s", - "2ecYzYceek6FAX9DsbryLy6eZKe7Z59DYUjQPhSpSwwza9EPV3", - "2nLRH3B3AFBrMe4nP2GTcnUSbW68agmEJ8G2M1NkcLfJySbQNu", - "2s1ba1qw9WYv87biWumt4A2MatbKhLpqqqCHcFR12en85dGNwv", - "2sy9iEarGLeQKMJiyBaSRDDBeqPJtXqoT2VJBYfZQBxVz3JBH6", - "9oYNsiaLXNAnH1wU5zNzNGYTKr5sBTGMHfBiCwCFmntMwuqPn", - "BKmKYwvvFszxoYaeKHfBikjWfL9fTnmbvcL4UAdhRkni1kF4n", - "DcMURdU3yZVgpqZHZhpsk6dXRpBt9gnhMfrfVGKMGUy15yr9Y", - "XBQLmGiD1oPGURQHp7aVfJJwftB3znK7zZuUGwiJcxp9RtgAz", - "druBcLhhqTyxkGTyieQNcnaBkJ8Z6VCMjbzzvWmXSoVazVdCt", - "g66txMyz1SmTYr8MR4VMCYvcaBD3Uq7hgvA8hZfpho2MnioqN", - "iqf8fdw8vN5wWsNhPTqwUfWdcxZD4ru3yvR7TKaLBtRNSB8n3", - "ue2e6kxrR4ZvgJcmmrQU9FsYkkfYVPBKYDtBK8bNSY1iNWJKv", - "viMudAudCxdqzJNJHpKG5P2Qc12Jna9jBLBeBsxhCCaCxVTVx" + "223opwBisPqPFJYMGbHvmvNaBb3EVjHqDbaCD2k4DWmBErychP", + "22QytoWHKDyqoSHzEg2jcnpy2K1ocGhfLVvV5eUL8M5WGQyDUo", + "22eMTpCKswsDmHzxC3rq1foxecqX27DveEJD1octSqzu8dLGSH", + "23xcXTT2TBGqos4qsNmfhH9UdvEo6SSgG3K8tHzZSHgqRpuqF1", + "26mZvbGt9PVowp86TZkX5y8AxX66qgcQg48f8m6PGaGyyiMRxt", + "27jmo6kXpEHD4QsPNiXDZvN2mauaMjQdPdfQ6yqjZZTgd5fopi", + "27sYpucSURKu6AbWSKNLz37kjhXVzdkAiWmWyxBef1MaLNXyKr", + "27uCd85pvFdjGsnP5H3WKei9W7DBJ1exsG8ySKzLZ24ffryds4", + "292ig1WtzAxvwfdC5RoqvMHVcyQk9jwJeKPUXmnJMNUBmubjTW", + "29oddG7fursmoQNLHANS6h2WNftczJivnx9srxPLhqyv8yUG89", + "2AAxNFWkm1TEYuCmZP9aaP4MAX4nKuRk6HBGwPAyBsjVSpDait", + "2ArnZkyEykgEYvPBUnDQoeT5hvp2djc5chhPMiBddC3MWTXume", + "2BKC5Rw5guhbtq5ZzPBPA6tB7p6KT3uyqJmL5HJpnJoMCTLJcc", + "2BtVqL41rwv1EpLHbLhGGH7qmbp8CS4iBVbchy4XyDjXpdw9VF", + "2C5hHCqoRLh8VrVVAAPJXXsMd6gTWF7y7T6Zw8cFTWhNBPF959", + "2EALbD88Aa3jG9tyJ1EeTuNrMQEripPgT45ENoWa6kCBey4fj1", + "2F3nmzZ4zJwhDHpXyCp7qHipiL5x3vZ4E7U5GbdMioML28eGYW", + "2FasL7vS1W7KYydt2SRexThpeRc2mj1mdwYQGFVJudXgtNxbK", + "2GGCrHkhqYFsmZzEHGXBKTT1MYicZMUkXENLsxwCJEJnbLds2X", + "2GvUnbuw1Tzat9ANiBe8VKTCqCKqRJhUYbU2ydMHzhacdVjs7d", + "2MyJWUpCj5sEEfocM2QK1yHikmsmUYj1ohy5qpuBTV6kBV7SLV", + "2N3FEhJwqa7yQj4yiEUQWmiUjPXrwbwUdhyjmTWG4RY16dstBG", + "2NdCscMk9ptgb6rNSNN2z9jbAVS8xrHMiXQ14nfs1ZtAebfmrJ", + "2NtjDcF7768wapKgGCP2QMtkviypLQ9PRbEQzVNGHUDKoAFe9r", + "2Q5ME4Qu9tXheNCbbvE9ARYTBwcyeSBsQQQAcvoyX9cfqCzVqi", + "2QGPPTEQn8iyDcQEyMrMH4NnFoeYgKCrfcYd3rBBkvu4YG2FwP", + "2Qya51sKi6kBH4AYAMQLcHpMT5uDsuVZgtounj7GqqqWVvHW8Y", + "2SqsMUwbdGp583RTpewTnVwn16kUQon7N1GpiHJAScE9sw9dwt", + "2T57a4UW8HPRagb6dBftpVEUWCBzwP2ZeLrjL3hJeusDTXB9no", + "2VzjdKN5CuPQbZnP1AmqTnk4zesvpLd1mnbS3Nga4T71Xx6nkH", + "2XSRDfkA8vyd4EEwntPbULegRsV4ZuNkREXnBpdoEw2Fma1KjG", + "2Y3oAtgb3KtxmCEcF4qm7piGFuRX17abzv8dEDGNXeVX9iaJwK", + "2Y61SGxffumcVCkUYw4ycGe4BXYtc94Xm68XPp4hSCYDFZTess", + "2ZbZUZWqvNNe2W2FtdKiXcUCPBrm5bmX3SiaanQREFAxg4ev3Y", + "2aYuGkvExCVfptTid4oqKAeQGYrKZsxwuaLot8tU48KjPQBJK8", + "2dbfhBpFjL5VM4uzbX6npNbWMKPxWF5DhunzEi1Hj5hxDp6hK4", + "2igtVfGcQsSiADeKuRLW39RRZLewkTwhCGRvfMSY7v7y4AD8h5", + "2ipN93J1esuG4e4AYc7ASZBUugNP3x4zNbKahSavkrxinigJu5", + "2j3RXzmGYkyjkqJSXBmZChEuq2d159XAq1dijjWsWRSYi7hmv8", + "2jtrFph9tduRQnrwrKx4qVmfPeZAWzPGTzW8FvRnzRVYhdTYHn", + "2kSoQFdwQiZ7cnH1mVV2pAYBh4M8BcKHHo4HuuVhs3XyRbmBYJ", + "2kXf6mnse3hpoY531Xdoo6fv2vNJdT8y7V4Ud9pjNzEpMREBzo", + "2m797oeWLxKj9UMYfmwZajEjG21PzEd5RHBsb14pmB7mWEbM1J", + "2mzCA32ZmnoCfSGVhqtdrKtXBg16edtoFQJAqqJvy3Be5r2m7N", + "2qnJE1DDHmk4K3R2LrvoJMiMhJh5PymmrtfWjwfVpyPHtUGqK7", + "2qxgRBRKWKNGaBQEyxc81MwyY822vL3EBh28xCVDY7jA2m2Tis", + "2r3JH3so16Sm2wR6DoEW9mztToDm4cotAJkQRxX23J8NrmTKUb", + "2rB1a6pzf9Bk7JaLBfDYUUJbznDCjHVbJdcNzxR2oCMzgqk5gy", + "2rXgjQJgtHsQX1ijwj1XvDULkqkFziDT7oqfYo2gxAe6HAtPd2", + "2tHb5NapTuTEzQNFearDkh2bFTNgk4Bv85vEuwVAxDaESRYGxH", + "2ubwFU7pYNw2EPNsVmb8mLAEp2xfUBnwAACjKVHuzeApEPaZVn", + "3v4Rs8kT4Hr7fr5p3K4Yc5GmvBDieZv96CQH1fEG1QShPLX7q", + "61EZVNqCY4Lu7kzWS7Y2rihXaiRX1jT1o3QZPwhrDFqyQ2ymZ", + "6kqdpwBMmo4YaJs79p2XbuGnH7KTwWSye8c2Sqjc8jfERYuGN", + "8x8PagWMhJDDaya6oTmxbSXC2cfubqkqcKeXRvXkEqPnHwTHn", + "9VEBvpL5jEHxA8bnicvTqkQyapdjrMdp4PQyANp8D3GLGSYxy", + "AFFTGZQmL1GWeucQ89GFNKvjXprQbEzUBthzwjeVmybKgWNbX", + "Ag8rmvXryhZfxGte4sQccqJ3ibKvmdLnYYxwxFZpsiiuadxW6", + "C2jR7wmNuAhqn4y5XAGMFTJJGoxtc6QhX9Td2Bmc2T32DxuSE", + "CPw6ptdo67PWvHhZi1axonjFZP9GyCcZnjSWaAcunU4FPVSdn", + "CeNMWvAE9yUsbAap7u6dquJ6NGrUbPfF6i2UWGRKTkneU29XJ", + "CyyG6WwyVLP8zj5jDCVyaXH11auzRaasikoWbyWRqWfE67YfM", + "DPeEFcS4MvCWEqj6s3MQyGRi8vjc3SKySD56piTZBeWjzRsu4", + "F5QoLN7bJWJsLv6RgG6JWfAe2XWj67wvN7crQnoAdHYiDjark", + "FkqGhwHZLWaAjTEWPpLwvSf9zNWnER4XhhuunqsjuTfNRWyZG", + "GDcvEKFfDbFpdRmUwCBmHdSF12SxxMjzL2PNK6EXGMVWYPPDp", + "GNd8AChiLADLnqTmypEhS86vre6QKYpcPKUKZUhFnyB8gftyF", + "Jjp1kBE4tPMmHqQq8XeopNMREWQa8RxfLtv41VhpUT6jxupCt", + "KKYswxetFUrEcDHgGv86R9TcAegkA454RSFVVFGnnGd4f45qJ", + "LQ71p9PjkYBVWTUz9GbKPaFxA69V5pv4KQkVWNChKbCpKghiN", + "LrxumguWFXGaXty4nPzSzkogUQ8WBUufC2JGQAQ7D7KqgupQd", + "P2PzegHfs769nr5nEz2fFhbnPEBpEWWr6cmD8cahvvkAL7SED", + "TmwsnFjxo1jFsBr5rPH8XHLm3AtimbF26xBaxdmw9SYcHGNax", + "V6oXi4fXSV5Q5tvGYquWfdaZBBzUWQDS5iepyzsUtXg1yB6NB", + "WWfS2sqozxfHD2z3AJ5vgkyNbyYD8nwkJJJEut4xgjstb6JKj", + "X6LFRvgSX4rP9A8Fswtus91fQbxhQm1GFYDgTBktiZxTDkj64", + "XUE6WNfCKmHTcaNEsZQ2KftvnXXfPTKnZi5YBw3pLWXjTYZzu", + "awbBnaBnjKBc79RzRPn4LXHMTxoYL8C97toXVvbKPZf81iUp1", + "e3zK4rU88osx7rB9Nq35uBXJrfShm7f3eqVk3T3CHCJD1SrGg", + "fDLU1xyDSihqWErnm62UeMXZ7HNe2atawSicdWamFGTQbLv5z", + "ffHAHY1qvDLcL3u48VHNEXtzqKgTvoi56vKDMcinoEHyy2FTQ", + "gT5RrrsG2bAephkx3bUT9VZGAGVoosGj9Yn6ZgVwbFVWJVv4x", + "hHQYrV9wu2S7hzkewJpotYymvjYpPb6RBeH1oUHPir1EZwyJc", + "iD2h4Qw88P4ce7rbKGJaxXwJLsPeRt4h3kcThDEXJ82HF84uz", + "jB3N7Rd1HCJeP9wLmrDy3NMFT9fkVJ1B5G5KBoFVVRQxc6fpQ", + "jGSYaQZQjieWrt9yq3yUWkW54RYYKfoHxHaRqo9fEBKZ9zAu8", + "mcAyTfg1i71Y7DXjTggfnWrfdjnSWqtg6uHrH3y51AHTi4Tjc", + "pSLCmmTDhnxHFiY3FX4fqCSii65EhWXaRPef2rTHjcp63nVYS", + "qHaV2XmsBRdXA1YDLn8nCYvRAfQue3CdZM3YBWYvvkcW2gMkQ", + "rghpCpaeyY6PVnWCQ9GnBDGtCsRLsdNS9z3tDCSTobsDCNUeM", + "rq7F6LXvXNioXQQyk7qVgMwoHWWAK2UGQrGyJJjbqYH1CYaVk", + "uLPzkqsPd78pLTUVuuXz257nfJmJcamQdAFjXYCoKDuM8FbTz", + "uUGfX6pZNS7jXJW4uF25xntf27AAZMT91NLRppMZhWw2x2aEu", + "uxDeD1vay1vbN24j7Rs5h4kV5q1oDYBmwj3iUvh2h5meCKacP", + "w9djCKT2Em3S6URCHXooEiDWwjeahf66sAL4tBeSa4ihJofLb", + "wZC4y3LB4SPbYZt1NbqrbTJtEo3iB1VyR1vTPm3UknSdsbA5y", + "wt7gkf58s9uiiapcC5DL3Y3iunfWnewQu2woS7FAQx5yDBL3B", + "yXKPp5iLD5mMZp9cV83yD9Yomm4o9nEPy11hU1aPFvRJhTqwa", + "zoe37ZDDigm6owSYNyEgRe6Dj7EiusjxrsnFzPpHLw7EzSDPP" ], "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm": [ + "1GBo9WQ1SyRFZse5xhiMXQgptnzhepqnajzpdCvAJ9TNSJT5t", + "21xHKbCFFxmo5EdGCqR24Wvind1LR2hMWkHztqRxuu2ezRhE6b", + "23zbXVVjaix7VcFcU3jxJpGiW6TFxaEV29ZixDDtoGTkPF3eUC", + "25H3WwoqYUApdSF5eugBWEwqfpbmDtdeFLKFDwQqMD9aKHSBAD", + "25HTUEFnmPc193wW4LZUFjcyya3jy3Ws4psiWp7EU8X6WhAHn", + "26NADDbcCqF2xx5yaKTA28nQYcPCs1gcda7WwH3Q7sznPXZ71u", + "28SHVtdhn9MvJzMuzzGC8odjvBNcYvyAbtV6qBBricfP65NjJU", + "28co43WdBgJP6pi9CnqkspSvqeujm8oTK4GoGroi5ZZZqPnSQF", + "294ofGLtC3h62jc8aYpbnnsKJ1ufAEmp19rViEC8senqk8iKWS", + "2FGfG9MqLzwq9jjHAfx1QGtss5xKH6p4cZr2KQkrjE1Tin9B1X", + "2Gmqc72MXrXT65hxkDjuGS7cAJmwY3habQcr5HmXLDAFzyVJMJ", + "2HCLX89frJuqbauSLFreHFQ1t6yJSPb213hn8gpDUJW4ABsr8q", + "2HgkU9sT1oN6pUNt7CGonaTrcgQJtTpY1yHMjj4BYoqfECcJT7", + "2KGfWNfFrcc2qYw4s9oMiS29buB52h3UPoz5WDarhs4Kcey6H1", + "2L7ZfaHezUSQKoKNotq481hAsqafuCMX6DjZjvaktRjRfprjw6", + "2MctCP1iN6hskg6iY2EeGJRKJWbficY35UgoUMRd5PoaE9aagz", + "2PDa7wqNYoAHr3oB89weNFZujVdcR8fpjMPmr6MbUsWDsFQ64p", + "2PKwDA8c8BpibsyHim7n152C48viUt4wtccoWy5qiLiKvZHUVR", + "2RydwjCt1qipkTUXtjdxdQzwVCDjPLE6eNVzSxzUHhjBHko6vR", + "2SssQkgDtWc7dTnY4DSw56ZrCXBvL8uLZjj16hS5C3piNqactA", "2UFZQKZ1gLuzqeEqX2sHLtZNL3Bxmv1NQL7GdqS6ZvSPMjkftT", "2V3QXva1iArd88hVB7JsEK8tHn12a5qgifcPBkhpZGWc7fRRis", + "2VvgwD21RGHpEJeUTxhEVyuTdMDQN2Di8L37xPtmirYW4r22d", + "2W6MYE4TJZV43hjj5cMBHG1rEeStNQLXE25VMydkecAorZNPRF", + "2WRmUjiKn4xtGyw33s9qtyhzLvYPBByRoP9vWr4H5Hy5WKYr5J", + "2ZX42ozafD1DaWAKK5Nfsh9FUEKiukFKYfSFtwpwBxU5VLpBHV", + "2ZfNzhvVrgMLy5jX3ztgZXxyfvvt5ng9fjqqmkEPBq1Ds39yCp", + "2b9au7DpArhJPXDJCSFR2cMczAacLT9Xi2umZG9MYXLprkm4iU", "2bKoipmXErGTPCZedKDwPFKR8v6X7yGmtgZr5r3esN9cRZNxud", + "2bLQd8omCjWuUik2LLPKaRo2AQ78BNjTvYbDsANhFgGjLBcEeW", "2d9azyeuYybkt25YBwSSVukSdWko2EB8Q1ii2TdvjuNoRwigJj", + "2dUUsFXPnytJjnPmX1pQufNUaBh96MFQuPZ92vMa3XcdGCg6pg", + "2fw1AN9jJHGTEuvNBxqbtejWukHRfxNJSqfVpsFYXJY4Vbw2c3", + "2gbWojYtNF8YZmpJUuq17vxRMDreTTHoD2dUXspDN2rtucHmT1", "2hLra7rDjb77NNF3U9LHMAZ9MqnJzkAY5xEG8ebMjs2DGR1KQD", "2hNwDNBFeaHZ93VicpE74a5PuLDbQYb71WHQUVdrHyy5ExXPLv", "2pCJ9gCnbCFC8e1xQNYgu63XQzCLqp9uupk7ePgDX3vWvwoPGb", "2pWxqGSc8vPJQheXoJNaRRSA2NZKQ6wSdCvdhWXjuKS4VPdDCX", + "2qDzuN2ooKLnEYc5ULhNMEKFTcWu5cSKyipCeJuVjwfu7mVKvy", + "2qTfSXsWBbmuai5iJFhUE4AdpPbwDNR6QWUgjsBPGKdc3R53xw", + "2sE3rjLpaNnu8HAa49hTjYJ3y5dDQwz8TzPphVcJkcihwPqi8q", + "2sTSDCaRduH2oAtCA6cihuDKRbF8b9N3r8bkLYur8dHiYStkQj", + "2tFh16Z6eTzzzUQYDMtMcW7vCYVnZJgNFmvcXKdKueqJeHduLo", + "2vf1B4QJwuhGNUVHitAggar9iZ6GMP6fvkNBBNFxmrwn78Xxqe", "2wfMYUvLzxtHK5b8PE938LrMLpzL7pMkoFfVZ2P1wb65FVSMDt", "3oxSU7pEZzr7MMSBLeWprp1e851JtwHT4YCvEzs4vzamAVCfj", + "3srNc7xjafT7pkXDawHisjRyEhdedyEaxpCVdeeSF2eFFFsp5", + "53CPVeV8Jr6amsGVWiB9SVNZVN9vFk7i6omyCrNZxer5mfWqZ", + "6G2qUWZCW2MvgxpWrnR1azuTEu5Gnv6C66eafJsEXbQbV2yRr", + "7qxMYH7p8QsHw5u6pE381gDFESwBHrzbYXK6BhQ9kMp9dmKe5", + "8khD5WmMbwDadv17WNPhsd6Cxu2XLun4n9Pc88Apmd1nNYK7S", + "988Sk4hRBN6V4GQk2rMzKhTXQ8xPy2p7bQBXyiFHknHSLeSdC", "CCgthPmrL6fsPRtVn5DJAkGs3wnYy8HUSNmJ4PCgDw2beZAKb", + "DKYASkaDm9HyVskLiw9foxUf2exWhWqzgBmnwx5yncX1jDJW4", + "DYdaBt3C2QS1qDoktpFsUQCb43F9a3RzNPefpCQ2csbLjr224", + "DsBjgvFW4AA3GkRav9VCDSnAFYZxvT6CEYAmJvgKaXHkpFNYg", + "DvkrWrKpM86FggT6Yzu4wM63Yw8MPWrNGBa4tujPm9NSR94vf", + "FWXEYzxYxoEQojLLsw9GhFrHA7NxYfrsiFHozt2xV419ih98P", + "FjL4WreWPpTFxCDa3mp2KSxuTDin2yeUfNDiHtMRhnZ7uXWaf", + "GFVDQyM6LiDbYnLQBjYUZQixk2fDLcEf1zSDb7KFLbTwJJfik", + "GaFX7JQGTVQgKuGHZL6fcRqHiKBioCJpYDQ7w4cijaUMQXnut", "HEEvCX7Af3TPBAJ9KLji1fVfjHKH2ZJwVsV1BnzVKoSR8Xs7C", + "HNgxTBLk1Wa2mTNeYkYYptQLANDTyT5mZHpMdaBjb2axziyAp", + "HqtaYoyEE92oMZaFzdh71Y6zNBs6T8FR6zHJUd3c7cyuhJVGT", + "L82zC58X8yvm8JgfyxtSBUU2GRUAdVbYhWYKbYu7B46ctgNBg", + "M1necnfahQee39ogPGbv7kkokYnUsM6P8npqegLV6GqiAXF1h", + "MEj3pMhy6aNowXkzgTDsnHoJf7E3zKf5sJi5vuxqf4AsdgTjs", + "NbJg4zwzKdc8S77BgoHyYknMrSXzdtWgj98tnPekbQ2z2NTis", + "PD5ZjG1cwFHDjyeWSWYoAhLkDfFmc7ucEmQGZkLPfygXLc4XG", "QwUfCXBeTiPL3Rv51CxT6BhDw1GkDbQovnQAWzp7sT5FH5a9J", + "Stp9k2uteisQPNwUG9A7RQmW6yHaFz95WbLDRWu6QukoDTpD6", + "X23yYJTmGHgMdAYc2joMAzPc8U6d3crwrTemDNRyWYvTfuUT1", + "XETk5x8XPHkX9tAuJa5LvkAc5BXCzCUeMtwc74gfxauH55mkV", + "XUR1jFfmi3G3CK8e6ckwDis3WJMXGowJH9KRTAs3HaNuCFemR", + "ZhxYDBMMLeDwcbzjmM1uybVcx6Ea5pW6gZ75FMxG2p1gAypPk", "a7d5UaCCbdW86qszpNc6WSow2a6RbNMALTLZwkjddk6WXfWEC", + "a7yqQ6WwRiJkyxmcFjQ7P6c6HD9ggMzw5RhxCkciBpoeEtwKQ", + "aBARTG3jtQcqY4iBu6ysCYfgv5qxNZ7tRgyc4vfKr42kbtzDo", "bV2La8TYp38PZZVHLcdf62dBxyshP5QdmxoM6AXwWwck6Bj5w", + "ezDVeSFwtsKVj2TKJgnfFk2Ron7XBAnSHkXQaCxg26kyFKKNY", + "fb2EBwXSKdfVMSANF4suB2gYgPZTTFHEgK31Be7Yduh8aUPwo", "fr1W1wLpVup55hsC7wap8Ry2TThMxbQYFmV1s8h7RDMTm6m2B", "iDTh19j3bYnSSkQ2zhpKYPFuep8hHZoRo6pKkWDotQU1CJzJF", + "iZpg4RdbgzWHJLD8fx9SvCTBJMcFRzBbsobSZj6YAYz671gs6", + "ifoWGTKercg2y3gdugrmzh3hZ4NyDm6xq2yGAXGngRLVRHU7S", "iuaz5BC3icH5f8y6koA9DUpnA34hvUDB1UALnBYednBeztpqC", - "pUgAh6Qik6Q1zgK6iHRkPnW3KHQ4htPJVUQK4SNRFvN3bwvaT" + "jhzhmCBQRwZZrw7pTt1S9Tx9FdJ9VjHq39z9yCadSk31ab9Hr", + "mbHxp14KyQwjvyaKjP2jErwK3Za6iwXvi5N49dRyzUhgTi8r6", + "mobi3yL3zSq9WwC764pihrR4ZUZyLfD4LTS7C5uosXdC7sQaH", + "nCA3JEEwcSfdwV9aCoG5VApSLHmBqaCBKSXT64KSuDSEix88n", + "odgEc4y2JaqMeoXnRoh78EL6jnQJjdhfeVFabmk8BKqeYhbvu", + "pUgAh6Qik6Q1zgK6iHRkPnW3KHQ4htPJVUQK4SNRFvN3bwvaT", + "pauQnSkSBdq1we7935UxwyPBaVE3ygnLeKk9AMZvy2nFPgtde", + "qTg4ng5mihJsLnuxedfn8pXggCoDEVZ8K4zKbebbCmnLYeST1", + "qx3w3KKVhVPD9hJsDxaVRoy9k8z1iWnQNXxM193T4zwJvJnY2", + "siTgYyVSBf4rFpKzZrW2KRKteSZRjvaPz3qudqQiZfCKFfQqs", + "xfjYyMgV6RU882WBsWoK17D1TmAbUDgsgyVqmmtPVpU8mr1iw", + "ybukLCCdJvShHUs4b5AzLK4J7tJ2R6teio7d2ty5uJcEd65a9", + "zL9t4UtcRCPa2LikAW2Rejdohe1B5zhuUZfaEnk7rpoxmuoxV" ], "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp": [ - "24oHHzQ31BsSnjJWW3etryAcjZxPSDCCmvKxDGhDoh32wz2WgS", - "29Pvnpsk7dsyiUNz54N8QeVqFoZfBQwbomEgM456sNr9hPvA7h", - "2Ea9P8ewiCJeaUMtRheXcDUCPhoeBoDUHVqmeFxQa2BbV235h9", - "2LrW1m2ZfnNRRSRit7XGNAHACoa6m9HX5bmxx1WMNXefpCrzDq", - "2MtxhboDRKRTAk5e1gWnvq4T79g6f5KXfbGSGruz3pkHHEBzup", - "2PUFvRQp3c1gdey3L7ZKo6Z4MrmYwkn66xtRKoDiiGGiWDkkwC", - "2ZgS99T8Prxe7H5N6294VEj572CdTFM5QJ8pBfqhDTPL6yJVJq", - "2csX3osi3bqW3QJpDTTaKxGSqAHNKQpatBjCK6WkGdmAzzoYqS", - "2to9JmAAemySQRyYdkSmtU3b2kLCr3kf7oZafxbfrQRMRkfHDk", - "C3gGVaxvCRCTT1NEtTxD7stp6bq5mL5h8f1H4E7fUWPLTu9FZ", - "DBKAunfGhpueh7NxFdgTFYLesHTVUko9S6JxSGMkVDp4YwvpN", - "DVbAaRP98iuo5rT2RPSCD8UcmbjcwNBZRjMkpuSrbWLTNuB13", - "GocGoWcjGgTA5KpYaxF3zct7j8ArVDCjDprqV9M2Xsyh2qKSg", - "JNVs4LwY6TtmcNXTStXtiLEdd3arofcmKjiVy6BZrJxjdHE6M", - "NhoFHDoCBHcABEki4ye5GY5tQhDYc9EapvgwyjgAbw1KY6R3K", - "SaCfseHdFRLhNMHkxvNxjhFwzfUykNQdQapC5P8y3LNMHcksr", - "qizRThCQ227VPGEXfEnT9h6RzVPx5vKYEKX2PFeHrmkqkVJgr", - "sTiUYRycE2YqVECcy5zVG4PQhJ3bbDV43m5YjUG93WbcG4riY", - "swEd63Sn9V4sxkXjZgMZaxY5w3aGdcJV9i5ng8pg5Q5PozNbM" + "21GNKBvs4HhijvxpNbJKzhm4VkRyWYtWH8M6oUDtTrwsTniBfw", + "21PgwetKvSkPPH7AC3H7eZ1qv35PrndNkfCcQL3L1cQFGqdM84", + "22PdLnjXarY5WX1iXedStruNJ79vUpGfkiiEWwLwnMg5KA9FgN", + "233ci4fEYoDtAgK6NARXc26Wkebf2YiyG2qfShHCN2GYbUz8nq", + "23a4BNuCSaoAa4tieecDAKq9Ao7JBxz7FyEVnoPZR5CB4x6UcY", + "24WKNeGBARwakAufqEH9M3Ymoq6RX8rXVu2qM1ohawSDPHPfsC", + "268ZMaHbzkwMQR2euzeLp8yBQGcCSM4BZNdLmjWGh3eYSuAaje", + "27ohgMuJntWGRWMTRwAmeyYFXZc94h2CmLyukBucXPAJ7BQMdj", + "281fnre1wsmf2nwxrEhrKbxQJ2UvchZCeJaNDs5oz16VXUfV71", + "28xDbZPW3eX2JRCbpbUSJjm9rNDP929v22fx5166Toco1k2xyu", + "2BLuHXttwYRuLhr9k5Hov8hei16f7de751teUQjR9bH7M9uEEV", + "2BnQhpZRqq49U7CnCisifzR9KEDofoGvPxLjSUjnkAhaCZqZdb", + "2D1Zb3PKoVJoiNvHhEsS6isYvXGctfWbtDaAHpjXiYsy1JqUve", + "2FJSx7HPKZRkgxGm23qb7r6db1XMtJhYTYwPwcLnxy3xnND6qR", + "2JJWwULZhyQsMrpUhDrKR9SA3PdSuj4iRdaXinYHUPgqohwRdC", + "2Jm8VmZ2pU5FZdLgTHfzmLVNdRWs8niqZVw473jwFtdPDTwwbs", + "2K4W7Wp6B6YsZ5UJaVfbwLHpEBTCJiN4MDLJwyJziSc2unMmHF", + "2LYqjjCfXZNkbTDCbVPRpHrYpEYTg2LMRy67pUAZUn13h98pyP", + "2LzahS7j2TG9147oZ9TJWpFQVRmaW6URMt9AVTUzZ2xgUrtnJv", + "2N6mbB2nyzRcf7kWqrm7bBFgwDbS9MhXHvXrqv83irukBV8fQm", + "2Q6hxeJDYs3Z6aWNQ2ZRx8wX4h3c59QoSYmUMz2jNyVaRLkjrm", + "2R8KBvX1C3fmLFhhHD3Wa9UKtPkSCJsV6m1DFgF5jP4JXPeqG8", + "2RtTPZMYnf2hbsg1nSMEVPHHEPD1UTjSc59fbdD4bjcG1UAaUQ", + "2VyPre7mHudGLHkVXSW99oWGG78hFgHiurLbQfWRV8p7oY8yEf", + "2YAyedNs1K6SniCwhBQzTM7uHAtydBo8DEq9MTw6BQ4DhFP96G", + "2YDKeYjiRYZCekKXUK1qqTtrDSAnLZ4fGEAjK5apUts55LJuLQ", + "2bkkPybDSwsMzJNN7yLMgWimU4oi3dCm469RHNBkEiLDoymVjB", + "2cqeDNEzjStiNUUTASYYT3zmGCvakZJUbxGZknEMrK78uXudRB", + "2dAL897U6Ab77e3sE7PL9eLc2eCaQTFLMvvrwQvaedQoYiyXDd", + "2e3pF6Dzko5wPgRsFgUuGqKVm3Ssk1or5moxYw8ibpJvS548v3", + "2fA73U4pTv8B3gK6UvAAHCa181ghsLmTdhFmv2oZoAdXkUyzzQ", + "2g8YVxJLEmPdAH3nziQgowXawhmRXuXGtJMepK7E8Gjb7Wz2wQ", + "2gXFqfQCuNMnTYrM1zbZjsju4gCRSbSopLG32c9JasTdKQP4T", + "2itBsCBxhuQ4ErGsmraeThpm8WXpU3jGzmGUP75amt8piN9nqg", + "2kvK9AB4TD3R78ZmEwqoH85r7FgU6Jf9rm16y72Fcw5X9vSrw1", + "2nEUP9oXSLzqpxw7i86jpj2HivTTLgN9qLFF8WvHZukaWon4uX", + "2o1LyHL5smQijHAyz5y4uA4rqxdmfSX2oqSr1mUXpESwK57FAg", + "2oFvuh3LdgUTqiFLrpcoyDU3zBwANsHRVYB4SKwiHCHa5aHqFv", + "2pYkTLFP7TTZSkLptwu5Ut9gJwCQ7ZqAdpCKuHwUeFjxFhGLzG", + "2q3QVQ7BMV1rMoQgmCtsVwSdEeWisbQJQbo2hNNyGko9ZHcYxU", + "2sDESZkJVvCeFUNoqRmjhVPBFyLr7mbhMgyVvYBfheoVU3iXjP", + "2sQf1Zp7rW9GGXWRUCWp98L2mPCN4sbmLULToEVSARRaeqmBnX", + "2stkQDENMmAq9sco9tqHn9oEjV8XwUruavKh9j42Svz4LLi6iE", + "2tXt7gKwFM31mz8fs3DVzHE41ZpQ3i4HUXeEHDGTvhssZqHh5C", + "2tdDEQD3P8MhLifiLzBdjAXeZmTVm2eQ9rPbo1i6e56QujpNkE", + "2vMp4tg6xdg7oDJALQnWXz4dbxBFtLGfc9vPC6roG36xTUwGqm", + "2wiYcTuboDY83BKaNksfiHR8K6zSK1t9TX1mz1DscFpkfR1oJ9", + "3TSLrc4qynaPNUYWr3oYU6EoDoe211mqfPv26CR1Ju6kL8cgN", + "4Lp4q99adt6cdyg3aUBhNuErtzG3g8AUMks6XSU2GawvALRWp", + "6BGtusvq8xGEQR4ovDBJ158Us4qd2LVJqqiUajfUN99JezwBZ", + "74De4FAm32yFP9Ejtes1Fx6mNCVNfbmxWkcatny7vdqF68rD9", + "83FVtcFsfCW3Nu85B4WFev8YZxKU2Ts7ANBU5QbViS1yhRkGc", + "Ck5PcwtPXECZt2h9zC9CTCcVuoH26YtkraJqTAEthdQUEoURa", + "DpXNEJsq8XxKwPjeB75aVv3LnCvC9oB4cVEnvaDq4Mo2oGmmq", + "Es9AxFN2t4hwUQ5qWHL6c8BhnEfcC9bEiSCdVnrwMAnWwAoP2", + "FVfCZyMKquDzbntdS4pTV999xbe24wBmDw1q6bCnz6ZJJZU9y", + "FiBGBWfoBLWVbukjHJj9qmfV8AdLcegnwHkxT9z1FHH3gBwYE", + "GcsFTALW34ZR3JUSb4wTJReoapA3RfcfeFef4JbbKzFURBt8L", + "HX6PvpRq9fxNDEfwZEjkWEH1GnEqoa3HL7HSWePfPdvrCzE68", + "JiP3U7J2c3mX3sgXJCw3KgBNgwUSsCB8cGhoshYnGbhoonmr1", + "LSCQ9uV368zXR7jbTHhh5ezDvMVDVx1oi1ZUA7UwSF7TufXAs", + "Lc2ywRq1p9tLHZQYV4VhSH82iiqscTtCCdjbVjgQjit3GVf1c", + "QNqWF71vto9XwxRQMfwcSoqjfwVoMsZLtoFRDyi8gCK73zNVi", + "QQk9LEJ5DtgZ89QAwiHLc1UCoVZgW1j5hQ7XTY6AgUtN6wpi8", + "QaPScyZyY73BRwNYbkufCssUo89824rueV1dfhAiPqSEFkyxx", + "SQYeqJtoSQTU98Nzr6e3RpS26S4EDgTZkKz6BYBK6enDKYv3Y", + "Sj2TbvJ4XR13BjpVoMQx9RVjTYC8FgACu41A8hnQWfiJWi5gB", + "WxrS61JftdWSPfbzDnMa79wyTUnP6WnFCwNAyS3fMJ2QPfTuv", + "aAn8L6SSNrfzjznjNvhWqyiyujqhLmpgCnysisHijDY3eY2R8", + "bZbk5F6DQcbaTarbdxqRvzCYR9zEyo1Cg4YC25hwXq9Fffj4S", + "byRkVkNkokJPuv8dYYapUZRqzULaWHRNR41CGmFJNPFDeMxae", + "c6ZdCeFbkjwJLHNbFnXazcTBeDnLEvoYabwhu4EJzi8wSBPAK", + "cS5WWG74Jmg41GshL7disGDxKd4zzoWbDczZbYhUj4J7YC67s", + "cXHF2XYiPbAC9w75ZJUUobxsNE7ChetrGzzk74ZnFdPcMpZTF", + "d2Fdqbjp7fSDft7sxuspiJgByDRSKboZLNZKi5PHpbQcDmMMC", + "dJHkfZCeaRhLDBBgaDCw5ahJRqZayv7vqkqzkf8iFuyTAmdRN", + "eTcgbeBUS9PKCo1FU3L2KSx1wMXQF7ZTV7heMaxEDaETd6sZd", + "eYserBwMadKAYAiXJxW7qxSo4Bwyia8LhFDK4jBE3G6zHo6BA", + "fTJBufr1q88PwarE5zcm8U2h8NHkXqzDXFD1pjNmpezaXzuEw", + "fbFpFhHM4cQri1eXme9sX8Uugn2yreivtNESWiG6DKeRVk5MG", + "fheNGaNLyixLRBzSZmRKiWBZ32ME4BoUWwzNEaCcRYtWyeiBh", + "hohRXL4setbqaQLBb1eojfSfst9ocNYmVKbdN9HebiFD9Mm91", + "i1gXvBb8GoccJ9j3S6Sq7Wfh2nVmcXBo2noJ5tV9U6DLMb4tP", + "kBi3g8z4MjUfx36VpcV7nqWgwUZgWsHUDwotLq5uSuFM8GJz3", + "koWa5Fa9QwBoi1MnGGGxx7CKEFVEmYSNBPdxmo4XQLBtDGwVp", + "mMDgi86eEcF5zH6p8iYCfYMmQ55GqbipReoKSKtMbRy6GvN2D", + "mr7JGGtKivG4GptruxFSC9bZ4BjMytyw2BvCKbYn1XcjAp6cd", + "n6ecmUhHDg6oqFcmgWF4md5LbzDZa61iAKeESAxSXEwTyefW5", + "nBpAqZ3oddawTXkVmjQvQ27ezZ8zt6Ab2Cw5wvzC389RiSVsA", + "oBy9JhVDypnQUhxV24ntayS13xp24i4R4QuTQ1rck46DFzNRE", + "rsTtK52PxBCNAYojZjPFap4VN2bdtdutCsKhreUZC88tLoYbE", + "rv8QJjbFUSWV6Mt4q8388TDG42vCu7mzuAKwxMvjHHLcxzmBb", + "tF4RgbgAaa4LqgCHdsP4RQGCQRfzypqESjXudyNPecPrNKCQ7", + "vw1HytqPYBxf1gSmC8jnri3eLJnb5mppYSrFd26iBdPCuYK9t", + "wqtAobnVmJrYR5BwFqz8yeCwm1Wm8KBCyuZNsMTNdC5n6vof8", + "xYRJxcX9gjqDTLRArA8brxjYpjeoS223Pkij9uNEtKB2K4JNn", + "ya9nXSKsd4BH5Wvtf913pKi8d7T3NFEAarW8ZALHMBqCN5TQV", + "zDBbKBYjqujewuSnSxqAuG1rDDpmk1mqSFpYJYB3K1AUqmep2", + "zHdoWFMVwqL8VA5eVANF5VEutB394wtCGerEdaRvZ81YH7ekL" ] }, "mainnet": { "11111111111111111111111111111111LpoYY": [ - "28dGi9aKqLv4PxShLdtH3SMcrJQ29rYFZBux2N75yqZnwp2tSG", - "2EJQYgLNCy4UvmcRHxjM9Jmiedaz8zRPKMsATeAPRXgu1TL6NZ", - "2MTALukNfX7F4kb1bdmifKYNYun3cZvYrTbxi5rxcVJzrVFhTt", - "2PcPtUgRjhvNztbFWZyjn8CSV2LEM7tSmyF74YLHqwpWtHK9Tg", - "2WA6E6F4n9GBcUySrpmwkRoEaj3Dg5eeQiMiuxAr3sYz21y8Lp", - "2WQmtk8nd3YRMEu755TJpjyUrqXRYG5B2FvspEzU6BbCkeJN32", - "2ZNpSCqAsMMW7jfkzm4yn8mLexRhiKTww6EkLcBtB6TTRFFU62", - "2ZvwU2XKskNJ7Yr8CeMAFtQ5LWDuNVaL6zA6hyjz4pc5xHiDX", - "2iJuyWqd8AxbR2rTrS49REENAeqWGnUKt3wegqteE2mPEGoTsD", - "2pAywJdJFu4Crz59u75Lo5fzpQwmP2GHuuS1omp2z7VmAygQfC", - "DKMfVHKPF2GA1gmoKLBxJwNbrZGU9J8fnfs2vDntUXHWa1Qbz", - "PbnP2Gjr8qHgNriKRBp9gr3b1CWYBxjqheHFPXGDbca1Mwms7", - "S5KxF6sNcwKUhR2dMC9wCsdY8zFcPEGS9XYTNiiXhQnP63Evi", - "UsAALF2bfvxwnykySvrpTXQCwanQRS5Zy1LuR1M3aJYM7zfSE", - "VHRVMDeZRm85zPw9y6Z5JRx7HEnZ3hf5wp3H1KXxNb4hskSVh", - "XXKhAbeLeG9JYEmbjVjgNmYWFt3Hs7iso3hgWfjAQkrhP2HxU", - "kVU2k7YkeeTegtunQHhoRpzKrXffTVaTNM4TSXDFkP8BkHRtv", - "rk2VNXsSuR8WxureE9xpNuVVonmEJ32rixtzaFpbTMK7M8DNG", - "vPRhn3zforT9idV3GZNupvkfoeH84fdjwqqxExV8qadpQMCKP" + "1C6QHJ96EHsvtZXVHdr5zBdgX5gW2BQJrpRFobNmLbgsNmGgt", + "21cPFYt4eLs4UGhEaTeAsfHB3fHwAHs3M6xvpt6cXQafspzUZR", + "22bkNkCejmkkciWmfH2GbWXNuEZuet42xYdp3LYVKBKimFz1jS", + "22gSESLegSmxtAGHSkmmJDDRicmWpi9ripoEkuYe9PhaUKBygt", + "25eYvwc6YadcxLC1ovd8oLPHxzLM11dZUZAhBEDxeeMpRtgZ89", + "26D1G9eY7gDchmWiiboKEEYEkEqyRYR5MkmtXA3y4ZTmHwzcY1", + "27ASJoM4Zfte6kjK3xo2PFDbzjMNo9NjbGHDdfbZsar4j54kBS", + "28YV4qAB8f11teL8omBemtR3RmtBRfBA8GQb5qM2dn7y21x7pr", + "29RWNuDRMRU1KSUQmRzzpcj9r3t7zafDEHNSV4tXzCNZLT7kP2", + "29TMvMA1cTFW2KcpHCoEGC9Jjdbn29Jw8rWSVpEsvishCj2PEZ", + "2A3q7KhJGstxmdSFQisJxDoixZp5edAJB971P5SAg2ZBtLNaZr", + "2ALeEyf8h2PVFuCMiqgVs9YcJirueU9V5uX54E47ETf4ULTwCv", + "2CBKim62T3n4eHpfaP5iYFskDbvmo46v8SbJxWK1eP22e7tpXd", + "2CveciW8Nj4aQpHcFthScRhX5Xvd3TRcsBBbpzu8XymMuHwLTZ", + "2DES1e1UMB467gYdu9W6Dt8V31SkbFjRKdn1Y3GS69TbD5qUMC", + "2DLPFyvTWwYZqqJeeTh1cn9tmujiUB6dYYRUQ7pX1WNWnQRiSh", + "2Ejmxq87W71UPwvZNsg1QdZaQ9qha3KCQEX81Hu2oNvLnMutab", + "2FoAaZfdmxwEk172WJUauiYFTnELxBa2tQV2rBQxPQb7BGBaN5", + "2G4BACrpNp7cXusHdhpZUe98uyNYJYqykBxbKR9QTJLFTEa2h2", + "2GBNsFSMJ9SYYn8gSRZtmrvj1L5TarjAJHzde4kYEuy8XqKawE", + "2GhPn8H2PVStEaBriW9jNq5Z8yxrGdBzTwcBwVNZ9riDEox5G3", + "2GugeVAPnFB9jZZuEZpRdAVpvPJLFBmrB2NbDdXNu8gCURNyQd", + "2HdUspZzeyTysFyCdsosKCofnM1YsoctU8Db5RKRg1mnYCfnqv", + "2Jsr7tFh6BfhQ5MawnYnyq7ZUKDiiCoZoPvCcGxWufesQ3DS1z", + "2LL4rFkTKrvtnGReSv1WyDok5NSPp25DkntkVAnD29AQqBMCZk", + "2MHMe7RHr9x7dR7XQfBA1fhowX5v9vuieqqqKfh6MZaYDTxLUu", + "2MXevTUW9n3ezZVBo5dqTrBHboi5iAqNZjvmcbt9URj73yKsD8", + "2Tb97jbZLq8GESeAJ8VkoRynsmXsWSZKUejaw5nVZnBgVtUBAv", + "2UhoJQQYBfAbKHd5tt4gTJLCQzNR87Umuhpce8Xg2hnXDyjbEM", + "2V7rXDs35go28mhHQbHLXSNTW5wi2dn9QrEjudrJU8bP9whxGH", + "2VBG34kMWNzni9kdZ2FuCzTiHAE7Kdj1uFFcbeVyD3v5a96JoH", + "2W8kKMtnK2ErjbSKDjzqPFS8LGZV9aSf4gTMVVLpVqr238svMC", + "2XZyA97ohpr63o3kUB5bJ6GNdbVBodtUSxy8J5AJwzXkiKPyv2", + "2XcczkXD33DGVhCWMjA6UnepG1YLnqn8mZFfnGk4fGCx4sd8At", + "2XkfVtyDXaGifzj1pfmgUNntf2Pr4fXBHB3C3ZPfCGsvxoB16k", + "2Zn898sAFoEHG1fwqd9YxGj9ir6n3jWim2JKa631B8TPcujv8m", + "2a5mXCtxms1v3Ky2Hh7ZU9ucmfyrWcsaofTW9iez1f9UAG3zMP", + "2aosThGqXYu3MYuw5e1XgJPqYbScpe3MxC3r5HcbNo32BXHst2", + "2b7y1VLTg1ezdt4htt4NTypvxso9k1u3E1vfZugdryZaj7Sbif", + "2bKEKV7p1Lq4m43c9CFYYVdN9hjswehDiSpGwBMQoXMhH2iaSw", + "2bUPodfKzYSwvphj71Ph6CaVkzb2G3b6nJ76CrQR2KQ9avF8fV", + "2buyBep4TDUsZusYEpp7rZFdVcb1kBzMxuvmWY1RbNhjWPRpGT", + "2czQEWQh34qWCC9kD2LZLj4WukHtmcnpRLBXir5wQYAqxsqu7H", + "2e5XxysedgYJJn1zEWBmr2Dw2mFuSbqxy1NJ37DfdvKWDJvqce", + "2eCTMdHJsRNUUKVGLBU259w6TEoCmar1yeacioqMwE92rncsgT", + "2g9C9h6zxSwCzmoBhyZdmtUHgb9cDrohtQ8e8Myt5LK68qEmB7", + "2hYQF8yVbFgfAcUmZCRJG8kmYdnJUGNQYJWeCVJXwiAtohB2UR", + "2hyfqoEVxazA3wL2WnDyNFhrP1fryVWwn5pe7HxYVYk6K7XW41", + "2jRftTtrpnPa2mbpzrbgHyU8DUifkM8oLkDUyVApCVX2FP7Dpt", + "2k2Y5pJMp2EaMohgz1ETti2DL56QnRAJtS8fpmW6yEsGD3cfai", + "2knNUfFFUpCeAjF4CFSLmWQ5LTN7S5DHhghf6kk8CEtgSXU2Fy", + "2m6rgAXqECZS6jVWGWaHhhWwrdq3T3FSCyKVbEJkYVEAoJSrtW", + "2nKxFMhREjrccDWdqTKT4xUYXjJCPD98Qp1qK5HRFA82h1aT3x", + "2pAF2gPZpMBDANr4CuhhZYgzxTQMPwHzTfcF3ZXhtxw8E1Lav9", + "2pcew6PE5gqLz3QjRePfip6wCKpTNjQ2kwWbmsHAuf9wMUtwDf", + "2piSpsdsrsER7mxfUCWtobtCC6f8M1uLyqbkqFZZcMn3DHnajc", + "2prgtuMz2ciww3g125HyskmbNgA32omRYTiWsrJ4xvWFvJmgQW", + "2rMS1BpUBn6J1sC4iMMtfKXUjSs1UD2kzSsbpAsJK3qH2fy8Ek", + "2sXHvbVDX6Lh34NnAZzeQtwttx3TJzo9VsBrSGYVcG5egRpN29", + "2vbHvNcvniwdUN8oza8sGGbwmQu2bc5hxCedJYbRFPTK55eAYz", + "2vfXBQBD171q379JCCxwqJE53kXfBRshdkEr3Tkahq8b2qHPkq", + "2vkrakreKK3bVZTDKT1qAHTn31sGWVANUnMJtzFQzwHS2tdp7y", + "69hBvxY4AejbAw7Aq5pVignWxispY8AzprZusfgP55rLgJrwV", + "7HzbfBRJa1QEpRp93DTiCh6iDUdWSdmCptbYCu4Dg4XtAEiR9", + "7nrufmvYZv8aMuc6Y35KUcizSDs2mJNwmtjKS9ceS4KJbJEiD", + "AKQ6DBuYMJqeTZNdQmzzVX8UoBF84ArvQTP5RFHoyeFr6yWGn", + "D9PToNuQBFQUEJKhApBZK3saFA2GoonSq3VNmWmpiAehNzsUD", + "F9ZxuAKpt4NofbEtxH48i3rUphmJD7HUHEK1oSMbSixeoun8J", + "GoXitxCfeu7YBLwKBrw8YHSXtfoo3xHgEMrGmbyr3ctYb2SHk", + "JfWCLAeTqHh2vHNkVd9gCX5XXmP8T898fLLgJ8wzoCr4F92fi", + "QNpykqJszm7PRgtqJia39AoHbBMDsnFUsvTJXuDg6UhwX1XU5", + "QnCMVKL1GVYZNqbpXvFeW9DqkgNWRKjypPigzXwxgCrVD2mzf", + "TLpgi7b5cjxft859M1wqVSGvJKR3B8CVPDVCztKMUKwMuTPwf", + "VB5oKNX4FfPaQTaSzbvPuCY3arAqEV21UD8pXiKtqkot7mTDC", + "W4SJoLCWJAwnfLNg7o2vRbnxXjJxR57p3BKeX5vXN8FJnuHMk", + "WhLrw8WVmAzZJ952aDv3DAJL6qZ9v8YPxtGEegJwLKRXNKZJv", + "Y8samrw2cohK4k3dve7jYdUHU5zkJyoCrhT3GKuprUKzW3TnR", + "ZKqYi1u9HX81629F8UpBw6YdSPFxtSCr5K7kDH9MfyNNnpVHk", + "aWHNQarLDHf595EG22k8RrrW5q778nppiXjbdRMHUvXyMPoAF", + "bUHUFyfERafSe39S4w7TY7d8yMaSVvY5Dgt4QgPu3H9vqH6M4", + "cz6qidcp4t5mNXq6CV5V91zHLJNYu3x36Fa2qnL8FJBBkaEdp", + "dgTXQk1q13TcU2FbX6DbRQKZVTCF1JGGifVqDtYpXNzp6zGDS", + "e4TTY7yDE8JDFnyvdtoEoaUkczxk7CVLAVcCWbxu5s2kgshNP", + "eUHureSVS2jEuyrHDEnxSadueDnDVQeGQJeNHQTQ5Frjqxa62", + "gHvoTeGqB4JTWgbyior2vLTk7cZ5FPqsaPyXhStQmar5xucrf", + "gP7MLMjfPYNHx8SuvHgD8HzyZfLyWxUC4tforRVHipKTit98z", + "hh4EVoPagPSjrJonPRLamgMvx8qgNUASPWV4Mz1AiNM93zRH1", + "jL9bA8DabP4xh3GSxhzUQoLWcZDNZDhS5VwCuwSX3UgJSEGzN", + "jNfmePL4zkHJxdyPD6tP5GpXY7yuADSG8V321qaRf5N4p6VEW", + "qz7rmEGGtBT6fq5a4vqgbWrzGDtcQLddtcf6NHhz6HV5mt7kH", + "r5TyiJhxwnXajMPiBqbbMrZwMk7zRvt5x9qc7gCQwwSY76cVA", + "sq7U58h7x2psrTQWTXNjjSzmmojreZoY5aRZ6SvQVMxxNKT9c", + "vPDVkxE92tvTTCjFRE5rThfafxveQtmMK94GDZjdtQFjAti1G", + "vQvx4FYdP79Pe6fcD2HkStQEt69EwzA3P9pSCPbtAq9RAvfdF", + "xug97dH1mMwpSdAbVALedmanVAuDwsELA6qNjKYDmFB4HyMSY", + "ygYAdjHCjAGS2jFUc14QUpnerHAhY7RPUHQKe5NSAJFFJrjsF", + "yjC1ZvZPnd1J98fqbM9FbFuzcUSmeti6jBiDBBSCAMbAJj53W", + "yvSgdK5ksf78yDmFr8njQtTodUD5AMHqQbfdBmAzP3gE4s73X", + "zCCboLrquQhWdAoJGWYok6twmbyGkWKDyMMtwvBaBWvrAReut" ], "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM": [ - "26XHYKSUVPHYW4kxdyTTHsq5TUpJjJ1CiuG7wx987ZZvb6jq25", - "2ASoynxpeeNJHLPBt1hnnFebgGNYjmgg2gRDL1TFWUVmyrqvUv", - "2FXaca8JETKg37Zyxcjt7qnunSidMtu7esreSmLP3dkw265rxd", - "2QFbxT1EzUqp5Pz21TbE5c6ycAXuJEVZcdPJVFcXdk61at4zbk", - "2UheKUo59ocm6ziMSd34MhjR8vVndVRY3fY7mcWfa1dfVm5npF", - "2dBVRK8obttmY9MJ6qHJF6rUTxSoGDXjpDcBXFPch2VCFmY28M", - "2kgw6QPds6jRRp1hKEQXnRcpVtDDK8ACRByZPmpZXM7jDwWW6G", - "CmNBZXe3ftxsUnzAe9maTkWDfhTwyJTmHNB7U6tTdobdM2Zra", - "E5ybD9WaQEerLdMWV95x9i4synu32fih1tp8sbfd4mVKux9bv", - "Ff7fQTynJt2FKBvu25VfdwLKc52oWKLmuZWYgGVBV4twDFFgj", - "V4wNqSUz6a5P1DmdBXjmAvuXsn9bNnUUiQE1wCwZhAoQKf8hm", - "cYUfY7t3mPiArvHTStCpysnYhp7DB8NC6RT4J5THD65SpDUb9", - "dEeXZpwpWx26N5xa21XrLDtNQWUho65QSGq3y9KYZg1b4dF9i", - "dSKAYrvokjFCTUg8QSW6Hy77drj1bh7Wd17MG9qYFR2Zmqpr6", - "gK9Yo8Sapf2FTy1utHgJdepHQjuLQFwg9wooxHQqCYXdABJw2", - "vh88AVj7hkpQGHRXTzNGsrd7xSQPPy1kEChkzbaoyCy3UvEmL", - "vhTHvg9RecciepKJcYT2sHHuAjDPhUT7tNikEPHwHckv5CSrQ", - "z5tLKeF9H8V3Xu4VFSyCDLme1XS7M7L8MuPTTJM3H6jayopTV", - "zQtgyGJoAWzRYKAhFEPKSBkGdCTRx5ZZ5dMuG6NJUVeZVh7hF" + "1Kdri5W9vFJqB2dYBf5ZhYWAmZkkP4aHedVoV9pGYPQd8C77p", + "21jEMY3teZTGfPQqs9gGvWwoYsEvMPJKFLVYfUFYQFtuNv61p2", + "22xzGXKDSum2UQLksu5Eyb7ikMN36iDStT6jbPio9gjyHuyFC5", + "25jYWtYr1zwYoYri74aTiMp82rHC86HP7bJ1sYfvyqBrS2b6st", + "26gohU9ZFmkenRHYYFyp9YZdyAJVtiWKcqEhiwtAyAz4GJssQi", + "288CjAHapx9kK2sseVRgDBBfq4JeMbS3F98S4PK2YQU33vpnDh", + "2BaCerd4yoKeB8wiyFYK6ARB46HcqXSb8SCBJT6onMsgr2fv9r", + "2CNkxrCycKSJVxmMHcxPwcYEGqf3royYBrmKGL55upEESLvqur", + "2CTCExtaeVzGvnsXatitBfeiVQJKmehDdRok8PQQALtzQoYM1K", + "2CVcqHWjQkuzpe9tuSGHWQwazNsFZrDPJdPvjpcPfxmJs5s5TN", + "2DD4QdN9SmBnktJc7daV4asJi9ozwUwi1s3M6WNDShSUb3byDx", + "2DK7hzB9XUgUxeBuC34KAe5hnDKqgmRYgN2is3WjUW4V1vYNtL", + "2EDHTze7RjsaWcdgGy4WFSXEiHz3maHkc2jYGRrTzhKRX9w4CQ", + "2EcjWWz29FZoX7bUBRG4RQqpbwoBrwrhHBft3B3iARiejcKwR7", + "2HQzjUaHr3LW7XQTp8MvJCTibhnu4wyuDkS8LGYKsAGncZoV7j", + "2LScQCmZKGDpMBX8vzrSNUTgXGLX69LFdpQchcrM2MGYADWQx3", + "2LZeM7Fj9qFjm1C2WB8AKoo97VQXEo71EguEp8ZmUMTemQxjs2", + "2Ngiovn4iW43XQrx95kzujiVezrkdiXHnymV4pt7me2Rp4JaRy", + "2VFRJacgybj4bqgD3E616j2zhGHvhqqiBBMTLiuXDNxehR6Faq", + "2WAS42i6Xfu8ggWGVE2xCENpKhhkkC6q3Zb9vmVagjHdE1WSc5", + "2Wu6fX1nT9t9sTJWNfu9WMVovdd4QR1vBVeETht2AsDP9qT5rx", + "2XkRkvQ4ujTP7Rb1j7J7grBxqmM71Ggod2HLGC8rTW5pj1VBd1", + "2YS3faaAM93Ev6GHCYp5uWhtsSGuryYdxuNaRcy3hcmuPnDk8C", + "2YdjjG6GW1WcYedSAwRCtpLJUQP2MDCX94aEMd2LPYFAfWXMFu", + "2YdwRT8da6kJsG3XHnK5uQxedMTpqESwoVyJKA9qZjGT8fALds", + "2ZWrZrXWJtPQgVeCdzuAXvPich8hEQuZ9MrhJ6A56KnRw19sFW", + "2bZJH6jDPikCUcjnApQZ9X9k2MV1twjjVoYBp4QPCAB7ZyQANr", + "2bp2TvngbGuY9KRxAxnHk7qZr1KstCKtz83svoNhscEqjt3S9H", + "2bxu7PuSUtCXoBGfjeMjRKxX3gvWsZBXk8x2sLJ8FrBHYDHsd", + "2cm82zfe9NofzqQyjbCi1AmusYm7bxmq5gG7ZKRJhGTTr66fTE", + "2gdhwWbupbvKmHXA5PTe7H7bxFL8TVzW5kA7HG8TK5xMrSsTp8", + "2hxYwQDJ7ZFpfxZBo5b4NnLTL1Bg9fRMZyt7xjNDszG8ezZeto", + "2iWpSR16FCGao7zMcDi3h1XN9u8TTJZpWFzMQizhUV8ZWxWnmR", + "2jkJ3tSmg69mouko9d8PtcfKqs3Z7gR5tuxdsaEnn7trkgSEs2", + "2jwvDvvRLdwYL5UuoigH9BVc2D5bVhFNaYhaygXSamJGi7woiS", + "2kY42u9ckGES78ocJ6nBYgyczvPwVfUujcCJniVM9ZtfWQooC6", + "2kqszyuJBHUN7KsbUkyTFpxGGxmWURLDmGu8nU5h8v3Fzv2zQ1", + "2ncWunFKptuXQs5SiabaFUi8guG827pjLtr2pwfViCCWK85mFv", + "2o92FQ42CfwjsicGnffFZjETGijhsFNG9Gd5Be8UH6TabY6KXa", + "2o9kcsdzCD8Pp1ZJugL5Ryk5YmRwPHyb3Z3orN7JK9Fxcf6iqU", + "2oU5yYfGhdi2NqbjM9Jsufejbj3The1TkWJfzTdKsCF9ouWVJ3", + "2pSpcprbpgACr73pf2JcP8di7eab8vd93QFk2Wd7JaHWrwjHxV", + "2sY7uuNMetZu28FR9rC5MtpqWDKbVHQCvvRqFg9Rz5A2hffa5M", + "2v513oh6biDsL5jFTfVBZdzL8GU5Ur5E4BQCdQ3q94qSYNRvKf", + "2vSaKbZiiKP5pv4PXE8NF7hET1qRxnfps85qCg8EJmAakTMbqk", + "2w3qumfoA21su5Gv5kNM6NjyDmGCaENsBDTGgNEajPvrNf5nuq", + "3py4ULD6d5FzbYXcVLcm5cLBJGCPFJEnzrfCbEXnQfEa8FmZi", + "4ACXU3PYb656PxgVV8M18jw9MiaRmGPYCvApe4uUTEdX7TPpU", + "4VcURBXcMcQjHgdVGJzpqLwaJ53bvyd2RFKqCZj3U41mGmuZB", + "5DCcfMAqj7hWNiJPMSXkfUMvcHoRhHcQAwYumqoiEpKPd3DHa", + "5mg74cn8UZTk1WoWpX1mvipxhSjtvmJPen462K9kh4nG68oL8", + "799PvVmpxzWpsyEzoNaYdSsmTTTxLCgqxybWckfiZPhr2R6nU", + "8JVnuR4znS2TWBg7Fg9dctzYbiT99LiNjzvkxPRJwJayinpiU", + "9StEXYCTAZ2BUW7tzACJny4jLnXwkVgZRy37r9wPJGhRYLgDi", + "AKQxgsjUAMuuadiy6YDTMAFA1om1fPqyVjR9hqdz6hhoWkg29", + "AknqzZuovseCGTjcSfJ5xP7CrgVD9qpxiTj7T9shoLK59sW3E", + "DG9JJCKAMRYThgWW7WK88rqzkBcgfNMWZifPQpj4cz8SVPvBg", + "G6U9ZAQxo2qDUZsnU6t5TFmPekP2ivoSbtb8JXzJV95URWJXy", + "GPgfuY8bY2CTWHUzbY52N1W73DJjTpRgLBrG4wqnd2QqaoHyF", + "GU1N5nss24TshQhmadTtWiSuUFK4d9YGi83FDyhMrrgR1b7Yr", + "H3x2CsQRbZhaQuQCjYRW4MadfEZ9Gu4by2DnG5Y8sv9sWZrUY", + "HCDaYhTaYh9639qofxnG2qiX1dCzhTD6bdDcmrYczrQ3ZHjsg", + "HEyb8Q5n5YkPgXGByAtupKGQR7CJanzvMZWfAcD5dkjuQAsrL", + "JJ7peJW4T9QXKcHb1Mefnd2FVYru318qEQGkuJStwP9WejWP1", + "QTkZ9bfE923YkEZ3LNZRZ82mMrcv5mXnosjPLCX1eZhzvxtCd", + "QaDdtpq1b7V7SeB59uwkCRpMuXqhaBiYigLnMCb3CbDLMjDzD", + "RkKECwRZQ7e2a34oirrDqVQwMNscvmqF12V6UbBETSdzhXJxh", + "RpQmzvjeDaHBqqm7A9iqpPkVvMEW4RXW8SXjR8vNNN16S7qNQ", + "UyunGfbFB12wfmJqS8xyoNpjnb9RCcqBKs8Vfxmjf96x2hFAs", + "VDycGV2Ps7stDUZ3kRvbmVuKkKoPUyVFAGtwKmU2W7nBFHjzq", + "W4QoHZErHuSaYn6V9ptAnmtjYsMxEDLWfdmMks6zFNZYjapxo", + "W4tMAUHZcSWQ3ck4q75XVwB2j9cgqtTHKeDGCBsJYu7jYXQGx", + "ZuDLBGTsryGHBSARE4zgM4Dtj1H5DNe1nxfZ8FQpCHmYunPn3", + "bTs52txp1o1z33uebucqS6sZ94c4XLuXQcgUdr97kwZK7BWEt", + "bZMYP5jmsTMyXRK5QTAyHt8bzGuwm4APboEHFbTqexhyc3Tm", + "cddXZXwkgMX4vHG5kxTG8ktXn6ujAtPe2rkZXvEGgAHgwkDSg", + "fDLZXMLLX77NdPYFRLyn2WNDSwtpKxCZqdRgTBuwCP9H3otgk", + "fGWn4NaAqK2BgQWadVtkHB7Q1n1qijrin91tkzq5Exndq3CNy", + "fM4tU4iDpLUYjwqnDeWkLtbkEqPhPRzwbkAD5GTviD4CpAnRN", + "fd4LC3i5w4w8TMmaPwmU7GPHyUsMk6fUtNykCZvmkp9iNuxtL", + "fptxfNAeQbDzTV78ryzqTE9xiQgViGnLZHHfipb3qvWHMvzAs", + "gJqkJ22xRqQ5SRVraoQiz1piMJKsb9QyhhTvbbRfZ4FCsjbxW", + "gdismVqRtUwW2X5DuU3ybYxtjiaSkAmqntXKFSpUkkgdtYMU3", + "i263AhAfgjqrTjEmJG8mA3dKDVX3rMPWRnn9pzT4EDG4pjxRH", + "i9sCwM19Ndxc1FH3nmSHDvt5QPD6StWgyKDGNwSF6LbhbiqhF", + "iuUYXFzNJYqLjA7sZQeXSDPMWShVkjAGykBcLzyZLt1BpH5Cw", + "ivECpWEqSRR9mA3fP6jTu2akET1rRtmJjqednYCjSdMXJAN1q", + "j6EquSChjB48xP64iHh6Bj67GEsvhCoV73uqsf7K5B6PRjfvf", + "kCd5nEUkHyFJLyqZ8NJhqa5GbsvCgBfj9cHXyAWWCin4HjosH", + "oQNJxqjJYaSLAHqyF3n9GpbtJzYwDwMD9WsUCAAGWSXAYUG5V", + "p9zGnppWJ1rUrqecGhozsBSsRvsiEwkj4vM7rUringMPL7cQ6", + "q14J1hczzqeQS8aKCJcog5bTFNNkFFWwza4XMjy89FuZRziNg", + "udPiCek7LmDmnkooWSsBe8SQzv9dmMgc4F4VpL5naudqdPQYW", + "vL8xjHKkhPkNrDpe7BkQksbvc1JAnwjTk9kCsJ55wmrBibKjf", + "vfshLdk8kS5hXFpKHDkg4FpwWCxzVXmUjv7Pzgb9WQJ2g6vuu", + "vg5LKAUU1YQSdP39zLx8vzUvmUiuAtM1dt5RqBvG3go4owo1N", + "wHwEP9TgGCQKe1viNvmcnHZtQvyEvJNf49fadLrAbXGjGRKaV", + "y1BYCkbExzrdonKbEvgTRwLmT3t7FE23ZAYbFCaShwFyVEeEm", + "zgKT1hRCBnXvxnzuQnxCZoV4TZAUTWA1UdF7Y1rZxgsqk29Ex" ], "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5": [ - "24SqsryHJRV8Q7qyPEruzXcj3yJfvgv5qequ2skJrEWoohpwm6", - "28BXQw5qfdwTHyV5p2pN9d6VzEahT2JWHT1Dd9RoHPLgC67gWS", - "2En3SNxo49Vdkx58J7UWvR5cwdXzbpt8cU6MS6dTgVdsYZBdHC", - "2K8tQm3BURGo8917v5nKm14yau8HzRHSvRYNSbHuebavaTy17i", - "2P4dyKpq25wGRokyCbidSKYXkhLJ8cpe7hUCp69aXwGr5rA5Jj", - "2PJpy8yqFWVm3Ew4qcuEe1rdnr5Uznq5X538G69YXuYAtY3gUS", - "2PzygucFpemhAAR53Jy34C3kgrUgAfGSbbj2UkUKn6AkAmTstz", - "2ahXAJ9teQE4nrExSt9J3r6oa9tCwLsP8fVsrLa7RnKHv8La9u", - "2hCKNRDwZSe9UhXcYUwaa6wHQzzyh4egQEexXncHKAnvXYdnTG", - "2rFR5KuqSo1dJtpYsNNrnWTYhmDN26s3zxSfBQphP61Xrzg5wr", - "2sdVixbBNZiAGnSska1m5YzokGPC9WP2arKWEidWZCCAF7BZYF", - "2uvUX23JiaNH8ZJnug75n3ummrxnjR7TWJPfvZ5goQDNY2TTH3", - "7v8FtNmL63T4U68cXutRABDRDWBFTLtGh7q5UuFtqouSMjn5j", - "KNTZTo5oE9npWbpGC3xYXcAN6sdS9hZ5wV6DVbZHyx4RY477G", - "KXVRT9rDVzRzvJz5ybuc4ogox8amHni9k7i61rGBztp9SYKEj", - "bNFYzR4XpAdvRHFAQxk7kPvCNUAFRThHdAeRUnZACmVfMfi3u", - "dCwyTrXC89Mcg6EkD77ERgCRnEdAjcad8c4SJGEvKkHQhN2zf", - "jhbWmPAWw6cuoJi7Z74B92wu4Cty17q3iR5hRv9KmEcFaUn4i", - "qE4UJDByJ1jPnbdx8j9z4QYa9xhD5DKZDvwJxFVQjm1QLt1zw", - "udtBGipZjvhWZkDxGkMceBzoRz3mrbc2eK6Acf81knaKmfTUk" + "21CreraF9rvZEG6MsoJF9TtX7bHVn2BLxVyRuzm7zKZjadsbXZ", + "23pb5FGvVxpuwhAbTapXQb3sJgTpVD9gRv2y9eTTuxChMKBDXC", + "265CjdcpfLQXEcJmFvChGsJ6C4zDjw17ED6s7eJCEzR4PvQpHh", + "26AAHTzNoYx9Nyo7J7ikP3KbpTzMhd5SxwGkuXa3ZjSWLrrapU", + "28EevMGw45HL7fg6uXkwfBbsxNgjV4N2eFdR2VoHcRxiGbMGq3", + "29cAK3vmV8z3mnFB3NvzGaBsc2DxzF5eS7zPRVdRkqHTHig67D", + "29jvTrUs7AYYvf8yxfdWajCBvLRRcT7H5BZZurW1mwrYYnQ4QR", + "2BNV2AxUKgoiARK2sUPS1MPLTiXJXqhR4GdjBXoHb2HG5gkgWC", + "2DmVARhBswxcL428kqDCiJeVFU7r2d8nCGrJWqVUZkmUuUt8ES", + "2EjbjrcwwbGquQAEb1FHY9addWdU1RHHFEGvDju9kvj91REDb", + "2FGVk4NRVEYN5dDbecC62XQgzV9DJy2fQPh9KgWUJffFWQRY2", + "2JXMbT4ssEZfE1uJN1PJfEx2vB95Jgu4SnrMJtm2X6BCGACFLK", + "2M5yrtJSZuX4ATPyGbKpK39SB4Q923hHduBs9x4GWf95bJixVq", + "2MWc4PWBeb7GALHPj78hu17EyYzQcd9es63zh3QMz8aKo5Uoou", + "2NE4AzZ5AsMYct4WoUhGdn61hfDXEqyBABTYCFfywAjjvPXhei", + "2NSZMhSmtFDnMGp7WqQBrpW5kWiibgGH1oU31mLEfPJMA1PzZY", + "2QACN8uzw3oLGxVKgCXafsQgV8Y8CfwDUZ6ms3owybc2c2aYzf", + "2Rie2Ud9og9FoLMZZDAQ6VZPHyTn4MJ48nzarJWLuxPTvViahd", + "2SSGNPRsxmEtLEm6qEbKhXtXufgVQgDiAk321Vr5iczRwQVkxM", + "2TRvFo9zuVDBYzKH2nYj3biyDsqSvgYG6s6rSqjsZnU4UHc3m3", + "2TeJo5wYNqBaomR7Bgv89GJGQBKNLb3JxVceCmYvU3Lee5j4ih", + "2ULGRcoNKppkUeqedVerMsdf2Y9hq7E6RxrqXamT455m2U5SWR", + "2W59GDbGUMe2Q757tQJ7p77o2xeAiSztoq2F6jG1xQ1MoYbzq9", + "2WLSi4pwumXsXwDDbwPqXUaddj1pQRJKyPEjwGHZbRy3c3NT9P", + "2ZgdutRM86WEM4H5AvkfL6uerRiyoVThf7xUUYkE5oCvpp1qJC", + "2aBaaaEYULkiqjVQHmwPUYYdPBMUuSnKmEhSzWyZB6GeWBXPCY", + "2btxsybZpwTyd9CRDXQLpDRWWidmZaRZLgCYkXhvB1zDxVWw2H", + "2cbFwLh2Vg9YvRoZeMeCfW1YN4zmowciYgkKxik3B6PAaKxAN3", + "2dXt515YZnoieDwcVAdWEGP8QkwTUW2f1rLD1me9EtKWZyf5bJ", + "2edyMHQ5saBuRmK2st2YSFpNdku8twpegsdjd7zNnHi6ZUukKU", + "2hJR29douLkQFBo68kuymnnKo8rZkUWc11AzmiJDnJf8MHfMe4", + "2iCea61uA5ZXWhYpvTDmnp2h7Wq3uv1o22k9kDi6WZuX4RsvDi", + "2k8LHm9kz96J4cbNWMvvqNtJpQa9xCc6YtbqAg1F9nXrJQ9pfS", + "2mMAZN2Ma3Rao3sBTRd3uSExEQXWFPbbQnxzQfK1SSp4mYTUUQ", + "2mMKRBy5ZWcEfmXRaWF2nR9gvPzRgRqrdFjQjuMsrfN9oNWxKf", + "2oSWX9ux25jXe55mEZN1cBingArYThWtCDLsDhr2isZtBh5ZU3", + "2p7HXkRya1trXfZ5kdNosALBFYaimLoFYr14QVo8qaMa3wTQws", + "2pmuxPNMfd2zxqfs6Xrt5754QmVR5aXUvGNWNn7fmM1jxvQoNK", + "2qj7qZ6WbVCtT2QTTATGjcdSU7LGC8eBHsMzYonLHLybSoi3zb", + "2sBfEUvMx7L7buD2nDLpSUXXS8sR4gznt3KxSfrHz5VeDKecK6", + "2sVWHCDgw8irCr1BCx4H62kbRfWzoVUGm9VEpw9WKTDSouZFL", + "2uEbkViaWa3uJTphvudNqAAY96kaDG7tzXRCQcGVLDav8Gbvao", + "2vKcsEcq1hkmJmtqchRRNdPPx3yUzCFwo3EzwYi1J1D5hMQriN", + "2vcGhKMBP5JNCYcuAazBxNQiLPxZ4FCocoDPgLHhFHSQK1zLmQ", + "2wLEVixVCLiHNEcSoh5Se7XjQ151BukevAP6Gd8qrEz9XhKXKb", + "2wRz5cLzPMATR1guVD1RptHHye3CydZ9KgfRzptUiK2YQyt5AH", + "3xdWqa1aXedPdWCyhtZi8n8DtiW2GaaHdvEnPCYRfY5bWuw1D", + "43db7QzNPdFxPqw9zBhMFcJSEkL7kutJpPBuQmTpYCHQRQEQu", + "4UadCQ3Uvjd4QLBPsUZjRXV2on9r2MXXymTJ4NHWVuXh4KU7Y", + "4XisoAHVHeNKytvTULTLMNNNAHE3cFG3WEkBHQcKjzQkYyeX6", + "5D4VjMN8c6fv6zBKu7KNcNTHQguH6sBnMNHoMiGZgUa26FaAP", + "693Aoq9TtEVi4QB51eqpEecpVLMWTG1W2DdNco2VRpEkAEowN", + "6JBGsVgWaNyzDnD9A2pmTRYTyRGYM1U6GLjCopCJyJun316ov", + "6fNsyD8zUStRKLR8A6TBVozH3ozJH4ea3tQGzrZpdFx7aaXgP", + "9JT71povEckWQvc8iwgoZmxNKhonmeBiQcGeG5uD8aSxzigJE", + "9TFR2TmyvJvsa8qUdED2K1iGvDu6iMUWE7rmt6cKamQiVp8nW", + "CULPvaK6i2C7V4eRnQqKosMjzDc2YeAbRrXqzc5nEYRRg5byF", + "CoiAuuPMNhVBGytjsM2D6QTSqAFkb9mbAaeJ8EELHrP78wyDo", + "EGHXu22WF9mSHfkmQGrcFa78aGKNpQHrf3kQMXvkroTp4KG57", + "FyuoVPbTvmAwoMMvauGsLu25QkRT2ffCtuveAAZGFnfrFXpGR", + "GhTxU8m3fkBzN1a1fxfnV4oFPACqAZfnu3iayiEMcV733yq3N", + "HKEFB2cTrLc3jq8Eevp5gNK2W783bgJntPT9LetzRThK4GWbF", + "LU9mnCVtCKVAh786Unb8rR53WWSWw5TaEfs5TkEhxZm1kDumW", + "MDAux1a22nQMTU2yNVgyrbDoPU5Ym37kFh3nSqtBKNSbu7B5U", + "MJbvKe3mG4PuCrGrgiKCmUiJqMW5iFbaYzLkPG3o6oF9sDb3S", + "MWeuiyZC2dovgSWxHwD2dtJwZ4bBb6kynrUH7qcwK7T9JDhSe", + "NjwaUveSc6nfRZdwsLp7LgDJCNXKTbwV5XusjK2wyxXNqtn4j", + "NmCqVhQWBbh9ogkWjoeVqWGgkHKTtosxoDh2nPdEWZ8AQfwgj", + "TcNkLFGvbk1oSy3BsR655T4irnvXq2o5aFcRSjV9vx3haPpoM", + "TgfoQbxhbvH5ukjUQz2aoZVau4p9zxYi1afYjHPCWuDmSbTG9", + "TqSP2Qwdcf6mmoLAwmh2B4PSZ8T5L6kbWuaVNFqHfUcTN9vLE", + "TxAbe5TanwQyh3yLiMjLfjZRE7GWhGqsybixCDFhppJZ79qzr", + "UWQ9xMgsmmnAnsLPPqnEAR8Qco5hEVD8H8WGMYtAAVzGvRCHy", + "YEjyUmUMva7AX8T2eUv2JrHeLf6cxjSppZN34XgWqGVkKSKER", + "YXZEoXrp68wmFg6S9i84YHkRcLJPrZEsT4oQGWipgwZArD54A", + "ZKskrRDWRWzYBk5zEEanuKJbYjxaVSg1FzJxKVuDT7LyYtmSe", + "ZwQH5ki9kwVVE5Qpeg6tSLF6ciid5Qtbg7HuJnYsr9RvpQTFV", + "a3cziexWAoPKNpue1yvsQNrLPCuNmbgxmaX7wP3cbYGfkTxYv", + "bC1uQUxr4fTk6WXqwhgMecBtGFWw3Uyzuk68GHZkn19k1S8rd", + "bQdKidaawr1NZTnbrEnAJn46TB7t8qyfnAxgDH47M93XuyQY7", + "bZxvvKp5GuwzDed4LgngN3rkdxxjnRV9ZMWJZmLteq2CiYfsj", + "baqCaeXpD886QdQPtfqBUHVq34KuiDPEcw1TDyDHHFS3PPUYe", + "c2TftZBnzAk2iE7QhNMeYGxG4cYK7p3S4WVHx8yWFDx38FtSz", + "c36RHow7SjbGHwkoy2yEeBnq8ZUiPqPndHxAYgEWu5pHrFV8G", + "cZK53Cyf7WsNch1arhdJbMUwGHu4NPAt32fQDCmePWcsDNrnN", + "egZE8zk5DFhGjfbRyCHV2hLAXh2NqXzpQN4HBKA8wYMuNjjFB", + "fw4ZYUiKbkenFZgGeszwKLiu7VkQKvhy2FPpmsH1ZYiAA43eS", + "g2wo44qqYqakCM4NDgYSo1YEQknWq9K92QP62SaNrExqGg3dX", + "hmUpps6g13vAiorcK3fJtaXeCs9C4pzygk269XoNpYWE9pwLA", + "hnV2YHfTxCBcjqwSzYDNBKTikiqiDfDsn3s4ypyukXog2bLyh", + "iGQfwhtJ8aKpatZtgHTgJDUAEzMuwePMbRGk86fSmTieNLn6", + "khWVWX8eL4ahGJBd4E7GySRXenfbF4bqX79ZPuMz5K7rB5P7j", + "nHR81kNRdwvJ66ZxyaT2dZ6pgJtET32aEWixk62W6QXT5ZR28", + "otVKKrh7Dkvpmd8BbnXiCh1ivnnvJLXft48ajHxduSEbHrshT", + "qvuGSY6oPt8a2jYPvtHPVKmR4Hg5K77rD2J84twVMxYhfZLHp", + "sp2ec7ivV4BheoGoBm7RUpjGnvz4AKruvtq2G9ekmJWRUKNuw", + "tNM6B5Wt2JJ1DXhChZbucfckBwwTxwX9fv7ZwBppsCifpqneh", + "v78MgFnTuxBm8hwYhLkjphFXqdSZaAHPJXwgpcHGbLYcKnrF8", + "zGhQDuTyFxZrY3NE3QzBU4v6r8RphEJfMPUgZ2cNHuC7xHbcB" ] } } \ No newline at end of file diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go index 128c25699877..b3e79cf4d660 100644 --- a/genesis/generate/checkpoints/main.go +++ b/genesis/generate/checkpoints/main.go @@ -20,7 +20,7 @@ const ( fujiURI = "http://localhost:9650" mainnetURI = "http://localhost:9660" - maxNumCheckpoints = 20 + maxNumCheckpoints = 100 ) var ( From db7c0c8f4073a180c010ce6182429cad1afb2f1c Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 14:32:46 -0400 Subject: [PATCH 73/85] update validators --- genesis/validators.json | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/genesis/validators.json b/genesis/validators.json index 4d3c616ab90e..70aafaecd367 100644 --- a/genesis/validators.json +++ b/genesis/validators.json @@ -83,12 +83,14 @@ "NodeID-41cr9VeX852rtHrELWnHthUV4Bbm75WBY", "NodeID-468yx2KFJV9M7uNiTXJrbqyFGeQxgiBfh", "NodeID-4B4rc5vdD1758JSBYL1xyvE5NHGzz6xzH", + "NodeID-4CWTbdvgXHY1CLXqQNAp22nJDo5nAmts6", "NodeID-4DDjS32CM5oK7tbba8iNnXv7VWJsrynDu", "NodeID-4H2NGT5zSc5Tt5KHTciLXVHW3CVofDmuG", "NodeID-4JwxRwRY8LgeSdDLNargL9NBEBUuvTk9v", "NodeID-4KKUrWvuKKEwNQWvZj7x6NDhUEan1m44C", "NodeID-4KXitMCoE9p2BHA6VzXtaTxLoEjNDo2Pt", "NodeID-4LJNqmxdSigcw9wnGcd8nRP7Z4XZrEMyt", + "NodeID-4QBwET5o8kUhvt9xArhir4d3R25CtmZho", "NodeID-4RApHGzbpwtrUEbL9BpkV8AfdCzr1ciCj", "NodeID-4SdtN4zCP8h3ZEymEfGxJRocAu5hrwphC", "NodeID-4TJyt2f7zGuusjc1yXcBJnkNvDMAJ9py4", @@ -213,6 +215,7 @@ "NodeID-7zbpDafC5Rxm6ZMXqSrz9D28ZdC4WV7Hp", "NodeID-83qSEo3NEDrRoNYzJJY4RUBM79cSz4zVR", "NodeID-84KbQHSDnojrmyuZjWM6hrM2vgPtMWt3", + "NodeID-84KbQHSDnojroCVY7vQ7u9Tx7pUonPaS", "NodeID-89GQ3qi4bif58ovQnQAehtccU8Jbynozk", "NodeID-89UCR1CsPzzEHuknxhJHKxuFPNCyPz7Bu", "NodeID-8Bh3X1LH6uW1q2USKQeu11PAozaSMgEjr", @@ -311,6 +314,7 @@ "NodeID-B8SLANqFYZnUqfnWMuJjsjfzcN8Fxs9rp", "NodeID-B8vH6dfELDJgPjYVMK5hjrRQkUMFFW7i2", "NodeID-BBt17ZXGPvov135835zT6BBAa6uTwriQi", + "NodeID-BFa1padLXBj7VHa2JYvYGzcTBPQGjPhUy", "NodeID-BHM9wtsHVPmqKbfmqqHTvTCiM4YXoRSvs", "NodeID-BJjQb2PFLPiHsvejL2Q3yX28nqRxGxEqA", "NodeID-BNYwWBYAidDqYiJYKhRahibQxPuG6hGvp", @@ -353,6 +357,7 @@ "NodeID-CU8Tq3pP9QniPeYWagh3TKDFccbvfwDkw", "NodeID-CYKruAjwH1BmV3m37sXNuprbr7dGQuJwG", "NodeID-CZP8JG4BKdDyiktxg3D2ZYgREHtFhqzjH", + "NodeID-CZmZ9xpCzkWqjAyS7L4htzh5Lg6kf1k18", "NodeID-CaHFWxHNLv1R4R9oGHMQR7n2vKy95LTei", "NodeID-CafHoeCqCjg8fWufaorRqFe3iX8s7z6A8", "NodeID-CcS3n2j4CEaQCEnY39qaBDZajeZaXkRGU", @@ -412,6 +417,7 @@ "NodeID-E7e5wZQb8QYEKYd1BrRrszjPxUaAQNaY7", "NodeID-E8dfbZCzX8VXgXYmjnA58GorajNrNcpFL", "NodeID-ECmPviPvgqFc4iXFi3soN1xpXnUUDHjoG", + "NodeID-EDESh4DfZFC15i613pMtWniQ9arbBZRnL", "NodeID-EEuQumHSHr2hV4C5S2FNL8LVofD2Wvqyi", "NodeID-EGzKzc9RU6HGCzBe8nK2qY6mVs6WqroBg", "NodeID-EHV8d1ezFyoA8DMzTU3WZXfVR95R7v1cv", @@ -457,6 +463,7 @@ "NodeID-Fcz43yNkFRu3jL97vjLi3ZkpmeAcVR8La", "NodeID-FdcqnJ1bwv976Ft4RibXmD5DTeWSnMzS5", "NodeID-FehvGhfc73qH6s4zTdiKrNA4WmSMbCW4X", + "NodeID-FesGqwKq7z5nPFHa5iwZctHE5EZV9Lpdq", "NodeID-FfiosnkKYLrMKoUpNTuFZz6gY5kb9cPb2", "NodeID-Ffr1YgeWw3h2Ct9dY7V3u79ScrAbhSUUz", "NodeID-FfxNCp6tZxTpj1JxA8GGVTtJWowqKDmvY", @@ -515,6 +522,7 @@ "NodeID-HDcjsGMHLaLgJFoQYmi4CBsbjMKPacuP6", "NodeID-HEdbAzR9GLht5p6b47J214UhdshCDX9TP", "NodeID-HFEef35BkgqRBYiQ2ou5JhsyB8LHRtyuo", + "NodeID-HGZ8ae74J3odT8ESreAdCtdnvWG1J4X5n", "NodeID-HHXxANboEXufRMuSFBHgc5dbpk67L7XPV", "NodeID-HHcVpHweLyANYAB3UoDYrBQLDznFeS42j", "NodeID-HM73QztvPuGikaADwnjpaJ1iKWAABuQon", @@ -564,6 +572,7 @@ "NodeID-JrKGcbdnCzXUijeLiwzJZQNX48Cyrs9Yx", "NodeID-JtgzXwsBLsJh6HWQGWfszrCCxpCnnzdwc", "NodeID-JvyHfY99GqXXWUsSaoeEEZZ64LQpMCUMU", + "NodeID-JyE4P8f4cTryNV8DCz2M81bMtGhFFHexG", "NodeID-JyRud4d7Sp77cjoXiuaThBsUVrSFEHgMQ", "NodeID-JzcJLa8bXBPBg75VVXUHh4fqgmhx8N83h", "NodeID-K2tnczAaPNak4WDoHs7thRxztKDc3LgoH", @@ -622,6 +631,7 @@ "NodeID-Lb7Ez9LWTXUeKRUMgHX4JJtg4WNh31JUS", "NodeID-LbijL9cqXkmq2Q8oQYYGs8LmcSRhnrDWJ", "NodeID-Le4BWsZM3dAuMXTDL4rkcRZBTyHpC9zzq", + "NodeID-LegbVf6qaMKcsXPnLStkdc1JVktmmiDxy", "NodeID-Lf75GiFUq2psqfd3e6GkMNuVEYx9BUuuT", "NodeID-Li2RswwproDXoFXPtrc4LvVWLxC1osx1C", "NodeID-LkER3oCznkUE1mTaRsugitboTtBSxNF7o", @@ -717,6 +727,7 @@ "NodeID-PcZGZ4CzwJ8NEGsL7ccQEgAGZ7AU6jtBc", "NodeID-Pd7rHrBk8hJyD5uCRcG3uWC3ZwPGtTohm", "NodeID-PgBvqpbMQzJk61yoN346xxrnrHad8y8LB", + "NodeID-PgXSBGwW6cNMwQv8P7kYXVr5AkJWs7i5R", "NodeID-PgheFFDtZftKj9mNpEvH27zeQ6c6qvoep", "NodeID-Pm3TC3M1pWDFhwa79YRqHGzG9Sjvgcdtd", "NodeID-Pn9jFroHyLVfDmsEruHABa73mpbnSU5RN", @@ -765,6 +776,7 @@ "NodeID-mce4CCkKp1Vx9ck6FwtjQVbTyUSvKe1V", "NodeID-mwGVBwDPG11rSWCjYwYyqBJJxM3ZEoPj", "NodeID-oRUBcQ7Lsrxi2S5bmWGD5CF69e2x8mct", + "NodeID-pCZeP48M5cMxycWR5QFfUumPgwKEXPFY", "NodeID-pQCdCxnzPybSowJ8aNuu3o1w7e7QCVNH", "NodeID-tFgE4qqgLiivtexeoojvJgSk7eHv1HRU", "NodeID-tkLPZudEk3RpVG2DLq5jfZS4KHLJf27E", @@ -878,6 +890,7 @@ "NodeID-3MFu1eLpGRrRcWksHJLBuk516Vk5PoYgC", "NodeID-3NJgvio7B47MB7BZWm31LHzbPWVdkEiEP", "NodeID-3NXS6ZAzHeqV7w4saG4vXxAd4tcbpmxfk", + "NodeID-3PJY4Rpb5BRR3xSUvuU5Dj3cyHcAmzfjD", "NodeID-3QvnmD9KrJt7BcoYytWfCsCD83TmKo16d", "NodeID-3ShFK7JbJ2LN2gFT2W4iXp4N2NVuP4vZC", "NodeID-3TWEGuLyjvyKYLQqXNvQ7GQqSNoSQrviN", @@ -1304,7 +1317,6 @@ "NodeID-8gndDR9ULm3ywRNbh3FUveaSyo5g7V3ns", "NodeID-8iQxXS1Zbm6tGzfp56kpSyUboE5kSNoH7", "NodeID-8ja1C24FM5FyQgUGjsm4qwpD6shiu71KH", - "NodeID-8mFFkAeyLkQ5Kgw85ZeAb5XFXjqsxPGUv", "NodeID-8mHndwCShG4xau63f5FMJC5r1kDCZNpNi", "NodeID-8oREeth2haQyVW7Bu1iGgiMe18h5Pqiwp", "NodeID-8qkeNyB3cbs7LqzP4AB7rHcrcHLAYVDEs", @@ -1468,7 +1480,6 @@ "NodeID-Ahy3pk9UZEeVLzks1BRSqsLL6zvJt4bN4", "NodeID-AiVA6rmmPhouiy3ERwF7k1eoLTrPErd2p", "NodeID-Aix93q3XbWsEcoNuuWjYuQM49ZeCX7NLS", - "NodeID-AkWM2duSrGSfWNEdN1pmWm9ZLrwZDg5MN", "NodeID-AmFfzQQtUYm1RNuhkQuoG6hzaXpYYbYtE", "NodeID-AoGM9c6bKC46YpEecEe9tHG5HfcjqPxtb", "NodeID-AoU4gTzEVKVmopKx7s9hKXBbQ14VYyAcc", @@ -1616,6 +1627,7 @@ "NodeID-CjX7mnJM1qasMtuyyxeuKoKy6b9fdSSbE", "NodeID-CjooWTHxne1o2w1hetMGgDL5Et8JzKMiw", "NodeID-Ck4VEAv4JTMgnijLQDeGCWST8Zdgxe9Q6", + "NodeID-CkMG3CThWnfAYCYE1MDsFqSU1n4NESoFt", "NodeID-Cn4ocmPe1Hqo29RyYCC1QXr8b763Wpw92", "NodeID-CoRQHCd3aSKe7FrhHSUnvNVZzW52xu2YA", "NodeID-Conr75BBUMBFNXD2VP6gvEbCRihCvjfej", @@ -1627,7 +1639,6 @@ "NodeID-CskPetRMvtH5Xr6gLa5cwfY4hR34UgkM5", "NodeID-CuEMaXrtX3tdegH3BPJowHr7cMUyf7P19", "NodeID-CuF2PsXiuZESJWa5itRLmXWQ66qL1NSE4", - "NodeID-CvzmyAWqVXtrEcJWfXDP742oE9PsnCyoB", "NodeID-CzW1jKjZwFXgkB2Ria2nNPvah4bMq85bH", "NodeID-D12qpTYhB3feogxvMBzS1QPvwyKyhRK8G", "NodeID-D1H3GmiDVvoMsp3foTPmWi9YPXweYv9fn", @@ -1670,6 +1681,7 @@ "NodeID-DUmZowZh6nxKskHUybupqNAhnXVA5yQ1r", "NodeID-DVh35F3R11HAAxzeSTbk3eR9w2BzPrJQt", "NodeID-DY2Tk5ZqUir1NpSiTwXVGdETCGGEV8wHe", + "NodeID-DYCS7WSBWdmMx8ioQ4Lq6gfnPtpKmKVB6", "NodeID-DaKj4jkyyCN4B5zVW65krECqpjxYGUFzX", "NodeID-Dbf2zdJeUXfi3bFzmjhJTSgyME2o8iEaY", "NodeID-DcCkk2wqS6L9XpNX41DVN5RZnwgixCYqE", @@ -1681,7 +1693,6 @@ "NodeID-DeT8Fw4Tp875GUQNxfcfKoBSPjKpGi6eR", "NodeID-DhNYzUwYHPF24Wfz9MmmVyqLBUF6tkEpb", "NodeID-DhuG2YhqQy26zabyLqTqNr85T9XscsWpY", - "NodeID-Dk754EMv2Tm1SP276G6sWuJgt1nWSNxXv", "NodeID-Do5ZUHCK8DHm194KGqdcwFc5wWE4fCQ6s", "NodeID-DoEC8uw9qRNi33EiYrPoK6Vu9pnsH2rnW", "NodeID-DoTTJmp8cmERizJdYQGFsPVFgZPJxfcis", @@ -1878,6 +1889,7 @@ "NodeID-G8yv8mWQy8FLdFfAhJ4v294T5Z2DWDVEH", "NodeID-G9aa4VXB19wnUzrmVq2SheaxnKEieUW3S", "NodeID-G9ucCcZoHdXC6mrVpKVqKzHsMrnoVZLU8", + "NodeID-GAEZpCd2Lg5RSrPtQhGvxw6Kid5tAL6bw", "NodeID-GBvezLieTFYRqHsd8QzWqH1JUhuwD21mJ", "NodeID-GCL85wyq71aw2FMRTct2PJ2F4qGQL7WH8", "NodeID-GD3XH39S9feuK74XEh8AhhNEapSt2hqHo", @@ -1945,6 +1957,7 @@ "NodeID-GwfPzhzby4Ur8mgdqPDjR3jSTevtmfmY", "NodeID-Gx4oY9nZmAzJrHUfobrmuK9LrJhwejykC", "NodeID-GxUaibkyR88sErviW2WK3ukDJsT3DFpoU", + "NodeID-GzSFF2tfNMc7YdJzGeNeNxfSWjDvENJUt", "NodeID-GzhNocnYWSCziBTP5Jj4xAKn29xDKW9Yr", "NodeID-H1R3mBHFDeBoQzVYyHzX6RGnVV4nMTrWZ", "NodeID-H1YSzbspeyANTzErprmBQgV2Crq5hXSW8", From ed549e3165d159ec170c26a7fb8636bceb0b9fb1 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 14:48:21 -0400 Subject: [PATCH 74/85] Add regression test --- network/ip_tracker_test.go | 45 ++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/network/ip_tracker_test.go b/network/ip_tracker_test.go index 233fd7f20c3a..be9ea59a51ee 100644 --- a/network/ip_tracker_test.go +++ b/network/ip_tracker_test.go @@ -829,19 +829,40 @@ func TestIPTracker_BloomFiltersEverything(t *testing.T) { require.NoError(tracker.ResetBloom()) } -func TestIPTracker_BloomGrowsWithValidatorSet(t *testing.T) { - require := require.New(t) - - tracker := newTestIPTracker(t) - initialMaxBloomCount := tracker.maxBloomCount - for i := 0; i < 2048; i++ { - tracker.OnValidatorAdded(ids.GenerateTestNodeID(), nil, ids.Empty, 0) +func TestIPTracker_BloomGrows(t *testing.T) { + tests := []struct { + name string + add func(tracker *ipTracker) + }{ + { + name: "Add Validator", + add: func(tracker *ipTracker) { + tracker.OnValidatorAdded(ids.GenerateTestNodeID(), nil, ids.Empty, 0) + }, + }, + { + name: "Manually Track", + add: func(tracker *ipTracker) { + tracker.ManuallyTrack(ids.GenerateTestNodeID()) + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + tracker := newTestIPTracker(t) + initialMaxBloomCount := tracker.maxBloomCount + for i := 0; i < 2048; i++ { + test.add(tracker) + } + requireMetricsConsistent(t, tracker) + + require.NoError(tracker.ResetBloom()) + require.Greater(tracker.maxBloomCount, initialMaxBloomCount) + requireMetricsConsistent(t, tracker) + }) } - requireMetricsConsistent(t, tracker) - - require.NoError(tracker.ResetBloom()) - require.Greater(tracker.maxBloomCount, initialMaxBloomCount) - requireMetricsConsistent(t, tracker) } func TestIPTracker_BloomResetsDynamically(t *testing.T) { From 2802c19ad69b66074c3336cdf0e4e6001b413233 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 15:34:10 -0400 Subject: [PATCH 75/85] Remove dead code --- snow/engine/common/tracker/peers.go | 43 +++--------------------- snow/engine/common/tracker/peers_test.go | 13 ------- 2 files changed, 4 insertions(+), 52 deletions(-) diff --git a/snow/engine/common/tracker/peers.go b/snow/engine/common/tracker/peers.go index fdf070613d83..1e76d42f4268 100644 --- a/snow/engine/common/tracker/peers.go +++ b/snow/engine/common/tracker/peers.go @@ -31,15 +31,9 @@ type Peers interface { ConnectedWeight() uint64 // ConnectedPercent returns the currently connected stake percentage [0, 1] ConnectedPercent() float64 - // TotalWeight returns the total validator weight - TotalWeight() uint64 // SampleValidator returns a randomly selected connected validator. If there // are no currently connected validators then it will return false. SampleValidator() (ids.NodeID, bool) - // PreferredPeers returns the currently connected validators. If there are - // no currently connected validators then it will return the currently - // connected peers. - PreferredPeers() set.Set[ids.NodeID] } type lockedPeers struct { @@ -104,13 +98,6 @@ func (p *lockedPeers) ConnectedPercent() float64 { return p.peers.ConnectedPercent() } -func (p *lockedPeers) TotalWeight() uint64 { - p.lock.RLock() - defer p.lock.RUnlock() - - return p.peers.TotalWeight() -} - func (p *lockedPeers) SampleValidator() (ids.NodeID, bool) { p.lock.RLock() defer p.lock.RUnlock() @@ -118,13 +105,6 @@ func (p *lockedPeers) SampleValidator() (ids.NodeID, bool) { return p.peers.SampleValidator() } -func (p *lockedPeers) PreferredPeers() set.Set[ids.NodeID] { - p.lock.RLock() - defer p.lock.RUnlock() - - return p.peers.PreferredPeers() -} - type meteredPeers struct { Peers @@ -169,20 +149,21 @@ func NewMeteredPeers(namespace string, reg prometheus.Registerer) (Peers, error) func (p *meteredPeers) OnValidatorAdded(nodeID ids.NodeID, pk *bls.PublicKey, txID ids.ID, weight uint64) { p.Peers.OnValidatorAdded(nodeID, pk, txID, weight) p.numValidators.Inc() - p.totalWeight.Set(float64(p.Peers.TotalWeight())) + p.totalWeight.Add(float64(weight)) p.percentConnected.Set(p.Peers.ConnectedPercent()) } func (p *meteredPeers) OnValidatorRemoved(nodeID ids.NodeID, weight uint64) { p.Peers.OnValidatorRemoved(nodeID, weight) p.numValidators.Dec() - p.totalWeight.Set(float64(p.Peers.TotalWeight())) + p.totalWeight.Sub(float64(weight)) p.percentConnected.Set(p.Peers.ConnectedPercent()) } func (p *meteredPeers) OnValidatorWeightChanged(nodeID ids.NodeID, oldWeight, newWeight uint64) { p.Peers.OnValidatorWeightChanged(nodeID, oldWeight, newWeight) - p.totalWeight.Set(float64(p.Peers.TotalWeight())) + p.totalWeight.Sub(float64(oldWeight)) + p.totalWeight.Add(float64(newWeight)) p.percentConnected.Set(p.Peers.ConnectedPercent()) } @@ -269,22 +250,6 @@ func (p *peerData) ConnectedPercent() float64 { return float64(p.connectedWeight) / float64(p.totalWeight) } -func (p *peerData) TotalWeight() uint64 { - return p.totalWeight -} - func (p *peerData) SampleValidator() (ids.NodeID, bool) { return p.connectedValidators.Peek() } - -func (p *peerData) PreferredPeers() set.Set[ids.NodeID] { - if p.connectedValidators.Len() == 0 { - connectedPeers := set.NewSet[ids.NodeID](p.connectedPeers.Len()) - connectedPeers.Union(p.connectedPeers) - return connectedPeers - } - - connectedValidators := set.NewSet[ids.NodeID](p.connectedValidators.Len()) - connectedValidators.Union(p.connectedValidators) - return connectedValidators -} diff --git a/snow/engine/common/tracker/peers_test.go b/snow/engine/common/tracker/peers_test.go index b627b79a16ed..1ed2daf6575b 100644 --- a/snow/engine/common/tracker/peers_test.go +++ b/snow/engine/common/tracker/peers_test.go @@ -20,36 +20,23 @@ func TestPeers(t *testing.T) { p := NewPeers() - require.Zero(p.TotalWeight()) require.Zero(p.ConnectedWeight()) - require.Empty(p.PreferredPeers()) p.OnValidatorAdded(nodeID, nil, ids.Empty, 5) require.Zero(p.ConnectedWeight()) - require.Equal(uint64(5), p.TotalWeight()) - require.Empty(p.PreferredPeers()) require.NoError(p.Connected(context.Background(), nodeID, version.CurrentApp)) require.Equal(uint64(5), p.ConnectedWeight()) - require.Contains(p.PreferredPeers(), nodeID) p.OnValidatorWeightChanged(nodeID, 5, 10) require.Equal(uint64(10), p.ConnectedWeight()) - require.Equal(uint64(10), p.TotalWeight()) - require.Contains(p.PreferredPeers(), nodeID) p.OnValidatorRemoved(nodeID, 10) require.Zero(p.ConnectedWeight()) - require.Zero(p.TotalWeight()) - require.Contains(p.PreferredPeers(), nodeID) p.OnValidatorAdded(nodeID, nil, ids.Empty, 5) require.Equal(uint64(5), p.ConnectedWeight()) - require.Equal(uint64(5), p.TotalWeight()) - require.Contains(p.PreferredPeers(), nodeID) require.NoError(p.Disconnected(context.Background(), nodeID)) require.Zero(p.ConnectedWeight()) - require.Equal(uint64(5), p.TotalWeight()) - require.Empty(p.PreferredPeers()) } From bb1748f63355b74ac2eebd8af378461a737010e1 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 15:58:52 -0400 Subject: [PATCH 76/85] fix tests --- snow/engine/snowman/bootstrap/bootstrapper.go | 41 ++++-- .../snowman/bootstrap/bootstrapper_test.go | 9 +- snow/engine/snowman/bootstrap/config.go | 1 + snow/networking/handler/handler_test.go | 126 ++++++++++++++---- snow/networking/handler/health_test.go | 18 ++- snow/networking/router/chain_router_test.go | 117 ++++++++++++---- snow/networking/sender/sender_test.go | 90 +++++++++---- 7 files changed, 302 insertions(+), 100 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 0cdc4a92a55c..5a6fa92b7259 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -40,6 +40,8 @@ const ( // maxOutstandingBroadcastRequests is the maximum number of requests to have // outstanding when broadcasting. maxOutstandingBroadcastRequests = 50 + + epsilon = 1e-6 // small amount to add to time to avoid division by 0 ) var ( @@ -95,7 +97,8 @@ type Bootstrapper struct { startTime time.Time // tracks which validators were asked for which containers in which requests - outstandingRequests *bimap.BiMap[common.Request, ids.ID] + outstandingRequests *bimap.BiMap[common.Request, ids.ID] + outstandingRequestTimes map[common.Request]time.Time // number of state transitions executed executedStateTransitions uint64 @@ -127,7 +130,8 @@ func New(config Config, onFinished func(ctx context.Context, lastReqID uint32) e minority: bootstrapper.Noop, majority: bootstrapper.Noop, - outstandingRequests: bimap.New[common.Request, ids.ID](), + outstandingRequests: bimap.New[common.Request, ids.ID](), + outstandingRequestTimes: make(map[common.Request]time.Time), executedStateTransitions: math.MaxInt, onFinished: onFinished, @@ -415,13 +419,12 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { b.requestID++ - b.outstandingRequests.Put( - common.Request{ - NodeID: nodeID, - RequestID: b.requestID, - }, - blkID, - ) + request := common.Request{ + NodeID: nodeID, + RequestID: b.requestID, + } + b.outstandingRequests.Put(request, blkID) + b.outstandingRequestTimes[request] = time.Now() b.Config.Sender.SendGetAncestors(ctx, nodeID, b.requestID, blkID) // request block and ancestors return nil } @@ -430,10 +433,11 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { // response to a GetAncestors message to [nodeID] with request ID [requestID] func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { // Make sure this is in response to a request we made - wantedBlkID, ok := b.outstandingRequests.DeleteKey(common.Request{ + request := common.Request{ NodeID: nodeID, RequestID: requestID, - }) + } + wantedBlkID, ok := b.outstandingRequests.DeleteKey(request) if !ok { // this message isn't in response to a request we made b.Ctx.Log.Debug("received unexpected Ancestors", zap.Stringer("nodeID", nodeID), @@ -441,6 +445,8 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request ) return nil } + requestTime := b.outstandingRequestTimes[request] + delete(b.outstandingRequestTimes, request) lenBlks := len(blks) if lenBlks == 0 { @@ -503,7 +509,11 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request blockSet[block.ID()] = block } - b.PeerTracker.RegisterResponse(nodeID, float64(numBytes)) + var ( + requestLatency = time.Since(requestTime).Seconds() + epsilon + bandwidth = float64(numBytes) / requestLatency + ) + b.PeerTracker.RegisterResponse(nodeID, bandwidth) if err := b.process(ctx, requestedBlock, blockSet); err != nil { return err @@ -513,10 +523,11 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request } func (b *Bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - blkID, ok := b.outstandingRequests.DeleteKey(common.Request{ + request := common.Request{ NodeID: nodeID, RequestID: requestID, - }) + } + blkID, ok := b.outstandingRequests.DeleteKey(request) if !ok { b.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", zap.Stringer("nodeID", nodeID), @@ -524,6 +535,7 @@ func (b *Bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID ) return nil } + delete(b.outstandingRequestTimes, request) // This node timed out their request. b.PeerTracker.RegisterFailure(nodeID) @@ -718,6 +730,7 @@ func (b *Bootstrapper) restartBootstrapping(ctx context.Context) error { b.Ctx.Log.Debug("Checking for new frontiers") b.restarted = true b.outstandingRequests = bimap.New[common.Request, ids.ID]() + b.outstandingRequestTimes = make(map[common.Request]time.Time) return b.startBootstrapping(ctx) } diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index 00d258676985..a196de40d8a9 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -379,9 +379,9 @@ func TestBootstrapperEmptyResponse(t *testing.T) { require.NoError(bs.startSyncing(context.Background(), blocksToIDs(blks[1:2]))) require.Equal(requestedNodeID, peerID) - // add another 2 validators to the fetch set to test behavior on empty - // response - bs.fetchFrom.Add(ids.GenerateTestNodeID(), ids.GenerateTestNodeID()) + // Add another 2 peers to the fetch set to test behavior on empty response. + bs.PeerTracker.Connected(ids.GenerateTestNodeID(), version.CurrentApp) + bs.PeerTracker.Connected(ids.GenerateTestNodeID(), version.CurrentApp) require.NoError(bs.Ancestors(context.Background(), requestedNodeID, requestID, nil)) // respond with empty require.NotEqual(requestedNodeID, peerID) @@ -389,9 +389,6 @@ func TestBootstrapperEmptyResponse(t *testing.T) { require.NoError(bs.Ancestors(context.Background(), requestedNodeID, requestID, blocksToBytes(blks[1:2]))) require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) requireStatusIs(require, blks, choices.Accepted) - - // check that peerID was removed from the fetch set - require.NotContains(bs.fetchFrom, peerID) } // There are multiple needed blocks and Ancestors returns all at once diff --git a/snow/engine/snowman/bootstrap/config.go b/snow/engine/snowman/bootstrap/config.go index d80b92c97029..bcf57f02e832 100644 --- a/snow/engine/snowman/bootstrap/config.go +++ b/snow/engine/snowman/bootstrap/config.go @@ -25,6 +25,7 @@ type Config struct { BootstrapTracker common.BootstrapTracker Timer common.Timer + // PeerTracker manages the set of nodes that we fetch the next block from. PeerTracker *p2p.PeerTracker // This node will only consider the first [AncestorsMaxContainersReceived] diff --git a/snow/networking/handler/handler_test.go b/snow/networking/handler/handler_test.go index 71809bd953f6..e8ab5f85ebb1 100644 --- a/snow/networking/handler/handler_test.go +++ b/snow/networking/handler/handler_test.go @@ -16,17 +16,20 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/networking/tracker" "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/subnets" + "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math/meter" "github.com/ava-labs/avalanchego/utils/resource" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/version" + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" commontracker "github.com/ava-labs/avalanchego/snow/engine/common/tracker" ) @@ -53,6 +56,16 @@ func TestHandlerDropsTimedOutMessages(t *testing.T) { time.Second, ) require.NoError(err) + + peerTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handlerIntf, err := New( ctx, vdrs, @@ -63,6 +76,7 @@ func TestHandlerDropsTimedOutMessages(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + peerTracker, ) require.NoError(err) handler := handlerIntf.(*handler) @@ -90,7 +104,7 @@ func TestHandlerDropsTimedOutMessages(t *testing.T) { }, }) ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, // assumed bootstrap is ongoing }) @@ -102,7 +116,7 @@ func TestHandlerDropsTimedOutMessages(t *testing.T) { chainID := ids.ID{} msg := Message{ InboundMessage: message.InboundGetAcceptedFrontier(chainID, reqID, 0*time.Second, nodeID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } handler.Push(context.Background(), msg) @@ -112,7 +126,7 @@ func TestHandlerDropsTimedOutMessages(t *testing.T) { reqID++ msg = Message{ InboundMessage: message.InboundGetAccepted(chainID, reqID, 1*time.Second, nil, nodeID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } handler.Push(context.Background(), msg) @@ -148,6 +162,16 @@ func TestHandlerClosesOnError(t *testing.T) { time.Second, ) require.NoError(err) + + peerTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handlerIntf, err := New( ctx, vdrs, @@ -158,6 +182,7 @@ func TestHandlerClosesOnError(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + peerTracker, ) require.NoError(err) handler := handlerIntf.(*handler) @@ -196,7 +221,7 @@ func TestHandlerClosesOnError(t *testing.T) { // assume bootstrapping is ongoing so that InboundGetAcceptedFrontier // should normally be handled ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, }) @@ -211,7 +236,7 @@ func TestHandlerClosesOnError(t *testing.T) { deadline := time.Nanosecond msg := Message{ InboundMessage: message.InboundGetAcceptedFrontier(ids.ID{}, reqID, deadline, nodeID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } handler.Push(context.Background(), msg) @@ -239,6 +264,16 @@ func TestHandlerDropsGossipDuringBootstrapping(t *testing.T) { time.Second, ) require.NoError(err) + + peerTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handlerIntf, err := New( ctx, vdrs, @@ -249,6 +284,7 @@ func TestHandlerDropsGossipDuringBootstrapping(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + peerTracker, ) require.NoError(err) handler := handlerIntf.(*handler) @@ -274,7 +310,7 @@ func TestHandlerDropsGossipDuringBootstrapping(t *testing.T) { }, }) ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, // assumed bootstrap is ongoing }) @@ -289,7 +325,7 @@ func TestHandlerDropsGossipDuringBootstrapping(t *testing.T) { reqID := uint32(1) inInboundMessage := Message{ InboundMessage: message.InternalGetFailed(nodeID, chainID, reqID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } handler.Push(context.Background(), inInboundMessage) @@ -318,6 +354,16 @@ func TestHandlerDispatchInternal(t *testing.T) { time.Second, ) require.NoError(err) + + peerTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handler, err := New( ctx, vdrs, @@ -328,6 +374,7 @@ func TestHandlerDispatchInternal(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + peerTracker, ) require.NoError(err) @@ -358,7 +405,7 @@ func TestHandlerDispatchInternal(t *testing.T) { }) ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, // assumed bootstrap is done }) @@ -393,6 +440,15 @@ func TestHandlerSubnetConnector(t *testing.T) { nodeID := ids.GenerateTestNodeID() subnetID := ids.GenerateTestID() + peerTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handler, err := New( ctx, vdrs, @@ -403,6 +459,7 @@ func TestHandlerSubnetConnector(t *testing.T) { connector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + peerTracker, ) require.NoError(err) @@ -426,7 +483,7 @@ func TestHandlerSubnetConnector(t *testing.T) { }, }) ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, // assumed bootstrap is done }) @@ -448,7 +505,7 @@ func TestHandlerSubnetConnector(t *testing.T) { subnetInboundMessage := Message{ InboundMessage: message.InternalConnectedSubnet(nodeID, subnetID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } handler.Push(context.Background(), subnetInboundMessage) } @@ -457,8 +514,8 @@ func TestHandlerSubnetConnector(t *testing.T) { func TestDynamicEngineTypeDispatch(t *testing.T) { tests := []struct { name string - currentEngineType p2p.EngineType - requestedEngineType p2p.EngineType + currentEngineType p2ppb.EngineType + requestedEngineType p2ppb.EngineType setup func( h Handler, b common.BootstrapableEngine, @@ -467,8 +524,8 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { }{ { name: "current - avalanche, requested - unspecified", - currentEngineType: p2p.EngineType_ENGINE_TYPE_AVALANCHE, - requestedEngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + currentEngineType: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, + requestedEngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, setup: func(h Handler, b common.BootstrapableEngine, e common.Engine) { h.SetEngineManager(&EngineManager{ Avalanche: &Engine{ @@ -482,8 +539,8 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { }, { name: "current - avalanche, requested - avalanche", - currentEngineType: p2p.EngineType_ENGINE_TYPE_AVALANCHE, - requestedEngineType: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + currentEngineType: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, + requestedEngineType: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, setup: func(h Handler, b common.BootstrapableEngine, e common.Engine) { h.SetEngineManager(&EngineManager{ Avalanche: &Engine{ @@ -497,8 +554,8 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { }, { name: "current - snowman, requested - unspecified", - currentEngineType: p2p.EngineType_ENGINE_TYPE_SNOWMAN, - requestedEngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + currentEngineType: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, + requestedEngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, setup: func(h Handler, b common.BootstrapableEngine, e common.Engine) { h.SetEngineManager(&EngineManager{ Avalanche: nil, @@ -512,8 +569,8 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { }, { name: "current - snowman, requested - avalanche", - currentEngineType: p2p.EngineType_ENGINE_TYPE_SNOWMAN, - requestedEngineType: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + currentEngineType: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, + requestedEngineType: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, setup: func(h Handler, b common.BootstrapableEngine, e common.Engine) { h.SetEngineManager(&EngineManager{ Avalanche: &Engine{ @@ -531,8 +588,8 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { }, { name: "current - snowman, requested - snowman", - currentEngineType: p2p.EngineType_ENGINE_TYPE_SNOWMAN, - requestedEngineType: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + currentEngineType: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, + requestedEngineType: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, setup: func(h Handler, b common.BootstrapableEngine, e common.Engine) { h.SetEngineManager(&EngineManager{ Avalanche: nil, @@ -563,6 +620,16 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { time.Second, ) require.NoError(err) + + peerTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handler, err := New( ctx, vdrs, @@ -573,6 +640,7 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ids.EmptyNodeID, subnets.Config{}), commontracker.NewPeers(), + peerTracker, ) require.NoError(err) @@ -635,6 +703,15 @@ func TestHandlerStartError(t *testing.T) { ) require.NoError(err) + peerTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handler, err := New( ctx, validators.NewManager(), @@ -645,6 +722,7 @@ func TestHandlerStartError(t *testing.T) { nil, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + peerTracker, ) require.NoError(err) @@ -652,7 +730,7 @@ func TestHandlerStartError(t *testing.T) { // handler to shutdown. handler.SetEngineManager(&EngineManager{}) ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Initializing, }) handler.Start(context.Background(), false) diff --git a/snow/networking/handler/health_test.go b/snow/networking/handler/health_test.go index adeb3430f277..256613827cf6 100644 --- a/snow/networking/handler/health_test.go +++ b/snow/networking/handler/health_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/consensus/snowball" "github.com/ava-labs/avalanchego/snow/engine/common" @@ -20,10 +20,13 @@ import ( "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/subnets" + "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math/meter" "github.com/ava-labs/avalanchego/utils/resource" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/version" + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" commontracker "github.com/ava-labs/avalanchego/snow/engine/common/tracker" ) @@ -69,6 +72,16 @@ func TestHealthCheckSubnet(t *testing.T) { ConsensusParameters: test.consensusParams, }, ) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + handlerIntf, err := New( ctx, vdrs, @@ -79,6 +92,7 @@ func TestHealthCheckSubnet(t *testing.T) { validators.UnhandledSubnetConnector, sb, peerTracker, + p2pTracker, ) require.NoError(err) @@ -103,7 +117,7 @@ func TestHealthCheckSubnet(t *testing.T) { }) ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, // assumed bootstrap is done }) diff --git a/snow/networking/router/chain_router_test.go b/snow/networking/router/chain_router_test.go index 18a224703edf..c17360f02486 100644 --- a/snow/networking/router/chain_router_test.go +++ b/snow/networking/router/chain_router_test.go @@ -15,7 +15,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/networking/benchlist" @@ -33,11 +33,12 @@ import ( "github.com/ava-labs/avalanchego/utils/timer" "github.com/ava-labs/avalanchego/version" + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" commontracker "github.com/ava-labs/avalanchego/snow/engine/common/tracker" ) const ( - engineType = p2p.EngineType_ENGINE_TYPE_AVALANCHE + engineType = p2ppb.EngineType_ENGINE_TYPE_AVALANCHE testThreadPoolSize = 2 ) @@ -92,6 +93,16 @@ func TestShutdown(t *testing.T) { time.Second, ) require.NoError(err) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( chainCtx, vdrs, @@ -102,6 +113,7 @@ func TestShutdown(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(chainCtx.NodeID, subnets.Config{}), commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -230,6 +242,16 @@ func TestShutdownTimesOut(t *testing.T) { time.Second, ) require.NoError(err) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( ctx, vdrs, @@ -240,6 +262,7 @@ func TestShutdownTimesOut(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -305,7 +328,7 @@ func TestShutdownTimesOut(t *testing.T) { chainID := ids.ID{} msg := handler.Message{ InboundMessage: message.InboundPullQuery(chainID, 1, time.Hour, ids.GenerateTestID(), 0, nodeID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } h.Push(context.Background(), msg) @@ -390,6 +413,15 @@ func TestRouterTimeout(t *testing.T) { ) require.NoError(err) + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( ctx, vdrs, @@ -400,6 +432,7 @@ func TestRouterTimeout(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -465,7 +498,7 @@ func TestRouterTimeout(t *testing.T) { return nil } ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, // assumed bootstrapping is ongoing }) @@ -504,7 +537,7 @@ func TestRouterTimeout(t *testing.T) { ctx.ChainID, requestID, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -523,7 +556,7 @@ func TestRouterTimeout(t *testing.T) { ctx.ChainID, requestID, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -542,7 +575,7 @@ func TestRouterTimeout(t *testing.T) { ctx.ChainID, requestID, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -561,7 +594,7 @@ func TestRouterTimeout(t *testing.T) { ctx.ChainID, requestID, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -579,9 +612,9 @@ func TestRouterTimeout(t *testing.T) { nodeID, ctx.ChainID, requestID, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -600,7 +633,7 @@ func TestRouterTimeout(t *testing.T) { ctx.ChainID, requestID, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -619,7 +652,7 @@ func TestRouterTimeout(t *testing.T) { ctx.ChainID, requestID, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -640,7 +673,7 @@ func TestRouterTimeout(t *testing.T) { common.ErrTimeout.Code, common.ErrTimeout.Message, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -662,7 +695,7 @@ func TestRouterTimeout(t *testing.T) { common.ErrTimeout.Code, common.ErrTimeout.Message, ), - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, ) } @@ -750,7 +783,7 @@ func TestRouterHonorsRequestedEngine(t *testing.T) { ctx.ChainID, requestID, ), - p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, ) msg := message.InboundStateSummaryFrontier( ctx.ChainID, @@ -760,7 +793,7 @@ func TestRouterHonorsRequestedEngine(t *testing.T) { ) h.EXPECT().Push(gomock.Any(), gomock.Any()).Do(func(_ context.Context, msg handler.Message) { - require.Equal(p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, msg.EngineType) + require.Equal(p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, msg.EngineType) }) chainRouter.HandleInbound(context.Background(), msg) } @@ -806,7 +839,7 @@ func TestRouterHonorsRequestedEngine(t *testing.T) { ) h.EXPECT().Push(gomock.Any(), gomock.Any()).Do(func(_ context.Context, msg handler.Message) { - require.Equal(p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, msg.EngineType) + require.Equal(p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, msg.EngineType) }) chainRouter.HandleInbound(context.Background(), msg) } @@ -963,6 +996,16 @@ func TestValidatorOnlyMessageDrops(t *testing.T) { time.Second, ) require.NoError(err) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( ctx, vdrs, @@ -973,6 +1016,7 @@ func TestValidatorOnlyMessageDrops(t *testing.T) { validators.UnhandledSubnetConnector, sb, commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -991,7 +1035,7 @@ func TestValidatorOnlyMessageDrops(t *testing.T) { return nil } ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, // assumed bootstrapping is ongoing }) @@ -1111,15 +1155,15 @@ func TestConnectedSubnet(t *testing.T) { myConnectedMsg := handler.Message{ InboundMessage: message.InternalConnected(myNodeID, version.CurrentApp), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } mySubnetConnectedMsg0 := handler.Message{ InboundMessage: message.InternalConnectedSubnet(myNodeID, subnetID0), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } mySubnetConnectedMsg1 := handler.Message{ InboundMessage: message.InternalConnectedSubnet(myNodeID, subnetID1), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } platformHandler := handler.NewMockHandler(ctrl) @@ -1133,28 +1177,28 @@ func TestConnectedSubnet(t *testing.T) { peerConnectedMsg := handler.Message{ InboundMessage: message.InternalConnected(peerNodeID, version.CurrentApp), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } platformHandler.EXPECT().Push(gomock.Any(), peerConnectedMsg).Times(1) chainRouter.Connected(peerNodeID, version.CurrentApp, constants.PrimaryNetworkID) peerSubnetConnectedMsg0 := handler.Message{ InboundMessage: message.InternalConnectedSubnet(peerNodeID, subnetID0), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } platformHandler.EXPECT().Push(gomock.Any(), peerSubnetConnectedMsg0).Times(1) chainRouter.Connected(peerNodeID, version.CurrentApp, subnetID0) myDisconnectedMsg := handler.Message{ InboundMessage: message.InternalDisconnected(myNodeID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } platformHandler.EXPECT().Push(gomock.Any(), myDisconnectedMsg).Times(1) chainRouter.Benched(constants.PlatformChainID, myNodeID) peerDisconnectedMsg := handler.Message{ InboundMessage: message.InternalDisconnected(peerNodeID), - EngineType: p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + EngineType: p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, } platformHandler.EXPECT().Push(gomock.Any(), peerDisconnectedMsg).Times(1) chainRouter.Benched(constants.PlatformChainID, peerNodeID) @@ -1235,6 +1279,15 @@ func TestValidatorOnlyAllowedNodeMessageDrops(t *testing.T) { ) require.NoError(err) + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( ctx, vdrs, @@ -1245,6 +1298,7 @@ func TestValidatorOnlyAllowedNodeMessageDrops(t *testing.T) { validators.UnhandledSubnetConnector, sb, commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -1564,6 +1618,16 @@ func newChainRouterTest(t *testing.T) (*ChainRouter, *common.EngineTest) { time.Second, ) require.NoError(t, err) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(t, err) + h, err := handler.New( ctx, vdrs, @@ -1574,6 +1638,7 @@ func newChainRouterTest(t *testing.T) (*ChainRouter, *common.EngineTest) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + p2pTracker, ) require.NoError(t, err) @@ -1605,7 +1670,7 @@ func newChainRouterTest(t *testing.T) (*ChainRouter, *common.EngineTest) { }, }) ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.NormalOp, // assumed bootstrapping is done }) diff --git a/snow/networking/sender/sender_test.go b/snow/networking/sender/sender_test.go index f1ef03e4c5c2..44b4a316fec2 100644 --- a/snow/networking/sender/sender_test.go +++ b/snow/networking/sender/sender_test.go @@ -16,7 +16,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/networking/benchlist" @@ -35,6 +35,7 @@ import ( "github.com/ava-labs/avalanchego/utils/timer" "github.com/ava-labs/avalanchego/version" + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" commontracker "github.com/ava-labs/avalanchego/snow/engine/common/tracker" ) @@ -98,7 +99,7 @@ func TestTimeout(t *testing.T) { externalSender, &chainRouter, tm, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, subnets.New(ctx.NodeID, subnets.Config{}), ) require.NoError(err) @@ -111,6 +112,16 @@ func TestTimeout(t *testing.T) { time.Second, ) require.NoError(err) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( ctx2, vdrs, @@ -121,6 +132,7 @@ func TestTimeout(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -150,7 +162,7 @@ func TestTimeout(t *testing.T) { }, }) ctx2.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, // assumed bootstrap is ongoing }) @@ -364,7 +376,7 @@ func TestReliableMessages(t *testing.T) { externalSender, &chainRouter, tm, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, subnets.New(ctx.NodeID, subnets.Config{}), ) require.NoError(err) @@ -377,6 +389,16 @@ func TestReliableMessages(t *testing.T) { time.Second, ) require.NoError(err) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( ctx2, vdrs, @@ -387,6 +409,7 @@ func TestReliableMessages(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -426,7 +449,7 @@ func TestReliableMessages(t *testing.T) { }, }) ctx2.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, // assumed bootstrap is ongoing }) @@ -510,7 +533,7 @@ func TestReliableMessagesToMyself(t *testing.T) { externalSender, &chainRouter, tm, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, subnets.New(ctx.NodeID, subnets.Config{}), ) require.NoError(err) @@ -523,6 +546,16 @@ func TestReliableMessagesToMyself(t *testing.T) { time.Second, ) require.NoError(err) + + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + h, err := handler.New( ctx2, vdrs, @@ -533,6 +566,7 @@ func TestReliableMessagesToMyself(t *testing.T) { validators.UnhandledSubnetConnector, subnets.New(ctx.NodeID, subnets.Config{}), commontracker.NewPeers(), + p2pTracker, ) require.NoError(err) @@ -571,7 +605,7 @@ func TestReliableMessagesToMyself(t *testing.T) { }, }) ctx2.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, State: snow.Bootstrapping, // assumed bootstrap is ongoing }) @@ -630,8 +664,8 @@ func TestSender_Bootstrap_Requests(t *testing.T) { ) }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.GetStateSummaryFrontier{}, msg.Message()) - innerMsg := msg.Message().(*p2p.GetStateSummaryFrontier) + require.IsType(&p2ppb.GetStateSummaryFrontier{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.GetStateSummaryFrontier) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) require.Equal(uint64(deadline), innerMsg.Deadline) @@ -673,8 +707,8 @@ func TestSender_Bootstrap_Requests(t *testing.T) { ) }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.GetAcceptedStateSummary{}, msg.Message()) - innerMsg := msg.Message().(*p2p.GetAcceptedStateSummary) + require.IsType(&p2ppb.GetAcceptedStateSummary{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.GetAcceptedStateSummary) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) require.Equal(uint64(deadline), innerMsg.Deadline) @@ -714,8 +748,8 @@ func TestSender_Bootstrap_Requests(t *testing.T) { ) }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.GetAcceptedFrontier{}, msg.Message()) - innerMsg := msg.Message().(*p2p.GetAcceptedFrontier) + require.IsType(&p2ppb.GetAcceptedFrontier{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.GetAcceptedFrontier) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) require.Equal(uint64(deadline), innerMsg.Deadline) @@ -753,8 +787,8 @@ func TestSender_Bootstrap_Requests(t *testing.T) { ) }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.GetAccepted{}, msg.Message()) - innerMsg := msg.Message().(*p2p.GetAccepted) + require.IsType(&p2ppb.GetAccepted{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.GetAccepted) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) require.Equal(uint64(deadline), innerMsg.Deadline) @@ -810,7 +844,7 @@ func TestSender_Bootstrap_Requests(t *testing.T) { externalSender, router, timeoutManager, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, subnets.New(ctx.NodeID, subnets.Config{}), ) require.NoError(err) @@ -829,7 +863,7 @@ func TestSender_Bootstrap_Requests(t *testing.T) { requestID, // Request ID tt.expectedResponseOp, // Operation expectedFailedMsg, // Failure Message - p2p.EngineType_ENGINE_TYPE_UNSPECIFIED, + p2ppb.EngineType_ENGINE_TYPE_UNSPECIFIED, ) } @@ -890,8 +924,8 @@ func TestSender_Bootstrap_Responses(t *testing.T) { ).Return(nil, nil) // Don't care about the message }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.StateSummaryFrontier{}, msg.Message()) - innerMsg := msg.Message().(*p2p.StateSummaryFrontier) + require.IsType(&p2ppb.StateSummaryFrontier{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.StateSummaryFrontier) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) require.Equal(summary, innerMsg.Summary) @@ -920,8 +954,8 @@ func TestSender_Bootstrap_Responses(t *testing.T) { ).Return(nil, nil) // Don't care about the message }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.AcceptedStateSummary{}, msg.Message()) - innerMsg := msg.Message().(*p2p.AcceptedStateSummary) + require.IsType(&p2ppb.AcceptedStateSummary{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.AcceptedStateSummary) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) for i, summaryID := range summaryIDs { @@ -952,8 +986,8 @@ func TestSender_Bootstrap_Responses(t *testing.T) { ).Return(nil, nil) // Don't care about the message }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.AcceptedFrontier{}, msg.Message()) - innerMsg := msg.Message().(*p2p.AcceptedFrontier) + require.IsType(&p2ppb.AcceptedFrontier{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.AcceptedFrontier) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) require.Equal(summaryIDs[0][:], innerMsg.ContainerId) @@ -982,8 +1016,8 @@ func TestSender_Bootstrap_Responses(t *testing.T) { ).Return(nil, nil) // Don't care about the message }, assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { - require.IsType(&p2p.Accepted{}, msg.Message()) - innerMsg := msg.Message().(*p2p.Accepted) + require.IsType(&p2ppb.Accepted{}, msg.Message()) + innerMsg := msg.Message().(*p2ppb.Accepted) require.Equal(ctx.ChainID[:], innerMsg.ChainId) require.Equal(requestID, innerMsg.RequestId) for i, summaryID := range summaryIDs { @@ -1029,7 +1063,7 @@ func TestSender_Bootstrap_Responses(t *testing.T) { externalSender, router, timeoutManager, - p2p.EngineType_ENGINE_TYPE_SNOWMAN, + p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, subnets.New(ctx.NodeID, subnets.Config{}), ) require.NoError(err) @@ -1071,7 +1105,7 @@ func TestSender_Single_Request(t *testing.T) { deadline = time.Second requestID = uint32(1337) containerID = ids.GenerateTestID() - engineType = p2p.EngineType_ENGINE_TYPE_SNOWMAN + engineType = p2ppb.EngineType_ENGINE_TYPE_SNOWMAN ) snowCtx := snowtest.Context(t, snowtest.PChainID) ctx := snowtest.ConsensusContext(snowCtx) @@ -1084,7 +1118,7 @@ func TestSender_Single_Request(t *testing.T) { setMsgCreatorExpect func(msgCreator *message.MockOutboundMsgBuilder) setExternalSenderExpect func(externalSender *MockExternalSender, sentTo set.Set[ids.NodeID]) sendF func(require *require.Assertions, sender common.Sender, nodeID ids.NodeID) - expectedEngineType p2p.EngineType + expectedEngineType p2ppb.EngineType } tests := []test{ From ad60d8ad5af2b00dea9b1cf312dd1d8872db47ad Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 16:02:17 -0400 Subject: [PATCH 77/85] Apply suggestions from code review Co-authored-by: Joshua Kim <20001595+joshua-kim@users.noreply.github.com> Signed-off-by: Stephen Buttolph --- genesis/checkpoints.go | 2 +- genesis/generate/checkpoints/main.go | 3 +-- genesis/generate/validators/main.go | 3 +-- genesis/validators.go | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/genesis/checkpoints.go b/genesis/checkpoints.go index 0a9ff78d1980..9d72b36b55d8 100644 --- a/genesis/checkpoints.go +++ b/genesis/checkpoints.go @@ -23,7 +23,7 @@ var ( func init() { if err := json.Unmarshal(checkpointsPerNetworkJSON, &checkpointsPerNetwork); err != nil { - panic(fmt.Sprintf("failed to decode checkpoints.json %v", err)) + panic(fmt.Sprintf("failed to decode checkpoints.json: %v", err)) } } diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go index b3e79cf4d660..544bf7918f2e 100644 --- a/genesis/generate/checkpoints/main.go +++ b/genesis/generate/checkpoints/main.go @@ -81,8 +81,7 @@ func main() { log.Fatalf("failed to marshal checkpoints: %v", err) } - err = perms.WriteFile("checkpoints.json", checkpointsJSON, perms.ReadWrite) - if err != nil { + if err := perms.WriteFile("checkpoints.json", checkpointsJSON, perms.ReadWrite; err != nil { log.Fatalf("failed to write checkpoints: %v", err) } } diff --git a/genesis/generate/validators/main.go b/genesis/generate/validators/main.go index 6a7adde12065..92312435ea63 100644 --- a/genesis/generate/validators/main.go +++ b/genesis/generate/validators/main.go @@ -39,8 +39,7 @@ func main() { log.Fatalf("failed to marshal validators: %v", err) } - err = perms.WriteFile("validators.json", validatorsJSON, perms.ReadWrite) - if err != nil { + if err := perms.WriteFile("validators.json", validatorsJSON, perms.ReadWrite); err != nil { log.Fatalf("failed to write validators: %v", err) } } diff --git a/genesis/validators.go b/genesis/validators.go index adb876cf6fc0..4e7d9ecb6550 100644 --- a/genesis/validators.go +++ b/genesis/validators.go @@ -23,7 +23,7 @@ var ( func init() { if err := json.Unmarshal(validatorsPerNetworkJSON, &validatorsPerNetwork); err != nil { - panic(fmt.Sprintf("failed to decode validators.json %v", err)) + panic(fmt.Sprintf("failed to decode validators.json: %v", err)) } } From bcf1c26fbf85efcce5bc274dee7f9f69f79d8d51 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 16:03:38 -0400 Subject: [PATCH 78/85] nits --- genesis/generate/checkpoints/main.go | 4 ++-- genesis/generate/validators/main.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/genesis/generate/checkpoints/main.go b/genesis/generate/checkpoints/main.go index 544bf7918f2e..05bb0b4c7fcf 100644 --- a/genesis/generate/checkpoints/main.go +++ b/genesis/generate/checkpoints/main.go @@ -76,12 +76,12 @@ func main() { mainnetCChainID: mainnetCChainCheckpoints, }, } - checkpointsJSON, err := json.MarshalIndent(checkpoints, "", " ") + checkpointsJSON, err := json.MarshalIndent(checkpoints, "", "\t") if err != nil { log.Fatalf("failed to marshal checkpoints: %v", err) } - if err := perms.WriteFile("checkpoints.json", checkpointsJSON, perms.ReadWrite; err != nil { + if err := perms.WriteFile("checkpoints.json", checkpointsJSON, perms.ReadWrite); err != nil { log.Fatalf("failed to write checkpoints: %v", err) } } diff --git a/genesis/generate/validators/main.go b/genesis/generate/validators/main.go index 92312435ea63..5f1a8565c5fe 100644 --- a/genesis/generate/validators/main.go +++ b/genesis/generate/validators/main.go @@ -34,7 +34,7 @@ func main() { constants.FujiName: fujiValidators, constants.MainnetName: mainnetValidators, } - validatorsJSON, err := json.MarshalIndent(validators, "", " ") + validatorsJSON, err := json.MarshalIndent(validators, "", "\t") if err != nil { log.Fatalf("failed to marshal validators: %v", err) } From 754fd1c80233726da3d19151df60b0ebea86a850 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 16:04:53 -0400 Subject: [PATCH 79/85] regen --- genesis/checkpoints.json | 1220 ++++----- genesis/validators.json | 5056 +++++++++++++++++++------------------- 2 files changed, 3137 insertions(+), 3139 deletions(-) diff --git a/genesis/checkpoints.json b/genesis/checkpoints.json index 298c488c3483..3481746c7a92 100644 --- a/genesis/checkpoints.json +++ b/genesis/checkpoints.json @@ -1,612 +1,612 @@ { - "fuji": { - "11111111111111111111111111111111LpoYY": [ - "223opwBisPqPFJYMGbHvmvNaBb3EVjHqDbaCD2k4DWmBErychP", - "22QytoWHKDyqoSHzEg2jcnpy2K1ocGhfLVvV5eUL8M5WGQyDUo", - "22eMTpCKswsDmHzxC3rq1foxecqX27DveEJD1octSqzu8dLGSH", - "23xcXTT2TBGqos4qsNmfhH9UdvEo6SSgG3K8tHzZSHgqRpuqF1", - "26mZvbGt9PVowp86TZkX5y8AxX66qgcQg48f8m6PGaGyyiMRxt", - "27jmo6kXpEHD4QsPNiXDZvN2mauaMjQdPdfQ6yqjZZTgd5fopi", - "27sYpucSURKu6AbWSKNLz37kjhXVzdkAiWmWyxBef1MaLNXyKr", - "27uCd85pvFdjGsnP5H3WKei9W7DBJ1exsG8ySKzLZ24ffryds4", - "292ig1WtzAxvwfdC5RoqvMHVcyQk9jwJeKPUXmnJMNUBmubjTW", - "29oddG7fursmoQNLHANS6h2WNftczJivnx9srxPLhqyv8yUG89", - "2AAxNFWkm1TEYuCmZP9aaP4MAX4nKuRk6HBGwPAyBsjVSpDait", - "2ArnZkyEykgEYvPBUnDQoeT5hvp2djc5chhPMiBddC3MWTXume", - "2BKC5Rw5guhbtq5ZzPBPA6tB7p6KT3uyqJmL5HJpnJoMCTLJcc", - "2BtVqL41rwv1EpLHbLhGGH7qmbp8CS4iBVbchy4XyDjXpdw9VF", - "2C5hHCqoRLh8VrVVAAPJXXsMd6gTWF7y7T6Zw8cFTWhNBPF959", - "2EALbD88Aa3jG9tyJ1EeTuNrMQEripPgT45ENoWa6kCBey4fj1", - "2F3nmzZ4zJwhDHpXyCp7qHipiL5x3vZ4E7U5GbdMioML28eGYW", - "2FasL7vS1W7KYydt2SRexThpeRc2mj1mdwYQGFVJudXgtNxbK", - "2GGCrHkhqYFsmZzEHGXBKTT1MYicZMUkXENLsxwCJEJnbLds2X", - "2GvUnbuw1Tzat9ANiBe8VKTCqCKqRJhUYbU2ydMHzhacdVjs7d", - "2MyJWUpCj5sEEfocM2QK1yHikmsmUYj1ohy5qpuBTV6kBV7SLV", - "2N3FEhJwqa7yQj4yiEUQWmiUjPXrwbwUdhyjmTWG4RY16dstBG", - "2NdCscMk9ptgb6rNSNN2z9jbAVS8xrHMiXQ14nfs1ZtAebfmrJ", - "2NtjDcF7768wapKgGCP2QMtkviypLQ9PRbEQzVNGHUDKoAFe9r", - "2Q5ME4Qu9tXheNCbbvE9ARYTBwcyeSBsQQQAcvoyX9cfqCzVqi", - "2QGPPTEQn8iyDcQEyMrMH4NnFoeYgKCrfcYd3rBBkvu4YG2FwP", - "2Qya51sKi6kBH4AYAMQLcHpMT5uDsuVZgtounj7GqqqWVvHW8Y", - "2SqsMUwbdGp583RTpewTnVwn16kUQon7N1GpiHJAScE9sw9dwt", - "2T57a4UW8HPRagb6dBftpVEUWCBzwP2ZeLrjL3hJeusDTXB9no", - "2VzjdKN5CuPQbZnP1AmqTnk4zesvpLd1mnbS3Nga4T71Xx6nkH", - "2XSRDfkA8vyd4EEwntPbULegRsV4ZuNkREXnBpdoEw2Fma1KjG", - "2Y3oAtgb3KtxmCEcF4qm7piGFuRX17abzv8dEDGNXeVX9iaJwK", - "2Y61SGxffumcVCkUYw4ycGe4BXYtc94Xm68XPp4hSCYDFZTess", - "2ZbZUZWqvNNe2W2FtdKiXcUCPBrm5bmX3SiaanQREFAxg4ev3Y", - "2aYuGkvExCVfptTid4oqKAeQGYrKZsxwuaLot8tU48KjPQBJK8", - "2dbfhBpFjL5VM4uzbX6npNbWMKPxWF5DhunzEi1Hj5hxDp6hK4", - "2igtVfGcQsSiADeKuRLW39RRZLewkTwhCGRvfMSY7v7y4AD8h5", - "2ipN93J1esuG4e4AYc7ASZBUugNP3x4zNbKahSavkrxinigJu5", - "2j3RXzmGYkyjkqJSXBmZChEuq2d159XAq1dijjWsWRSYi7hmv8", - "2jtrFph9tduRQnrwrKx4qVmfPeZAWzPGTzW8FvRnzRVYhdTYHn", - "2kSoQFdwQiZ7cnH1mVV2pAYBh4M8BcKHHo4HuuVhs3XyRbmBYJ", - "2kXf6mnse3hpoY531Xdoo6fv2vNJdT8y7V4Ud9pjNzEpMREBzo", - "2m797oeWLxKj9UMYfmwZajEjG21PzEd5RHBsb14pmB7mWEbM1J", - "2mzCA32ZmnoCfSGVhqtdrKtXBg16edtoFQJAqqJvy3Be5r2m7N", - "2qnJE1DDHmk4K3R2LrvoJMiMhJh5PymmrtfWjwfVpyPHtUGqK7", - "2qxgRBRKWKNGaBQEyxc81MwyY822vL3EBh28xCVDY7jA2m2Tis", - "2r3JH3so16Sm2wR6DoEW9mztToDm4cotAJkQRxX23J8NrmTKUb", - "2rB1a6pzf9Bk7JaLBfDYUUJbznDCjHVbJdcNzxR2oCMzgqk5gy", - "2rXgjQJgtHsQX1ijwj1XvDULkqkFziDT7oqfYo2gxAe6HAtPd2", - "2tHb5NapTuTEzQNFearDkh2bFTNgk4Bv85vEuwVAxDaESRYGxH", - "2ubwFU7pYNw2EPNsVmb8mLAEp2xfUBnwAACjKVHuzeApEPaZVn", - "3v4Rs8kT4Hr7fr5p3K4Yc5GmvBDieZv96CQH1fEG1QShPLX7q", - "61EZVNqCY4Lu7kzWS7Y2rihXaiRX1jT1o3QZPwhrDFqyQ2ymZ", - "6kqdpwBMmo4YaJs79p2XbuGnH7KTwWSye8c2Sqjc8jfERYuGN", - "8x8PagWMhJDDaya6oTmxbSXC2cfubqkqcKeXRvXkEqPnHwTHn", - "9VEBvpL5jEHxA8bnicvTqkQyapdjrMdp4PQyANp8D3GLGSYxy", - "AFFTGZQmL1GWeucQ89GFNKvjXprQbEzUBthzwjeVmybKgWNbX", - "Ag8rmvXryhZfxGte4sQccqJ3ibKvmdLnYYxwxFZpsiiuadxW6", - "C2jR7wmNuAhqn4y5XAGMFTJJGoxtc6QhX9Td2Bmc2T32DxuSE", - "CPw6ptdo67PWvHhZi1axonjFZP9GyCcZnjSWaAcunU4FPVSdn", - "CeNMWvAE9yUsbAap7u6dquJ6NGrUbPfF6i2UWGRKTkneU29XJ", - "CyyG6WwyVLP8zj5jDCVyaXH11auzRaasikoWbyWRqWfE67YfM", - "DPeEFcS4MvCWEqj6s3MQyGRi8vjc3SKySD56piTZBeWjzRsu4", - "F5QoLN7bJWJsLv6RgG6JWfAe2XWj67wvN7crQnoAdHYiDjark", - "FkqGhwHZLWaAjTEWPpLwvSf9zNWnER4XhhuunqsjuTfNRWyZG", - "GDcvEKFfDbFpdRmUwCBmHdSF12SxxMjzL2PNK6EXGMVWYPPDp", - "GNd8AChiLADLnqTmypEhS86vre6QKYpcPKUKZUhFnyB8gftyF", - "Jjp1kBE4tPMmHqQq8XeopNMREWQa8RxfLtv41VhpUT6jxupCt", - "KKYswxetFUrEcDHgGv86R9TcAegkA454RSFVVFGnnGd4f45qJ", - "LQ71p9PjkYBVWTUz9GbKPaFxA69V5pv4KQkVWNChKbCpKghiN", - "LrxumguWFXGaXty4nPzSzkogUQ8WBUufC2JGQAQ7D7KqgupQd", - "P2PzegHfs769nr5nEz2fFhbnPEBpEWWr6cmD8cahvvkAL7SED", - "TmwsnFjxo1jFsBr5rPH8XHLm3AtimbF26xBaxdmw9SYcHGNax", - "V6oXi4fXSV5Q5tvGYquWfdaZBBzUWQDS5iepyzsUtXg1yB6NB", - "WWfS2sqozxfHD2z3AJ5vgkyNbyYD8nwkJJJEut4xgjstb6JKj", - "X6LFRvgSX4rP9A8Fswtus91fQbxhQm1GFYDgTBktiZxTDkj64", - "XUE6WNfCKmHTcaNEsZQ2KftvnXXfPTKnZi5YBw3pLWXjTYZzu", - "awbBnaBnjKBc79RzRPn4LXHMTxoYL8C97toXVvbKPZf81iUp1", - "e3zK4rU88osx7rB9Nq35uBXJrfShm7f3eqVk3T3CHCJD1SrGg", - "fDLU1xyDSihqWErnm62UeMXZ7HNe2atawSicdWamFGTQbLv5z", - "ffHAHY1qvDLcL3u48VHNEXtzqKgTvoi56vKDMcinoEHyy2FTQ", - "gT5RrrsG2bAephkx3bUT9VZGAGVoosGj9Yn6ZgVwbFVWJVv4x", - "hHQYrV9wu2S7hzkewJpotYymvjYpPb6RBeH1oUHPir1EZwyJc", - "iD2h4Qw88P4ce7rbKGJaxXwJLsPeRt4h3kcThDEXJ82HF84uz", - "jB3N7Rd1HCJeP9wLmrDy3NMFT9fkVJ1B5G5KBoFVVRQxc6fpQ", - "jGSYaQZQjieWrt9yq3yUWkW54RYYKfoHxHaRqo9fEBKZ9zAu8", - "mcAyTfg1i71Y7DXjTggfnWrfdjnSWqtg6uHrH3y51AHTi4Tjc", - "pSLCmmTDhnxHFiY3FX4fqCSii65EhWXaRPef2rTHjcp63nVYS", - "qHaV2XmsBRdXA1YDLn8nCYvRAfQue3CdZM3YBWYvvkcW2gMkQ", - "rghpCpaeyY6PVnWCQ9GnBDGtCsRLsdNS9z3tDCSTobsDCNUeM", - "rq7F6LXvXNioXQQyk7qVgMwoHWWAK2UGQrGyJJjbqYH1CYaVk", - "uLPzkqsPd78pLTUVuuXz257nfJmJcamQdAFjXYCoKDuM8FbTz", - "uUGfX6pZNS7jXJW4uF25xntf27AAZMT91NLRppMZhWw2x2aEu", - "uxDeD1vay1vbN24j7Rs5h4kV5q1oDYBmwj3iUvh2h5meCKacP", - "w9djCKT2Em3S6URCHXooEiDWwjeahf66sAL4tBeSa4ihJofLb", - "wZC4y3LB4SPbYZt1NbqrbTJtEo3iB1VyR1vTPm3UknSdsbA5y", - "wt7gkf58s9uiiapcC5DL3Y3iunfWnewQu2woS7FAQx5yDBL3B", - "yXKPp5iLD5mMZp9cV83yD9Yomm4o9nEPy11hU1aPFvRJhTqwa", - "zoe37ZDDigm6owSYNyEgRe6Dj7EiusjxrsnFzPpHLw7EzSDPP" - ], - "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm": [ - "1GBo9WQ1SyRFZse5xhiMXQgptnzhepqnajzpdCvAJ9TNSJT5t", - "21xHKbCFFxmo5EdGCqR24Wvind1LR2hMWkHztqRxuu2ezRhE6b", - "23zbXVVjaix7VcFcU3jxJpGiW6TFxaEV29ZixDDtoGTkPF3eUC", - "25H3WwoqYUApdSF5eugBWEwqfpbmDtdeFLKFDwQqMD9aKHSBAD", - "25HTUEFnmPc193wW4LZUFjcyya3jy3Ws4psiWp7EU8X6WhAHn", - "26NADDbcCqF2xx5yaKTA28nQYcPCs1gcda7WwH3Q7sznPXZ71u", - "28SHVtdhn9MvJzMuzzGC8odjvBNcYvyAbtV6qBBricfP65NjJU", - "28co43WdBgJP6pi9CnqkspSvqeujm8oTK4GoGroi5ZZZqPnSQF", - "294ofGLtC3h62jc8aYpbnnsKJ1ufAEmp19rViEC8senqk8iKWS", - "2FGfG9MqLzwq9jjHAfx1QGtss5xKH6p4cZr2KQkrjE1Tin9B1X", - "2Gmqc72MXrXT65hxkDjuGS7cAJmwY3habQcr5HmXLDAFzyVJMJ", - "2HCLX89frJuqbauSLFreHFQ1t6yJSPb213hn8gpDUJW4ABsr8q", - "2HgkU9sT1oN6pUNt7CGonaTrcgQJtTpY1yHMjj4BYoqfECcJT7", - "2KGfWNfFrcc2qYw4s9oMiS29buB52h3UPoz5WDarhs4Kcey6H1", - "2L7ZfaHezUSQKoKNotq481hAsqafuCMX6DjZjvaktRjRfprjw6", - "2MctCP1iN6hskg6iY2EeGJRKJWbficY35UgoUMRd5PoaE9aagz", - "2PDa7wqNYoAHr3oB89weNFZujVdcR8fpjMPmr6MbUsWDsFQ64p", - "2PKwDA8c8BpibsyHim7n152C48viUt4wtccoWy5qiLiKvZHUVR", - "2RydwjCt1qipkTUXtjdxdQzwVCDjPLE6eNVzSxzUHhjBHko6vR", - "2SssQkgDtWc7dTnY4DSw56ZrCXBvL8uLZjj16hS5C3piNqactA", - "2UFZQKZ1gLuzqeEqX2sHLtZNL3Bxmv1NQL7GdqS6ZvSPMjkftT", - "2V3QXva1iArd88hVB7JsEK8tHn12a5qgifcPBkhpZGWc7fRRis", - "2VvgwD21RGHpEJeUTxhEVyuTdMDQN2Di8L37xPtmirYW4r22d", - "2W6MYE4TJZV43hjj5cMBHG1rEeStNQLXE25VMydkecAorZNPRF", - "2WRmUjiKn4xtGyw33s9qtyhzLvYPBByRoP9vWr4H5Hy5WKYr5J", - "2ZX42ozafD1DaWAKK5Nfsh9FUEKiukFKYfSFtwpwBxU5VLpBHV", - "2ZfNzhvVrgMLy5jX3ztgZXxyfvvt5ng9fjqqmkEPBq1Ds39yCp", - "2b9au7DpArhJPXDJCSFR2cMczAacLT9Xi2umZG9MYXLprkm4iU", - "2bKoipmXErGTPCZedKDwPFKR8v6X7yGmtgZr5r3esN9cRZNxud", - "2bLQd8omCjWuUik2LLPKaRo2AQ78BNjTvYbDsANhFgGjLBcEeW", - "2d9azyeuYybkt25YBwSSVukSdWko2EB8Q1ii2TdvjuNoRwigJj", - "2dUUsFXPnytJjnPmX1pQufNUaBh96MFQuPZ92vMa3XcdGCg6pg", - "2fw1AN9jJHGTEuvNBxqbtejWukHRfxNJSqfVpsFYXJY4Vbw2c3", - "2gbWojYtNF8YZmpJUuq17vxRMDreTTHoD2dUXspDN2rtucHmT1", - "2hLra7rDjb77NNF3U9LHMAZ9MqnJzkAY5xEG8ebMjs2DGR1KQD", - "2hNwDNBFeaHZ93VicpE74a5PuLDbQYb71WHQUVdrHyy5ExXPLv", - "2pCJ9gCnbCFC8e1xQNYgu63XQzCLqp9uupk7ePgDX3vWvwoPGb", - "2pWxqGSc8vPJQheXoJNaRRSA2NZKQ6wSdCvdhWXjuKS4VPdDCX", - "2qDzuN2ooKLnEYc5ULhNMEKFTcWu5cSKyipCeJuVjwfu7mVKvy", - "2qTfSXsWBbmuai5iJFhUE4AdpPbwDNR6QWUgjsBPGKdc3R53xw", - "2sE3rjLpaNnu8HAa49hTjYJ3y5dDQwz8TzPphVcJkcihwPqi8q", - "2sTSDCaRduH2oAtCA6cihuDKRbF8b9N3r8bkLYur8dHiYStkQj", - "2tFh16Z6eTzzzUQYDMtMcW7vCYVnZJgNFmvcXKdKueqJeHduLo", - "2vf1B4QJwuhGNUVHitAggar9iZ6GMP6fvkNBBNFxmrwn78Xxqe", - "2wfMYUvLzxtHK5b8PE938LrMLpzL7pMkoFfVZ2P1wb65FVSMDt", - "3oxSU7pEZzr7MMSBLeWprp1e851JtwHT4YCvEzs4vzamAVCfj", - "3srNc7xjafT7pkXDawHisjRyEhdedyEaxpCVdeeSF2eFFFsp5", - "53CPVeV8Jr6amsGVWiB9SVNZVN9vFk7i6omyCrNZxer5mfWqZ", - "6G2qUWZCW2MvgxpWrnR1azuTEu5Gnv6C66eafJsEXbQbV2yRr", - "7qxMYH7p8QsHw5u6pE381gDFESwBHrzbYXK6BhQ9kMp9dmKe5", - "8khD5WmMbwDadv17WNPhsd6Cxu2XLun4n9Pc88Apmd1nNYK7S", - "988Sk4hRBN6V4GQk2rMzKhTXQ8xPy2p7bQBXyiFHknHSLeSdC", - "CCgthPmrL6fsPRtVn5DJAkGs3wnYy8HUSNmJ4PCgDw2beZAKb", - "DKYASkaDm9HyVskLiw9foxUf2exWhWqzgBmnwx5yncX1jDJW4", - "DYdaBt3C2QS1qDoktpFsUQCb43F9a3RzNPefpCQ2csbLjr224", - "DsBjgvFW4AA3GkRav9VCDSnAFYZxvT6CEYAmJvgKaXHkpFNYg", - "DvkrWrKpM86FggT6Yzu4wM63Yw8MPWrNGBa4tujPm9NSR94vf", - "FWXEYzxYxoEQojLLsw9GhFrHA7NxYfrsiFHozt2xV419ih98P", - "FjL4WreWPpTFxCDa3mp2KSxuTDin2yeUfNDiHtMRhnZ7uXWaf", - "GFVDQyM6LiDbYnLQBjYUZQixk2fDLcEf1zSDb7KFLbTwJJfik", - "GaFX7JQGTVQgKuGHZL6fcRqHiKBioCJpYDQ7w4cijaUMQXnut", - "HEEvCX7Af3TPBAJ9KLji1fVfjHKH2ZJwVsV1BnzVKoSR8Xs7C", - "HNgxTBLk1Wa2mTNeYkYYptQLANDTyT5mZHpMdaBjb2axziyAp", - "HqtaYoyEE92oMZaFzdh71Y6zNBs6T8FR6zHJUd3c7cyuhJVGT", - "L82zC58X8yvm8JgfyxtSBUU2GRUAdVbYhWYKbYu7B46ctgNBg", - "M1necnfahQee39ogPGbv7kkokYnUsM6P8npqegLV6GqiAXF1h", - "MEj3pMhy6aNowXkzgTDsnHoJf7E3zKf5sJi5vuxqf4AsdgTjs", - "NbJg4zwzKdc8S77BgoHyYknMrSXzdtWgj98tnPekbQ2z2NTis", - "PD5ZjG1cwFHDjyeWSWYoAhLkDfFmc7ucEmQGZkLPfygXLc4XG", - "QwUfCXBeTiPL3Rv51CxT6BhDw1GkDbQovnQAWzp7sT5FH5a9J", - "Stp9k2uteisQPNwUG9A7RQmW6yHaFz95WbLDRWu6QukoDTpD6", - "X23yYJTmGHgMdAYc2joMAzPc8U6d3crwrTemDNRyWYvTfuUT1", - "XETk5x8XPHkX9tAuJa5LvkAc5BXCzCUeMtwc74gfxauH55mkV", - "XUR1jFfmi3G3CK8e6ckwDis3WJMXGowJH9KRTAs3HaNuCFemR", - "ZhxYDBMMLeDwcbzjmM1uybVcx6Ea5pW6gZ75FMxG2p1gAypPk", - "a7d5UaCCbdW86qszpNc6WSow2a6RbNMALTLZwkjddk6WXfWEC", - "a7yqQ6WwRiJkyxmcFjQ7P6c6HD9ggMzw5RhxCkciBpoeEtwKQ", - "aBARTG3jtQcqY4iBu6ysCYfgv5qxNZ7tRgyc4vfKr42kbtzDo", - "bV2La8TYp38PZZVHLcdf62dBxyshP5QdmxoM6AXwWwck6Bj5w", - "ezDVeSFwtsKVj2TKJgnfFk2Ron7XBAnSHkXQaCxg26kyFKKNY", - "fb2EBwXSKdfVMSANF4suB2gYgPZTTFHEgK31Be7Yduh8aUPwo", - "fr1W1wLpVup55hsC7wap8Ry2TThMxbQYFmV1s8h7RDMTm6m2B", - "iDTh19j3bYnSSkQ2zhpKYPFuep8hHZoRo6pKkWDotQU1CJzJF", - "iZpg4RdbgzWHJLD8fx9SvCTBJMcFRzBbsobSZj6YAYz671gs6", - "ifoWGTKercg2y3gdugrmzh3hZ4NyDm6xq2yGAXGngRLVRHU7S", - "iuaz5BC3icH5f8y6koA9DUpnA34hvUDB1UALnBYednBeztpqC", - "jhzhmCBQRwZZrw7pTt1S9Tx9FdJ9VjHq39z9yCadSk31ab9Hr", - "mbHxp14KyQwjvyaKjP2jErwK3Za6iwXvi5N49dRyzUhgTi8r6", - "mobi3yL3zSq9WwC764pihrR4ZUZyLfD4LTS7C5uosXdC7sQaH", - "nCA3JEEwcSfdwV9aCoG5VApSLHmBqaCBKSXT64KSuDSEix88n", - "odgEc4y2JaqMeoXnRoh78EL6jnQJjdhfeVFabmk8BKqeYhbvu", - "pUgAh6Qik6Q1zgK6iHRkPnW3KHQ4htPJVUQK4SNRFvN3bwvaT", - "pauQnSkSBdq1we7935UxwyPBaVE3ygnLeKk9AMZvy2nFPgtde", - "qTg4ng5mihJsLnuxedfn8pXggCoDEVZ8K4zKbebbCmnLYeST1", - "qx3w3KKVhVPD9hJsDxaVRoy9k8z1iWnQNXxM193T4zwJvJnY2", - "siTgYyVSBf4rFpKzZrW2KRKteSZRjvaPz3qudqQiZfCKFfQqs", - "xfjYyMgV6RU882WBsWoK17D1TmAbUDgsgyVqmmtPVpU8mr1iw", - "ybukLCCdJvShHUs4b5AzLK4J7tJ2R6teio7d2ty5uJcEd65a9", - "zL9t4UtcRCPa2LikAW2Rejdohe1B5zhuUZfaEnk7rpoxmuoxV" - ], - "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp": [ - "21GNKBvs4HhijvxpNbJKzhm4VkRyWYtWH8M6oUDtTrwsTniBfw", - "21PgwetKvSkPPH7AC3H7eZ1qv35PrndNkfCcQL3L1cQFGqdM84", - "22PdLnjXarY5WX1iXedStruNJ79vUpGfkiiEWwLwnMg5KA9FgN", - "233ci4fEYoDtAgK6NARXc26Wkebf2YiyG2qfShHCN2GYbUz8nq", - "23a4BNuCSaoAa4tieecDAKq9Ao7JBxz7FyEVnoPZR5CB4x6UcY", - "24WKNeGBARwakAufqEH9M3Ymoq6RX8rXVu2qM1ohawSDPHPfsC", - "268ZMaHbzkwMQR2euzeLp8yBQGcCSM4BZNdLmjWGh3eYSuAaje", - "27ohgMuJntWGRWMTRwAmeyYFXZc94h2CmLyukBucXPAJ7BQMdj", - "281fnre1wsmf2nwxrEhrKbxQJ2UvchZCeJaNDs5oz16VXUfV71", - "28xDbZPW3eX2JRCbpbUSJjm9rNDP929v22fx5166Toco1k2xyu", - "2BLuHXttwYRuLhr9k5Hov8hei16f7de751teUQjR9bH7M9uEEV", - "2BnQhpZRqq49U7CnCisifzR9KEDofoGvPxLjSUjnkAhaCZqZdb", - "2D1Zb3PKoVJoiNvHhEsS6isYvXGctfWbtDaAHpjXiYsy1JqUve", - "2FJSx7HPKZRkgxGm23qb7r6db1XMtJhYTYwPwcLnxy3xnND6qR", - "2JJWwULZhyQsMrpUhDrKR9SA3PdSuj4iRdaXinYHUPgqohwRdC", - "2Jm8VmZ2pU5FZdLgTHfzmLVNdRWs8niqZVw473jwFtdPDTwwbs", - "2K4W7Wp6B6YsZ5UJaVfbwLHpEBTCJiN4MDLJwyJziSc2unMmHF", - "2LYqjjCfXZNkbTDCbVPRpHrYpEYTg2LMRy67pUAZUn13h98pyP", - "2LzahS7j2TG9147oZ9TJWpFQVRmaW6URMt9AVTUzZ2xgUrtnJv", - "2N6mbB2nyzRcf7kWqrm7bBFgwDbS9MhXHvXrqv83irukBV8fQm", - "2Q6hxeJDYs3Z6aWNQ2ZRx8wX4h3c59QoSYmUMz2jNyVaRLkjrm", - "2R8KBvX1C3fmLFhhHD3Wa9UKtPkSCJsV6m1DFgF5jP4JXPeqG8", - "2RtTPZMYnf2hbsg1nSMEVPHHEPD1UTjSc59fbdD4bjcG1UAaUQ", - "2VyPre7mHudGLHkVXSW99oWGG78hFgHiurLbQfWRV8p7oY8yEf", - "2YAyedNs1K6SniCwhBQzTM7uHAtydBo8DEq9MTw6BQ4DhFP96G", - "2YDKeYjiRYZCekKXUK1qqTtrDSAnLZ4fGEAjK5apUts55LJuLQ", - "2bkkPybDSwsMzJNN7yLMgWimU4oi3dCm469RHNBkEiLDoymVjB", - "2cqeDNEzjStiNUUTASYYT3zmGCvakZJUbxGZknEMrK78uXudRB", - "2dAL897U6Ab77e3sE7PL9eLc2eCaQTFLMvvrwQvaedQoYiyXDd", - "2e3pF6Dzko5wPgRsFgUuGqKVm3Ssk1or5moxYw8ibpJvS548v3", - "2fA73U4pTv8B3gK6UvAAHCa181ghsLmTdhFmv2oZoAdXkUyzzQ", - "2g8YVxJLEmPdAH3nziQgowXawhmRXuXGtJMepK7E8Gjb7Wz2wQ", - "2gXFqfQCuNMnTYrM1zbZjsju4gCRSbSopLG32c9JasTdKQP4T", - "2itBsCBxhuQ4ErGsmraeThpm8WXpU3jGzmGUP75amt8piN9nqg", - "2kvK9AB4TD3R78ZmEwqoH85r7FgU6Jf9rm16y72Fcw5X9vSrw1", - "2nEUP9oXSLzqpxw7i86jpj2HivTTLgN9qLFF8WvHZukaWon4uX", - "2o1LyHL5smQijHAyz5y4uA4rqxdmfSX2oqSr1mUXpESwK57FAg", - "2oFvuh3LdgUTqiFLrpcoyDU3zBwANsHRVYB4SKwiHCHa5aHqFv", - "2pYkTLFP7TTZSkLptwu5Ut9gJwCQ7ZqAdpCKuHwUeFjxFhGLzG", - "2q3QVQ7BMV1rMoQgmCtsVwSdEeWisbQJQbo2hNNyGko9ZHcYxU", - "2sDESZkJVvCeFUNoqRmjhVPBFyLr7mbhMgyVvYBfheoVU3iXjP", - "2sQf1Zp7rW9GGXWRUCWp98L2mPCN4sbmLULToEVSARRaeqmBnX", - "2stkQDENMmAq9sco9tqHn9oEjV8XwUruavKh9j42Svz4LLi6iE", - "2tXt7gKwFM31mz8fs3DVzHE41ZpQ3i4HUXeEHDGTvhssZqHh5C", - "2tdDEQD3P8MhLifiLzBdjAXeZmTVm2eQ9rPbo1i6e56QujpNkE", - "2vMp4tg6xdg7oDJALQnWXz4dbxBFtLGfc9vPC6roG36xTUwGqm", - "2wiYcTuboDY83BKaNksfiHR8K6zSK1t9TX1mz1DscFpkfR1oJ9", - "3TSLrc4qynaPNUYWr3oYU6EoDoe211mqfPv26CR1Ju6kL8cgN", - "4Lp4q99adt6cdyg3aUBhNuErtzG3g8AUMks6XSU2GawvALRWp", - "6BGtusvq8xGEQR4ovDBJ158Us4qd2LVJqqiUajfUN99JezwBZ", - "74De4FAm32yFP9Ejtes1Fx6mNCVNfbmxWkcatny7vdqF68rD9", - "83FVtcFsfCW3Nu85B4WFev8YZxKU2Ts7ANBU5QbViS1yhRkGc", - "Ck5PcwtPXECZt2h9zC9CTCcVuoH26YtkraJqTAEthdQUEoURa", - "DpXNEJsq8XxKwPjeB75aVv3LnCvC9oB4cVEnvaDq4Mo2oGmmq", - "Es9AxFN2t4hwUQ5qWHL6c8BhnEfcC9bEiSCdVnrwMAnWwAoP2", - "FVfCZyMKquDzbntdS4pTV999xbe24wBmDw1q6bCnz6ZJJZU9y", - "FiBGBWfoBLWVbukjHJj9qmfV8AdLcegnwHkxT9z1FHH3gBwYE", - "GcsFTALW34ZR3JUSb4wTJReoapA3RfcfeFef4JbbKzFURBt8L", - "HX6PvpRq9fxNDEfwZEjkWEH1GnEqoa3HL7HSWePfPdvrCzE68", - "JiP3U7J2c3mX3sgXJCw3KgBNgwUSsCB8cGhoshYnGbhoonmr1", - "LSCQ9uV368zXR7jbTHhh5ezDvMVDVx1oi1ZUA7UwSF7TufXAs", - "Lc2ywRq1p9tLHZQYV4VhSH82iiqscTtCCdjbVjgQjit3GVf1c", - "QNqWF71vto9XwxRQMfwcSoqjfwVoMsZLtoFRDyi8gCK73zNVi", - "QQk9LEJ5DtgZ89QAwiHLc1UCoVZgW1j5hQ7XTY6AgUtN6wpi8", - "QaPScyZyY73BRwNYbkufCssUo89824rueV1dfhAiPqSEFkyxx", - "SQYeqJtoSQTU98Nzr6e3RpS26S4EDgTZkKz6BYBK6enDKYv3Y", - "Sj2TbvJ4XR13BjpVoMQx9RVjTYC8FgACu41A8hnQWfiJWi5gB", - "WxrS61JftdWSPfbzDnMa79wyTUnP6WnFCwNAyS3fMJ2QPfTuv", - "aAn8L6SSNrfzjznjNvhWqyiyujqhLmpgCnysisHijDY3eY2R8", - "bZbk5F6DQcbaTarbdxqRvzCYR9zEyo1Cg4YC25hwXq9Fffj4S", - "byRkVkNkokJPuv8dYYapUZRqzULaWHRNR41CGmFJNPFDeMxae", - "c6ZdCeFbkjwJLHNbFnXazcTBeDnLEvoYabwhu4EJzi8wSBPAK", - "cS5WWG74Jmg41GshL7disGDxKd4zzoWbDczZbYhUj4J7YC67s", - "cXHF2XYiPbAC9w75ZJUUobxsNE7ChetrGzzk74ZnFdPcMpZTF", - "d2Fdqbjp7fSDft7sxuspiJgByDRSKboZLNZKi5PHpbQcDmMMC", - "dJHkfZCeaRhLDBBgaDCw5ahJRqZayv7vqkqzkf8iFuyTAmdRN", - "eTcgbeBUS9PKCo1FU3L2KSx1wMXQF7ZTV7heMaxEDaETd6sZd", - "eYserBwMadKAYAiXJxW7qxSo4Bwyia8LhFDK4jBE3G6zHo6BA", - "fTJBufr1q88PwarE5zcm8U2h8NHkXqzDXFD1pjNmpezaXzuEw", - "fbFpFhHM4cQri1eXme9sX8Uugn2yreivtNESWiG6DKeRVk5MG", - "fheNGaNLyixLRBzSZmRKiWBZ32ME4BoUWwzNEaCcRYtWyeiBh", - "hohRXL4setbqaQLBb1eojfSfst9ocNYmVKbdN9HebiFD9Mm91", - "i1gXvBb8GoccJ9j3S6Sq7Wfh2nVmcXBo2noJ5tV9U6DLMb4tP", - "kBi3g8z4MjUfx36VpcV7nqWgwUZgWsHUDwotLq5uSuFM8GJz3", - "koWa5Fa9QwBoi1MnGGGxx7CKEFVEmYSNBPdxmo4XQLBtDGwVp", - "mMDgi86eEcF5zH6p8iYCfYMmQ55GqbipReoKSKtMbRy6GvN2D", - "mr7JGGtKivG4GptruxFSC9bZ4BjMytyw2BvCKbYn1XcjAp6cd", - "n6ecmUhHDg6oqFcmgWF4md5LbzDZa61iAKeESAxSXEwTyefW5", - "nBpAqZ3oddawTXkVmjQvQ27ezZ8zt6Ab2Cw5wvzC389RiSVsA", - "oBy9JhVDypnQUhxV24ntayS13xp24i4R4QuTQ1rck46DFzNRE", - "rsTtK52PxBCNAYojZjPFap4VN2bdtdutCsKhreUZC88tLoYbE", - "rv8QJjbFUSWV6Mt4q8388TDG42vCu7mzuAKwxMvjHHLcxzmBb", - "tF4RgbgAaa4LqgCHdsP4RQGCQRfzypqESjXudyNPecPrNKCQ7", - "vw1HytqPYBxf1gSmC8jnri3eLJnb5mppYSrFd26iBdPCuYK9t", - "wqtAobnVmJrYR5BwFqz8yeCwm1Wm8KBCyuZNsMTNdC5n6vof8", - "xYRJxcX9gjqDTLRArA8brxjYpjeoS223Pkij9uNEtKB2K4JNn", - "ya9nXSKsd4BH5Wvtf913pKi8d7T3NFEAarW8ZALHMBqCN5TQV", - "zDBbKBYjqujewuSnSxqAuG1rDDpmk1mqSFpYJYB3K1AUqmep2", - "zHdoWFMVwqL8VA5eVANF5VEutB394wtCGerEdaRvZ81YH7ekL" - ] - }, - "mainnet": { - "11111111111111111111111111111111LpoYY": [ - "1C6QHJ96EHsvtZXVHdr5zBdgX5gW2BQJrpRFobNmLbgsNmGgt", - "21cPFYt4eLs4UGhEaTeAsfHB3fHwAHs3M6xvpt6cXQafspzUZR", - "22bkNkCejmkkciWmfH2GbWXNuEZuet42xYdp3LYVKBKimFz1jS", - "22gSESLegSmxtAGHSkmmJDDRicmWpi9ripoEkuYe9PhaUKBygt", - "25eYvwc6YadcxLC1ovd8oLPHxzLM11dZUZAhBEDxeeMpRtgZ89", - "26D1G9eY7gDchmWiiboKEEYEkEqyRYR5MkmtXA3y4ZTmHwzcY1", - "27ASJoM4Zfte6kjK3xo2PFDbzjMNo9NjbGHDdfbZsar4j54kBS", - "28YV4qAB8f11teL8omBemtR3RmtBRfBA8GQb5qM2dn7y21x7pr", - "29RWNuDRMRU1KSUQmRzzpcj9r3t7zafDEHNSV4tXzCNZLT7kP2", - "29TMvMA1cTFW2KcpHCoEGC9Jjdbn29Jw8rWSVpEsvishCj2PEZ", - "2A3q7KhJGstxmdSFQisJxDoixZp5edAJB971P5SAg2ZBtLNaZr", - "2ALeEyf8h2PVFuCMiqgVs9YcJirueU9V5uX54E47ETf4ULTwCv", - "2CBKim62T3n4eHpfaP5iYFskDbvmo46v8SbJxWK1eP22e7tpXd", - "2CveciW8Nj4aQpHcFthScRhX5Xvd3TRcsBBbpzu8XymMuHwLTZ", - "2DES1e1UMB467gYdu9W6Dt8V31SkbFjRKdn1Y3GS69TbD5qUMC", - "2DLPFyvTWwYZqqJeeTh1cn9tmujiUB6dYYRUQ7pX1WNWnQRiSh", - "2Ejmxq87W71UPwvZNsg1QdZaQ9qha3KCQEX81Hu2oNvLnMutab", - "2FoAaZfdmxwEk172WJUauiYFTnELxBa2tQV2rBQxPQb7BGBaN5", - "2G4BACrpNp7cXusHdhpZUe98uyNYJYqykBxbKR9QTJLFTEa2h2", - "2GBNsFSMJ9SYYn8gSRZtmrvj1L5TarjAJHzde4kYEuy8XqKawE", - "2GhPn8H2PVStEaBriW9jNq5Z8yxrGdBzTwcBwVNZ9riDEox5G3", - "2GugeVAPnFB9jZZuEZpRdAVpvPJLFBmrB2NbDdXNu8gCURNyQd", - "2HdUspZzeyTysFyCdsosKCofnM1YsoctU8Db5RKRg1mnYCfnqv", - "2Jsr7tFh6BfhQ5MawnYnyq7ZUKDiiCoZoPvCcGxWufesQ3DS1z", - "2LL4rFkTKrvtnGReSv1WyDok5NSPp25DkntkVAnD29AQqBMCZk", - "2MHMe7RHr9x7dR7XQfBA1fhowX5v9vuieqqqKfh6MZaYDTxLUu", - "2MXevTUW9n3ezZVBo5dqTrBHboi5iAqNZjvmcbt9URj73yKsD8", - "2Tb97jbZLq8GESeAJ8VkoRynsmXsWSZKUejaw5nVZnBgVtUBAv", - "2UhoJQQYBfAbKHd5tt4gTJLCQzNR87Umuhpce8Xg2hnXDyjbEM", - "2V7rXDs35go28mhHQbHLXSNTW5wi2dn9QrEjudrJU8bP9whxGH", - "2VBG34kMWNzni9kdZ2FuCzTiHAE7Kdj1uFFcbeVyD3v5a96JoH", - "2W8kKMtnK2ErjbSKDjzqPFS8LGZV9aSf4gTMVVLpVqr238svMC", - "2XZyA97ohpr63o3kUB5bJ6GNdbVBodtUSxy8J5AJwzXkiKPyv2", - "2XcczkXD33DGVhCWMjA6UnepG1YLnqn8mZFfnGk4fGCx4sd8At", - "2XkfVtyDXaGifzj1pfmgUNntf2Pr4fXBHB3C3ZPfCGsvxoB16k", - "2Zn898sAFoEHG1fwqd9YxGj9ir6n3jWim2JKa631B8TPcujv8m", - "2a5mXCtxms1v3Ky2Hh7ZU9ucmfyrWcsaofTW9iez1f9UAG3zMP", - "2aosThGqXYu3MYuw5e1XgJPqYbScpe3MxC3r5HcbNo32BXHst2", - "2b7y1VLTg1ezdt4htt4NTypvxso9k1u3E1vfZugdryZaj7Sbif", - "2bKEKV7p1Lq4m43c9CFYYVdN9hjswehDiSpGwBMQoXMhH2iaSw", - "2bUPodfKzYSwvphj71Ph6CaVkzb2G3b6nJ76CrQR2KQ9avF8fV", - "2buyBep4TDUsZusYEpp7rZFdVcb1kBzMxuvmWY1RbNhjWPRpGT", - "2czQEWQh34qWCC9kD2LZLj4WukHtmcnpRLBXir5wQYAqxsqu7H", - "2e5XxysedgYJJn1zEWBmr2Dw2mFuSbqxy1NJ37DfdvKWDJvqce", - "2eCTMdHJsRNUUKVGLBU259w6TEoCmar1yeacioqMwE92rncsgT", - "2g9C9h6zxSwCzmoBhyZdmtUHgb9cDrohtQ8e8Myt5LK68qEmB7", - "2hYQF8yVbFgfAcUmZCRJG8kmYdnJUGNQYJWeCVJXwiAtohB2UR", - "2hyfqoEVxazA3wL2WnDyNFhrP1fryVWwn5pe7HxYVYk6K7XW41", - "2jRftTtrpnPa2mbpzrbgHyU8DUifkM8oLkDUyVApCVX2FP7Dpt", - "2k2Y5pJMp2EaMohgz1ETti2DL56QnRAJtS8fpmW6yEsGD3cfai", - "2knNUfFFUpCeAjF4CFSLmWQ5LTN7S5DHhghf6kk8CEtgSXU2Fy", - "2m6rgAXqECZS6jVWGWaHhhWwrdq3T3FSCyKVbEJkYVEAoJSrtW", - "2nKxFMhREjrccDWdqTKT4xUYXjJCPD98Qp1qK5HRFA82h1aT3x", - "2pAF2gPZpMBDANr4CuhhZYgzxTQMPwHzTfcF3ZXhtxw8E1Lav9", - "2pcew6PE5gqLz3QjRePfip6wCKpTNjQ2kwWbmsHAuf9wMUtwDf", - "2piSpsdsrsER7mxfUCWtobtCC6f8M1uLyqbkqFZZcMn3DHnajc", - "2prgtuMz2ciww3g125HyskmbNgA32omRYTiWsrJ4xvWFvJmgQW", - "2rMS1BpUBn6J1sC4iMMtfKXUjSs1UD2kzSsbpAsJK3qH2fy8Ek", - "2sXHvbVDX6Lh34NnAZzeQtwttx3TJzo9VsBrSGYVcG5egRpN29", - "2vbHvNcvniwdUN8oza8sGGbwmQu2bc5hxCedJYbRFPTK55eAYz", - "2vfXBQBD171q379JCCxwqJE53kXfBRshdkEr3Tkahq8b2qHPkq", - "2vkrakreKK3bVZTDKT1qAHTn31sGWVANUnMJtzFQzwHS2tdp7y", - "69hBvxY4AejbAw7Aq5pVignWxispY8AzprZusfgP55rLgJrwV", - "7HzbfBRJa1QEpRp93DTiCh6iDUdWSdmCptbYCu4Dg4XtAEiR9", - "7nrufmvYZv8aMuc6Y35KUcizSDs2mJNwmtjKS9ceS4KJbJEiD", - "AKQ6DBuYMJqeTZNdQmzzVX8UoBF84ArvQTP5RFHoyeFr6yWGn", - "D9PToNuQBFQUEJKhApBZK3saFA2GoonSq3VNmWmpiAehNzsUD", - "F9ZxuAKpt4NofbEtxH48i3rUphmJD7HUHEK1oSMbSixeoun8J", - "GoXitxCfeu7YBLwKBrw8YHSXtfoo3xHgEMrGmbyr3ctYb2SHk", - "JfWCLAeTqHh2vHNkVd9gCX5XXmP8T898fLLgJ8wzoCr4F92fi", - "QNpykqJszm7PRgtqJia39AoHbBMDsnFUsvTJXuDg6UhwX1XU5", - "QnCMVKL1GVYZNqbpXvFeW9DqkgNWRKjypPigzXwxgCrVD2mzf", - "TLpgi7b5cjxft859M1wqVSGvJKR3B8CVPDVCztKMUKwMuTPwf", - "VB5oKNX4FfPaQTaSzbvPuCY3arAqEV21UD8pXiKtqkot7mTDC", - "W4SJoLCWJAwnfLNg7o2vRbnxXjJxR57p3BKeX5vXN8FJnuHMk", - "WhLrw8WVmAzZJ952aDv3DAJL6qZ9v8YPxtGEegJwLKRXNKZJv", - "Y8samrw2cohK4k3dve7jYdUHU5zkJyoCrhT3GKuprUKzW3TnR", - "ZKqYi1u9HX81629F8UpBw6YdSPFxtSCr5K7kDH9MfyNNnpVHk", - "aWHNQarLDHf595EG22k8RrrW5q778nppiXjbdRMHUvXyMPoAF", - "bUHUFyfERafSe39S4w7TY7d8yMaSVvY5Dgt4QgPu3H9vqH6M4", - "cz6qidcp4t5mNXq6CV5V91zHLJNYu3x36Fa2qnL8FJBBkaEdp", - "dgTXQk1q13TcU2FbX6DbRQKZVTCF1JGGifVqDtYpXNzp6zGDS", - "e4TTY7yDE8JDFnyvdtoEoaUkczxk7CVLAVcCWbxu5s2kgshNP", - "eUHureSVS2jEuyrHDEnxSadueDnDVQeGQJeNHQTQ5Frjqxa62", - "gHvoTeGqB4JTWgbyior2vLTk7cZ5FPqsaPyXhStQmar5xucrf", - "gP7MLMjfPYNHx8SuvHgD8HzyZfLyWxUC4tforRVHipKTit98z", - "hh4EVoPagPSjrJonPRLamgMvx8qgNUASPWV4Mz1AiNM93zRH1", - "jL9bA8DabP4xh3GSxhzUQoLWcZDNZDhS5VwCuwSX3UgJSEGzN", - "jNfmePL4zkHJxdyPD6tP5GpXY7yuADSG8V321qaRf5N4p6VEW", - "qz7rmEGGtBT6fq5a4vqgbWrzGDtcQLddtcf6NHhz6HV5mt7kH", - "r5TyiJhxwnXajMPiBqbbMrZwMk7zRvt5x9qc7gCQwwSY76cVA", - "sq7U58h7x2psrTQWTXNjjSzmmojreZoY5aRZ6SvQVMxxNKT9c", - "vPDVkxE92tvTTCjFRE5rThfafxveQtmMK94GDZjdtQFjAti1G", - "vQvx4FYdP79Pe6fcD2HkStQEt69EwzA3P9pSCPbtAq9RAvfdF", - "xug97dH1mMwpSdAbVALedmanVAuDwsELA6qNjKYDmFB4HyMSY", - "ygYAdjHCjAGS2jFUc14QUpnerHAhY7RPUHQKe5NSAJFFJrjsF", - "yjC1ZvZPnd1J98fqbM9FbFuzcUSmeti6jBiDBBSCAMbAJj53W", - "yvSgdK5ksf78yDmFr8njQtTodUD5AMHqQbfdBmAzP3gE4s73X", - "zCCboLrquQhWdAoJGWYok6twmbyGkWKDyMMtwvBaBWvrAReut" - ], - "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM": [ - "1Kdri5W9vFJqB2dYBf5ZhYWAmZkkP4aHedVoV9pGYPQd8C77p", - "21jEMY3teZTGfPQqs9gGvWwoYsEvMPJKFLVYfUFYQFtuNv61p2", - "22xzGXKDSum2UQLksu5Eyb7ikMN36iDStT6jbPio9gjyHuyFC5", - "25jYWtYr1zwYoYri74aTiMp82rHC86HP7bJ1sYfvyqBrS2b6st", - "26gohU9ZFmkenRHYYFyp9YZdyAJVtiWKcqEhiwtAyAz4GJssQi", - "288CjAHapx9kK2sseVRgDBBfq4JeMbS3F98S4PK2YQU33vpnDh", - "2BaCerd4yoKeB8wiyFYK6ARB46HcqXSb8SCBJT6onMsgr2fv9r", - "2CNkxrCycKSJVxmMHcxPwcYEGqf3royYBrmKGL55upEESLvqur", - "2CTCExtaeVzGvnsXatitBfeiVQJKmehDdRok8PQQALtzQoYM1K", - "2CVcqHWjQkuzpe9tuSGHWQwazNsFZrDPJdPvjpcPfxmJs5s5TN", - "2DD4QdN9SmBnktJc7daV4asJi9ozwUwi1s3M6WNDShSUb3byDx", - "2DK7hzB9XUgUxeBuC34KAe5hnDKqgmRYgN2is3WjUW4V1vYNtL", - "2EDHTze7RjsaWcdgGy4WFSXEiHz3maHkc2jYGRrTzhKRX9w4CQ", - "2EcjWWz29FZoX7bUBRG4RQqpbwoBrwrhHBft3B3iARiejcKwR7", - "2HQzjUaHr3LW7XQTp8MvJCTibhnu4wyuDkS8LGYKsAGncZoV7j", - "2LScQCmZKGDpMBX8vzrSNUTgXGLX69LFdpQchcrM2MGYADWQx3", - "2LZeM7Fj9qFjm1C2WB8AKoo97VQXEo71EguEp8ZmUMTemQxjs2", - "2Ngiovn4iW43XQrx95kzujiVezrkdiXHnymV4pt7me2Rp4JaRy", - "2VFRJacgybj4bqgD3E616j2zhGHvhqqiBBMTLiuXDNxehR6Faq", - "2WAS42i6Xfu8ggWGVE2xCENpKhhkkC6q3Zb9vmVagjHdE1WSc5", - "2Wu6fX1nT9t9sTJWNfu9WMVovdd4QR1vBVeETht2AsDP9qT5rx", - "2XkRkvQ4ujTP7Rb1j7J7grBxqmM71Ggod2HLGC8rTW5pj1VBd1", - "2YS3faaAM93Ev6GHCYp5uWhtsSGuryYdxuNaRcy3hcmuPnDk8C", - "2YdjjG6GW1WcYedSAwRCtpLJUQP2MDCX94aEMd2LPYFAfWXMFu", - "2YdwRT8da6kJsG3XHnK5uQxedMTpqESwoVyJKA9qZjGT8fALds", - "2ZWrZrXWJtPQgVeCdzuAXvPich8hEQuZ9MrhJ6A56KnRw19sFW", - "2bZJH6jDPikCUcjnApQZ9X9k2MV1twjjVoYBp4QPCAB7ZyQANr", - "2bp2TvngbGuY9KRxAxnHk7qZr1KstCKtz83svoNhscEqjt3S9H", - "2bxu7PuSUtCXoBGfjeMjRKxX3gvWsZBXk8x2sLJ8FrBHYDHsd", - "2cm82zfe9NofzqQyjbCi1AmusYm7bxmq5gG7ZKRJhGTTr66fTE", - "2gdhwWbupbvKmHXA5PTe7H7bxFL8TVzW5kA7HG8TK5xMrSsTp8", - "2hxYwQDJ7ZFpfxZBo5b4NnLTL1Bg9fRMZyt7xjNDszG8ezZeto", - "2iWpSR16FCGao7zMcDi3h1XN9u8TTJZpWFzMQizhUV8ZWxWnmR", - "2jkJ3tSmg69mouko9d8PtcfKqs3Z7gR5tuxdsaEnn7trkgSEs2", - "2jwvDvvRLdwYL5UuoigH9BVc2D5bVhFNaYhaygXSamJGi7woiS", - "2kY42u9ckGES78ocJ6nBYgyczvPwVfUujcCJniVM9ZtfWQooC6", - "2kqszyuJBHUN7KsbUkyTFpxGGxmWURLDmGu8nU5h8v3Fzv2zQ1", - "2ncWunFKptuXQs5SiabaFUi8guG827pjLtr2pwfViCCWK85mFv", - "2o92FQ42CfwjsicGnffFZjETGijhsFNG9Gd5Be8UH6TabY6KXa", - "2o9kcsdzCD8Pp1ZJugL5Ryk5YmRwPHyb3Z3orN7JK9Fxcf6iqU", - "2oU5yYfGhdi2NqbjM9Jsufejbj3The1TkWJfzTdKsCF9ouWVJ3", - "2pSpcprbpgACr73pf2JcP8di7eab8vd93QFk2Wd7JaHWrwjHxV", - "2sY7uuNMetZu28FR9rC5MtpqWDKbVHQCvvRqFg9Rz5A2hffa5M", - "2v513oh6biDsL5jFTfVBZdzL8GU5Ur5E4BQCdQ3q94qSYNRvKf", - "2vSaKbZiiKP5pv4PXE8NF7hET1qRxnfps85qCg8EJmAakTMbqk", - "2w3qumfoA21su5Gv5kNM6NjyDmGCaENsBDTGgNEajPvrNf5nuq", - "3py4ULD6d5FzbYXcVLcm5cLBJGCPFJEnzrfCbEXnQfEa8FmZi", - "4ACXU3PYb656PxgVV8M18jw9MiaRmGPYCvApe4uUTEdX7TPpU", - "4VcURBXcMcQjHgdVGJzpqLwaJ53bvyd2RFKqCZj3U41mGmuZB", - "5DCcfMAqj7hWNiJPMSXkfUMvcHoRhHcQAwYumqoiEpKPd3DHa", - "5mg74cn8UZTk1WoWpX1mvipxhSjtvmJPen462K9kh4nG68oL8", - "799PvVmpxzWpsyEzoNaYdSsmTTTxLCgqxybWckfiZPhr2R6nU", - "8JVnuR4znS2TWBg7Fg9dctzYbiT99LiNjzvkxPRJwJayinpiU", - "9StEXYCTAZ2BUW7tzACJny4jLnXwkVgZRy37r9wPJGhRYLgDi", - "AKQxgsjUAMuuadiy6YDTMAFA1om1fPqyVjR9hqdz6hhoWkg29", - "AknqzZuovseCGTjcSfJ5xP7CrgVD9qpxiTj7T9shoLK59sW3E", - "DG9JJCKAMRYThgWW7WK88rqzkBcgfNMWZifPQpj4cz8SVPvBg", - "G6U9ZAQxo2qDUZsnU6t5TFmPekP2ivoSbtb8JXzJV95URWJXy", - "GPgfuY8bY2CTWHUzbY52N1W73DJjTpRgLBrG4wqnd2QqaoHyF", - "GU1N5nss24TshQhmadTtWiSuUFK4d9YGi83FDyhMrrgR1b7Yr", - "H3x2CsQRbZhaQuQCjYRW4MadfEZ9Gu4by2DnG5Y8sv9sWZrUY", - "HCDaYhTaYh9639qofxnG2qiX1dCzhTD6bdDcmrYczrQ3ZHjsg", - "HEyb8Q5n5YkPgXGByAtupKGQR7CJanzvMZWfAcD5dkjuQAsrL", - "JJ7peJW4T9QXKcHb1Mefnd2FVYru318qEQGkuJStwP9WejWP1", - "QTkZ9bfE923YkEZ3LNZRZ82mMrcv5mXnosjPLCX1eZhzvxtCd", - "QaDdtpq1b7V7SeB59uwkCRpMuXqhaBiYigLnMCb3CbDLMjDzD", - "RkKECwRZQ7e2a34oirrDqVQwMNscvmqF12V6UbBETSdzhXJxh", - "RpQmzvjeDaHBqqm7A9iqpPkVvMEW4RXW8SXjR8vNNN16S7qNQ", - "UyunGfbFB12wfmJqS8xyoNpjnb9RCcqBKs8Vfxmjf96x2hFAs", - "VDycGV2Ps7stDUZ3kRvbmVuKkKoPUyVFAGtwKmU2W7nBFHjzq", - "W4QoHZErHuSaYn6V9ptAnmtjYsMxEDLWfdmMks6zFNZYjapxo", - "W4tMAUHZcSWQ3ck4q75XVwB2j9cgqtTHKeDGCBsJYu7jYXQGx", - "ZuDLBGTsryGHBSARE4zgM4Dtj1H5DNe1nxfZ8FQpCHmYunPn3", - "bTs52txp1o1z33uebucqS6sZ94c4XLuXQcgUdr97kwZK7BWEt", - "bZMYP5jmsTMyXRK5QTAyHt8bzGuwm4APboEHFbTqexhyc3Tm", - "cddXZXwkgMX4vHG5kxTG8ktXn6ujAtPe2rkZXvEGgAHgwkDSg", - "fDLZXMLLX77NdPYFRLyn2WNDSwtpKxCZqdRgTBuwCP9H3otgk", - "fGWn4NaAqK2BgQWadVtkHB7Q1n1qijrin91tkzq5Exndq3CNy", - "fM4tU4iDpLUYjwqnDeWkLtbkEqPhPRzwbkAD5GTviD4CpAnRN", - "fd4LC3i5w4w8TMmaPwmU7GPHyUsMk6fUtNykCZvmkp9iNuxtL", - "fptxfNAeQbDzTV78ryzqTE9xiQgViGnLZHHfipb3qvWHMvzAs", - "gJqkJ22xRqQ5SRVraoQiz1piMJKsb9QyhhTvbbRfZ4FCsjbxW", - "gdismVqRtUwW2X5DuU3ybYxtjiaSkAmqntXKFSpUkkgdtYMU3", - "i263AhAfgjqrTjEmJG8mA3dKDVX3rMPWRnn9pzT4EDG4pjxRH", - "i9sCwM19Ndxc1FH3nmSHDvt5QPD6StWgyKDGNwSF6LbhbiqhF", - "iuUYXFzNJYqLjA7sZQeXSDPMWShVkjAGykBcLzyZLt1BpH5Cw", - "ivECpWEqSRR9mA3fP6jTu2akET1rRtmJjqednYCjSdMXJAN1q", - "j6EquSChjB48xP64iHh6Bj67GEsvhCoV73uqsf7K5B6PRjfvf", - "kCd5nEUkHyFJLyqZ8NJhqa5GbsvCgBfj9cHXyAWWCin4HjosH", - "oQNJxqjJYaSLAHqyF3n9GpbtJzYwDwMD9WsUCAAGWSXAYUG5V", - "p9zGnppWJ1rUrqecGhozsBSsRvsiEwkj4vM7rUringMPL7cQ6", - "q14J1hczzqeQS8aKCJcog5bTFNNkFFWwza4XMjy89FuZRziNg", - "udPiCek7LmDmnkooWSsBe8SQzv9dmMgc4F4VpL5naudqdPQYW", - "vL8xjHKkhPkNrDpe7BkQksbvc1JAnwjTk9kCsJ55wmrBibKjf", - "vfshLdk8kS5hXFpKHDkg4FpwWCxzVXmUjv7Pzgb9WQJ2g6vuu", - "vg5LKAUU1YQSdP39zLx8vzUvmUiuAtM1dt5RqBvG3go4owo1N", - "wHwEP9TgGCQKe1viNvmcnHZtQvyEvJNf49fadLrAbXGjGRKaV", - "y1BYCkbExzrdonKbEvgTRwLmT3t7FE23ZAYbFCaShwFyVEeEm", - "zgKT1hRCBnXvxnzuQnxCZoV4TZAUTWA1UdF7Y1rZxgsqk29Ex" - ], - "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5": [ - "21CreraF9rvZEG6MsoJF9TtX7bHVn2BLxVyRuzm7zKZjadsbXZ", - "23pb5FGvVxpuwhAbTapXQb3sJgTpVD9gRv2y9eTTuxChMKBDXC", - "265CjdcpfLQXEcJmFvChGsJ6C4zDjw17ED6s7eJCEzR4PvQpHh", - "26AAHTzNoYx9Nyo7J7ikP3KbpTzMhd5SxwGkuXa3ZjSWLrrapU", - "28EevMGw45HL7fg6uXkwfBbsxNgjV4N2eFdR2VoHcRxiGbMGq3", - "29cAK3vmV8z3mnFB3NvzGaBsc2DxzF5eS7zPRVdRkqHTHig67D", - "29jvTrUs7AYYvf8yxfdWajCBvLRRcT7H5BZZurW1mwrYYnQ4QR", - "2BNV2AxUKgoiARK2sUPS1MPLTiXJXqhR4GdjBXoHb2HG5gkgWC", - "2DmVARhBswxcL428kqDCiJeVFU7r2d8nCGrJWqVUZkmUuUt8ES", - "2EjbjrcwwbGquQAEb1FHY9addWdU1RHHFEGvDju9kvj91REDb", - "2FGVk4NRVEYN5dDbecC62XQgzV9DJy2fQPh9KgWUJffFWQRY2", - "2JXMbT4ssEZfE1uJN1PJfEx2vB95Jgu4SnrMJtm2X6BCGACFLK", - "2M5yrtJSZuX4ATPyGbKpK39SB4Q923hHduBs9x4GWf95bJixVq", - "2MWc4PWBeb7GALHPj78hu17EyYzQcd9es63zh3QMz8aKo5Uoou", - "2NE4AzZ5AsMYct4WoUhGdn61hfDXEqyBABTYCFfywAjjvPXhei", - "2NSZMhSmtFDnMGp7WqQBrpW5kWiibgGH1oU31mLEfPJMA1PzZY", - "2QACN8uzw3oLGxVKgCXafsQgV8Y8CfwDUZ6ms3owybc2c2aYzf", - "2Rie2Ud9og9FoLMZZDAQ6VZPHyTn4MJ48nzarJWLuxPTvViahd", - "2SSGNPRsxmEtLEm6qEbKhXtXufgVQgDiAk321Vr5iczRwQVkxM", - "2TRvFo9zuVDBYzKH2nYj3biyDsqSvgYG6s6rSqjsZnU4UHc3m3", - "2TeJo5wYNqBaomR7Bgv89GJGQBKNLb3JxVceCmYvU3Lee5j4ih", - "2ULGRcoNKppkUeqedVerMsdf2Y9hq7E6RxrqXamT455m2U5SWR", - "2W59GDbGUMe2Q757tQJ7p77o2xeAiSztoq2F6jG1xQ1MoYbzq9", - "2WLSi4pwumXsXwDDbwPqXUaddj1pQRJKyPEjwGHZbRy3c3NT9P", - "2ZgdutRM86WEM4H5AvkfL6uerRiyoVThf7xUUYkE5oCvpp1qJC", - "2aBaaaEYULkiqjVQHmwPUYYdPBMUuSnKmEhSzWyZB6GeWBXPCY", - "2btxsybZpwTyd9CRDXQLpDRWWidmZaRZLgCYkXhvB1zDxVWw2H", - "2cbFwLh2Vg9YvRoZeMeCfW1YN4zmowciYgkKxik3B6PAaKxAN3", - "2dXt515YZnoieDwcVAdWEGP8QkwTUW2f1rLD1me9EtKWZyf5bJ", - "2edyMHQ5saBuRmK2st2YSFpNdku8twpegsdjd7zNnHi6ZUukKU", - "2hJR29douLkQFBo68kuymnnKo8rZkUWc11AzmiJDnJf8MHfMe4", - "2iCea61uA5ZXWhYpvTDmnp2h7Wq3uv1o22k9kDi6WZuX4RsvDi", - "2k8LHm9kz96J4cbNWMvvqNtJpQa9xCc6YtbqAg1F9nXrJQ9pfS", - "2mMAZN2Ma3Rao3sBTRd3uSExEQXWFPbbQnxzQfK1SSp4mYTUUQ", - "2mMKRBy5ZWcEfmXRaWF2nR9gvPzRgRqrdFjQjuMsrfN9oNWxKf", - "2oSWX9ux25jXe55mEZN1cBingArYThWtCDLsDhr2isZtBh5ZU3", - "2p7HXkRya1trXfZ5kdNosALBFYaimLoFYr14QVo8qaMa3wTQws", - "2pmuxPNMfd2zxqfs6Xrt5754QmVR5aXUvGNWNn7fmM1jxvQoNK", - "2qj7qZ6WbVCtT2QTTATGjcdSU7LGC8eBHsMzYonLHLybSoi3zb", - "2sBfEUvMx7L7buD2nDLpSUXXS8sR4gznt3KxSfrHz5VeDKecK6", - "2sVWHCDgw8irCr1BCx4H62kbRfWzoVUGm9VEpw9WKTDSouZFL", - "2uEbkViaWa3uJTphvudNqAAY96kaDG7tzXRCQcGVLDav8Gbvao", - "2vKcsEcq1hkmJmtqchRRNdPPx3yUzCFwo3EzwYi1J1D5hMQriN", - "2vcGhKMBP5JNCYcuAazBxNQiLPxZ4FCocoDPgLHhFHSQK1zLmQ", - "2wLEVixVCLiHNEcSoh5Se7XjQ151BukevAP6Gd8qrEz9XhKXKb", - "2wRz5cLzPMATR1guVD1RptHHye3CydZ9KgfRzptUiK2YQyt5AH", - "3xdWqa1aXedPdWCyhtZi8n8DtiW2GaaHdvEnPCYRfY5bWuw1D", - "43db7QzNPdFxPqw9zBhMFcJSEkL7kutJpPBuQmTpYCHQRQEQu", - "4UadCQ3Uvjd4QLBPsUZjRXV2on9r2MXXymTJ4NHWVuXh4KU7Y", - "4XisoAHVHeNKytvTULTLMNNNAHE3cFG3WEkBHQcKjzQkYyeX6", - "5D4VjMN8c6fv6zBKu7KNcNTHQguH6sBnMNHoMiGZgUa26FaAP", - "693Aoq9TtEVi4QB51eqpEecpVLMWTG1W2DdNco2VRpEkAEowN", - "6JBGsVgWaNyzDnD9A2pmTRYTyRGYM1U6GLjCopCJyJun316ov", - "6fNsyD8zUStRKLR8A6TBVozH3ozJH4ea3tQGzrZpdFx7aaXgP", - "9JT71povEckWQvc8iwgoZmxNKhonmeBiQcGeG5uD8aSxzigJE", - "9TFR2TmyvJvsa8qUdED2K1iGvDu6iMUWE7rmt6cKamQiVp8nW", - "CULPvaK6i2C7V4eRnQqKosMjzDc2YeAbRrXqzc5nEYRRg5byF", - "CoiAuuPMNhVBGytjsM2D6QTSqAFkb9mbAaeJ8EELHrP78wyDo", - "EGHXu22WF9mSHfkmQGrcFa78aGKNpQHrf3kQMXvkroTp4KG57", - "FyuoVPbTvmAwoMMvauGsLu25QkRT2ffCtuveAAZGFnfrFXpGR", - "GhTxU8m3fkBzN1a1fxfnV4oFPACqAZfnu3iayiEMcV733yq3N", - "HKEFB2cTrLc3jq8Eevp5gNK2W783bgJntPT9LetzRThK4GWbF", - "LU9mnCVtCKVAh786Unb8rR53WWSWw5TaEfs5TkEhxZm1kDumW", - "MDAux1a22nQMTU2yNVgyrbDoPU5Ym37kFh3nSqtBKNSbu7B5U", - "MJbvKe3mG4PuCrGrgiKCmUiJqMW5iFbaYzLkPG3o6oF9sDb3S", - "MWeuiyZC2dovgSWxHwD2dtJwZ4bBb6kynrUH7qcwK7T9JDhSe", - "NjwaUveSc6nfRZdwsLp7LgDJCNXKTbwV5XusjK2wyxXNqtn4j", - "NmCqVhQWBbh9ogkWjoeVqWGgkHKTtosxoDh2nPdEWZ8AQfwgj", - "TcNkLFGvbk1oSy3BsR655T4irnvXq2o5aFcRSjV9vx3haPpoM", - "TgfoQbxhbvH5ukjUQz2aoZVau4p9zxYi1afYjHPCWuDmSbTG9", - "TqSP2Qwdcf6mmoLAwmh2B4PSZ8T5L6kbWuaVNFqHfUcTN9vLE", - "TxAbe5TanwQyh3yLiMjLfjZRE7GWhGqsybixCDFhppJZ79qzr", - "UWQ9xMgsmmnAnsLPPqnEAR8Qco5hEVD8H8WGMYtAAVzGvRCHy", - "YEjyUmUMva7AX8T2eUv2JrHeLf6cxjSppZN34XgWqGVkKSKER", - "YXZEoXrp68wmFg6S9i84YHkRcLJPrZEsT4oQGWipgwZArD54A", - "ZKskrRDWRWzYBk5zEEanuKJbYjxaVSg1FzJxKVuDT7LyYtmSe", - "ZwQH5ki9kwVVE5Qpeg6tSLF6ciid5Qtbg7HuJnYsr9RvpQTFV", - "a3cziexWAoPKNpue1yvsQNrLPCuNmbgxmaX7wP3cbYGfkTxYv", - "bC1uQUxr4fTk6WXqwhgMecBtGFWw3Uyzuk68GHZkn19k1S8rd", - "bQdKidaawr1NZTnbrEnAJn46TB7t8qyfnAxgDH47M93XuyQY7", - "bZxvvKp5GuwzDed4LgngN3rkdxxjnRV9ZMWJZmLteq2CiYfsj", - "baqCaeXpD886QdQPtfqBUHVq34KuiDPEcw1TDyDHHFS3PPUYe", - "c2TftZBnzAk2iE7QhNMeYGxG4cYK7p3S4WVHx8yWFDx38FtSz", - "c36RHow7SjbGHwkoy2yEeBnq8ZUiPqPndHxAYgEWu5pHrFV8G", - "cZK53Cyf7WsNch1arhdJbMUwGHu4NPAt32fQDCmePWcsDNrnN", - "egZE8zk5DFhGjfbRyCHV2hLAXh2NqXzpQN4HBKA8wYMuNjjFB", - "fw4ZYUiKbkenFZgGeszwKLiu7VkQKvhy2FPpmsH1ZYiAA43eS", - "g2wo44qqYqakCM4NDgYSo1YEQknWq9K92QP62SaNrExqGg3dX", - "hmUpps6g13vAiorcK3fJtaXeCs9C4pzygk269XoNpYWE9pwLA", - "hnV2YHfTxCBcjqwSzYDNBKTikiqiDfDsn3s4ypyukXog2bLyh", - "iGQfwhtJ8aKpatZtgHTgJDUAEzMuwePMbRGk86fSmTieNLn6", - "khWVWX8eL4ahGJBd4E7GySRXenfbF4bqX79ZPuMz5K7rB5P7j", - "nHR81kNRdwvJ66ZxyaT2dZ6pgJtET32aEWixk62W6QXT5ZR28", - "otVKKrh7Dkvpmd8BbnXiCh1ivnnvJLXft48ajHxduSEbHrshT", - "qvuGSY6oPt8a2jYPvtHPVKmR4Hg5K77rD2J84twVMxYhfZLHp", - "sp2ec7ivV4BheoGoBm7RUpjGnvz4AKruvtq2G9ekmJWRUKNuw", - "tNM6B5Wt2JJ1DXhChZbucfckBwwTxwX9fv7ZwBppsCifpqneh", - "v78MgFnTuxBm8hwYhLkjphFXqdSZaAHPJXwgpcHGbLYcKnrF8", - "zGhQDuTyFxZrY3NE3QzBU4v6r8RphEJfMPUgZ2cNHuC7xHbcB" - ] - } + "fuji": { + "11111111111111111111111111111111LpoYY": [ + "223opwBisPqPFJYMGbHvmvNaBb3EVjHqDbaCD2k4DWmBErychP", + "22QytoWHKDyqoSHzEg2jcnpy2K1ocGhfLVvV5eUL8M5WGQyDUo", + "22eMTpCKswsDmHzxC3rq1foxecqX27DveEJD1octSqzu8dLGSH", + "23xcXTT2TBGqos4qsNmfhH9UdvEo6SSgG3K8tHzZSHgqRpuqF1", + "26mZvbGt9PVowp86TZkX5y8AxX66qgcQg48f8m6PGaGyyiMRxt", + "27jmo6kXpEHD4QsPNiXDZvN2mauaMjQdPdfQ6yqjZZTgd5fopi", + "27sYpucSURKu6AbWSKNLz37kjhXVzdkAiWmWyxBef1MaLNXyKr", + "27uCd85pvFdjGsnP5H3WKei9W7DBJ1exsG8ySKzLZ24ffryds4", + "292ig1WtzAxvwfdC5RoqvMHVcyQk9jwJeKPUXmnJMNUBmubjTW", + "29oddG7fursmoQNLHANS6h2WNftczJivnx9srxPLhqyv8yUG89", + "2AAxNFWkm1TEYuCmZP9aaP4MAX4nKuRk6HBGwPAyBsjVSpDait", + "2ArnZkyEykgEYvPBUnDQoeT5hvp2djc5chhPMiBddC3MWTXume", + "2BKC5Rw5guhbtq5ZzPBPA6tB7p6KT3uyqJmL5HJpnJoMCTLJcc", + "2BtVqL41rwv1EpLHbLhGGH7qmbp8CS4iBVbchy4XyDjXpdw9VF", + "2C5hHCqoRLh8VrVVAAPJXXsMd6gTWF7y7T6Zw8cFTWhNBPF959", + "2EALbD88Aa3jG9tyJ1EeTuNrMQEripPgT45ENoWa6kCBey4fj1", + "2F3nmzZ4zJwhDHpXyCp7qHipiL5x3vZ4E7U5GbdMioML28eGYW", + "2FasL7vS1W7KYydt2SRexThpeRc2mj1mdwYQGFVJudXgtNxbK", + "2GGCrHkhqYFsmZzEHGXBKTT1MYicZMUkXENLsxwCJEJnbLds2X", + "2GvUnbuw1Tzat9ANiBe8VKTCqCKqRJhUYbU2ydMHzhacdVjs7d", + "2MyJWUpCj5sEEfocM2QK1yHikmsmUYj1ohy5qpuBTV6kBV7SLV", + "2N3FEhJwqa7yQj4yiEUQWmiUjPXrwbwUdhyjmTWG4RY16dstBG", + "2NdCscMk9ptgb6rNSNN2z9jbAVS8xrHMiXQ14nfs1ZtAebfmrJ", + "2NtjDcF7768wapKgGCP2QMtkviypLQ9PRbEQzVNGHUDKoAFe9r", + "2Q5ME4Qu9tXheNCbbvE9ARYTBwcyeSBsQQQAcvoyX9cfqCzVqi", + "2QGPPTEQn8iyDcQEyMrMH4NnFoeYgKCrfcYd3rBBkvu4YG2FwP", + "2Qya51sKi6kBH4AYAMQLcHpMT5uDsuVZgtounj7GqqqWVvHW8Y", + "2SqsMUwbdGp583RTpewTnVwn16kUQon7N1GpiHJAScE9sw9dwt", + "2T57a4UW8HPRagb6dBftpVEUWCBzwP2ZeLrjL3hJeusDTXB9no", + "2VzjdKN5CuPQbZnP1AmqTnk4zesvpLd1mnbS3Nga4T71Xx6nkH", + "2XSRDfkA8vyd4EEwntPbULegRsV4ZuNkREXnBpdoEw2Fma1KjG", + "2Y3oAtgb3KtxmCEcF4qm7piGFuRX17abzv8dEDGNXeVX9iaJwK", + "2Y61SGxffumcVCkUYw4ycGe4BXYtc94Xm68XPp4hSCYDFZTess", + "2ZbZUZWqvNNe2W2FtdKiXcUCPBrm5bmX3SiaanQREFAxg4ev3Y", + "2aYuGkvExCVfptTid4oqKAeQGYrKZsxwuaLot8tU48KjPQBJK8", + "2dbfhBpFjL5VM4uzbX6npNbWMKPxWF5DhunzEi1Hj5hxDp6hK4", + "2igtVfGcQsSiADeKuRLW39RRZLewkTwhCGRvfMSY7v7y4AD8h5", + "2ipN93J1esuG4e4AYc7ASZBUugNP3x4zNbKahSavkrxinigJu5", + "2j3RXzmGYkyjkqJSXBmZChEuq2d159XAq1dijjWsWRSYi7hmv8", + "2jtrFph9tduRQnrwrKx4qVmfPeZAWzPGTzW8FvRnzRVYhdTYHn", + "2kSoQFdwQiZ7cnH1mVV2pAYBh4M8BcKHHo4HuuVhs3XyRbmBYJ", + "2kXf6mnse3hpoY531Xdoo6fv2vNJdT8y7V4Ud9pjNzEpMREBzo", + "2m797oeWLxKj9UMYfmwZajEjG21PzEd5RHBsb14pmB7mWEbM1J", + "2mzCA32ZmnoCfSGVhqtdrKtXBg16edtoFQJAqqJvy3Be5r2m7N", + "2qnJE1DDHmk4K3R2LrvoJMiMhJh5PymmrtfWjwfVpyPHtUGqK7", + "2qxgRBRKWKNGaBQEyxc81MwyY822vL3EBh28xCVDY7jA2m2Tis", + "2r3JH3so16Sm2wR6DoEW9mztToDm4cotAJkQRxX23J8NrmTKUb", + "2rB1a6pzf9Bk7JaLBfDYUUJbznDCjHVbJdcNzxR2oCMzgqk5gy", + "2rXgjQJgtHsQX1ijwj1XvDULkqkFziDT7oqfYo2gxAe6HAtPd2", + "2tHb5NapTuTEzQNFearDkh2bFTNgk4Bv85vEuwVAxDaESRYGxH", + "2ubwFU7pYNw2EPNsVmb8mLAEp2xfUBnwAACjKVHuzeApEPaZVn", + "3v4Rs8kT4Hr7fr5p3K4Yc5GmvBDieZv96CQH1fEG1QShPLX7q", + "61EZVNqCY4Lu7kzWS7Y2rihXaiRX1jT1o3QZPwhrDFqyQ2ymZ", + "6kqdpwBMmo4YaJs79p2XbuGnH7KTwWSye8c2Sqjc8jfERYuGN", + "8x8PagWMhJDDaya6oTmxbSXC2cfubqkqcKeXRvXkEqPnHwTHn", + "9VEBvpL5jEHxA8bnicvTqkQyapdjrMdp4PQyANp8D3GLGSYxy", + "AFFTGZQmL1GWeucQ89GFNKvjXprQbEzUBthzwjeVmybKgWNbX", + "Ag8rmvXryhZfxGte4sQccqJ3ibKvmdLnYYxwxFZpsiiuadxW6", + "C2jR7wmNuAhqn4y5XAGMFTJJGoxtc6QhX9Td2Bmc2T32DxuSE", + "CPw6ptdo67PWvHhZi1axonjFZP9GyCcZnjSWaAcunU4FPVSdn", + "CeNMWvAE9yUsbAap7u6dquJ6NGrUbPfF6i2UWGRKTkneU29XJ", + "CyyG6WwyVLP8zj5jDCVyaXH11auzRaasikoWbyWRqWfE67YfM", + "DPeEFcS4MvCWEqj6s3MQyGRi8vjc3SKySD56piTZBeWjzRsu4", + "F5QoLN7bJWJsLv6RgG6JWfAe2XWj67wvN7crQnoAdHYiDjark", + "FkqGhwHZLWaAjTEWPpLwvSf9zNWnER4XhhuunqsjuTfNRWyZG", + "GDcvEKFfDbFpdRmUwCBmHdSF12SxxMjzL2PNK6EXGMVWYPPDp", + "GNd8AChiLADLnqTmypEhS86vre6QKYpcPKUKZUhFnyB8gftyF", + "Jjp1kBE4tPMmHqQq8XeopNMREWQa8RxfLtv41VhpUT6jxupCt", + "KKYswxetFUrEcDHgGv86R9TcAegkA454RSFVVFGnnGd4f45qJ", + "LQ71p9PjkYBVWTUz9GbKPaFxA69V5pv4KQkVWNChKbCpKghiN", + "LrxumguWFXGaXty4nPzSzkogUQ8WBUufC2JGQAQ7D7KqgupQd", + "P2PzegHfs769nr5nEz2fFhbnPEBpEWWr6cmD8cahvvkAL7SED", + "TmwsnFjxo1jFsBr5rPH8XHLm3AtimbF26xBaxdmw9SYcHGNax", + "V6oXi4fXSV5Q5tvGYquWfdaZBBzUWQDS5iepyzsUtXg1yB6NB", + "WWfS2sqozxfHD2z3AJ5vgkyNbyYD8nwkJJJEut4xgjstb6JKj", + "X6LFRvgSX4rP9A8Fswtus91fQbxhQm1GFYDgTBktiZxTDkj64", + "XUE6WNfCKmHTcaNEsZQ2KftvnXXfPTKnZi5YBw3pLWXjTYZzu", + "awbBnaBnjKBc79RzRPn4LXHMTxoYL8C97toXVvbKPZf81iUp1", + "e3zK4rU88osx7rB9Nq35uBXJrfShm7f3eqVk3T3CHCJD1SrGg", + "fDLU1xyDSihqWErnm62UeMXZ7HNe2atawSicdWamFGTQbLv5z", + "ffHAHY1qvDLcL3u48VHNEXtzqKgTvoi56vKDMcinoEHyy2FTQ", + "gT5RrrsG2bAephkx3bUT9VZGAGVoosGj9Yn6ZgVwbFVWJVv4x", + "hHQYrV9wu2S7hzkewJpotYymvjYpPb6RBeH1oUHPir1EZwyJc", + "iD2h4Qw88P4ce7rbKGJaxXwJLsPeRt4h3kcThDEXJ82HF84uz", + "jB3N7Rd1HCJeP9wLmrDy3NMFT9fkVJ1B5G5KBoFVVRQxc6fpQ", + "jGSYaQZQjieWrt9yq3yUWkW54RYYKfoHxHaRqo9fEBKZ9zAu8", + "mcAyTfg1i71Y7DXjTggfnWrfdjnSWqtg6uHrH3y51AHTi4Tjc", + "pSLCmmTDhnxHFiY3FX4fqCSii65EhWXaRPef2rTHjcp63nVYS", + "qHaV2XmsBRdXA1YDLn8nCYvRAfQue3CdZM3YBWYvvkcW2gMkQ", + "rghpCpaeyY6PVnWCQ9GnBDGtCsRLsdNS9z3tDCSTobsDCNUeM", + "rq7F6LXvXNioXQQyk7qVgMwoHWWAK2UGQrGyJJjbqYH1CYaVk", + "uLPzkqsPd78pLTUVuuXz257nfJmJcamQdAFjXYCoKDuM8FbTz", + "uUGfX6pZNS7jXJW4uF25xntf27AAZMT91NLRppMZhWw2x2aEu", + "uxDeD1vay1vbN24j7Rs5h4kV5q1oDYBmwj3iUvh2h5meCKacP", + "w9djCKT2Em3S6URCHXooEiDWwjeahf66sAL4tBeSa4ihJofLb", + "wZC4y3LB4SPbYZt1NbqrbTJtEo3iB1VyR1vTPm3UknSdsbA5y", + "wt7gkf58s9uiiapcC5DL3Y3iunfWnewQu2woS7FAQx5yDBL3B", + "yXKPp5iLD5mMZp9cV83yD9Yomm4o9nEPy11hU1aPFvRJhTqwa", + "zoe37ZDDigm6owSYNyEgRe6Dj7EiusjxrsnFzPpHLw7EzSDPP" + ], + "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm": [ + "1GBo9WQ1SyRFZse5xhiMXQgptnzhepqnajzpdCvAJ9TNSJT5t", + "21xHKbCFFxmo5EdGCqR24Wvind1LR2hMWkHztqRxuu2ezRhE6b", + "23zbXVVjaix7VcFcU3jxJpGiW6TFxaEV29ZixDDtoGTkPF3eUC", + "25H3WwoqYUApdSF5eugBWEwqfpbmDtdeFLKFDwQqMD9aKHSBAD", + "25HTUEFnmPc193wW4LZUFjcyya3jy3Ws4psiWp7EU8X6WhAHn", + "26NADDbcCqF2xx5yaKTA28nQYcPCs1gcda7WwH3Q7sznPXZ71u", + "28SHVtdhn9MvJzMuzzGC8odjvBNcYvyAbtV6qBBricfP65NjJU", + "28co43WdBgJP6pi9CnqkspSvqeujm8oTK4GoGroi5ZZZqPnSQF", + "294ofGLtC3h62jc8aYpbnnsKJ1ufAEmp19rViEC8senqk8iKWS", + "2FGfG9MqLzwq9jjHAfx1QGtss5xKH6p4cZr2KQkrjE1Tin9B1X", + "2Gmqc72MXrXT65hxkDjuGS7cAJmwY3habQcr5HmXLDAFzyVJMJ", + "2HCLX89frJuqbauSLFreHFQ1t6yJSPb213hn8gpDUJW4ABsr8q", + "2HgkU9sT1oN6pUNt7CGonaTrcgQJtTpY1yHMjj4BYoqfECcJT7", + "2KGfWNfFrcc2qYw4s9oMiS29buB52h3UPoz5WDarhs4Kcey6H1", + "2L7ZfaHezUSQKoKNotq481hAsqafuCMX6DjZjvaktRjRfprjw6", + "2MctCP1iN6hskg6iY2EeGJRKJWbficY35UgoUMRd5PoaE9aagz", + "2PDa7wqNYoAHr3oB89weNFZujVdcR8fpjMPmr6MbUsWDsFQ64p", + "2PKwDA8c8BpibsyHim7n152C48viUt4wtccoWy5qiLiKvZHUVR", + "2RydwjCt1qipkTUXtjdxdQzwVCDjPLE6eNVzSxzUHhjBHko6vR", + "2SssQkgDtWc7dTnY4DSw56ZrCXBvL8uLZjj16hS5C3piNqactA", + "2UFZQKZ1gLuzqeEqX2sHLtZNL3Bxmv1NQL7GdqS6ZvSPMjkftT", + "2V3QXva1iArd88hVB7JsEK8tHn12a5qgifcPBkhpZGWc7fRRis", + "2VvgwD21RGHpEJeUTxhEVyuTdMDQN2Di8L37xPtmirYW4r22d", + "2W6MYE4TJZV43hjj5cMBHG1rEeStNQLXE25VMydkecAorZNPRF", + "2WRmUjiKn4xtGyw33s9qtyhzLvYPBByRoP9vWr4H5Hy5WKYr5J", + "2ZX42ozafD1DaWAKK5Nfsh9FUEKiukFKYfSFtwpwBxU5VLpBHV", + "2ZfNzhvVrgMLy5jX3ztgZXxyfvvt5ng9fjqqmkEPBq1Ds39yCp", + "2b9au7DpArhJPXDJCSFR2cMczAacLT9Xi2umZG9MYXLprkm4iU", + "2bKoipmXErGTPCZedKDwPFKR8v6X7yGmtgZr5r3esN9cRZNxud", + "2bLQd8omCjWuUik2LLPKaRo2AQ78BNjTvYbDsANhFgGjLBcEeW", + "2d9azyeuYybkt25YBwSSVukSdWko2EB8Q1ii2TdvjuNoRwigJj", + "2dUUsFXPnytJjnPmX1pQufNUaBh96MFQuPZ92vMa3XcdGCg6pg", + "2fw1AN9jJHGTEuvNBxqbtejWukHRfxNJSqfVpsFYXJY4Vbw2c3", + "2gbWojYtNF8YZmpJUuq17vxRMDreTTHoD2dUXspDN2rtucHmT1", + "2hLra7rDjb77NNF3U9LHMAZ9MqnJzkAY5xEG8ebMjs2DGR1KQD", + "2hNwDNBFeaHZ93VicpE74a5PuLDbQYb71WHQUVdrHyy5ExXPLv", + "2pCJ9gCnbCFC8e1xQNYgu63XQzCLqp9uupk7ePgDX3vWvwoPGb", + "2pWxqGSc8vPJQheXoJNaRRSA2NZKQ6wSdCvdhWXjuKS4VPdDCX", + "2qDzuN2ooKLnEYc5ULhNMEKFTcWu5cSKyipCeJuVjwfu7mVKvy", + "2qTfSXsWBbmuai5iJFhUE4AdpPbwDNR6QWUgjsBPGKdc3R53xw", + "2sE3rjLpaNnu8HAa49hTjYJ3y5dDQwz8TzPphVcJkcihwPqi8q", + "2sTSDCaRduH2oAtCA6cihuDKRbF8b9N3r8bkLYur8dHiYStkQj", + "2tFh16Z6eTzzzUQYDMtMcW7vCYVnZJgNFmvcXKdKueqJeHduLo", + "2vf1B4QJwuhGNUVHitAggar9iZ6GMP6fvkNBBNFxmrwn78Xxqe", + "2wfMYUvLzxtHK5b8PE938LrMLpzL7pMkoFfVZ2P1wb65FVSMDt", + "3oxSU7pEZzr7MMSBLeWprp1e851JtwHT4YCvEzs4vzamAVCfj", + "3srNc7xjafT7pkXDawHisjRyEhdedyEaxpCVdeeSF2eFFFsp5", + "53CPVeV8Jr6amsGVWiB9SVNZVN9vFk7i6omyCrNZxer5mfWqZ", + "6G2qUWZCW2MvgxpWrnR1azuTEu5Gnv6C66eafJsEXbQbV2yRr", + "7qxMYH7p8QsHw5u6pE381gDFESwBHrzbYXK6BhQ9kMp9dmKe5", + "8khD5WmMbwDadv17WNPhsd6Cxu2XLun4n9Pc88Apmd1nNYK7S", + "988Sk4hRBN6V4GQk2rMzKhTXQ8xPy2p7bQBXyiFHknHSLeSdC", + "CCgthPmrL6fsPRtVn5DJAkGs3wnYy8HUSNmJ4PCgDw2beZAKb", + "DKYASkaDm9HyVskLiw9foxUf2exWhWqzgBmnwx5yncX1jDJW4", + "DYdaBt3C2QS1qDoktpFsUQCb43F9a3RzNPefpCQ2csbLjr224", + "DsBjgvFW4AA3GkRav9VCDSnAFYZxvT6CEYAmJvgKaXHkpFNYg", + "DvkrWrKpM86FggT6Yzu4wM63Yw8MPWrNGBa4tujPm9NSR94vf", + "FWXEYzxYxoEQojLLsw9GhFrHA7NxYfrsiFHozt2xV419ih98P", + "FjL4WreWPpTFxCDa3mp2KSxuTDin2yeUfNDiHtMRhnZ7uXWaf", + "GFVDQyM6LiDbYnLQBjYUZQixk2fDLcEf1zSDb7KFLbTwJJfik", + "GaFX7JQGTVQgKuGHZL6fcRqHiKBioCJpYDQ7w4cijaUMQXnut", + "HEEvCX7Af3TPBAJ9KLji1fVfjHKH2ZJwVsV1BnzVKoSR8Xs7C", + "HNgxTBLk1Wa2mTNeYkYYptQLANDTyT5mZHpMdaBjb2axziyAp", + "HqtaYoyEE92oMZaFzdh71Y6zNBs6T8FR6zHJUd3c7cyuhJVGT", + "L82zC58X8yvm8JgfyxtSBUU2GRUAdVbYhWYKbYu7B46ctgNBg", + "M1necnfahQee39ogPGbv7kkokYnUsM6P8npqegLV6GqiAXF1h", + "MEj3pMhy6aNowXkzgTDsnHoJf7E3zKf5sJi5vuxqf4AsdgTjs", + "NbJg4zwzKdc8S77BgoHyYknMrSXzdtWgj98tnPekbQ2z2NTis", + "PD5ZjG1cwFHDjyeWSWYoAhLkDfFmc7ucEmQGZkLPfygXLc4XG", + "QwUfCXBeTiPL3Rv51CxT6BhDw1GkDbQovnQAWzp7sT5FH5a9J", + "Stp9k2uteisQPNwUG9A7RQmW6yHaFz95WbLDRWu6QukoDTpD6", + "X23yYJTmGHgMdAYc2joMAzPc8U6d3crwrTemDNRyWYvTfuUT1", + "XETk5x8XPHkX9tAuJa5LvkAc5BXCzCUeMtwc74gfxauH55mkV", + "XUR1jFfmi3G3CK8e6ckwDis3WJMXGowJH9KRTAs3HaNuCFemR", + "ZhxYDBMMLeDwcbzjmM1uybVcx6Ea5pW6gZ75FMxG2p1gAypPk", + "a7d5UaCCbdW86qszpNc6WSow2a6RbNMALTLZwkjddk6WXfWEC", + "a7yqQ6WwRiJkyxmcFjQ7P6c6HD9ggMzw5RhxCkciBpoeEtwKQ", + "aBARTG3jtQcqY4iBu6ysCYfgv5qxNZ7tRgyc4vfKr42kbtzDo", + "bV2La8TYp38PZZVHLcdf62dBxyshP5QdmxoM6AXwWwck6Bj5w", + "ezDVeSFwtsKVj2TKJgnfFk2Ron7XBAnSHkXQaCxg26kyFKKNY", + "fb2EBwXSKdfVMSANF4suB2gYgPZTTFHEgK31Be7Yduh8aUPwo", + "fr1W1wLpVup55hsC7wap8Ry2TThMxbQYFmV1s8h7RDMTm6m2B", + "iDTh19j3bYnSSkQ2zhpKYPFuep8hHZoRo6pKkWDotQU1CJzJF", + "iZpg4RdbgzWHJLD8fx9SvCTBJMcFRzBbsobSZj6YAYz671gs6", + "ifoWGTKercg2y3gdugrmzh3hZ4NyDm6xq2yGAXGngRLVRHU7S", + "iuaz5BC3icH5f8y6koA9DUpnA34hvUDB1UALnBYednBeztpqC", + "jhzhmCBQRwZZrw7pTt1S9Tx9FdJ9VjHq39z9yCadSk31ab9Hr", + "mbHxp14KyQwjvyaKjP2jErwK3Za6iwXvi5N49dRyzUhgTi8r6", + "mobi3yL3zSq9WwC764pihrR4ZUZyLfD4LTS7C5uosXdC7sQaH", + "nCA3JEEwcSfdwV9aCoG5VApSLHmBqaCBKSXT64KSuDSEix88n", + "odgEc4y2JaqMeoXnRoh78EL6jnQJjdhfeVFabmk8BKqeYhbvu", + "pUgAh6Qik6Q1zgK6iHRkPnW3KHQ4htPJVUQK4SNRFvN3bwvaT", + "pauQnSkSBdq1we7935UxwyPBaVE3ygnLeKk9AMZvy2nFPgtde", + "qTg4ng5mihJsLnuxedfn8pXggCoDEVZ8K4zKbebbCmnLYeST1", + "qx3w3KKVhVPD9hJsDxaVRoy9k8z1iWnQNXxM193T4zwJvJnY2", + "siTgYyVSBf4rFpKzZrW2KRKteSZRjvaPz3qudqQiZfCKFfQqs", + "xfjYyMgV6RU882WBsWoK17D1TmAbUDgsgyVqmmtPVpU8mr1iw", + "ybukLCCdJvShHUs4b5AzLK4J7tJ2R6teio7d2ty5uJcEd65a9", + "zL9t4UtcRCPa2LikAW2Rejdohe1B5zhuUZfaEnk7rpoxmuoxV" + ], + "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp": [ + "21JvTSoPZPqoqrWobnUorujLTmYXsUWNUv5rBgBseVWPdXiGDa", + "21U1M7PKTzUVgZuQExDPPPiSW9bA3TiNs3D1aJjreqGWPcx2yN", + "24ixT1xYtAUCyVsfW8TbCMBzgtohjnM6YVxy9cScFc1uUrMpdz", + "25UMxnQNE2hbxr2Xy6oyZ2Q3B7cmD87RFhpj3CSAJaeXfyCtnt", + "26LqvB7kgRmoaLwLWaPhwcCCvrihGrmrGk66A1PECikaD3K3Bk", + "26X99fmDv36gVAD3tFQBTUiGBDQ36fB9usfnqPA2MWRVXiZ3eM", + "29FLDEM4v7V8d4xtyZd55pWvLSSTUFpcqcctyQwFFcvLyhA8Yk", + "29XVtjg3s5iZBYAYNoB392FLv6SCW7bdCC9nW723rE9mEve9xi", + "2ATHMbVCerezgWHK5DCSv47sKTL1CpyZcJAavuyoNJQrnjrGbn", + "2DFMZrvfLAQg17dKVVSXMyqT7cXLwSmbTUuM2rVRJHuVKhGRqD", + "2GPn3DL4GjCq75QfBWVsMmJte2BDARTrqvPX4rvDZasQMkuWt6", + "2GXt7XVXurpZWFkQK8eJ8ShJgUwxxr8ZHJU2DK7Gvm9nkkQDUV", + "2MJJKZrbnvxMrDTEHdrmQyVNdaeyy6o8R4n3UsGVUkEtBViSSu", + "2MtCLFzvzNT42WFCW2UooFuxFxdaBqKGVAh3EGr4vHHNnv2Cfi", + "2Prd2E1oQ61Bnx6rQMPvLJXW3DLApiHdH7D5m1j7ohwmHUuzwU", + "2QB2q7TiiFjLUgda1A9bBLBQGgjNgkyLdyHDvBe1bGZsmAVgeX", + "2S6N9zzrmACZymMBadkoseAxj14EKkgY3nABYDegRJiqZQfm7Q", + "2ShjekPdvVJSCPCXVascxcoX3JJ2vn8Utqar9XkBx2LNwLWsWW", + "2TD4e2fq5bvAsJ87k5sbsu7BMGnbA1ffYRxcfdtfHYaYH4i14s", + "2THb6vcU4jNg2EnJ3Q2y6a3UKEoXjp8eSykiPaYfLVj8ZtaHmp", + "2TfNb95FxPuEbZYjBDcQ54cMv5RDS7XiYcAZUUuDqrBkVQbN3w", + "2UYC4hjcgk1UiQwGrCeXX7dSoQe3ep3Er6BHgLKqMKD6e5nyoM", + "2V6r1qcMQFBLB6YcF5xihgFKqwREUGjwin2wBokTx35T1zw5Kx", + "2VnJqxnuW1AydCb8BZq7wc4hduVrhwkuiY48pdwfZ4iUTHqTSS", + "2WaZXPPa7f4vvuqc3Cx5EFjXJSGb4p4cmnu3HBhQZTuBykEZ9v", + "2Z77eDdjw5gLyi15bFxMeV4ur3pZ9Jj6Yg3iVq724iRxrMkN9z", + "2ZhTJ2PBZWmoahQRDCh665bFXpXQ4r9LKGpH5qJwLDU6moYtE6", + "2a4vLzJy2BJEA7EnTyppWWhjBSwmAzF9acgyVfuoXdbi57de9W", + "2aRPLJ3Qc21zTKB6rfzQigeLoPootswtKseS5nA8mbppCS8AZf", + "2bwhz3TBxpvUpsCYjgfLr8EhVSox8N87EjCjU44c95kmM1YTKg", + "2ddNjV8voVqYbhUHJqRZJEq8YVChWFGyexzSvXzoxtsDJziUhn", + "2g6McaqCUaz8qqCKwwL5kqYpuejTKcoGUmBQm3LSZxHunJd4BE", + "2hDZAR56aJCR1M5BTGpoMPB8cqp4SAF36FevBNvoG7iUtmrNxg", + "2hTq3Zz5J81egcdTgCkxDZP2Dkb43SDG78byiL5TAVa6hrYVhj", + "2iWvFy8kCQpYFaiAt9hEos9XYsLASMXdfuESmAQLB7UAVbRfN7", + "2j3kJruoJ4fiLGwS14t3X51jPfi3zK7J7Cmx6wfKQTwdvjmeW1", + "2jJ3eCS7QBy3h62zfFSFMhBEMtKH4ygwE3rJ42nZkdsc44TanY", + "2kSTivAkKgr59AbEiqt9mYq22GMcudguiLSkutHheub82Vhn79", + "2kTeTwm9WVLGgrS3iorTtnK6tKosodzZnG6m1kBwJeaUgtxMdR", + "2q2dqAZ7onwU1uHTBs1CN54QSU32xzPb1ayHdHT1GVcZ5NfmqH", + "2qnaz9dWFgkKSmQ5uoKpDqC5Qxz4P3u67YPd2f2qXGu7WGtLEC", + "2rJ9bGk2wQtzx5fQuj9oX7kEUbSxdHmpXTLgfYyNqGa9ymt12Q", + "2sC1AGd6DvCQUpThn1bXM5bAB8zpgVTfJm9XtHPaqModdcFrzX", + "2sFhs8sYewidvBEaGKvPKFQj68qZ2cJsf1hHvhmUdeaqryiaSo", + "2sUcqBr1wYUBdRv1vmLVcW4NT6c5EnTYDFEz2UzXPnXSrXmJX", + "2t3Z23G2orACLFMhKsPoBGup1X52fbMmjsiH3fenmF7VxJJrqx", + "2unuQJLD19dap3h3WwCMuhYmNrWXhAAMnbzxKDf7GsWyxwPuM5", + "2uvxKKb2zhjjWTGLWouyNJW3zhu66XJiTxjeusN1VuP96gS4Bd", + "2vNaxXF62P3QhRn5EDnpuwHR7BsXs8iVDwnbypjK3KMVBXNoxr", + "2vuhJYm9CUdvbDkGB2H9tyHX3GRR7dn8TcEUbcdBvYencdg2Fw", + "2w8zFCZSs4xw5amonFdynnTKrGR2d7p88YZwaSonxtqMo2HkHg", + "2wUpYxpygcnCAuh3bt4rNfgq8Apz5TebLRADmRJBgoQgJFZAw2", + "3Gswg4voZGNRc9GMRLSk8kt6C3ZcxTqkRXJvPj1DMwNrjrAVv", + "3ZQmVFXx8yG1Pu7oVGUZend251zpjFMNrnDAHrXDYJH34uxpJ", + "3nbPns1MGu9oU625GrNXfhUq6N5on8Ywxt6drcBFdxQFbafar", + "4jnyBE8LLB9eEFGaDbCvQ2L9f5oXCK6BXW6Wts4crPe7LpTVA", + "6YVQC3zCTtBF9HJdgjQaU9USXnAUWizBPXp1Dg7tJpqe1hRCJ", + "6vCbBtofJL4MPK5Axvy7cTDgupqKcnN9D5uabtGvDo7wG2ey8", + "7KSG1AqANFavZ7mmfYAiMJ4k4xuSeUEcNZPEKw4uQm7HbHLBQ", + "8szbitEiP9x8sMqSq9nG232vCUt6SJkY44kwZ6kVfeyiBdeQy", + "9mKsC3XBsdqaBZ5ZcyyUhvfHNQQdNdxzTMPD5XoeZqqJV2QGb", + "BjFDePq9vY6bA35jBhV5WzaD7rCD3SEebrTQUygVpnNw8Ufda", + "EW551Lo3aDRBVgcz8qbGpiUjXZ6kAqtwMhtqnhfJG2Adp9opW", + "FqDib8XetbBKSLnr8rQZAzLfeiEqBb98dXwErgPwedphY7sno", + "FugpHTBdfWeYCQBQz6KuZeBjRAS2VBe4m5HVaK8o3oeZcmQKb", + "GUUR3s8Wvgjz9YMoj6Q261PNHLRKYgFCH8q3ihcGyWh4A8SK5", + "JZqdS91PEVohzTFymZGHdcCfRG93oLjc8a5PH9iJ2Gp7TjPYz", + "JbazoyEJPKjEHprDNBYsfpk23LRrCVAwpESoWVYZ5zAnRqz54", + "Lq4ojZLNYFXZ9Wau2yVwiBVBptqT1bmEZUGKCAGCQjdRgB9Pg", + "M2SSXGemukiiXBi45L233AbYjUxcXuu962VXMjwECi2ez4UbS", + "MYpMva6MUX2vZUKwiQ36i2q5Fhh3U8au2unMJ7fq9HxKcwLPq", + "NXHYS3sy32Bf2KoTUZzb6H4tu6EqnQafYp28ocd77WHh4vFZS", + "Nhs19efmaFctiS14S63YXM4Bub5DwPCLBemDXXs4mTjkeWGMw", + "RRjQBW6bk3XvADmJbzSxryU3vmcus5MAEXy1x15ZDR5psRJZD", + "Ui44APYUHu4TBdc2qp3mif87NmVbwhwsMbH63rW6cALgkCF7n", + "VUUxGtSRdz2n1QzMpLNUs5bBM55t5T94T5RfwyA1PAY8gqk1e", + "W33o9U9nHrf9hjPBfUxxRGxxkJ8oegyYFusE2347nKqwiXwg3", + "YoC76Q2LSxph3zRwEVp8dtayt1x2cHvzxuRihTKgrQzv3kckm", + "aE8bKYQ3nmeRbFWgDxwEJE19m9yvSoswHcu9x23uh1LtS2by1", + "b5x6iFkBDuP4uctnR53uGoFk8HK3w8cvxX2UzcSPYBsJaproQ", + "bSeBDhAPUG8FwJgJEDRVgHqWbcba6Wk2KgHxTDwpdUcTd9t2p", + "dkTyTfRSLJpbj14MH5Nru2GpjyW9d1HR8AWTkDFWyAZhVpNx9", + "hw1KLhzE6Qjsroi3EDm52hueAwgMk5Nz611VrX3MwX9bqa4aQ", + "jMwZAAGm6CxbmPhRz25vXnbpyDBN5D2zJBGLKkDAPFRMA4oZM", + "jSjNuDpRdStvdE1FAgLG6UcgiB7MMT2uQjUvY6p7DmjYSYnqY", + "k1CRCGyW5DwSATvUFmwjdufAVYM7ggENgLunPS6NPXV4dWAYW", + "kew14pgXuZVT2E2ZkE81LECKyD87Cs5umwmmaHnAsxjhsCohu", + "mmQbLnboofBqSwgbhPHo5PhXGjSXH4276BECEteDGJtgTxBkL", + "nf5UKNozY7qvt6HGmDFJQEoNoLF8be1SHLoHQt1yxQihm2AP3", + "oHoyVMzizDpf27HjaK5oRgpPUSQDeE2y1uFd5K8JvSoyZnTFQ", + "ouRzG5HtwcvbF89V84R2HojvA7i9c216hiFhxGiZjaJuMLsQw", + "pvQik9xSAbTHVDB1oT1JuwzKHpcU86k64pBWp29eS5RwHDKAx", + "qstPcyGzSMDEN9qdoKQ8zLZLtdua5HetNqVGv9Pxt3MaAMt45", + "sir3USCoRgGLgRviad9ghYZEa5f78WXjn8gJdXCpkw3iBZyHj", + "tKaXsKyhJeyhqXqeBrrot2y7DeSzAPhxR3JYECuGD6FX8BRtW", + "tV7mPELhdGwmvTDzRfX6nKZQ6vdw7MGkndybx3HMHmzmPXSX8", + "tjjaF5todmrADuDu6pbCUTgF5pRPH4HWyLBMfoxu5nj5zVac7", + "uQsjrStSxqJD4vNRGbiD4quyrU2kxZFYgeCLGXRm4cHr8xKdT", + "wCdMuaDh4iLn1oxrrm9otdQzToSvSHKbqhw4R8NgYZfozJ6Pz" + ] + }, + "mainnet": { + "11111111111111111111111111111111LpoYY": [ + "21dW4Z8zuKUpVskZSwFZbNAF1SPTUUBKhipZYxDWhAs7YtKzQg", + "21pB8ejhmvfmLWPFEicVMHfbYufv6gL5iqvYVeHZFh6ZMk2vtm", + "22yzBbX19yE52VBQgkYpSHZcjCpMP2qg253VnpWiQHeJ4wXW2w", + "23GTgAvaBxN9zhBfwymkEcNcNM4k7xjbf9Hfq5QjjZh2A8WiRa", + "24h1gSWZqD8wYAb7j3SEjJjhdmTXvYAQiPSHt3Eg4mdroprZu6", + "25fSTefQEkpqvrd8xLDiyqUBqLYWJPeksDJP5fJKCUmprg5bF4", + "25xdggMGJh5N8VwLP3ZPqx6Cscwt6oPuX4YM4HNUcvcniimCY9", + "28uHUK3WcLJ4ridusCd14ZsQy2cTDSBVsVNh53ymfhhVrGFmHS", + "2Abe67z1SJxcRfD4Y8EWz99CZQ6oNiayTBotPa4yHmgE9SsX5H", + "2BJ4izHDThAg3T9rSTzZinYYFJwNCmUFTcV9TPv88yvDPbLBBk", + "2BLBzaR5pGFwa4bA8yUMrqm4zDe5LaCTHsepSJ9EVBWVdU8xnT", + "2Bd5ChA8c1x3tHTEdnqM75CQ9sdMYeY9Ccd3Lky4T9CotrK6eH", + "2BpMKjdPVyQupJjjG79otwCqUfQM5cXMcVTpz2UxGkBLTpKzq1", + "2CDKHCkEaS4CZx7UJvQVsZXtsndBaaKuq8Y5wTcoBNp2TTKupx", + "2CfuXwhMXeq3Xo8RSzgP6yZax9oFps7BvFizG3S3c9uLhWVaJS", + "2E3b8DACP9rp6zWSVFkxcmXxYDWRdMHkjcQMz9RmX5XGYvcDB5", + "2H23j5d44EVxwDgDw1XDBQ21Yt8jGi5Bk9kiSi1N7bVNe2nBKW", + "2LXi2TagZMbS2VYZoB1HhV24eGpFN26WtNPS6mUGsDFPYy9PhP", + "2MshV3qy8WmXSUEFjnAiZXPNDpzZb9RR1DZMY91uUDcYmpsLrV", + "2NWffsfUpmW2EnJTYLAw5c3DBGjVds9z7x82SP4VKFB25RCpJA", + "2QZ7pat7WqMMCseqheSgZBAwGBd6ySsznEVLSLJJh4f43tDwn7", + "2QfzZ5W4DAgeYmvkqB9U2EEavzGJA549XqrDtAHTKsUyY1aKi3", + "2Qqk23b3Fzc9Tibww2uh9Xit7L3jxG8QkDKR9KvdSLmCJfaFw8", + "2RPzaikSStR1FnPL4x9UJgUwFgqGpX8DVLm54Sa44vjSLUJvAZ", + "2TGCyLfQo7ya82Qbw7jeq7rJR1B3cFG2vkLEJL39fb1DQvbG6v", + "2ToBCrrkQ7CdXEVxYHLoZ7K3cBasFW812yjA5HmNeP4aVscC2t", + "2WoS4aQJAL6azWA4tXJauBsCjshLyRRG884KdD9TUnCh8XbBFC", + "2XNtzj37k8FeKgJTeFkWnVC3Z8PkHa1JXE5rwKTJ9m6ReXQnvs", + "2YZM5YUy7znhpMjvFipdhLCipvvVutePEZcGzCAAqyTdTByiDE", + "2YjevVf2FPWrHwPescaiuC7k82v2JmjHVM6ZruuRCGHTqHeXzC", + "2ab6d7CpHJzsknreTVCFmZTCNoU8wCefaFNB5rQyDX2mTWCUY8", + "2bTdq6zTrw3aqyXNNmM9MkQ4PZrMsftUegxZRfmWsDgc2QSeZ3", + "2bqm3gFWAG6td4GTFuTx2uqKW7vc4uYRW4R8tKSW7WzPT1b1fQ", + "2d3rqordy3HTLeEbwJ9286Mpzyty66nHALbsoMmvqntVUMCL8E", + "2eaJEpkNEjU73MK3E3njW1Ab6Lhhi4sYTJ8oL4A9iPXTahBUBT", + "2ebDUe4DfvecEPWvK3gARRjXbKNSbsvbV2KCi35qeeHuPshSRi", + "2fezvdpCGvaRdoHmviJY2PYdLZWTkSCNgM9YiH9iJbS1kr32BG", + "2fuJCRTbEwi2EnXmF4DMgYdEz5fVgy2uL4jng2CWSLRyXNm1BL", + "2gagMEdwA3jKgdHkk3dFeCEDjqB44MVD8Si1FXpeE6Dstn6mPo", + "2hE2jyuicMNX3qBYYiSB9c8tQuEQvDf94cn6enU4RaBwnXkuei", + "2hG9XxsT14sSF16mmcRV5PGLfjBE4GgsRbhqRhT1qEBnZ124Vb", + "2hnpLUZx69Brk9X4ho8fBxFWuLpBEXCigKmtDAwn3F41fW4utr", + "2hwqQXGYpFDqc4HAcS1kqVE4dcpDqdG2RSP2xNQCAdRtrdxUM6", + "2iPnGH68dmFRytXceaAo4PAUcqTNq4vHr14Rndzysc8d4qfVWW", + "2iYS69eq5p2GC2zC5HDHrTqiswXcjLqGYYi2AFB3gWJ7EUW3j2", + "2iiF5GPo2rauQzkiHqEBPw1k3e4dUk7giXcaVVb9uS25HRyTYj", + "2o3rTsiHv8D2dcgNKJDcVwrL7NgYLQiPoTB9HFgKAESMF4pE1d", + "2pC1c1zT1w2g8XYimXty9rUFXceqhEjbXXpYu8iX1w5JQ51edf", + "2sfnRNCQnF82DV2V2V7VQycokG6n3HMEVwLdD6XV69Y8wfjojY", + "2uyYEALe2oDUo4Lb2J1qYKQBuhVUm7aNUUnLRVYKYAexV8p2xs", + "2vB9H4JbhRFaSbMnqDuoyhTT4QARbxxBojswmkXgjqGAMZS4pt", + "2w6gm3AXt3597RmSV4h3GpXKjVkz8C9ENQPj67o2Bs7CowhihG", + "2wgN5mCzzLmKShfARuh32i7s4aU3EVo5fbi7wBjoHri7KmUXtU", + "4rshF4L6BNyawp2HPkJGyQc52MRU3JQyixdNjpGNYW17v9rpo", + "5UrLPTVwEiLf86wvvxQbrx3wwgG1vrPKaN88owiPpqtE3gGZK", + "5oXiNcj2mmqSbEbRWZzHsPig8TwUyf3Pkg8tGtuNp64jqB5nz", + "7dpuZBeaBf2U35LfcruGzjFoDhpM4EaH7aFmg5MBTDE3QfTWX", + "9hFDay3tyKJc9UhZ8t66u8UCvzTcypDk6o6RpdiTvHrVBaTCZ", + "B4jkgVYJUmwiGU2khi5jVVQbLkWJWq6jUgMm5Df29xPHj6VmP", + "BQHaGhTA3E1PERKijtMMfPjVpyyMG3y9GS7QbHhQQWykxAqmF", + "C9ndvx4yTAJJYYrFZ7gX3tTYCaWPjCA1SuNjdkGdCXfiVhF6A", + "CVsQMtmA919WWR27C7MKfNPEXCP45jmEzUYpQVZZMqLVLbMAS", + "Dmx2pEWieTEABHxSmB7J3o24TmGbTsdJkRUkxEsF6Zd3LSaTj", + "HXkUpybLU1yRiJYVz6FDJ8o5V6cFsd2T7hbERcDuE9MqQUSW8", + "JQiVeXKisTsYj5KDUvhNDSemXKwmYfRZJ57woBWv5npghCkWz", + "KSJYGu3E5gK8fpHcwpzKh8LGUSjfb7QmH9RydCWFHd5qdzJUs", + "PD4nf2YX7hYiqjtH13hwHgkEfXnwAWwn71ViGQDv11JdYWdCL", + "PQjnMUTwykrKucTfgJeRUZVBW9SVh18swDKUYAxNi2SELiLc9", + "PZDE6Upmm91e4wRq11akRCiCbCp97Xg4mtByhKaSyKNqE6nUg", + "Pa2D9o6BZcXuN9BFtWwkJFx9Tn2s6BMRqNEPUBwWn4kEcHeD8", + "QBRGgKVWfKogPKm8A7DU8pt9jvJ8bD7XvNo2j6hAqUSPvT4ev", + "RxoMDV8LD2Jy7e1HqzWWQJmr3UYzSptoDp9736yAnVzzVc9Rp", + "SbEKmAhYN6ooSERuN2uS2QCac8wWsWQfeNXDCPXh39r8murbf", + "Tbq5pbo1JkBLBwop3PjVE56mySsXQXQiYxT1QTA7DsjizGPUv", + "TsobpXTYZWsDKN3ScjdW8ZXu7qFK4MyJcUgtfYN6wMCTKWSZL", + "Um4DWEohSQiE7Zip5fcPUkbF4s4vYN2QjxWRiYP4igCCeSmVW", + "XJAYMBq9LypWFvPwbzFTaqtqUi8g72pKnCLe7YeTmChRV5ckn", + "Xf1n2j6pkmWZEeZ6qZzQnSZkXQyApup2ZQ28qpMfyErVwtomC", + "Xi8qQgoCBtBDbeAMLQDFaVQaH3M5RqjuA7t7rJURCeQchWeWM", + "YgVJDfiByLxqujYr755nDhN4YXzFP9sUbwiuw632DPMEzqq9Q", + "ZfJioW81b8YQL5hB8Sna1RbntZjkTmgaHSP7u7tVENL24Xd1W", + "aiq2tzZKeJcygfXEkA9soY92s7YvoFfpQRN9oHL313upDkpqV", + "cKf18aKdKfLedh2kFUAUVu92UHUoTiJEAyDBNhT3PibrPpHM9", + "cYhbXnRyBVUv8RF1dPiyPHQ12bBdRxMmL2t1SyX5DPoxAAQgX", + "cu6Bq6ZpEC6FJ81TcrniXknmzMttqxRvsyaMdBW62fjjn2ZMF", + "eVMrLraoHucQJpScwTNb8oKTj1orjEuE6dd6iw7sG3KFVeRZs", + "gnX7p8akFyKJ2EKcxzwA23iskzkGmr5ytKfanFFwu6sDXYgds", + "go3MYTHoEFHzNKKSwQUSoKKWwKgd49RvrjEqsF4zy4nW9zZrH", + "kMQnn1wVZFHK5CSfWAPqTWGcyCNyE7YA6vYPSqWTQFVePUVU1", + "kwpEspMB4NdzEwGXVLDudbGhpDK1q7JkvowF88P9fjKFqeDoN", + "oYtL7sA8FpGAGPhQqo4iKBxXeSmcS2HKzdG5KG4JDyrRL8HAS", + "pLJ6bVAxh8dptyicnqduWmLC1z663vzD2cdsAsXMrPwusKPzA", + "pMgxdKA8pKd69KfQGEwV9nfQXYBbxQL8JbcYc3JNtTavvdYDg", + "w6SfeK1abuZcDKPEhhGQtxA1KC19AfvrnXPZ8pLQqgKrzRAf3", + "wLMk9dHUrTu8mUs77vUnxNJTUe5K3Zx6BEES68oWUzDqWtv2u", + "xCxuBYyqHFHZ9inVnL8tX2zBQrSxPuMUQxcToxvVkR2G9ChmP", + "yhB33nzYvFjZUYPP15NzUKDAs9H1uND8wemo7nTF6G22hWhtu", + "yrBWj3sYEbmjJdZn8Q7SC24VCDbSSntwMhHdcMcVh5dhRGHnc", + "zat7FisFCmuXzwNjFujicAPjtsCFEQG31ptHD74HK2SEy4is8" + ], + "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM": [ + "1Kdri5W9vFJqB2dYBf5ZhYWAmZkkP4aHedVoV9pGYPQd8C77p", + "21jEMY3teZTGfPQqs9gGvWwoYsEvMPJKFLVYfUFYQFtuNv61p2", + "22xzGXKDSum2UQLksu5Eyb7ikMN36iDStT6jbPio9gjyHuyFC5", + "25jYWtYr1zwYoYri74aTiMp82rHC86HP7bJ1sYfvyqBrS2b6st", + "26gohU9ZFmkenRHYYFyp9YZdyAJVtiWKcqEhiwtAyAz4GJssQi", + "288CjAHapx9kK2sseVRgDBBfq4JeMbS3F98S4PK2YQU33vpnDh", + "2BaCerd4yoKeB8wiyFYK6ARB46HcqXSb8SCBJT6onMsgr2fv9r", + "2CNkxrCycKSJVxmMHcxPwcYEGqf3royYBrmKGL55upEESLvqur", + "2CTCExtaeVzGvnsXatitBfeiVQJKmehDdRok8PQQALtzQoYM1K", + "2CVcqHWjQkuzpe9tuSGHWQwazNsFZrDPJdPvjpcPfxmJs5s5TN", + "2DD4QdN9SmBnktJc7daV4asJi9ozwUwi1s3M6WNDShSUb3byDx", + "2DK7hzB9XUgUxeBuC34KAe5hnDKqgmRYgN2is3WjUW4V1vYNtL", + "2EDHTze7RjsaWcdgGy4WFSXEiHz3maHkc2jYGRrTzhKRX9w4CQ", + "2EcjWWz29FZoX7bUBRG4RQqpbwoBrwrhHBft3B3iARiejcKwR7", + "2HQzjUaHr3LW7XQTp8MvJCTibhnu4wyuDkS8LGYKsAGncZoV7j", + "2LScQCmZKGDpMBX8vzrSNUTgXGLX69LFdpQchcrM2MGYADWQx3", + "2LZeM7Fj9qFjm1C2WB8AKoo97VQXEo71EguEp8ZmUMTemQxjs2", + "2Ngiovn4iW43XQrx95kzujiVezrkdiXHnymV4pt7me2Rp4JaRy", + "2VFRJacgybj4bqgD3E616j2zhGHvhqqiBBMTLiuXDNxehR6Faq", + "2WAS42i6Xfu8ggWGVE2xCENpKhhkkC6q3Zb9vmVagjHdE1WSc5", + "2Wu6fX1nT9t9sTJWNfu9WMVovdd4QR1vBVeETht2AsDP9qT5rx", + "2XkRkvQ4ujTP7Rb1j7J7grBxqmM71Ggod2HLGC8rTW5pj1VBd1", + "2YS3faaAM93Ev6GHCYp5uWhtsSGuryYdxuNaRcy3hcmuPnDk8C", + "2YdjjG6GW1WcYedSAwRCtpLJUQP2MDCX94aEMd2LPYFAfWXMFu", + "2YdwRT8da6kJsG3XHnK5uQxedMTpqESwoVyJKA9qZjGT8fALds", + "2ZWrZrXWJtPQgVeCdzuAXvPich8hEQuZ9MrhJ6A56KnRw19sFW", + "2bZJH6jDPikCUcjnApQZ9X9k2MV1twjjVoYBp4QPCAB7ZyQANr", + "2bp2TvngbGuY9KRxAxnHk7qZr1KstCKtz83svoNhscEqjt3S9H", + "2bxu7PuSUtCXoBGfjeMjRKxX3gvWsZBXk8x2sLJ8FrBHYDHsd", + "2cm82zfe9NofzqQyjbCi1AmusYm7bxmq5gG7ZKRJhGTTr66fTE", + "2gdhwWbupbvKmHXA5PTe7H7bxFL8TVzW5kA7HG8TK5xMrSsTp8", + "2hxYwQDJ7ZFpfxZBo5b4NnLTL1Bg9fRMZyt7xjNDszG8ezZeto", + "2iWpSR16FCGao7zMcDi3h1XN9u8TTJZpWFzMQizhUV8ZWxWnmR", + "2jkJ3tSmg69mouko9d8PtcfKqs3Z7gR5tuxdsaEnn7trkgSEs2", + "2jwvDvvRLdwYL5UuoigH9BVc2D5bVhFNaYhaygXSamJGi7woiS", + "2kY42u9ckGES78ocJ6nBYgyczvPwVfUujcCJniVM9ZtfWQooC6", + "2kqszyuJBHUN7KsbUkyTFpxGGxmWURLDmGu8nU5h8v3Fzv2zQ1", + "2ncWunFKptuXQs5SiabaFUi8guG827pjLtr2pwfViCCWK85mFv", + "2o92FQ42CfwjsicGnffFZjETGijhsFNG9Gd5Be8UH6TabY6KXa", + "2o9kcsdzCD8Pp1ZJugL5Ryk5YmRwPHyb3Z3orN7JK9Fxcf6iqU", + "2oU5yYfGhdi2NqbjM9Jsufejbj3The1TkWJfzTdKsCF9ouWVJ3", + "2pSpcprbpgACr73pf2JcP8di7eab8vd93QFk2Wd7JaHWrwjHxV", + "2sY7uuNMetZu28FR9rC5MtpqWDKbVHQCvvRqFg9Rz5A2hffa5M", + "2v513oh6biDsL5jFTfVBZdzL8GU5Ur5E4BQCdQ3q94qSYNRvKf", + "2vSaKbZiiKP5pv4PXE8NF7hET1qRxnfps85qCg8EJmAakTMbqk", + "2w3qumfoA21su5Gv5kNM6NjyDmGCaENsBDTGgNEajPvrNf5nuq", + "3py4ULD6d5FzbYXcVLcm5cLBJGCPFJEnzrfCbEXnQfEa8FmZi", + "4ACXU3PYb656PxgVV8M18jw9MiaRmGPYCvApe4uUTEdX7TPpU", + "4VcURBXcMcQjHgdVGJzpqLwaJ53bvyd2RFKqCZj3U41mGmuZB", + "5DCcfMAqj7hWNiJPMSXkfUMvcHoRhHcQAwYumqoiEpKPd3DHa", + "5mg74cn8UZTk1WoWpX1mvipxhSjtvmJPen462K9kh4nG68oL8", + "799PvVmpxzWpsyEzoNaYdSsmTTTxLCgqxybWckfiZPhr2R6nU", + "8JVnuR4znS2TWBg7Fg9dctzYbiT99LiNjzvkxPRJwJayinpiU", + "9StEXYCTAZ2BUW7tzACJny4jLnXwkVgZRy37r9wPJGhRYLgDi", + "AKQxgsjUAMuuadiy6YDTMAFA1om1fPqyVjR9hqdz6hhoWkg29", + "AknqzZuovseCGTjcSfJ5xP7CrgVD9qpxiTj7T9shoLK59sW3E", + "DG9JJCKAMRYThgWW7WK88rqzkBcgfNMWZifPQpj4cz8SVPvBg", + "G6U9ZAQxo2qDUZsnU6t5TFmPekP2ivoSbtb8JXzJV95URWJXy", + "GPgfuY8bY2CTWHUzbY52N1W73DJjTpRgLBrG4wqnd2QqaoHyF", + "GU1N5nss24TshQhmadTtWiSuUFK4d9YGi83FDyhMrrgR1b7Yr", + "H3x2CsQRbZhaQuQCjYRW4MadfEZ9Gu4by2DnG5Y8sv9sWZrUY", + "HCDaYhTaYh9639qofxnG2qiX1dCzhTD6bdDcmrYczrQ3ZHjsg", + "HEyb8Q5n5YkPgXGByAtupKGQR7CJanzvMZWfAcD5dkjuQAsrL", + "JJ7peJW4T9QXKcHb1Mefnd2FVYru318qEQGkuJStwP9WejWP1", + "QTkZ9bfE923YkEZ3LNZRZ82mMrcv5mXnosjPLCX1eZhzvxtCd", + "QaDdtpq1b7V7SeB59uwkCRpMuXqhaBiYigLnMCb3CbDLMjDzD", + "RkKECwRZQ7e2a34oirrDqVQwMNscvmqF12V6UbBETSdzhXJxh", + "RpQmzvjeDaHBqqm7A9iqpPkVvMEW4RXW8SXjR8vNNN16S7qNQ", + "UyunGfbFB12wfmJqS8xyoNpjnb9RCcqBKs8Vfxmjf96x2hFAs", + "VDycGV2Ps7stDUZ3kRvbmVuKkKoPUyVFAGtwKmU2W7nBFHjzq", + "W4QoHZErHuSaYn6V9ptAnmtjYsMxEDLWfdmMks6zFNZYjapxo", + "W4tMAUHZcSWQ3ck4q75XVwB2j9cgqtTHKeDGCBsJYu7jYXQGx", + "ZuDLBGTsryGHBSARE4zgM4Dtj1H5DNe1nxfZ8FQpCHmYunPn3", + "bTs52txp1o1z33uebucqS6sZ94c4XLuXQcgUdr97kwZK7BWEt", + "bZMYP5jmsTMyXRK5QTAyHt8bzGuwm4APboEHFbTqexhyc3Tm", + "cddXZXwkgMX4vHG5kxTG8ktXn6ujAtPe2rkZXvEGgAHgwkDSg", + "fDLZXMLLX77NdPYFRLyn2WNDSwtpKxCZqdRgTBuwCP9H3otgk", + "fGWn4NaAqK2BgQWadVtkHB7Q1n1qijrin91tkzq5Exndq3CNy", + "fM4tU4iDpLUYjwqnDeWkLtbkEqPhPRzwbkAD5GTviD4CpAnRN", + "fd4LC3i5w4w8TMmaPwmU7GPHyUsMk6fUtNykCZvmkp9iNuxtL", + "fptxfNAeQbDzTV78ryzqTE9xiQgViGnLZHHfipb3qvWHMvzAs", + "gJqkJ22xRqQ5SRVraoQiz1piMJKsb9QyhhTvbbRfZ4FCsjbxW", + "gdismVqRtUwW2X5DuU3ybYxtjiaSkAmqntXKFSpUkkgdtYMU3", + "i263AhAfgjqrTjEmJG8mA3dKDVX3rMPWRnn9pzT4EDG4pjxRH", + "i9sCwM19Ndxc1FH3nmSHDvt5QPD6StWgyKDGNwSF6LbhbiqhF", + "iuUYXFzNJYqLjA7sZQeXSDPMWShVkjAGykBcLzyZLt1BpH5Cw", + "ivECpWEqSRR9mA3fP6jTu2akET1rRtmJjqednYCjSdMXJAN1q", + "j6EquSChjB48xP64iHh6Bj67GEsvhCoV73uqsf7K5B6PRjfvf", + "kCd5nEUkHyFJLyqZ8NJhqa5GbsvCgBfj9cHXyAWWCin4HjosH", + "oQNJxqjJYaSLAHqyF3n9GpbtJzYwDwMD9WsUCAAGWSXAYUG5V", + "p9zGnppWJ1rUrqecGhozsBSsRvsiEwkj4vM7rUringMPL7cQ6", + "q14J1hczzqeQS8aKCJcog5bTFNNkFFWwza4XMjy89FuZRziNg", + "udPiCek7LmDmnkooWSsBe8SQzv9dmMgc4F4VpL5naudqdPQYW", + "vL8xjHKkhPkNrDpe7BkQksbvc1JAnwjTk9kCsJ55wmrBibKjf", + "vfshLdk8kS5hXFpKHDkg4FpwWCxzVXmUjv7Pzgb9WQJ2g6vuu", + "vg5LKAUU1YQSdP39zLx8vzUvmUiuAtM1dt5RqBvG3go4owo1N", + "wHwEP9TgGCQKe1viNvmcnHZtQvyEvJNf49fadLrAbXGjGRKaV", + "y1BYCkbExzrdonKbEvgTRwLmT3t7FE23ZAYbFCaShwFyVEeEm", + "zgKT1hRCBnXvxnzuQnxCZoV4TZAUTWA1UdF7Y1rZxgsqk29Ex" + ], + "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5": [ + "2191BgNTL88zXHVwVJEnHuZy5zFQsjzij1qj8EoGFTZQcGB3B6", + "21dH9gpxjPttySTz3r2by8akMXXt136U3nECkWf5VudmpvgUEi", + "21oEHrhwJpF2AKPQQSTWFDETXrcFDCGkkzymF1j7Pxm8qL2mBo", + "22SGfV6X3f4UtcmGqCgnUvQjazc6gcdbxGxnuZWhRsuvid3qpF", + "23f3ZeENaJqm7FnSGMU9eCSEoycwLnm5JKyEoxeYiu3GwANUba", + "25A13jm8tX5574XgsqSuCYgbpHuNNq8NMGQPaKPHf9GS5yAADL", + "27wMrwKGVQJFnPZ8EziZhVYEbHrpAQxtWx2M17pk6jknSfKdt9", + "29SPUbhumM83K7oRCoa4TviiQV81uwgf2fi6L1gGt4c2MjbPQ9", + "2ANYGa1AHU2amY3epYvktRihnHxVDm9LmNUXRvzbHitPGyczzu", + "2CGQ9iksuJfHZAfUAuLABn2QYKmHHKcfUePdkFpqaWDbCnJqCr", + "2CKaosKd4RmKY4t2T1K84X9VXfpVX9ZoaiuRjbRY1d9M15Xv4k", + "2DRVqKq3FfYTZR88LGfXg1YDxqbz9B7f5Tz9vB2p1y4GwaJNdF", + "2E6c49tin3rkV2ryVuijjZHFz194CGDfhSTNftJbwen2dUg6Zf", + "2EXrYLc9vLDhWYnmQXTB1TYKBrfiVJHMyGXCgVF7czVTVQJdbe", + "2G1CAL5NMrQ6jhwWXs8jB1sbaSJsi58PkTkoKP9PLpRKHF3y8j", + "2GhEcNCy8q2gEUjnBLJ842nmmYiwgSuW7Bdy24hbvENU32weu4", + "2HUz5KyB2GgkAoLd2aaVEBsfbKhTJ7dhiLamQQzkacaWi7KDDo", + "2JDiCDikgadtNFpEknb5MRB4QWfJ7fx3xcGAmqC9o9Ljw3cLn7", + "2JqZF1PFLgYprYJMVVKVsLHPHDgMJXVraKL72HwKuUGpcq5GiN", + "2L7e2Bfdh9hGYxXqvbZ5M9UuyiNzJsmQ3GdSrfzjYGkMVR7uFy", + "2L8S8gnQFx8C3JYKadBedcrfYyMDgHd2szVyn9BTJFX5PMuYr4", + "2MN1cqYpY5YqQkpLhthLggss3aPjJChAQ7HRAi5QQuWFF6yULf", + "2Pj3v3P6ygtYmeBT13bTKfX8mi3ftGcpRhm7apxi2Aw3MwGeHT", + "2PxXfyJHmekpqeXVDo8teWa76KMMXmRDm8ewMYff1vknnzPPS", + "2S9HfyYpV6bikYTZtPJcRDaCtZS49RFBqXiiqi4WxxLtTy3kQ7", + "2TZobisjahLmCX23tbDrjcY6FtS8PfTxK4HHpTXFWpVnuqDECs", + "2UEuSCXVohzXkRPqCaadMtuED7t1utyzEhGcoTiAXHKhBK14ww", + "2VfStqKWXsCJoGpE8dMXAn3ZbP5t8ujUjGEGFWEyGnzBcbrcuJ", + "2WGnUgz6oBaFGfMsw1RfCq29tBjQ4FKGcBmrwND9j7QPq3gaVg", + "2YFpEqmhjG7hFLrU9bSbimDu13jtzJjuxqzwu2MDLujRMMia34", + "2aFTwNXMZZ4djieGPFMtnh22mSa3anTfsNVo9YdWLLhtp3CHfX", + "2aikkxSHpbfjtxnWjKixjvBMLiCodSf8xCEg5FXRMkJuNRKjEH", + "2bu7jnkwymY7CA1eT6t6SSsUysThNNyCRGY3AJ94nutPC9NoZ3", + "2c6hJZnbfNFq9ZBAMHxNhjm2T3hWV8o3vxfDbFegsTCND1WyMJ", + "2cQHRtTFDiGG4ZPMderVzaJqstxeqRYixU4JtmcSf1jUd3keQw", + "2eYSf5zeCsR9sJrsCtADpP3VgoRBZdDf8vj9btoXZxJaogxzTH", + "2ebsxYwArxW6aYUxfCYjCmGkPCvCq88QbL4zEP3FufSyNf1QcY", + "2g5ZiEH51FHHRcvHeGof8WVs1J6cXyv7FDBLRfu3tNLToXazTg", + "2g5wKMsoRscrApnQXne7JT9eS51Mvi7wzcdmyof5z5PtnsEN48", + "2jYQwo6GggNVk3pX5hKQKDJP3fxqx9ZBzQESiTFX8v48uqCh6S", + "2mUQDAusJuq45Kyp8g8UK2iFG7ddgGdxCmLgmabfRCUNfb2xRC", + "2mxTxfefZuJqmQ2hqAFuRGqDDXSCjGY6Vi2iPBejDbVT7rRFng", + "2pVQUaMWyEsmK8xtzd2Hw3m71pRuvSf71QzgynTPjDXHaCH8nZ", + "2qhg77oAQN1WeL5CgAy2jBFJzkNXTFURxWNfvYpLaHM1VTWspU", + "2tXdE5Av5WnX6EDqtkRcJaW8WsyiyZVtDpR2Ft7sbmMLCR2Vbz", + "2tgJgkKHKaQ77QtdM8mNFDsYZA1jaMr99566k2ri8TM6QFuoxA", + "2vaxxDqnQDbfGcQKPzmmdma4ofp5zBEX9CpmVnvq6BdAVpyGzV", + "38hXSvKwB4wbjxn7h5JUEjhAg7cWksbsyZn7LtTD1GTQSpCPC", + "3WXFPYtgRbqTreHPm3y7se34Wgm2V7MT5ftkokuq3Ca3CeZo3", + "4DDrzDxqa1QyB3jnEpDdJ2xmMJ94BrBAEbFr2nWHQ1miM8JDV", + "5Rzxipi9zRooqZS88hqSZhB3pAGknsr7agjjNkcXnEZyCUP8r", + "6TiVaW1k6UiFqU9cwn5PjeFEhUCJFHX2gqf36hDr7ybmC2Haz", + "7tzD3R987j2JP4P1K1ETvtXuFquNCcHStftYxEifZEAeTkMBh", + "8x8ShU3o69HGCB8UbfsagjCoQtFn7UCiG5BbVfEfYixPzD7Gx", + "AWYLuTuf82VJPerkLAwu1wKY3EdexGYWFbAdCpsTyx8Poty1g", + "CUVq69qdJY3D9aWzc8nuyzKFJbREJz2Cz4R3NVkKJMQYc1AoQ", + "DVMHj8Xtwpf6nn4Hap3AZbgWmva3jUs3k5KuzixdorW2eXNaj", + "DpufaDkK7hUFbskyZnzM4LLXjs6eLFBAXZTskppfNHFR8wQPm", + "EBTdsArGiC8Ac8KMvqTdBZpJ8QrhpEaqf8CERCP1g7uQLqn8y", + "Emgjjtv5c6uTpAQjLsy5KkMADX6xBr4kkpPYrAzbGBNMDUuQh", + "FyZACp1WyxRjcTHujqyRztBGZsBCRUegxxMPsnyb7JZxxgGa3", + "GSBQCSGDBBXwQUtXFcjjWgJgSSvBewyoQ5vEVHysyr2w3YzL4", + "HRfxa9UJyA6CyikAJEjKyVbNsjP6ZzrtsyGq6tk6ZUBr2xSrT", + "HdZ2EdKizZbeubZU55DEJZ9miMphvfUYX72kwixB7DnESvPjf", + "KVZNAwDxnbhSa7ttEVCiXSGwXJRpeMDk1incuMuyYjF97dpHF", + "Kxgo4yJ1hGX8Lx1AZDPGBKTXLMDukPGaBEPd9r7vJwaE5XHhT", + "MHEJw7cjsxA568CiHYxmgQRRSuWUHBzverPYAjB8QcwYL4Jku", + "QM2FVSFp2WfuDjTvbhhTyuP5ANYH3kxzx6RirstAsG6yvYQm6", + "Tw12eGYUUhZHhUX2X9mg2N7ULLkide33CdjD877w1ub2E7c5T", + "UodCmwwa8deSz1XD1TWJhMTj9ppZLEpEctB5YUmZNb6z71vwF", + "V6F217VqFEg976XniW24skBadrZf8LWcMngYmMwex9qLhdJAR", + "VML5orUvch5Apdhq9Kh8Rp45scraQTKxYAMQ27RYnQf7Wy4RM", + "VkHSPHvu8nFYCQQh2PPp36eyvYAr7k2EUMv54qwToiPWArdPp", + "W67thhNc43CbsopPds6UwonFf8vHNqpcFLuJyfj6wuCSvft2", + "WAMcqVC25wx9C6qVz7WZUAXnft5LAHj8tm8aQ4NLaGKPtM4NK", + "WDGMe4S7Sx1HpN84iy5fanLycLG7dRd44DuhJFRuGASA5cT2y", + "XCtJ7mvw216yU4ibjEHJ1wFhPenQP7GTpgsgB8ZBB67x38mHX", + "Y1VJAKqwjdvJZTzXiQ69XJedZgBFijQxx9MwQj9qTuoQyL47w", + "bcw6vPCwh11XRaSQAfXDNFZtScZi63hgPoP33wkRzSxwqXEJg", + "d5PHFZDid2p2QRJ78JCHwsU4gu5qkwESGBYwB9SkRgPi2n1NM", + "d9JuwJU8pGWrq4zbr3yUpFBKriaQnqbE8EnJC2XsgHy12TdT8", + "dfTYwqCJkCa8cv2C77kAb53AMKNZSaM19ss8z9pzC7mM1NjR7", + "dmceoqHMteJTnhSYFHzfWzYvEcbHp1fLcxBYcarT5AmgjCyEY", + "fw6ABwp7NjyoCuYdd4CTKPLrnsArEwCpKRMsoqeU8xws1DW7w", + "fyreXQj8rQbQt5pnLu1T1Gqf6Jg2ZdGTuc78uurgFpkMCQbnH", + "gLk84YhajHPJKvTkp1X9Pm3ScLj4ZXtTHwu1rnLsQXkX2ga9W", + "hNqgkW9FXXHr8B9NESUvJ8H3oFe5trjG9TfLAfcrSX4HqHaKf", + "i5fidM7y7T9uQdjjSy4ZRWFrbCiJHyDKEuqkFfGzs6SBkDXeW", + "joJFtcQ3Uc3uRSt15LLUuhk8DuvxYr2PYeZ7B3t7r8cr177nW", + "kNac14sb6M8Rm5sn6qadTB416xPE1kcU5Ed6K4V3BuEnaH1w4", + "oX8eYJUNDacpr6mFHUqnQbhMzp8vv4Mk4JByj6SKFM1j1Ajuv", + "pAbzroSdcCfa4XafBPiiH7zm9jYkyGvKpP65ooXx5XYpTV44V", + "q3XXPoVkj4XaRs8iwvTGySZB2gWDjUNcXBxPDU3S9DPpVSFw", + "sQ1EuhYAJjp2pAZJo457FJEFzdDUr3McmNYoh7EFajUPFxLyf", + "tSMeLpk1Ag7bHzNwsjnfC6xEzcDdYw2TW3bLy8y8324SBBQdK", + "wLpj7xFcnBvdMcFucuVFDXC6jaLWCgc9mfLfrhfXfvcvhtfpm", + "ws9g9bVCNnj4ZAGNFpCcpv1QXKqxDgdmfjVXGnwiMbjf2Ukn", + "xx2jqP66m3B2zijGPVnMsHeyxXLBg5L6LShx3p5fRA3m5EL4t", + "zryWwRG4P69ZV8CoLkUPvxLxkS8XjrU1eEGpSkdEE4TRNUkk7" + ] + } } \ No newline at end of file diff --git a/genesis/validators.json b/genesis/validators.json index 70aafaecd367..7c4d76657ead 100644 --- a/genesis/validators.json +++ b/genesis/validators.json @@ -1,2531 +1,2529 @@ { - "fuji": [ - "NodeID-11112jHXqNowaUzgEwjMAdiKRm57b5cM", - "NodeID-15uUYVJH5xM396PKH5d9GTjGErkciLdBx", - "NodeID-1REAt4C9SQUo17pseGmHL2oNUdpkBkrB", - "NodeID-22hnv3WsLkax27PmQdYJrVRDJVm17XCCX", - "NodeID-23GCcht221hDaKdtH8BhSLpUrugsfRAY6", - "NodeID-24WK7qiKXAumya1kKEktwj2ubBbRyq5UW", - "NodeID-24nupT8dLucgRn2HuYGzqUZEbkfKRaUnX", - "NodeID-26yNpVkHNGxboUshTXtFAy76yYLmWa7bU", - "NodeID-27n6vtWe35N6JmbpVQKfeVqy7KJ874tFU", - "NodeID-29tGiEe2rxuoHJgjEZ4sDytQAivwjJmaC", - "NodeID-2Bxm4MQUKqq7yMtHLWsfYpKqRAfSterR2", - "NodeID-2CDAbZAYzHv4imG3sC9hBx9WGMzJdAJeX", - "NodeID-2CVgPTjtmaxSSjKuZXUwrgG4cPapmEgmD", - "NodeID-2D9EnSs4qEtZVPB2kxUX2xEATUUgXX3Nh", - "NodeID-2GKxWMGx19NvTSorxibapih9DcuRx6WzV", - "NodeID-2GXYggxghp56hz5zkdSvtVXEQ3AZB1gGM", - "NodeID-2Gp8ZuzK92tZDzLknZxmsm48RvppFYSqc", - "NodeID-2JGdGihFqGFcKEZEUswXDSWwaBJcU797P", - "NodeID-2MrvT4zf7GNN32eeGizM34s6UaX9SuZsx", - "NodeID-2PPDjKZvz1RTRiKQaojA4vsrno6N8mWuh", - "NodeID-2PfNAhAG7nypsyDRHzPwZaZsDcj1jA6rU", - "NodeID-2Pvoq8Stniirtie17djAh3ys7rUxn21F5", - "NodeID-2Ty5YxnuVTUkPX8SPMcS1b1qfE3sMbcRV", - "NodeID-2bRcmz6BF39s7bMoG7wWPWST73LWcaAUp", - "NodeID-2cU7F76JcCHXcsY6L8pMeHQBxwXqMumNC", - "NodeID-2cu2JVaQDucg81tff1W4PBeZ5oMUG3vj6", - "NodeID-2ebMFnGycbMsnxJ3VV2WLhJSQPLQUSJgk", - "NodeID-2kwc3kKwtfgTQ7aPahndbHAer236maSBH", - "NodeID-2m38qc95mhHXtrhjyGbe7r2NhniqHHJRB", - "NodeID-2mMkmzYVHw4YWojaAuAHpNoEz3mqyEbBJ", - "NodeID-2n8rK9kL8N7y1P6hyKu5ZwrMFUX1NEXG8", - "NodeID-2pV9ukRgk7eBJR9Ab5DSZqU3uZSfA9TvM", - "NodeID-2vtBaWPqDCi1rzQWdmcSXG3R2hJbnpMvg", - "NodeID-2wejWSTCbLboLdsgu9YAUeT2h5bnpzcNc", - "NodeID-2ywA5crdZzPPV41rXRPkPktyRKHHSCdEZ", - "NodeID-31NFpxN7VniDZbDDNkvvZaFuuNhDJyYro", - "NodeID-33PdW8ge5VAHD98Bmxy6kYhm992Mhnu8x", - "NodeID-345wyACGatmkic8wWga8Tr4qxoeuoiZvQ", - "NodeID-34qTBTrvhsF3MQDuwdNUDHBvj982Wm6NV", - "NodeID-34sJYzSaqAD8GSoK1WVguqLgdg9uVotGH", - "NodeID-36e7GjwMCYr1d9tDUgUyz9swewgNhKArs", - "NodeID-36ktMvm5GFTkfTAd5pPw7zpAXZG174Fvo", - "NodeID-37fc7hgUGsXKxPx3rMYyBdHatNpKRb8z2", - "NodeID-3932bao9oUnjfwGwWgsBk96M8rBhgQdeG", - "NodeID-39V1962v35f5Rs1NsaCskg84uaMqyxeAs", - "NodeID-39w4saojjUihKVNHJiQuSwugYbiGraXGU", - "NodeID-3DgkJ24cK9scEWQnoa7BwgP6YpB9ibccJ", - "NodeID-3FQZUAfKMJVzV5opV1DC3EpEYiZ5aYJQm", - "NodeID-3FYxUrCrACjqdBYFc8SnTzJ7Xq9fY3i2G", - "NodeID-3FaY3uSPkatMS3HUWXDeq6WuYyFPrHoj1", - "NodeID-3HNtqQ9HQftuHD8gApoDTLMH78z33P4Ze", - "NodeID-3KSEXMHijPpZbUHHgpqubFvjA2N4GJ6MC", - "NodeID-3KixTZkLBUqrDDeaaEpXaTTiU4Qan9xdC", - "NodeID-3M7L6w9a1G7o6ywAuY47HTnuGaMPZKQWx", - "NodeID-3M8ZqnsX6DDFkxVUnBzcKgVxce8vFLf68", - "NodeID-3NghhwXzgEMZNnjpJGiYrrpfCMNYCtbsf", - "NodeID-3PjPmpuCghoVT7AJRb8qTjyZ6DtCPuURp", - "NodeID-3QKhsmp2cj4eJ1hYecqQ6UAPYGTfZhWfr", - "NodeID-3RGiNDT55RwAQARCjrKgFc1hjdjVVchDR", - "NodeID-3RaFvh85MNRXdUmsjMPjvfNHmdbrSn9kx", - "NodeID-3U18hPBaGyELh3ZFEBPsvidFv5gP2Pv38", - "NodeID-3UhYTVhNbwBBALPyvwhRiGmgJts3obFvr", - "NodeID-3VWnZNViBP2b56QBY7pNJSLzN2rkTyqnK", - "NodeID-3Z6K13A3BogE9oMPg81vWgfitgvN1kCRh", - "NodeID-3bqNW8gEe1uwQus6dr8uux2g227tnXB5A", - "NodeID-3d2VDPUTpXd97ukrx9Faepmb79wzFicQZ", - "NodeID-3dahoBAqDyB1vskabnMHPy47zg8gJ9tD4", - "NodeID-3hdUZJo43ZTmFe6KdYxaPS92tqbR9woqw", - "NodeID-3jFnB85bDiJ8f1G8EgptsZMENJfGCeBVD", - "NodeID-3jbJ1eh1i8iqQKsrMjcG5WzAmPhkFU1Ds", - "NodeID-3kuuAaJKZWFYp4dy8rcrBWVkV4LDb86hE", - "NodeID-3nhpqPqAz8og2A2DBeVjb4fmFK1d2rRvQ", - "NodeID-3oFxfDPzWo4YhvYzswCMzLrcJwx2UKkwV", - "NodeID-3ry1arUtntKBQ4shFYgF9VB6AbGRHnPwe", - "NodeID-3tJhpEC14rjctSoh7ZN6TXAijmrMvjRNf", - "NodeID-3uK65P4yQGns5wVB9Bv955dHP2rRiXzFF", - "NodeID-3uRhwbfSajPyvWGaNSJyjhDKGPACGqHz4", - "NodeID-3um9mPx53CkfV1KSDdYkdrv6tEVR2E8vg", - "NodeID-3uq87hQvpuXWoqpmPhLRWavFpqzGDZbn1", - "NodeID-3vtMDZ9Eqs3AzwNbqudMoxuUXyi97MKut", - "NodeID-41cr9VeX852rtHrELWnHthUV4Bbm75WBY", - "NodeID-468yx2KFJV9M7uNiTXJrbqyFGeQxgiBfh", - "NodeID-4B4rc5vdD1758JSBYL1xyvE5NHGzz6xzH", - "NodeID-4CWTbdvgXHY1CLXqQNAp22nJDo5nAmts6", - "NodeID-4DDjS32CM5oK7tbba8iNnXv7VWJsrynDu", - "NodeID-4H2NGT5zSc5Tt5KHTciLXVHW3CVofDmuG", - "NodeID-4JwxRwRY8LgeSdDLNargL9NBEBUuvTk9v", - "NodeID-4KKUrWvuKKEwNQWvZj7x6NDhUEan1m44C", - "NodeID-4KXitMCoE9p2BHA6VzXtaTxLoEjNDo2Pt", - "NodeID-4LJNqmxdSigcw9wnGcd8nRP7Z4XZrEMyt", - "NodeID-4QBwET5o8kUhvt9xArhir4d3R25CtmZho", - "NodeID-4RApHGzbpwtrUEbL9BpkV8AfdCzr1ciCj", - "NodeID-4SdtN4zCP8h3ZEymEfGxJRocAu5hrwphC", - "NodeID-4TJyt2f7zGuusjc1yXcBJnkNvDMAJ9py4", - "NodeID-4WP36nX46eS27wcRsW1agg7bzpNDonEf6", - "NodeID-4ZrTre1sS8qxndZvsMNzBGm3MxxWBpbJb", - "NodeID-4aAK5LmtRsrAGnZgHTWXcK8EwrtxEk26Q", - "NodeID-4aQfCERvSk5sn9SJfzGZtb4ea6UQtxXNf", - "NodeID-4aa1L1AKqdG76yQ7Y3eGYV1wProfTVjc9", - "NodeID-4bPd6dgavJ9sggrbTMou3jkjcJ6Ng9L43", - "NodeID-4bo3ptnJcE25b9YSZvzUYxkXipqptKGer", - "NodeID-4dNvbt8gNJWXtTMA8BARk8haL8agc8emC", - "NodeID-4eruhJFiLfkgmeKrG9udZthPCvGpyyw9d", - "NodeID-4jkdfkuyACE6K5YV3YtbCieZazm6Gjjat", - "NodeID-4kMv27g3A6x2RMkiJjiK73zmAxvPDmbct", - "NodeID-4kSPhc76z8Nxfta8gjxHDCHcNx7TrNSLX", - "NodeID-4syxSZ2LPcCeE96VL1HsY3fx3AYnnGfsi", - "NodeID-4t94JpNNhRT9v6uoUWFY5G4jKmNqV6BQh", - "NodeID-4tsmKt9tHvMocmyHe9oKD1PkAa67iHn4k", - "NodeID-4wL6VGogpJKy7EB69BxaRi1R7sg4npMxV", - "NodeID-4wnwAREi6cY2vYccTktFC1gCEJfxwMJrU", - "NodeID-4xKQvNdSepnCAUZ5JMvqNxanaUQ4Qn22k", - "NodeID-4xpmwNTMoAxA4XGPyrBzas5Vnu1Beykmw", - "NodeID-4xyPSDPrx6wecMnPu754XG6hnb2HYCYLz", - "NodeID-52UrdjqkYxmkasCeLaH2jkHMXEYayFn61", - "NodeID-53BzXzD64f4CrJQZJmn5VWhwwys1cpzGU", - "NodeID-53QuyRVXP99F83s85cp7Fe8Aax8KAFQct", - "NodeID-54RagM4VF5VNeKWoVV5UNHJfM6ccHtBob", - "NodeID-54WkEbocc1ACvV6N6Qu4NVDGHGfpFhBzr", - "NodeID-59HRzrFCmhEmUJAncPdXZ5H1NrreBQR6e", - "NodeID-5KtwUENNLTnfjAeVWpED9jq2TeCPZjTxU", - "NodeID-5LtxGcaXocgCfx5qn2uMKiLnoJZi8Q11P", - "NodeID-5M11QQFMk3iqV8g6QoRiDNSDwR2XsQSe7", - "NodeID-5RHueEiTPCFb2T8YuDid94rJtr31UvnYW", - "NodeID-5T4381mMgVqnW1b6y9ddyHBfYAqaB8C8b", - "NodeID-5TcM4MkRoE7Vhnv9kcawSwpVSiTPDDBKw", - "NodeID-5UVT7fNKF22XkWXMxCDvGHZW2auLgxprr", - "NodeID-5Vd1XuN87ZgjBzpGL5NDhVPbmaqzd4YfU", - "NodeID-5WPHvkgxcwSE3XhuLf3rVNU3crqoF1BJ2", - "NodeID-5XgY2PdtB5DdELR3CzSt4U5gpC7XEUNVp", - "NodeID-5ZKjaekNVNoi6xaEEuKLQ6ZbYMQk4wA2u", - "NodeID-5aXqEaEkJH58WjMzuw6h8i7b16SNHq5uD", - "NodeID-5aqkYoNRpwJ3EhBvc8uF3626mzfiUsxdG", - "NodeID-5bGeKYsDjDfMwPAipVDPk5rYX5b8vc1aN", - "NodeID-5d7oCjzEfhVhRVtyR2FPEB7HVJ78N6dx7", - "NodeID-5ewkSj3RxqMG7shRumy4USF5ibHMaFAJY", - "NodeID-5fvPxB3edzXX3Eb5x5r7tbknoxqKyELtf", - "NodeID-5ivzLGz96pAJWd3o83x4JWHTpWZoHJvc9", - "NodeID-5kGqjBKnQ9gEm6gBXieWvP9oGZoFXPA8e", - "NodeID-5naAivQLhjbpVw35YGaD4HJwXTwuDufXA", - "NodeID-5oRZWHEqipzXDnScB5UgPP5cUqfgPa9GR", - "NodeID-5q6drRMuNYp3hfZokxgB2m5NxBoFZXc6X", - "NodeID-5rLsXFYvpZqjWfXkPouCUAmXc3Xcvebvn", - "NodeID-5rZ6LbEm6o3baUxVyV4GV21sPD4QqjPk1", - "NodeID-5tqDUvtVzpChaPgXcrXjuRRS5EJU648en", - "NodeID-5vCs6XJWRNTLpAkQP2HK8fwprGb1v86Q9", - "NodeID-5ztQ9vcGysCVPY56bfht1GsxV6Xce6tJ2", - "NodeID-653BnnF1HfEQY9APtAu7V23FNEmRMBGDW", - "NodeID-678Z9gkWVfFoAAnRJBEtgSm6Th6TUhsMa", - "NodeID-67tGW3yXGqnDVnEwEAwVv84yZtm1AiZPA", - "NodeID-6DjE25mD9X5AXWf8xpfgJ5tK94SFq11Vw", - "NodeID-6DxE723urFNy3H7SyMMs76ZLRYx6bDJdz", - "NodeID-6FgfGS3McpD27X8hdC7ZgQVhs6DoKvBzq", - "NodeID-6Kgqv9SV42oRBk2KNSRwFfJwsLBia49De", - "NodeID-6KtZFnJUHfu92NNRdgdea9ZA5mjbADDBR", - "NodeID-6LZ6k2VRSdaF4qLHgfjER6gjVjrjDEAmm", - "NodeID-6MnjianNNDMpLNhCnirZsw47aGGkkfCZd", - "NodeID-6N15qNZphbUdxRSfThfDbbFpgDdJvoHrR", - "NodeID-6NHaJnvJtHSbdtJHzdDesKdj3Wu9mAuNh", - "NodeID-6Powgn3qZ8HZGmHUeQ7b1acypxzXhA9Lq", - "NodeID-6Pq5DKB1kzJjvnc8KPNSDYfMCsUGJxCyZ", - "NodeID-6TrmPJiRneiG2ztDxBPWQAxAqv976ZJmU", - "NodeID-6Uh985Lx96QQZ6LmbqJF1j4CxLu4ZCcd7", - "NodeID-6W4LCoXP8T2QYRGWcAcpNftMYyHcVuKCF", - "NodeID-6YPFxT3358wbWFW6zHTnVtUYYedASEnVu", - "NodeID-6ZmBHXTqjknJoZtXbnJ6x7af863rXDTwx", - "NodeID-6edspGWTTSWm3N7Zot3kGrEMHPtLrK3VW", - "NodeID-6f4T9BgmXJVJBNTwAj2giidTU7WiomG8G", - "NodeID-6gVjCexoCvwXqApW3YVLnQSjsCUjbSDYx", - "NodeID-6iky1tgQsZupgN75GcSjFyJxC7a3rUc3D", - "NodeID-6pMsJc16h9YF2mMY5VkZu8rDS5Qco23fC", - "NodeID-6qzz3HV9nEmVLrDKGo9L5k94BZksKgwXL", - "NodeID-6tWHHU9uVWAf46qTYTsnTnVZJeL65hwgR", - "NodeID-6tkEtqzyUzqkPZ1KGH8XS9ZTasYGk68iq", - "NodeID-6uRAYA8LDmiD4se1Ve9fBSRrjNi5TZjw7", - "NodeID-6uicgS3fAizqshZgZPrNqm66YieUeZkbj", - "NodeID-6voVgdj8tVSWrgprYtrQYyidN8myXQUXj", - "NodeID-6xEvEA7hcEAnqaXW7R9RFZSkdsAniHPad", - "NodeID-6z161fCLZDJjvLNSPXCK1bAxkK6gjiDXc", - "NodeID-6z3AiSaoYsmFgjqsc1w8rPx4vGaA3Bni3", - "NodeID-77ebv49H9yRLLiUC46Hm9H371wXYNZNjL", - "NodeID-79idCdyu498QoEFzvqKBbWFsXECKSYbpb", - "NodeID-79u7mCRHvc9q5piSciiTphM8H1TDEq4Ab", - "NodeID-7A8w1M4GpWHy8UMwQkARRoB9a67Rod7yR", - "NodeID-7BPqDUFt9F5Vs9eqZiBYXmnaeC5UtZ2U", - "NodeID-7DYhQRawvQ3hoDTfytAa5KHeMTUM7buBN", - "NodeID-7EexMiaXNY1HYVV7gWdXtsiKh8j9gW1Fy", - "NodeID-7FXaqpRJgAPGWAUPs1UunagASkxPZps2D", - "NodeID-7GM3ww9CL3uXtZuK6nSpdKJmEbiiyYgu2", - "NodeID-7H5yeX5kkfdUBFCHLbDfDRxqWCDoFrCcL", - "NodeID-7HvCZsgMXsCTjddz7cYNpKrGxK1i1SxMr", - "NodeID-7L9oKJx6AsgGfG2GR8qQ7ndbKBVxqV9At", - "NodeID-7NenT29nACMVLj8K685mBLodfp6GehVy7", - "NodeID-7QjQJHgVxMFBZzNG6n7ULTeaa7dAbd1U9", - "NodeID-7SKSvUU5xyRiTJxsKsoeXnLa6idNEtZ19", - "NodeID-7Uq7GYJHYNh6LxFinWQpyB4ZitqDkUC6E", - "NodeID-7XRaRs6shZG5VVVoaKeUxdJfbPmuVU4CB", - "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", - "NodeID-7YJB8mcHCRmzsrrkxxpvqjyQH4cCEBXQq", - "NodeID-7b3i18ygt1A2gPpXKeEfAuC3ekHB5J4DP", - "NodeID-7cukmtqdCLDWG6N8BJswwKidxe5iGyVvm", - "NodeID-7dCZydYmPM846KqjhL9b4gRT1C7MDFFxG", - "NodeID-7dZ86Yv4Md2dwhHPpJNyuh83LjKNKvw44", - "NodeID-7eR9d4bjMsTgpwCbvXz4ynETmbXiQrJ1X", - "NodeID-7epJ8SkPeY9rL49JY8ELYJSduMt6eEnAk", - "NodeID-7fi9HdQSPQbnDrSjiVBUAAy5YfisSweEk", - "NodeID-7kVsskXDhAQ2grucq8sUwJARmtqsTmw9a", - "NodeID-7kfKeW5gRRVj7XgsssdWaKNU4AvC8dLiG", - "NodeID-7peBGoPt8rGfPUEeH1VCqnKyMFJg9y6z", - "NodeID-7rxhbsWmUqQ74N3FqoeUo1jpEspkEPeuL", - "NodeID-7uXxUx1VAs3NUs2J472MdQ4V9xVNKZHxN", - "NodeID-7yTMMzMTd1Fuct5tTeCB34HoZ9kLdKCpF", - "NodeID-7zbpDafC5Rxm6ZMXqSrz9D28ZdC4WV7Hp", - "NodeID-83qSEo3NEDrRoNYzJJY4RUBM79cSz4zVR", - "NodeID-84KbQHSDnojrmyuZjWM6hrM2vgPtMWt3", - "NodeID-84KbQHSDnojroCVY7vQ7u9Tx7pUonPaS", - "NodeID-89GQ3qi4bif58ovQnQAehtccU8Jbynozk", - "NodeID-89UCR1CsPzzEHuknxhJHKxuFPNCyPz7Bu", - "NodeID-8Bh3X1LH6uW1q2USKQeu11PAozaSMgEjr", - "NodeID-8CgGmdahNXvmuhyK7NziR9zTEMiArgrrr", - "NodeID-8DLjsnc2R3mm64NJ5puhrgisrLXHXihKc", - "NodeID-8F62HdqXVhqGTySVZ7HyQbEyFDMo33iKd", - "NodeID-8JC2wNQkExELqhtzoGnyBcC7b5Su1C9ju", - "NodeID-8JtmUUx6NHGVACFTReQbFxx1mWMJTdsWb", - "NodeID-8JvHG2u3R6DLSBpv55rHhNvj7MCbeWRGL", - "NodeID-8L6pLG9PQ3XUhsWHT7E2VGuW1S5mgs6LG", - "NodeID-8Lf1apT2CuoLpsqF3sHd5DQCRQ4cs8oYX", - "NodeID-8LjNUkzYVge7UvJkrJmaCYyWvmRb4oxoA", - "NodeID-8MXE4VNHGfx5d5NM7zVeU4KU8kZVs17VG", - "NodeID-8PvUVsNyrXj2SpTyrfxM7AcgjWU4xCufs", - "NodeID-8WJr4wGhcXChCXKXQpSidvTW5RiCQzX64", - "NodeID-8XhZkWckQGKgzhv3XSmUeM3NSrskD4bew", - "NodeID-8YHqGprPt4vva7TqVbzTtVFRv38BmpDUD", - "NodeID-8bVFU3U2PpHCwavsvzfMTE54cir79cmPr", - "NodeID-8boFLW2GXq6DxBRTxAguJ9N6dBYmBd2Ld", - "NodeID-8byCCMYn6aaNs4sQmwemcQfMwrnxBDA7U", - "NodeID-8eZ8eW3Q2Kf6YV1wEVCaFpEsRMm2vfmqy", - "NodeID-8efhLH97RLg7fodqvk16qQbscnGQtV5CP", - "NodeID-8ftKdL6NkAz7K2yUJwNuhZJVLrNiz5qjN", - "NodeID-8gYpz72F1GBoTwufD9FfjESwKAnRRYnwt", - "NodeID-8hqGf72EsTsRTWpP1kxGJkbzeJjnosiDM", - "NodeID-8i9eqbVxzf2KtQkBPiX2BvZujYza6fDe9", - "NodeID-8jUnxLxkowHFhDrEZ1FmucLDC62c3xJVi", - "NodeID-8miY3PqR6f9C6GDr6WFqAwpqqVFheJhrP", - "NodeID-8nCutCx3GgDYrNL1ancH4ZsE5tXHRYj2Z", - "NodeID-8nXdZLTjc3FLaPGbS41WXt3Qwa3JvKaHF", - "NodeID-8pDV7WK6kEp4mw2kupK1bSXTsShiZamE4", - "NodeID-8qNPJ4cmRiqaM7LA9v9tishQvkqqHLCeY", - "NodeID-8qTXyZZtMFdVqfEvr1nhnCJgh1i4ZGqqz", - "NodeID-8rLtFc9Ds7Liw6mF9vz51fmHfxFqDuCvF", - "NodeID-8rcfydaHitUhBWcUuDxf5p24p4qwfvucw", - "NodeID-8tpPNhuBrXw8KKqJjrsxUwVqsgdgbuoc5", - "NodeID-8vGhAbGtfHhi1nNg8A1Jof4ivgLCRdU8M", - "NodeID-93n7QZ5J8s1hej9LEVKX8g8yV8g9FvqCY", - "NodeID-96B6wPgw4HKySZk2C65c33YzzNx5VGmE4", - "NodeID-96ugvCFSQ4Df84uPhPwqHQNRCxVvkpxep", - "NodeID-97jPS9hQkuWC7DhEchgwC2aUN75oto4XL", - "NodeID-989RjLGtpnUjDHGD9mqxgyHLcXfnsaw4H", - "NodeID-9B3HLkYWERnM5daHNb6XaX8on8WP3XiGE", - "NodeID-9DQ6UMDYYWZccC5MRmT2xqE5TaMZUDbLN", - "NodeID-9DnRjykQ4ZdyebJ3FeoqKBBjJcbMC4nsV", - "NodeID-9FKZ4X9iEb3aBqmqzBHsu9kXmhn6aUhzd", - "NodeID-9HUatTvqyEsDD4bUaocsDGpVeePh7KEdE", - "NodeID-9KhiEguiCdK9KGCsfwkWY7M4VLvM5dbuo", - "NodeID-9NsPTteByFVHbn26rvU9NjjLjRKKCR84g", - "NodeID-9QhM9oKKXbAV5xtfARnyKXM97L7nwvGSu", - "NodeID-9TCq8np31pHjjhGaHtLjs6ptYYPEt3LGb", - "NodeID-9X4SMAESCQz8H32PMq4wrSafx6sAUv6oN", - "NodeID-9Xp5yzoLDUuCzUdaU6uFxXTjUYjwoCvPp", - "NodeID-9YzkgDFxmnRQxV4M8E7cuWPd5HukCaQkt", - "NodeID-9bk3GQD8qBvHfFTFaBCBURupAKLQEYg6", - "NodeID-9c5whzpb1QstunxbQ9PGqKQLanAU32Wnu", - "NodeID-9cQwDnPkD4Km3rQFvyJuWD5GUCMYrPHkk", - "NodeID-9dqCQXBAv1AdbNPrR4HCbRDgDjMebHk61", - "NodeID-9j9p75hBtn6rMES3TuWrGc7Q7tQZrfWf5", - "NodeID-9jTrqaVKZpevKsGoiixjVSAc8b2Md18RA", - "NodeID-9jpUT6Zjmsi2MjU8xBh5MWWR2rmTHuurM", - "NodeID-9yrLEmUoyFvZ6MVwrtsXr82LpFExgsfim", - "NodeID-A1SAHmXVC3D7dn67LPmWgd8bMvoNKgqTj", - "NodeID-A1YeC21gHYrEf4HBdRvxFheviXct4MUQ", - "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", - "NodeID-A2Z8m7egVLhKf1Qj14uvXadhExM5zrB7p", - "NodeID-A3Y24F5vNuDy3L2pLwmvZG8s976nCQ5Mj", - "NodeID-A7az7ffBywSGhgSGvwC2WbUgNxcQSiJD8", - "NodeID-A8VrzZuMjMGkFce5zqSQ4nbSwUMwNmnHt", - "NodeID-AAvXsy99V6dtcjwvweVC6FRWRk4fxwhjZ", - "NodeID-ABCBD3w6GosyujRHjEAXfbRkU14YxX1Af", - "NodeID-ACQt5KkctKfdLSNB6bfu7dVzmsyqpm3z2", - "NodeID-AHnXYg7f19R1MMmtt8D2yNejuBwha5i8Y", - "NodeID-ANZVxnoYnsWdzBUQePUsXHC1pVSdsGNca", - "NodeID-APKTqeD7UsfjYqfYBtDGaDCwLpr3ECVBN", - "NodeID-APhFyzYExri3n5GtDz7ytXCgbt8x5NAud", - "NodeID-AUFGUsjF8DR9cPfh4kLWCjtwdKyop1Y6H", - "NodeID-AYWEvPkJB7nePGujP9zWkHjrL76ppQqYK", - "NodeID-AZsVs7FHdKmNfjDDesfRY5w9J3bJd2e9j", - "NodeID-AeQY8TMBdDVVUgvsgRtZjFkArRybvbANS", - "NodeID-Ahtb1pwX6ugZfmb8ioJrBRWkPqg762Ed4", - "NodeID-Amf3N6UZZ5Q4PukDPttqqMDrkjYyu7Qfq", - "NodeID-AnJkYoj9mvGqv1A7WBujia17Hq1rDZp4Y", - "NodeID-AnZdc4zkKTSkYUDUByvX6u3HJP2MU53Pq", - "NodeID-AohNLSFbhRMHRdF9CPe72epbRtYPeZwjB", - "NodeID-AqXr2RXWtX9FcPndqPZmEDHqfd8Rm5cxq", - "NodeID-Ar9txpfoVW1LxzfYpQ1itPWpjq8b3c3s2", - "NodeID-AuyddbmFnAXCgeN388tMWzvAYu3nMzi4m", - "NodeID-B1SoG2eCceT7YhdRq8EdcuVZgcXeWB5VD", - "NodeID-B1jRRwEACvv92YJWyZrWwQn8DaAhEQA8K", - "NodeID-B3KbeQXjwDat2ySJrVppBxRrTxb7RwRjy", - "NodeID-B3si8iQ5MxJDRnwMBJyVt6puzici5tufY", - "NodeID-B5EdUCfcqnnHKgYzZfoVE3BBabQt165y", - "NodeID-B6GaYh7RRopBAkQJGiMeMZAsAbHXyYi6e", - "NodeID-B7R5mup1BGypqosat4fvCxWXGgziRaZgB", - "NodeID-B8SLANqFYZnUqfnWMuJjsjfzcN8Fxs9rp", - "NodeID-B8vH6dfELDJgPjYVMK5hjrRQkUMFFW7i2", - "NodeID-BBt17ZXGPvov135835zT6BBAa6uTwriQi", - "NodeID-BFa1padLXBj7VHa2JYvYGzcTBPQGjPhUy", - "NodeID-BHM9wtsHVPmqKbfmqqHTvTCiM4YXoRSvs", - "NodeID-BJjQb2PFLPiHsvejL2Q3yX28nqRxGxEqA", - "NodeID-BNYwWBYAidDqYiJYKhRahibQxPuG6hGvp", - "NodeID-BQTWT6W3Ke4PUweoYHThhuQgerhuAFVZH", - "NodeID-BSE4qod6VYM7Xxeausg2UzgxZqMmTTWnU", - "NodeID-BVXicWEU3ULP9aBsmRT82PLJMCXfdXDMp", - "NodeID-BWhTVK8YDrRmK6NeoLDn8oSk7pGu9386L", - "NodeID-BZq3oJcE1Unw1rYTB86B1q56x2VYQ7PwD", - "NodeID-Ba4X4hJ4bz51Hm1L6M4rRhu9JwniJgyUx", - "NodeID-BbDHoP1Th9LSr8iEuoHktCF38MQ6Wx5Ws", - "NodeID-Bd7EUL6WhVm1wF5bVNefWxHYsg8q2ttuh", - "NodeID-BdhYSwf3LW3bBqt3235WS6Cw7P5GYDFSV", - "NodeID-BdpT6z1FRz6vjEQp7Cb7nRFUgvcquBXT2", - "NodeID-BemmZ7Y5HLGHSz2kUjmPUDD7bbJDebVd4", - "NodeID-Bevezp7VTbNs4wGiiB115f8NrBwuRa79F", - "NodeID-BffXkmzM8EwrBZgpqFp9pwgE9DbDgYKG2", - "NodeID-Bgskmf8PocRPgtHgnAYKUgyifo9qD3Y5g", - "NodeID-Bh1NKhN5t6MBcHvY7XuGhLK14q7FwQjmf", - "NodeID-BhmBgAcV8WiNyrVUdDYJ9CVi7TvjPfJV", - "NodeID-Bk8Etvn1q5cEbZcn4y9QjbXoEAPwsHxB", - "NodeID-BmkswdTypyATT3xP9as8BeUCyq2sGScBD", - "NodeID-BrYXghQSu6KKGjuzhs3nrkcB46Wc2yYHy", - "NodeID-Bvr4dL7pK3FHqXvPs3X21y6QaZS86g4z4", - "NodeID-C2Yoi9vTGPppDhpFMx8J1XvKJv3CY2x8n", - "NodeID-C34t8rtehJ2BXMkok68K7ZuUZEk9ryJrA", - "NodeID-C7E4ym1BsDbraGxymND3zGYHmo8SJfMRb", - "NodeID-CA74JxFwV5BeRMCesYQruxjiKw4ofkEKQ", - "NodeID-CBy6ZLEwBBuYFtVDDvz8Wra2AfeAd96fs", - "NodeID-CCDSFhaQAuXWpiLviESSUPJmWUUTVxdGj", - "NodeID-CCPjVQc87Ka7nbXVBN5cVtGTfTzPVnEyb", - "NodeID-CET8PwdAu6Q2Cx7iqHrfdSyo4WEnkoxFr", - "NodeID-CEzYD3rFjsGtKFu7JLGpD7rMcGRNJFLGB", - "NodeID-CKZg819tz5CXMxMtrRfKS8XxVURFDuHVB", - "NodeID-CMSgVPNXC5R1kL19KHCNgbbRTeStUWPJA", - "NodeID-CMaW3TiXtNHzPGm7xzjkJvE8fthGibhAv", - "NodeID-CNK8vDPGbKfS3YSptRPPN4VYUEpoNH4Vz", - "NodeID-CNp6HLV3F1RnbBF977E93KReTXTkZ4t32", - "NodeID-CT2Fqk6d8eYAx627aYB8HAr7VjWHZYPQc", - "NodeID-CTtkcXvVdhpNp6f97LEUXPwsRD3A2ZHqP", - "NodeID-CU8Tq3pP9QniPeYWagh3TKDFccbvfwDkw", - "NodeID-CYKruAjwH1BmV3m37sXNuprbr7dGQuJwG", - "NodeID-CZP8JG4BKdDyiktxg3D2ZYgREHtFhqzjH", - "NodeID-CZmZ9xpCzkWqjAyS7L4htzh5Lg6kf1k18", - "NodeID-CaHFWxHNLv1R4R9oGHMQR7n2vKy95LTei", - "NodeID-CafHoeCqCjg8fWufaorRqFe3iX8s7z6A8", - "NodeID-CcS3n2j4CEaQCEnY39qaBDZajeZaXkRGU", - "NodeID-CduWdu3Gv7bsqAxnsdTCWuuMEyLYQqchX", - "NodeID-CehvZ1zrpo5HAb7K2sDiQcrks1Cn4d5Ew", - "NodeID-CfN57fb8f1jS3NWKsYSxfsHf2Lo8HUFSY", - "NodeID-CfdN2fVKKjDBRjqMLsxZNSaSKFdBgpMmr", - "NodeID-Ch8GJYTFsdPRzMVyWgVJTVV8MsHvbS4h6", - "NodeID-CipRaLt4Ym8yKegs45dpeEscA2x5w29Q9", - "NodeID-CkS5zL9rUsJkYHgSMtoYF7yBwBCV6Gn3X", - "NodeID-CkWijvSj2dEenuJeXu5fyJcxc5Wtg1feo", - "NodeID-CoKgGkWBUGouNZTqKCYLBNJ9dw4yJXUEW", - "NodeID-CpLDjTHrAuB8p3G42uRtGhnGKJ5YzGkFa", - "NodeID-Cq8kbEVqteYEqfNNW1CJSkrG7S16GiZ3u", - "NodeID-CqDq4nGVYJoSgKVpZpyutzkZPfcugTdjG", - "NodeID-CqGy1ZUkq4ZTznvsvzwwXtQiu8gBT3eYW", - "NodeID-CvFCEpXymDz9A2EftqnJmCNi8qVHxwKXq", - "NodeID-CwcD65rnKwedLNcsc98MZK6RghPMptEyo", - "NodeID-CyQc7xjJ2gJtCQNL6RVMEJf1KysJXG6QF", - "NodeID-CyS27tGGmcmxeKhCuCwhT4GwiZGBE8QEb", - "NodeID-CzBZTXGcxZqfB7UiN9ALzssfyHMWbMKH6", - "NodeID-D3BkKn3N6chukRSZN3yr6zQvu4DgCSvp2", - "NodeID-D3x6QzTaTdXxkMXYFx1MDc3T224H2Pmh6", - "NodeID-D6MxfVN4395J9jSmuPHDueQJue4Gitwns", - "NodeID-D7jdvPnW8XX3Yz1k4YYKCZxaY1FF7x6at", - "NodeID-D8bHw3BUjyGycV3dDTknNp1p6w8LHkNhh", - "NodeID-DE5iNyHAPisnXpaf8e16diJWL5y33VB7u", - "NodeID-DJHKfhFKe4QjX6AY7tyj2VTjZrpxUWUyQ", - "NodeID-DMbbEVaCyas1EXR5ubg2naKgEBmVerPne", - "NodeID-DQ4PJvysogwgzru7R8oDiRLv6qoF7Wwxc", - "NodeID-DSCwZSNFHcZFg5kbWrbbMHJNdpLUAuWB5", - "NodeID-DUNsbAcHScpFE2uwBQ2o3SPZ46C2svMqq", - "NodeID-DV4fFyxuvwUUUQbTKuc9bYnRibVixtSDs", - "NodeID-DVQevoevYh5pYSNCwoGpn3QnqewfibCJP", - "NodeID-DVZ7ffBkVkXDbpjGPEqwyYQgvcHhuTynj", - "NodeID-Da1yBnfJmUsS366wMN9b2Kzw3EL3WMdkC", - "NodeID-DdhG9cNQmDpPwWSpEW9u6T7PNCc9GKv2S", - "NodeID-DeeVioFXeoXx718FkbAk2unyikBN8iLJo", - "NodeID-DfWyvyBF7XF33B9kkSiXYcJyzxRBATXN", - "NodeID-Dh1JnVoEMU5zEQtvR6LHPVsyw6AGqbLuG", - "NodeID-DhQSUszPR4zHoxF2Cicx3pCUnjrfsewnp", - "NodeID-DnyNinbTZWYSyoekJ1xMmh8TxQCw9kHdz", - "NodeID-DonmTGabi4TZjWH1ue6W9GnHB9ZSjTrqG", - "NodeID-DpwRt5xkd3rKici9ikuo9aEH4AMfzsT7E", - "NodeID-DqogihFFxTyKaUTqmjDt1Fh82hWwkeq9v", - "NodeID-Dr3k3Xb2uFHqztcbVtAbbfhtrwYjsRysu", - "NodeID-Drb1UM6uo69KiAy8tyD2QXv3JUGU9exaz", - "NodeID-Ds4BPVEDoEPu9wHT5rk7ry8vWaHoY4cDo", - "NodeID-DuXPSVSZUeEJA8QP9QV4Vt2G3y3WbPvRx", - "NodeID-DxV8FsH9amd8cjQhEboKZerAPsBR94maA", - "NodeID-Dyd6GY1EnBTGi9WEMvFo7kkjsZBWWRDo7", - "NodeID-DzyJouyxaQRYYyfYEvTaWrB4uaPTTKn2V", - "NodeID-E1tni7wFcu9CizXdckfgxo9dhUwR3243v", - "NodeID-E24tDGQ6uRbTZaFCpqnUgZdWq2Y9YX4qy", - "NodeID-E6CBZzykpEJSqKyNjDdFeLvDN1AmZccWY", - "NodeID-E7Cm2d6wVhaA4Q7AnuRg2S3sD6noReX91", - "NodeID-E7e5wZQb8QYEKYd1BrRrszjPxUaAQNaY7", - "NodeID-E8dfbZCzX8VXgXYmjnA58GorajNrNcpFL", - "NodeID-ECmPviPvgqFc4iXFi3soN1xpXnUUDHjoG", - "NodeID-EDESh4DfZFC15i613pMtWniQ9arbBZRnL", - "NodeID-EEuQumHSHr2hV4C5S2FNL8LVofD2Wvqyi", - "NodeID-EGzKzc9RU6HGCzBe8nK2qY6mVs6WqroBg", - "NodeID-EHV8d1ezFyoA8DMzTU3WZXfVR95R7v1cv", - "NodeID-ENMu41b1avXe4yRxmF1uzymNJP9Xf4jcy", - "NodeID-ER95YbfDrVih5Ja8F81ac1RZ3Bk8h6dTj", - "NodeID-ESYYcZZMJkLzC9raPoRvH4rUeErh6YF7P", - "NodeID-EThtNJN89zd1cGjVPyThdEwHknvV6XeML", - "NodeID-EXuaP8HAE4anxXGR4QJX2em2nfEiTR9tz", - "NodeID-EYEsr6Srmjn4XM8DijPFLFT3Hf7fsDMHA", - "NodeID-EdSG1Dy4kqqaDJRn3kSAdM7RVSdW5eyyz", - "NodeID-EdbD6AHYPYNqv4X9KMUA4RBkuHnd54E9a", - "NodeID-EfGKSr1JxRXofvpSo1kABnyjuyJWLr19K", - "NodeID-Ej578hCdtGtaSQUMQFkPkoXVHHByJJzZM", - "NodeID-Ej5WQFmSCm27bZuRPoK6PeFe5tMURCgdG", - "NodeID-EjSCX6FJvzVA1gaja4cWqfaXEkZeAgnQb", - "NodeID-EjvGBJ65yHcJMwV5RhDJBEcKb1QP4Du1L", - "NodeID-EqJ1JGnx7zPAEvGy9JRgytDDTrsPtZUet", - "NodeID-Et4ic8Ew2HhDqKzb4Zx68SMbC8mCLUWzi", - "NodeID-EtBgBdH22chVR1fzZZPky3jzUZDTigCbV", - "NodeID-EtUZs6wf6j5kZMUuABEzUY7Z16Ja9DtoM", - "NodeID-EuQ17UhJAMCCPKo6qhEkeiEgeyNQk3vLt", - "NodeID-EzGaipqomyK9UKx9DBHV6Ky3y68hoknrF", - "NodeID-EzN4q9mU6TVFkND6oghbdLAUqDacE9Czp", - "NodeID-F19vhTXhznYNp6pAvaUmUpj4VWq7qjUyP", - "NodeID-F3c4DfFS8crrJUyExRhgaMiXtZrn3TuP", - "NodeID-F6AdvbZj7E2JZDfG9WhafyQeFAqiU3geT", - "NodeID-F9kHeXw8eoxEMpKVCi7yCUwYGry5zPURy", - "NodeID-FDXS1jxwngimMxWwdysC5N1dNZVPZ9GQ2", - "NodeID-FGA3erWUCbD9rUBXy1Ea2rzp4xas5zLgW", - "NodeID-FPZ87ZH95TeFm1su82QJRX8PCJi4oBAoJ", - "NodeID-FQ4TUmX7RFf84qxGPBdmPkrUCzCVoWuVR", - "NodeID-FQuy4XRiNwdHunxKvAEsSG7N2oTFvcKiJ", - "NodeID-FSDQT7qCdqgxZZq4AnFDcMpxukPrXUoyL", - "NodeID-FT27zhjAL6HYVkfBHoWk8FQ3pCt4xyVsA", - "NodeID-FTtpSNGEGH4HiQbi99qcgwGsgHthwMUGZ", - "NodeID-FXLBpf4W1QenLua7FMGTKqvk2Anobbi4m", - "NodeID-FYBQVFbWhaazHHXnr2gaVXdSqdGN5PBTo", - "NodeID-FYD28utCsypYL6THXnyT8bTW9syP4WQrm", - "NodeID-FaADDvJH51EAP4vhJEKCEfCtgpUUnTNX6", - "NodeID-FamFBmBfwGwjn7fKpbaWjzcnTiGNfmgWN", - "NodeID-Fc8JvkNuUmo9oSy8jXiNXUczUM2q3jWrS", - "NodeID-FcG6viphauzUYhxsCtbaJUKqirYqp8YbK", - "NodeID-Fcz43yNkFRu3jL97vjLi3ZkpmeAcVR8La", - "NodeID-FdcqnJ1bwv976Ft4RibXmD5DTeWSnMzS5", - "NodeID-FehvGhfc73qH6s4zTdiKrNA4WmSMbCW4X", - "NodeID-FesGqwKq7z5nPFHa5iwZctHE5EZV9Lpdq", - "NodeID-FfiosnkKYLrMKoUpNTuFZz6gY5kb9cPb2", - "NodeID-Ffr1YgeWw3h2Ct9dY7V3u79ScrAbhSUUz", - "NodeID-FfxNCp6tZxTpj1JxA8GGVTtJWowqKDmvY", - "NodeID-FgvaeMrL2GqxSBV9R2hkLL7jH29vhBeao", - "NodeID-FkbkPTVMLbZZJKFHYUKZTt1Z3quNUurV", - "NodeID-FnQRH8p5JrhLRUT9wK2rtEc17EtN8Tcb1", - "NodeID-FnsrF37UrgFtzoEKNxyAV7wN516SwqFVN", - "NodeID-FqAXbqQUVaXS6z6jTaLPZGivbLnHf3G7q", - "NodeID-FsBU6yEVf9ZVEhuFy5sRixYwio3LRN9Ey", - "NodeID-FvMWujr57hToQPSfGsd2exqaFBdZzJBTk", - "NodeID-FxgVB4Wwgg4dZ5WTkkBp9EbwJhAgwZgWd", - "NodeID-FynRLYTNZroGso229UyxpxsjqmQqJgAQF", - "NodeID-G1MJv3mVMjo2SueWzr6rvn1gWyAvgTXrQ", - "NodeID-G3axaqp4Grtc2S6LD3qhFR3wN1NEZRuGx", - "NodeID-G3h4X9o4Rk71ijtpEdsQpjWCM46GNCXPk", - "NodeID-G4Za1ZuLLinkM5skf1LZqAWqKs3P5xs7F", - "NodeID-G5p6Hn8XFSQJKH1YzA5iS53rgDfCCE7a6", - "NodeID-G6g8fYiCrp6ZNryP3Ni2fJKysDxHbaafU", - "NodeID-G7fjDTJ9DH2P3ckC4VqKvH9q9Zqsv9b6b", - "NodeID-GDZpG8cVCndUcnoHiub4XPM5WR2hF7tmk", - "NodeID-GEC1zVazREQmLUpj1fF2qvuATpRvMgf62", - "NodeID-GHvQsCAUehhZi5psMeBxDfKHuoVGfRoDt", - "NodeID-GJsdSRahtgdsTBjr3jbew5uqTXLcjJkG9", - "NodeID-GK8GSuLrw6jk9CVZ7ryAjSTm3pFEmeVF8", - "NodeID-GNJqrL7nMYPaYXcrSSfsY7ffe5JAzTRGh", - "NodeID-GPc1Si7SQ6oAEfP8MzQ3cFN3fsAtkwC6i", - "NodeID-GQTbQ8qJYwBEhQEa92V1yjHzeVyjTDKFP", - "NodeID-GR5Hc9oEi2AvNBAoUaQDZtWEYz73jP6jq", - "NodeID-GTgPUiVqjBX1UAFmdDmBoyHuiRhTPrZen", - "NodeID-GTx2HdjpdzYuQEpjrKnuuvXDzd8XPBxBG", - "NodeID-GWRSuAdKF4LjKSgEYFXR1crtjov8vnW4a", - "NodeID-GXtJyspnxHxzLWWyUqJ3xgXNidoxwAtdw", - "NodeID-GYXpBJh1SYjG9heFSV51NVhJHh5LindGx", - "NodeID-Ga88DP7f7F12ePN3LEYUGge9kjKi3qHP5", - "NodeID-GbUcqW9qSUuKZPMJ89qL5YJWDfAuUjdq5", - "NodeID-GgDJXjd35ewugJyG9tonbjBEKVZambFAb", - "NodeID-GhLyXd9aVH4xujx9SzC9oy2JcQQ5amXuC", - "NodeID-GhsAAVi8nXhvLS1Xv4ast3EbcL4BDU8NK", - "NodeID-GiAS7J8Aiuj2iBAnKT2wmnxWWqp1QLd2v", - "NodeID-GkiKRa6ww4zJqXKQUcqHXnGaRKD6JNoYx", - "NodeID-GoVFrxwF41mzpVyt6Pb8K83ynj3q2U1CV", - "NodeID-Gohrw1ApuWhwFwUbCLKjS6hbijukerjuo", - "NodeID-GrL2hD5CdKU4CE8fbN97kVH5DpztHMLPX", - "NodeID-GsGzZFRypbZdhosjortCTbGCHiMGAifhw", - "NodeID-GsoJqaJe9SBrouxVCtSriYE64e2cQB4NP", - "NodeID-GsufzM4GKTutEFEAkDunS2wkhjdUPUvCu", - "NodeID-GtJaZR21ZmzB8CcPYXVA2Ks6Qgb26upj5", - "NodeID-H5Kcdpnye7iumF8ad4EHEFxvYzPAg4o89", - "NodeID-H5yv8taAdDWeCGNSLzdM1u2FA9cavk8ka", - "NodeID-H6FuMzUuGxjcko4hoBhPaZ56F4pheS2Sj", - "NodeID-H6Y7aEKkKz5HeWp4nE7nKHR4PUksjBuke", - "NodeID-H7Wq3A1RJsb5skBd9iy8zY37yW72zrNLy", - "NodeID-HB5cY5e67mzjNwrcqucGAxh7SyNMWLY2z", - "NodeID-HBkBmNgoiab6dDBZ3d7Atiq8ja9achxwV", - "NodeID-HD9qhGtz18TdEbLeuMhn4ZXNCxvdvQTwy", - "NodeID-HDcjsGMHLaLgJFoQYmi4CBsbjMKPacuP6", - "NodeID-HEdbAzR9GLht5p6b47J214UhdshCDX9TP", - "NodeID-HFEef35BkgqRBYiQ2ou5JhsyB8LHRtyuo", - "NodeID-HGZ8ae74J3odT8ESreAdCtdnvWG1J4X5n", - "NodeID-HHXxANboEXufRMuSFBHgc5dbpk67L7XPV", - "NodeID-HHcVpHweLyANYAB3UoDYrBQLDznFeS42j", - "NodeID-HM73QztvPuGikaADwnjpaJ1iKWAABuQon", - "NodeID-HME2ASYZmCcpRRpKQRsCLPJ83ZkWDBkQ5", - "NodeID-HPpKmAyrXsouQTaxMJR2YFgSDVV8BA5xP", - "NodeID-HQ4mk1kjeNvfsan5qrmynaMhQLCsQ4pYv", - "NodeID-HThbCMfRbs6nVRR1ySihYtWLraLZw8x16", - "NodeID-HTkPf7hwzrLyDDjAZAqMNQh9oF4B9iebY", - "NodeID-HVYnT9MUfcK8sFV9tRirmkppWiNmFWQya", - "NodeID-HXdPaFvKy2oaDKcd1ufP7cjUuRLk4T3cQ", - "NodeID-HYDf2HUkHFDiUKYmort7tjUFLq3253dHc", - "NodeID-HbH45yH52gVWeFe91A873QBG8a1uGBD3S", - "NodeID-Hcg9iX24FKp1zumDpJbXF4vPzkbcHBDhw", - "NodeID-HcrXuRruPjFEdc3snCR9wqxbh87sNCJWj", - "NodeID-HeWWhU8g5KQBNFaVdwnj2TZLvBVuke7kB", - "NodeID-Hfm8gpD4DpCz4KTzt2osJPfFvu7az3qiD", - "NodeID-HiX1MqbbJLeV96jrYH6uTkuWr7ofbiAHy", - "NodeID-HkyME9tYN3G6DR9bvrha6XWNB3kYaDJbq", - "NodeID-Hm1uax9QMFjwNrrAmriWVQVcChyfmrqFB", - "NodeID-Hn6ji4ie91SEhmpgs7PZzDajaMZoH3eZg", - "NodeID-HnZNJY2KscixbVi58em86faLMY1BbT5Zf", - "NodeID-HwYioQttyXRmGzdGAfNcZ8cAkrhfCqSuj", - "NodeID-HyWNPsQZyve88fbwmxgUzq8FnNfE6wR9E", - "NodeID-J3s61uikXhXGVxC8ffsgbctVLV1Mbvxz6", - "NodeID-J7EzGdbSy8EFrQM9bBJXdLfwCoRHtXok3", - "NodeID-J7yqAsDbJ9jXTg3dbszqUoJMgUwDgnmyn", - "NodeID-JAyKNPqtqsmjizdEWgTy8C8dM1tgZ7XNz", - "NodeID-JBWVRVMqqTR9sYFQqESA1V9YQNoi8oa1b", - "NodeID-JBiRdFNc9he8ivyGkdAzH9WaL4GKHoQG4", - "NodeID-JHQyndxosLrdixA6TjB6bexisQxCuQkgR", - "NodeID-JHVmPLfE3YrKdBozJM5MEn1BzgMJzUyPz", - "NodeID-JLw6tbjnhJZLhEq5jnWsrxRgP3AEbxAtT", - "NodeID-JMoiLcTY2t9P94nTXfm68pYq7LMQ4fdFt", - "NodeID-JNRTA7Q6t5azWZrT3qaVeeXnT4vH73zDF", - "NodeID-JPvPvJLYDc89thb7UhqrqhndNCHGggxbM", - "NodeID-JQGMqAo4i7uXuS49vgaZDeJedDRp6oyuH", - "NodeID-JSNDtZdthVnHjSt7NY3HWd1ub4gw1pKez", - "NodeID-JXw6V9Bwidgc7c2aCZEebHDRT2FuWzBLu", - "NodeID-JYJRG5ZYgd6kuQ6RvqHMs9CGh8RkyEpvv", - "NodeID-JgQWdp2K5yq7Bj2Z3TfGDP8GYAmeqtUQX", - "NodeID-JhWkuVZGeJ42FLktoMVoiGuoaepWjxyqx", - "NodeID-JjvzhxnLHLUQ5HjVRkvG827ivbLXPwA9u", - "NodeID-JkadBNex6QYkFN6MRMjrRq8LHn6jp6qKk", - "NodeID-JnVy96b53CKBAPiqJTRTK7FnPxRk15gZ", - "NodeID-Jni7c9DhGu4aMvU4axvH8jfnKLmi5iaCo", - "NodeID-JqPCvrvnKgNEKdsKfCnhVcaP9KJ3GWPq8", - "NodeID-JrKGcbdnCzXUijeLiwzJZQNX48Cyrs9Yx", - "NodeID-JtgzXwsBLsJh6HWQGWfszrCCxpCnnzdwc", - "NodeID-JvyHfY99GqXXWUsSaoeEEZZ64LQpMCUMU", - "NodeID-JyE4P8f4cTryNV8DCz2M81bMtGhFFHexG", - "NodeID-JyRud4d7Sp77cjoXiuaThBsUVrSFEHgMQ", - "NodeID-JzcJLa8bXBPBg75VVXUHh4fqgmhx8N83h", - "NodeID-K2tnczAaPNak4WDoHs7thRxztKDc3LgoH", - "NodeID-K7X83JX64HEzj4xSLF8MZWNNtUbQmwnn7", - "NodeID-KEkCHDs3iiF5U9xaKSVg6xzDU27oe6bBp", - "NodeID-KEkeqcndUcaWVXNjNCXUUbX3gUepXqvCm", - "NodeID-KFerpW79qQ1whckFbjUvuP7eLwtXEHndV", - "NodeID-KGfpnGi2LiRyTFfeq866B4skCpo5xuwFp", - "NodeID-KKMxwJXjz4iB6G1VopYYst5W9VJ7dE5RH", - "NodeID-KNGEydgzXRZzNcibfSDGfQwZBUHaA91ij", - "NodeID-KPi6dGARXc6A8vMjKuA8troteNsArT2nB", - "NodeID-KRibmCkicP8FkeGM5Xm9yykNcrED2sjaK", - "NodeID-KRvfLaiAUDLBEixkmdTDf43nNppas96Mg", - "NodeID-KTnhPkucgchw74sGCrkpuCUmv5y2Nwnnz", - "NodeID-KUVib5Ye7nrnA7RdKWz9nv8q7gZuCZwp6", - "NodeID-KYr2Ldd1YHibJx38nkQ1vfqzRmsc41Gzu", - "NodeID-KcC4UA5WXJtgRBdhtEnECqxyNcxh6bsno", - "NodeID-KeNHPP5bXbGV25Ujjp6cYfExVzQrmCfkq", - "NodeID-Ked7WpBzVYe4DthczsGV3CCYpEvj2F2bD", - "NodeID-KerQSdj93DReMZFcDxqCVqs37jwEQb1Ji", - "NodeID-KfWrRxNQACEGRqPw7RNkpn2AYh5kPbCFt", - "NodeID-KjKVvgJ71tiwHGwqBmhQLKGqrNeQBpqeR", - "NodeID-KmzXj1CfPzG2WoTJiXr2DACTksgeQARJp", - "NodeID-Kn1JzoTMNzKS67fuEtcLU73dUTCdjoomR", - "NodeID-KpdyakxPD8mdLHV7XDYjrtUZ6BG4rXRKu", - "NodeID-KrZPkFHQnZWqdSC76pXRvnPVXBC7PyWWZ", - "NodeID-Kskhj6CSMxyA3Y6VsjrjGUDGZdMXTMjjv", - "NodeID-Ksmvwp6BpSszz917AjDWG9mHqi2cdXVW2", - "NodeID-KuvxfizxywPLkup6RtzmaJcCECjBrSACL", - "NodeID-KyP1LyscPyThYCEbN1KXekaeNgCtUgFhq", - "NodeID-Kzj2Jr4XWUdVhLkRsaYC5WH3tKVKyqX8x", - "NodeID-L1UD9fwiT1VtFUVX7en9Pnz4EcLTwAvwP", - "NodeID-L2LTo1cbHtyqkZfgKpPdo861Lgz8WmJzj", - "NodeID-L2kZ947yAuzugQaduZPJdysWRqxxsT2Ak", - "NodeID-L3eNEFiZPrdiToXvDvcR2Yepk9p23NK7X", - "NodeID-L5SLiTDbpJAgt4VFJ7CtVscaYcLk4L8jT", - "NodeID-L9Md43FWvJz6gQJ2eAS1QVigXSecSM7LC", - "NodeID-LCXfgTWLmmxazX8C3JuRbvpzmzqjzT3xe", - "NodeID-LDKGrAwCoz5Tdhu4tVDjqFFQsR7nKqNHz", - "NodeID-LE9q4y22nKHCv1gHSJfUyYY1qXcziLkFx", - "NodeID-LGGrrgqBdzT3smcojPh7nTKiPRu4Q8G9g", - "NodeID-LJH9JffagSPthZ4adGRjHByXFytPdrmmc", - "NodeID-LLH3HuzG4eaxJYYMiZTpQPVJNuEAZEaa4", - "NodeID-LQE7F5TjyfGV3HqrzAwYYAjdeUZzp4Fzh", - "NodeID-LQwRLm4cbJ7T2kxcxp4uXCU5XD8DFrE1C", - "NodeID-LRPi25wApvsNUuUFwwQtUMyuUNgrhmZPG", - "NodeID-LRZMF1NjDo4neYWtbA1vRD6P7rmLKu3RL", - "NodeID-LSsApoxv5refjrydswTevcdtddK4LU392", - "NodeID-LUMxSYFmov1nDn7KZE1Z4RmT1EYgTCu3v", - "NodeID-LVSzcr2TXAjTTNbEi8Nxfjwk3GQyZo2s9", - "NodeID-LX75T9BwhW85T9Vz9mxvUEQhFqR1688Qn", - "NodeID-LZMzeFFuZvg2fL3JYoAGd8sChmBncgPA2", - "NodeID-LZYJZxAqgn28K3g2crJtGgr5mW9mo7NFc", - "NodeID-La8YHdyQZHuaaoEb6ww2BznRa1N4c54J3", - "NodeID-LaidvDiaEiYSxKhqPsJx3ST2PQKFidmY8", - "NodeID-Lb7Ez9LWTXUeKRUMgHX4JJtg4WNh31JUS", - "NodeID-LbijL9cqXkmq2Q8oQYYGs8LmcSRhnrDWJ", - "NodeID-Le4BWsZM3dAuMXTDL4rkcRZBTyHpC9zzq", - "NodeID-LegbVf6qaMKcsXPnLStkdc1JVktmmiDxy", - "NodeID-Lf75GiFUq2psqfd3e6GkMNuVEYx9BUuuT", - "NodeID-Li2RswwproDXoFXPtrc4LvVWLxC1osx1C", - "NodeID-LkER3oCznkUE1mTaRsugitboTtBSxNF7o", - "NodeID-LkcSuyM6DZa1ZMWDpybe6VJVD1RjNF3JW", - "NodeID-LkdxkfYhg6nSw1EEUxDUSYPXPwmr2cUet", - "NodeID-LmzaWSmdA8jM4hfYjsEZ9QJnHZP9K7nET", - "NodeID-Lpb442HkX5sNFDeKcf5zXZJ349cuqiWdg", - "NodeID-LsgAS4nCNrjL4gxPmTSDmNu2ywWrPwvVK", - "NodeID-LtUqKXZBqZj37HCNQGqjaor6TZVBVF51x", - "NodeID-LtmsxApSVQQ68HiczFYmweUUFFLG85CBr", - "NodeID-LyaNgPqgHTrKSiLdEpp1JPF3Qkv1k6n1B", - "NodeID-M1745j4YUixszHoRfPq52DpyQ4TSiM8pL", - "NodeID-MEEDgr35ZZm61jCzguAYDqFipBGrEnMtP", - "NodeID-MEe8K9JFZHtovv515bNciv3YGC3jci3yN", - "NodeID-MGkAX1DhKPPUudKPgP9qu2bCh3h2KY2ea", - "NodeID-MKaR86DivZF1UA77gwUtRjHp6ddUHBr6T", - "NodeID-MLHMrE994WwHxKqF6tf6E6DF4SuQyeP2Q", - "NodeID-MMiSVwiACfxkyURcAYV2EXUShAYpmpkWJ", - "NodeID-MMsdXcGMAN1RgytS3EfsEFzF9opLeEryY", - "NodeID-MPw5DtJq8yeFFuEj9LrhiM6p6hhdTXBsd", - "NodeID-MSF7z6rWEhimnDUJwwaGTiuWxkQEjT1Di", - "NodeID-MT8bs75x9ZZYTCC2G3FdBfSiSPmW5nste", - "NodeID-MViNUVT7MHKe7jS91EtfJixZG1nDowv9y", - "NodeID-MXwySzKc2JDDg2GLR8NsmHXDQ3XJcWFtT", - "NodeID-MZxyHcXmSRh6uLruUmgBEhXRxYge4rooz", - "NodeID-MbibpFmGwGXAL1yPQVDvJfjL5GgbGqDEJ", - "NodeID-McsVE9skuHHM3ebcFwWLhzXvhpT2Dc8Z8", - "NodeID-Md59LZThQ9xsihEFmbgv4SVktSuQkXnN6", - "NodeID-MeDZKLP7y9ydHRVixZ54yxZQzWqS8YvG", - "NodeID-MeZyN4H2yUfvu3KuiTFDh7KLctHWni9tF", - "NodeID-MiMhJNePYcQNGrAVsXRYEKXQ8AA85Nhb9", - "NodeID-Mj7LRrnqPK2UPrAKYHY3aNSDpshsM9tXP", - "NodeID-MjFgGwGpHSsvyJPk7d5XRhWWyihttVLNU", - "NodeID-Mn5pQf8vkLQtic9W6beXzE592Gyctr4qo", - "NodeID-Mn9484xnB1NnnrfPfeJ9UrdakNXdD1B85", - "NodeID-MnAL4QmHAqYihdL8Ad61AY5NuKAtYjz9j", - "NodeID-MnBVormBXdmpzuFUVFX7XVdwoMHEbH2bV", - "NodeID-MnNiFH3NJLWYsH1MU7C4U6fXdzhqtZW6a", - "NodeID-MoW5hERQWaaaZDvy2g3LDHqUNqkf7Bjo6", - "NodeID-MtR3HLYP88Xmsd8whwWHRvijdAuWsPsBA", - "NodeID-MucxfzaqiKNQCznykW8XPPM7JZFPVEbhF", - "NodeID-MvxNcbGGUifjjh41nnrm7RRsTqmU75mH1", - "NodeID-Mw9wURaGBAXkgbpX5fkipsmoqnWXXxzdF", - "NodeID-MwBo6z1rpGZqbD9xuo3ByvcKTw55D4393", - "NodeID-MxsyPb1TKJzaTxyVvEvYqmkYfAH2NKED4", - "NodeID-MySLmc7236dztdt3jA5znemeaSHWGCg8x", - "NodeID-MzpGqPgcjmT5ALuCnZXbociRiWJTQyncW", - "NodeID-MzqqzQwU5BGCTTTj7FTEG8eGK35Sp4jrB", - "NodeID-N1dQ3zWTgcpnxDqejNYLevSQQPGNZSgvg", - "NodeID-N2vaQwWF6MeLWTT8Y9pBKV2oGjKVxZ6K2", - "NodeID-N59JVgQCpF5cRt4e6zKQUBgDkgyNH5GAa", - "NodeID-N5gc5soT3Gpr98NKpqvQQG2SgGrVPL64w", - "NodeID-NEeaczgsLrh5DKparo914eAz4SHCNrCSn", - "NodeID-NF3dhwiiGHc1MoT85T7MwWk2xLF9zpgeh", - "NodeID-NGCgVZpeUaJXdjVq2moRRha8tM8tfYEcc", - "NodeID-NHkrKzwkkva75HTqd1RDWBdH7tRe9FAFo", - "NodeID-NHv8CEWXzT8z8A4xDU9qDVp9yGfM9SZVo", - "NodeID-NK38Y3Y1gg3duKmwEmPURY5ngYLYb1yAq", - "NodeID-NL8ivcdpDokN2c2XB36iBbqTP2dmtDN2z", - "NodeID-NQxiZFkiHvPMdFnVQer5K3mPJPxctBefD", - "NodeID-NRhg5SrvPn8CvtisAdgFXA1QkLoPsqRdp", - "NodeID-NTELjonQCqJzT1QFvRdvMSDtJ2qwnqXGR", - "NodeID-NTvmKq2wmTvqoccqpxW7fQd1iGCiGhAsj", - "NodeID-NYrHxv8EfFjM2wnsvXSickbq6XEqwwB34", - "NodeID-NZeTWb3Ri5eR3tim5hAntmiwEWoLVdkDE", - "NodeID-NZfe5jh36pdgmAN4yX3MgafwUFmvMTCXW", - "NodeID-NctFDTRfjWrT5cfC831NNBA12XCLmoLTC", - "NodeID-NhqNSzgKY5HahcosTxbcB887htZgzcrjS", - "NodeID-NjPTsac32vTLnYBmz95TLBmMZZyy68Y8t", - "NodeID-NmGx6qD19PwiQRPwJq5fxfoKc4QUaSYPc", - "NodeID-NmUiTVDryDrut41qnwaNrBref4FMfn9Wg", - "NodeID-NpagUxt6KQiwPch9Sd4osv8kD1TZnkjdk", - "NodeID-NtyTVeUSdkNrAEQo3vPLzrqhQfrYg8f7Q", - "NodeID-NwkffS9VYtwYH1pDJ3xMD5ZKKt3ZAqCW2", - "NodeID-PA9LANCKQbk9Un8Wv4SbBXoDCW4bP9yLk", - "NodeID-PB6nGgZqX8ccEvyEutDiasS8ndhnrakdf", - "NodeID-PCuSoYTWTcZwQUZW41HpW3VaU5ogsAGER", - "NodeID-PEdsT2FKxpXiemSctvHry8gbZJC6bJrF7", - "NodeID-PEsmPuBRtjpBRnaV6gTrTxTFehVUtjDf7", - "NodeID-PGhVwQYM5eidnACK7jQ5ZkL1CnFpKTAm3", - "NodeID-PHiFH2SQRhBFnaNsLVZX179np4y8gjmk5", - "NodeID-PKSwUUGdADabw5br1MosKrSPyyeYdRKAu", - "NodeID-PMYYkxDpE7RPrtmACDaHi6RESLwhoHcYw", - "NodeID-PNXWeCUduveVZYuHRf9Mi6b4suVMJsxSK", - "NodeID-PPCdQBpQ5THZzWrbKAHTdwj5fcx2x3wBs", - "NodeID-PQRNvZxSZi598GNxbH6joNaUPgxaD5Yaa", - "NodeID-PWko2VpWPb748ARPENzdAfak6NZ6pYG1D", - "NodeID-PWnPrE1Sckzuoj4Di5zBwrRc5q8UYGm7j", - "NodeID-PWxEYBRBbKai9U3t8jgfb2SA8uAECKvju", - "NodeID-PYXgapX8Yi28W2Xib9oNDxuaaLkZ1gZ42", - "NodeID-PZATpKoYGFhHosyUfecJXUAzbXiMVEWcr", - "NodeID-PZCSrsorCsvyTxkt2aq1yCMXPxEUm5PGF", - "NodeID-PcZGZ4CzwJ8NEGsL7ccQEgAGZ7AU6jtBc", - "NodeID-Pd7rHrBk8hJyD5uCRcG3uWC3ZwPGtTohm", - "NodeID-PgBvqpbMQzJk61yoN346xxrnrHad8y8LB", - "NodeID-PgXSBGwW6cNMwQv8P7kYXVr5AkJWs7i5R", - "NodeID-PgheFFDtZftKj9mNpEvH27zeQ6c6qvoep", - "NodeID-Pm3TC3M1pWDFhwa79YRqHGzG9Sjvgcdtd", - "NodeID-Pn9jFroHyLVfDmsEruHABa73mpbnSU5RN", - "NodeID-PnZAZuzfg7xchQ3qbCMAtg4bAW9XSx1Jx", - "NodeID-PoyWPaU4f25ev8h5KQYWrnTdGMiN9scHK", - "NodeID-PpR5kKTZTpF2VstAXn4BwNKHeNEvo3LiA", - "NodeID-PqKQwU5B1hzz11kW9BE4G642BMB6xrdnz", - "NodeID-PqZJgjNLDbeqmSg7hMWU8R1a5HCEjbBP9", - "NodeID-Pr6ZsMxfFr6uyMyZeN95ZJ1yHqGrDhqRP", - "NodeID-PrZZEFnhrsgdbWr7hZYBw1vTpLpkntFLv", - "NodeID-PtHsgZydMzwYNT3GcUXmaKptmScFwJkZY", - "NodeID-PvST69voCJeusKj2UGoFvK1UJxuZYWjmZ", - "NodeID-PzPoTUQaErAzPd5EBdRzJeNSFr1kVMX3h", - "NodeID-Q2J1vGj5FvVz5rDST2nC2saG1BeDofUbY", - "NodeID-Q5Jk89SmFTSnxonorozufMhqnyY1RiUQx", - "NodeID-Q5XuPs5dhsQRuGJebnzStvyF7GKWt9JVp", - "NodeID-Q6uYpvGDEJUUqgN1eiiKNkDCfbPCjB11s", - "NodeID-Q7e8iAC8sdAhnhPuegkFchun2yHo7UAC7", - "NodeID-Q7y45kPeb692xEHNUXA5rCdZgDqvQtHtF", - "NodeID-QAnYYbuWU1PfEqVFgZQz9EHKEWd8fky9z", - "NodeID-QBtEYnbWGX5PtbsD1cd37Jx4eATeJoDuA", - "NodeID-QE8ipEQ1Sc56Fa15G6HdCfUFk9SpFRBjM", - "NodeID-QFG9ZiXr7boyFonB2D5B4MLfPHRgQDwLd", - "NodeID-QGGJXjdsv7EKVKy1EG5Hq9GzeFcNFMbMh", - "NodeID-QKheyKgFVkDyMxLcnoUHregsKHFuzuR6h", - "NodeID-SCtrKtb5k75f8KUnTPj2gBsq6yrxpmk3", - "NodeID-SvkCVFNKhd5VEo8Hgdky2TyxZ4J18NpV", - "NodeID-TJvKKLYAycYi23bnFiSFpq9pZBNktyer", - "NodeID-UCaJK1qXng91C24jExSCkRhqE8hSCXWW", - "NodeID-UujvYYJGbxFXh357EMppUFsXzPKvU3sN", - "NodeID-WqHQbG5MYQAYBRzjJV3qqy263mbz6iko", - "NodeID-ZYrkX7KzmDHfRzUhtVu7B1EYy1dCbbQZ", - "NodeID-a4kVGB6zfhfHgz3JpoLY7Yqr6aXM9BRv", - "NodeID-bQd33gr3fvRae95TLYkF6LcuyqrJeKK2", - "NodeID-bpSs3H78Q6kdMPHyy1WAYGdVXhVMmuWg", - "NodeID-c6NmA1sCyFvKV6NeKBndEykD3a5Y3Svc", - "NodeID-cCZxQ6nBdNcPMpKdKHHxm5kjwfR3caTk", - "NodeID-dFaWdTjZH3FryPCs2MTiivJuia52711h", - "NodeID-ei9CM9pS3ePsg2UYUrdRRALKr61jyJav", - "NodeID-fJcYnNFYcnf9Tn4sLVPSyKnpFr7yivMH", - "NodeID-ftRqiSfcMstsADKTtMnHGX8svv95tPXn", - "NodeID-hArafGhY2HFTbwaaVh1CSCUCUCiJ2Vfb", - "NodeID-hpZLLFfwLit3Az5SDfXAtgCsErQfdQ9A", - "NodeID-jRBYRTWyowM2FUvfyZkg8cmhtKwqRYb3", - "NodeID-kCqLujZC9JuZp7sqe3vhffxgMgVwq7bu", - "NodeID-mce4CCkKp1Vx9ck6FwtjQVbTyUSvKe1V", - "NodeID-mwGVBwDPG11rSWCjYwYyqBJJxM3ZEoPj", - "NodeID-oRUBcQ7Lsrxi2S5bmWGD5CF69e2x8mct", - "NodeID-pCZeP48M5cMxycWR5QFfUumPgwKEXPFY", - "NodeID-pQCdCxnzPybSowJ8aNuu3o1w7e7QCVNH", - "NodeID-tFgE4qqgLiivtexeoojvJgSk7eHv1HRU", - "NodeID-tkLPZudEk3RpVG2DLq5jfZS4KHLJf27E", - "NodeID-vDc7LhjzpkqnPoFNMisr4BvijCQKe2oQ", - "NodeID-vZMp41xfebyKTCjNNT8wq6bm2u2xo46B", - "NodeID-wvLAxGEDoLcPaTWzEkmV1n7ipXFiWAA1", - "NodeID-yJAXXBzvB3sTVciXpoyku7uWuvhPnnqa", - "NodeID-z7b2btT1NfrouM5xCJPescQW1QxWLq2v" - ], - "mainnet": [ - "NodeID-12dyQ7nhRzsNSiFzEoW1RWK819Zkssf5g", - "NodeID-13XrVPjS5dVxBKaweeG94SjY1Q6yeM4EJ", - "NodeID-1431VdHCWJgM15Wcg3zaSBYbpXGTSd7Hu", - "NodeID-158YgSNVidjeFx76vtQ5SxWq8B1F3ai1E", - "NodeID-15AuPME9h4AS8CAEDsokNE5KMjLovnphr", - "NodeID-1A1GTyMcDcassSiTBZFVuoXs7AS5HcHu", - "NodeID-1Z67stQzn6v2hi1wD1Zd7nooPoqJE4es", - "NodeID-1aA7BtLfTX4SRXaWR8HttP4z2UapE1R9", - "NodeID-21TUfex3GmhmusTHmp5SDUQTEaCkaXwH9", - "NodeID-22jB4hF45iUrVhqiHvbDETRgpHKJdirY3", - "NodeID-22k7HZj3D9DSAD7ujyvvuYn8XzWuwA1Hi", - "NodeID-22wjev1roSt8jieZ4SW8rJLG3YiWyvbV3", - "NodeID-23NsVPT7XuxbAmisVH2LFwXAN1JsGvCjb", - "NodeID-23Po1dKrXFmpQaRafo1ZEdv8qbHC7i1yi", - "NodeID-23Xaok4Hr7SgTcCjjMnVsYJaN5cSZLR3Z", - "NodeID-23jyZenUu8Fm26ebdyXEEVH6PDoEXJ9j2", - "NodeID-24gzuDUUhGEsAGbxhMZNJJ2x5G1wDVHEo", - "NodeID-25GWqcvqc8m2ZT5ULNWfan5SEJNFBZMcw", - "NodeID-25RzatyYmpsm3QbYj9QdSWqdFQLKxdMR3", - "NodeID-25vUwC2XTURgqbtYripLhP7V6HPrkji96", - "NodeID-26VN5FUvCmFWEhHm2k85hHn4rDqyKsV3W", - "NodeID-28wbL4a2ozWTgYXt7NekGT12h5wp6UyKg", - "NodeID-2A2CytyzFR1r5m81cfUPL4BR2MAAp5U3g", - "NodeID-2BSvxuZFVVSpjrezuABMPvC6cLMwH8TT8", - "NodeID-2Bct3bqbgyNctwUahjFDCF3siViyVBiuJ", - "NodeID-2BjnggzgeiPAgrSmpzf3Hd1r4DTan3Rdo", - "NodeID-2Bq98e7Q94vVWipc5tv9jCL4aMxL7pjxr", - "NodeID-2EH9c6NwjHLZLWC2Ah3vekv3XUwcup62L", - "NodeID-2F2gRAyyVkaNC7jtPzJ4zgcQh64QyMkvx", - "NodeID-2HvkjoRiMzEcZgpWKNAruLKNv9r7Lb2pv", - "NodeID-2HwdM25EpGSt2M2BDaYREmGJrbYNudMma", - "NodeID-2KSietvSEq4mX2C8p1DAT83RTJPykxUqN", - "NodeID-2KfgS6P7vf9L55fMRTbHPgS4ugVSDW3nj", - "NodeID-2L2wFDTAv9Ti1wpqbFzqLbTa87dMw7QQM", - "NodeID-2PZiqgTALZcdU1TUvQeypFARYEgjkQZPg", - "NodeID-2Q8DS1hgPgsaMB1y8VqmxeworYJ2h2Ubt", - "NodeID-2THa3uLP7oEvBj19k4E4jm1tCpT4muhYi", - "NodeID-2UXMFjdXTw96iQHNL23PxH2hcLJUxnWic", - "NodeID-2VJfSPqaevBmiJKSVDnw7GBwsdfgA1XuM", - "NodeID-2WfvcQumS36rdyubDSioc8B5YinToKAaf", - "NodeID-2ZtHY1RPNrq1y5YuJLaCShK617g6CjRsU", - "NodeID-2aCXkeemxpBXiFui8BX1tVpyVsvhoZCU8", - "NodeID-2aSKmf99roSwDq7MChQ5pvmCKoS1qbcHS", - "NodeID-2bRK9nCjngVig5fMFjLhVgqf18L7dbTj6", - "NodeID-2cH1ggEZ8Z6CoKoQsEeZudUy5kEihW4T2", - "NodeID-2dsDfPgPdjhqMfDHskgiwDcqkqhhG6f7H", - "NodeID-2eBu8RjbvCFTZMcxu1oh2oKtfHT7V4zyM", - "NodeID-2eJ2XJDpUagguhE9wKFR9JUxYNaBk49Ko", - "NodeID-2eraCsE3WijaEnkcFX77hbK494TneHXkY", - "NodeID-2ff3RLJaMK5VdQ4jnXELc9yas4iKoKuLG", - "NodeID-2hoNSdthtVU9RE6g4VJ7Y6tGdWm3s1PKN", - "NodeID-2iVvryG4GyPR5XBQebYMMVTFYfsNKy9oB", - "NodeID-2iWqUM3VWvrcTLyXi2KgBLVhunMvFW7vY", - "NodeID-2iY9tRvYLGjeGtjnUGyGbMz7uoaBdZR58", - "NodeID-2itoUKTyTyhGLyN1sYKNiyKHG2UkDGjgk", - "NodeID-2jnJ9jJrW2EULmCCNnZz88HHCAQYo1Bja", - "NodeID-2mWa8ytKEtviCNwmHfSPmDvkTGPLH3kf7", - "NodeID-2nfH8Mmj5ZY6Tx5oD8ebst7prrEmbS4Ex", - "NodeID-2pC9PZWbWLdaxTuXX3zvh4xZ4WobwiExr", - "NodeID-2pNQqfaBqMqwWgeJiqPbmHZk1cUtWcjqb", - "NodeID-2sNYafYrpqSjsGspW2emjd6TqNTtWz74S", - "NodeID-2sspVTzGYqTkeiQeBsdFKv57gWpLg6Efg", - "NodeID-2vPh5nJm68PNyauc2ot6LJgubxBaJbBkV", - "NodeID-2vbdREFyZitz6LvSBca5gCe3eCPHZGq3b", - "NodeID-2ves7JhkWUcLfPWWtKVgh7uvJogz8HLnR", - "NodeID-2wWroHMggzJvKh6t3tdPtJTTP9DNmdc4K", - "NodeID-2xWeMjBPrnJejBo1vFiyNZzy2FcquZnae", - "NodeID-2yC7fWX23kGjCd7ytqGzQQcRJf7xaj1N1", - "NodeID-2yZivvmC5XD2M6CwcVVBdPGGgU3MNta1o", - "NodeID-2yrtwg1pRGi9jB6ayaXgpNbMTeGHUyofw", - "NodeID-2zzp8nVwqw7ssQsMXniESwjwpZYMzeFsa", - "NodeID-32JAXT6PVdHqpvDuXXHfWrFLXg8oZGqiv", - "NodeID-32aVnE9HYv1FesKKbvvUh1ZvFU3ARNtR2", - "NodeID-32dhPQyEQArm4ybXTxAvAAWAap7DkZAPh", - "NodeID-33Ztk39cwheRHZbWLMyrNFUea7y7VoaWW", - "NodeID-33miCHPn9eN8H9Yi4bCzEaL9Sc5BLeKMg", - "NodeID-33sja4uJHmJ3fpDDu5byuG6V8icdSAke7", - "NodeID-34QP8d17f1XjB778dCTCsBfjL3T4PeMAf", - "NodeID-35rq6ZWsLWs3coxC38LACEayLh99jxMav", - "NodeID-36Vywf4J2tu9gA8xJCxZjwi2JABWSF7qo", - "NodeID-36i6jQQTfB6Z8NXFPQJsY3FVukaSGKTDp", - "NodeID-37Aec6FfbDxVtjLNUv3bTsaXWaw5EGUrM", - "NodeID-37ZMQ9ZZ4e7ZD1kmRg1WSTpRrEPSQ5LGT", - "NodeID-39ZN7XxaD4si7XdTrhiaPJfQqusjzLP9M", - "NodeID-3A2diR9QLdWU77zW1sS39tAb1rSYexhSG", - "NodeID-3AUVAzMqQ66svzG1H7JVgURhUQHU8Y3r7", - "NodeID-3BmiiYjMNvspTqKKo4fXJWbjDbaaWRNXE", - "NodeID-3CHc7PuHw5sGxtSVjujpHRxgiFDSFfucK", - "NodeID-3DwhPYMEQABuocceWDAZEpi8GMcLyvTYy", - "NodeID-3DyUWkRptB3CRUVHk39Ni6Dpr6QvGWXwA", - "NodeID-3EzewMeb8MrVyWam8FhnHPHPoKsT7ERXM", - "NodeID-3FhRFK6UxSfMED5EkK7jZT84pFZy9f17D", - "NodeID-3HLAgdaA61zPrTx5yQ7Cc6waKWidsiqMT", - "NodeID-3HvUXQy1siDNUBGWMYxwMfjufh8mxLtQY", - "NodeID-3JSPJv6xHFBekjausg4m8e5JP7UXSPWj4", - "NodeID-3K3PUAqo3cKxRoQyYto1EsXtuTHoDZ2B6", - "NodeID-3KAxYX7JeLQgm1fwzVqbzjow6eNzSS9Aa", - "NodeID-3KX9tgCEQcTHbC8W9yY4zY32Cj3ET9MNQ", - "NodeID-3KyemFW2jou47TCfoJG4YQhtCDd6Si64q", - "NodeID-3M5i35f5u99QbBn6fP1FzeAto7NA4TFKt", - "NodeID-3MFu1eLpGRrRcWksHJLBuk516Vk5PoYgC", - "NodeID-3NJgvio7B47MB7BZWm31LHzbPWVdkEiEP", - "NodeID-3NXS6ZAzHeqV7w4saG4vXxAd4tcbpmxfk", - "NodeID-3PJY4Rpb5BRR3xSUvuU5Dj3cyHcAmzfjD", - "NodeID-3QvnmD9KrJt7BcoYytWfCsCD83TmKo16d", - "NodeID-3ShFK7JbJ2LN2gFT2W4iXp4N2NVuP4vZC", - "NodeID-3TWEGuLyjvyKYLQqXNvQ7GQqSNoSQrviN", - "NodeID-3U6UcmBu6WVCgodXYsH72VwVKpgE4XomQ", - "NodeID-3U945Ju6EUzVaiA25ea2BvaapV111iqcW", - "NodeID-3V8B3h9bS1cQerQMF47sw8Tr9jmJz4uHG", - "NodeID-3ViTS5vVn4uLoQQ5d7Qs8mF5eYvgQcLQe", - "NodeID-3WH62agC9m63q5SmAyPvhhLygsUjboQe3", - "NodeID-3YkLrm1D9MqZ6K4YTwaQkt1NBb6wP9Ldx", - "NodeID-3Zbddv2qkn6gWAfd12ysNN7N9EsDTjc9v", - "NodeID-3b2dLL4mSiGK2gx9pmML5n2Za4T9pLHe3", - "NodeID-3bciNCJdZcW5k8jMtHujT6msFbGMotkSF", - "NodeID-3dan8fxgCWWJZpNUkrBBEw1vhL8E85h4i", - "NodeID-3douD9GDP69zSq1eMzRAYfKCUVtjEEUCt", - "NodeID-3fntmpjeW5JhEgbVfKT9fy8xeaMg4tquo", - "NodeID-3fuaS8gCD4cWtgZDCLrffU17gfHUNHX8Y", - "NodeID-3iXKmHPAMgJa7z7pGcPpMC6pAmx8fjM1q", - "NodeID-3iknBWGJowmNu2d63Qv7mRM52xoQ3mCoB", - "NodeID-3ir9ZQxz7rrTVDcfieFUHcaVNVhV4ysUR", - "NodeID-3izZtcg2iecpF5rEkQF7Mwofd4puVGZwz", - "NodeID-3kGMSCRnasr5CjsgNm1D8FbZnY4C5iNRE", - "NodeID-3kTMjX1jJvdH2S94GHLi6Qxy1DKyLhuc3", - "NodeID-3kUUeZB7umtaENekUfWxa1bxrAU2eq1AD", - "NodeID-3kpT5aLGx1dFdDY1Dfn3qPH3qYkoj9dWy", - "NodeID-3mvtMQ554k7VbrbYFUaNZR4JmeCoggD5P", - "NodeID-3nuVL5JFrrumBeA3xqAk7BqTkRpu5mJsh", - "NodeID-3oJ5XYknQTmDrwTkBxLx4DCuFgFKFP2h6", - "NodeID-3oaegcGaKyncpiWQCzEVd7vN1Vcsue3Wc", - "NodeID-3p3GjN8gxjGNpFCEKyErnWoXJGENDdj7W", - "NodeID-3p3zJHazEyiVrhRXKL6jJds5esWnwzbW4", - "NodeID-3pSYSkZy99npP3NS1UfES7beUM1y84EjP", - "NodeID-3pfvvxwJWQb1w7KrtGfGhd9ZtLZhrBrBc", - "NodeID-3qUq9jKXL43HwdMEov6KBsnCjcvWXmAoF", - "NodeID-3rw6bDxFFNVoRnZmBAnTV4ZEXnkjooVq4", - "NodeID-3tTQWaeudKziFWpbmzbawLJTunDsQnjnu", - "NodeID-3tjM63VDvTaHkhzxWxV3zrnJjAfHFAgfC", - "NodeID-3txc7u47G8EyCyD5aSZdTxeVdhAWSbpoa", - "NodeID-3vkjzH23PgBPmHixW9xpdUD9vndf6ffBZ", - "NodeID-3wd8cyGCDmhuoZYWmNDab2FhAVpnKYKJE", - "NodeID-3xmutK2VUntMTYcAL5F8A8AYuDcyeAZ4K", - "NodeID-3xtitFQ6k29E476KCq7a6CoZtDmUgKqmQ", - "NodeID-3yiw3g5Rer7repmzoJaATJpkf7GnWD5j9", - "NodeID-419QFcweSxfj2ZgxFMR619CkMNupjpAW4", - "NodeID-41CFoAtQx8Bqivuq3tkg5oqnj6WpBz32S", - "NodeID-42kmqmMDkmMyw2q6gS1uLi4wiXdC2NLwW", - "NodeID-43AKDBv1R4hvnt9bjDFA4SEcwFMzZqpXX", - "NodeID-43LKNkQ9avhKgVj7KrHXjq1bYi6mvxQ2C", - "NodeID-45hNv286MEyVSjGrtiYLt3qqnj8G7FecS", - "NodeID-45kFbHHYtgXEXEy53LCaLMBE8CA5XEdKL", - "NodeID-45p6WjZk3E9Je9Sw4q4SvEaagbYF7Jsud", - "NodeID-47pbycgGRRWtAB4FZ5fJZApoeG4nzv41U", - "NodeID-49LTjmBTcdjMyD33u7gKkfREPqEhhfPaj", - "NodeID-49tGSAiEbwhRcTvnu2EaskxZPiPb9Lv2T", - "NodeID-4ALu7Jfcp5S7S4BXnQgGXMZ3rm3fQkxNR", - "NodeID-4AW19ZAJMCyr64UKfFAUhZXuZDtVshQ36", - "NodeID-4AWHc6b817tKesbKJ22EAEsJa4GkrDuNE", - "NodeID-4BQYSFMqtFcjNgwS1bQgLnzvoKqqMx18E", - "NodeID-4CJDfSDWT9X3hTosPsgui1ZRkBNRhX6jV", - "NodeID-4CL8XnuYqfVVLxRre5C5A1dpRv3cZN2Zs", - "NodeID-4DHwFAw2xZ8HuSu3jFzMU9cXvNhUHCkZ9", - "NodeID-4G6U36ehMMYjJ3C9gzLmYRzQFho8c4U4w", - "NodeID-4GFFG65jrNUU3X6vsZKgUhmz5iCG21nyS", - "NodeID-4GcMxoKhvXDebqgeZq2zKWPgQZF5aDPm4", - "NodeID-4GkgAWZzSWHi3hZZLjLGes5HwuJ5FXDuj", - "NodeID-4JcnzK8FQKGHGMt5EQHRWgBVxxdA4sFy7", - "NodeID-4K6rXew2J41T5LTWmTi8AjMbUFsidXGpE", - "NodeID-4MqtiVkCYGD4TmoBhH3b6a6UTGNrPhvvW", - "NodeID-4PKUhJMxeL5C7A5epar2X5TAAzXLqH44r", - "NodeID-4PTYheMTMhPZvYhJJ1Hj2FwCZSR6rSWsr", - "NodeID-4Q7EdeK1p9JkHULo5nZ9KVwgWYjDjDf9F", - "NodeID-4QRHMt4aejVDLqY1VNmSXnLxaQiZoZbej", - "NodeID-4R4zmBEWqY3dCtKHmvDd56Dupq97UAwtP", - "NodeID-4RV8eRbw9andBLK2og4rtt3W7txBmSuxA", - "NodeID-4RVd14QquiKdEXitdrnTuZiYpaBY1W6QM", - "NodeID-4S2uvFvPmHh2Q4f2To1XznG2HMsyohuA1", - "NodeID-4S5sLovGppHvP9uv4v6jZHV7JtASRpUUk", - "NodeID-4S6TMWiPdBW55NS9ZU95y4aHTBjUqr2eh", - "NodeID-4SkHqMZLGsjBmMXF7Dnpg7tYESgo9zAC8", - "NodeID-4SvFyvJPHPYvkMnJqBaNcwr5yuU8sCsem", - "NodeID-4TSV8FnyRHrVAmPALXfvLnGaHGspS5W2R", - "NodeID-4TaEnGcWM77nvEityjYDxB4zYdLQ6LiZ1", - "NodeID-4Ubqsj2vfwdGUUYNg1jtYpkYNNLugNBQ9", - "NodeID-4V2KBeNd58jdBXej3ohL8E5d1bNTTp4tT", - "NodeID-4WGNJ4vv6bH3FLCJgovqn3D7RCJ8rKBDR", - "NodeID-4Wt44Y2AAuuD8iRvFfh1va5K7p7v697my", - "NodeID-4Xw1ekhVqhHqzZ4pLTPtofbTZxpkvcQNi", - "NodeID-4YLHgpase4iRi6a4wH6c2jUMdWsKr74j6", - "NodeID-4YYQc96D2kyeXh2z5Eb9U2owhPXKPJgS5", - "NodeID-4aLF7SfieaFRqFtLBKo6eeEbQbpVYVjoX", - "NodeID-4abzhcVga2Mc1BJYEfypmRVtVctYwsvpx", - "NodeID-4bKCgF7VcG9ZtcfMwAVFfBJoh2xDgvz1j", - "NodeID-4bajtcpjERHRChiaYpovKU8XE5qAE4usY", - "NodeID-4btZGj8TmrycK22kwgBK5wJEFighAFWiZ", - "NodeID-4cJyBoufFfiMShtRhcd6WGTYdvUCE3Ai4", - "NodeID-4cuTK1XYjm1VMTitd4MPBcwZ7LYyiqjfd", - "NodeID-4cw926TqMXDNo7QyraCShjWMXNSCDZqMQ", - "NodeID-4cwQT5hvhnhgYM7kJia4MK5kT8XLVZSNz", - "NodeID-4dJTYbWkF82oeT3gYAjoVNNbaga2zXsy4", - "NodeID-4dNrRsASZXHs7XdZ1sPuj6kKWs5bdqHZ9", - "NodeID-4e1C32U5TBUFuQpykL6rSw46RijbjdwRz", - "NodeID-4eaj7e8pXaR1TSuCF5n7tKDCHPPemZGky", - "NodeID-4edDKb3xKovZjTSuFbhNzJZ3Y9KTAzDaQ", - "NodeID-4fK92LkTyEUzPoDW44Bo9b5YvL5kJ7369", - "NodeID-4fwq4Tcz2ERoDWDzcow2JNmT2KaxtJrjY", - "NodeID-4gTwepTF5fcacXB7gdYZLTtfSFsYh4faj", - "NodeID-4givb8yw6262YETrNnm4hTSRPeK4qEBfk", - "NodeID-4iabwkRVrx3KWgYgFuDAR23EZna6rjKxc", - "NodeID-4jvscnKzJyMUpbsZzfoaZVHd2ez6Vj5ad", - "NodeID-4k9FLLYj63sJNrrGycj6MTRm6JqyacEav", - "NodeID-4kCLS16Wy73nt1Zm54jFZsL7Msrv3UCeJ", - "NodeID-4m1TLqY9ob5u23YrJx9zWDj11dz6DmV19", - "NodeID-4nc9Pi32BZwWxcM21U95mVHsbExbPSmkq", - "NodeID-4o17gdHmyD1dWGxwez5KqKdyLDfiYmPX9", - "NodeID-4oA58fddyvuKuRtqanZtp8V1Sz9mbr6sS", - "NodeID-4ocksMuoXQXnBH9XPRnH8j5x48cLLpFmC", - "NodeID-4ofBXitDMQ6QZi83yvPjCYn5LG6HBwqSn", - "NodeID-4pZqGB9JdyanFMVQEeq5VZ6YG9yZNsCF8", - "NodeID-4ppYtgngzEnrgBZ7JUVw8bTbaBD76efcR", - "NodeID-4qzj4sLxsLnmhhktyTyR3BWXu8nXTABnY", - "NodeID-4rqntan9eh1AmkCW7RNKwzVVB1r6hhnxc", - "NodeID-4soc4KzELnfnTLLw4FTgpEefZpE6aSQbw", - "NodeID-4ttQXnMSk443JHiMCRaoHBjjLArwEWbya", - "NodeID-4uHXbHesQbAzcDBRqaFyJ5kpgovHpU576", - "NodeID-4ux8p7PdNGBzrcwYE9U3gHF8ehb882VGp", - "NodeID-519R4edrXr2qJBZnFX7X9dJvo2JjJcesT", - "NodeID-51wXjrXuQkpHqgnyZ6pgQVbiBwTWgVQZi", - "NodeID-5517ZjCrBhnLs1aqw2YVqRopDnAu5z8FT", - "NodeID-56PBmfRBSmT2sYsPLiBPKVq2fQUVGEg9g", - "NodeID-56RnA8AJBddFSt2rrGu5WmsZF8qW4zNeP", - "NodeID-57VYS3UDdnkurTnK9WVzfpNT4H4V2fCmT", - "NodeID-57o8JLPG29tydZsDVGuD8iBZ3rVorYeoB", - "NodeID-57vP1ZP91HztWSRTHurGdrMSw3TWHYumo", - "NodeID-599kjqvHr1rEhyvT2mFA2whFJZS2Yoexg", - "NodeID-5A3vbPTyhDj14bLRCBs75HvsjMJ1h32FT", - "NodeID-5AzNzec73Pth9Acw6jVd2BYZWyY5KjV6y", - "NodeID-5B2Uyysf1nWcRbiCYdKwXzevVF5a7sN6T", - "NodeID-5C4VhhoWhTJ2LewfxQNvM6AKk1o5oHS3o", - "NodeID-5C5QEUprYutWMbxYicmQd8dUFhc4eh6TW", - "NodeID-5CDfrTrcGndVpY6qtuWsKWLm3j93GXyey", - "NodeID-5CwgaeHgQgWbeaMB2ERYZ1ntrhKCmSs5D", - "NodeID-5EuG66om4jxQDK8hRFyq89SsMqfdvESew", - "NodeID-5F6HiZ34F4oRtMX8PZoJcfvQiH7K9mGSs", - "NodeID-5HkCsXm4TQUb9uXxM6Cjy1WzvuDSspPui", - "NodeID-5KGMoDk3pwPz5LgQ8FTJ5jJXJFnJ9CuRc", - "NodeID-5L14VfdhVJvi4GowA2zgqj78bGriVMLxr", - "NodeID-5LGFWx2kfwMZXpyG52FkRtrfYfVRimjh5", - "NodeID-5PMCtewYFfdxWmE5gcxuZeXAQAxHqMhu3", - "NodeID-5PMGUqdapvGYEATmbQ48hMJTwcYyKFNDg", - "NodeID-5PeQVPLrJH9xiSQZ8hcmeXWtUzhcArEhQ", - "NodeID-5Pg156uQvovbZQ3F6JKUiyAg5MrdFseMP", - "NodeID-5PvfcnfPd3MLnpq4MujxvBQHPwtdjYk8s", - "NodeID-5PxpmHkfB3gNh3spZWuzEKis3DJ8WKxLt", - "NodeID-5Q8GBt1GY6fUToWZ9txSGzWr8QTDUXKJF", - "NodeID-5QzeGmasNDHSxzxBqiUQ9TBPqkkwzJWGe", - "NodeID-5RuEXmu7SJpf8bwuY17UpMpoEsGZRWnuj", - "NodeID-5S729stbM7nFyWHdsoBeFzo5NMUXaTrjR", - "NodeID-5SmDUGU8WwZkvxKMnjwKAYvfa9w2qEe1U", - "NodeID-5UW1pHAXDJi1tRFfGSEgujuExMztq6sCc", - "NodeID-5WCpR3DKFt9665Wj9jDCTdncLNX7AbzfK", - "NodeID-5YX9uqiPm6hmJEmDy2fUyvFEjvSvSbiWE", - "NodeID-5ZXpg581dpjG8AdoJgTDeXXLnxrQc9Wtd", - "NodeID-5aCHiSvLejirNRt8Xgw6SNzd1dDq3XviL", - "NodeID-5aQHgP4cTuyentoPz9KK3y2anCBYyG7tG", - "NodeID-5aiXb9CdCDJ6vRmJ6reLPehKFeKvdnHxy", - "NodeID-5bJYpPDsUq3JpGJrFjVRtr1GybXQDP1M1", - "NodeID-5bNomTz89SyKffJWnEZGXXdwvSnZanVTS", - "NodeID-5cL4dSEdWWKnzZxvg1rqen4M31YeZhFkf", - "NodeID-5dP5pp3AQeD9GbRPbhuyXfFcNsU8RsgmM", - "NodeID-5eFuL1vXb4NSxW4ZF16WZsJM3gyjS7i2Z", - "NodeID-5eVCCzU5VQXhj2iqpqneRxTUNSD8aCJki", - "NodeID-5eogZcASu4bDhWxMuUF6h7VFK5SCt3msp", - "NodeID-5gcdejFBQ3wMPFpo7qKUKBREJ8w3PRTM1", - "NodeID-5gmMRqNob9UjcgroCKH67bQb9PVwtnoeD", - "NodeID-5h3GjwRs4cndBMxxfRpuDMyrX9SF9dPoe", - "NodeID-5hNGcpQHUrBDd19vV5QcugACUAmwiWU3D", - "NodeID-5hSVoN9CgKTxGVj2M3pXBDBYtfZkjQF1D", - "NodeID-5idht8398Yg1AqYyBkTQf2kN7zFK1J7Qn", - "NodeID-5mmVqScHrzTiSa2WVjo99g2yzL83EBS6W", - "NodeID-5nWWPwUZPzdTJYGXJoWxzWj3Xm63vLL7p", - "NodeID-5naWZjifbRQdBoW5bDtAcvuFjKr3k6G2o", - "NodeID-5o4eWuhvE9cmScEoZHr8ngGebxa94rFLo", - "NodeID-5ppnn5JSeWMAznssuPMJujyJhzHkXHN8E", - "NodeID-5qr8okF4mnAB2JhAvaJuwqMGXN3gi9QXD", - "NodeID-5qxuSbJfb3xqgNQ2pFycD4ybuEH3ATg66", - "NodeID-5tUAsBWWmhHrLnjmieom6twf8YREwfosQ", - "NodeID-5uYQ6R4WF7kmGfraM9LtsUJG2CDmh78Lf", - "NodeID-5wCTAXLJSc5i9RpksPG5fFZXemq4dm2A6", - "NodeID-5wQr9SafAyQ6BKMjtTomLB7Bc4tg8iYD4", - "NodeID-5wUKLtxUEckPyuzLQSozcPmqVzMRx6v7j", - "NodeID-5wf3A9TPUALDHaRhufq3Ry4jfH3cA9SEe", - "NodeID-5xEL4zcSuMjZCEzY3WhQ81Sb1Pw4E5VL8", - "NodeID-5xhFgBpc99AjBEXqfzNAG3W8mX8vnmXWZ", - "NodeID-5yYNsLs1TZoj93f27GD1CBr424tZJVpVh", - "NodeID-5zENHPe3oP2SdU13oTAvxZA2cEupejYhD", - "NodeID-5zP7p1nk2KnAL4SHvgFWcF9Xei3Q13CC3", - "NodeID-5zWQQHoMSd29NfKUMziBuccvtt2aahnHH", - "NodeID-5ztBWB4caxbw121xfsXc9JqsknrwxrRob", - "NodeID-61nHqrF65PzDx4SeUmaxrdbBLHNxGfv1z", - "NodeID-61rJbupdhGqaumerueZFVVJT4Sbp4fciN", - "NodeID-62XYpHtuv92hHhJJXVd4wxJqPFv9rbWA8", - "NodeID-62hEBGiabBK34vV52kGT64T6S9QVcdMVN", - "NodeID-63JGDZZtRyCMUiGmqQcL2rxXx4MrbNzNt", - "NodeID-643Sjdbh4n7krQXPSNbSK491xfVbh3hqy", - "NodeID-64Y4Dq4dwfnhTjNnZEFjCexmc2Wwi1fyM", - "NodeID-64Zz8dh68ypXYWaUcfkXDm9UuG9VNXrk8", - "NodeID-65KSgMC8R7CjSQoyBc85UMjW9YZ1cTKke", - "NodeID-65zy7gGi1v2US2tkBFfjpwuDoWVPjPsZW", - "NodeID-68ZngAKzsRbzQMq4CpuZ41J7AgCDEijPp", - "NodeID-69vkfdsq14i5HZSd6m2kUwRAu59ePbeWw", - "NodeID-6AKFYXuxWErAD6nqqFkPnbwHzXB1JC4VW", - "NodeID-6AXAfsfvp25QX5Tff6Ag6ERLXQ577wurM", - "NodeID-6Aed6k5Zj6vffgNdvr29Z9VcdDxk5PoMq", - "NodeID-6CGouDLcYyiuBY9xEi4rEaHCoBzH6UQrS", - "NodeID-6DX3ppjVpWsV8EUihpbRh73K5dGXBSmGr", - "NodeID-6DqFjxDUK7nh68zrFDE7iHfVsXvoM5yzt", - "NodeID-6ETncdUXndB43iT4LijRYLHF711gWeAgJ", - "NodeID-6Ef219qf1xYjFL5SCFQo29ZYKDrcNi6xT", - "NodeID-6F2LZ5hykkwmnRYYabqHH19MnzknJ7rij", - "NodeID-6FSSZuuLEZ4sHJZGfpY4Wuz8M3qnK6ec5", - "NodeID-6FWuMoDyCe1gsmeQj2RsGBmYv1hoGUbzs", - "NodeID-6GEno5sempCQdCZvTEuPZpDLqVvpN2JEB", - "NodeID-6GuJTV6P89ZgzzYM1CJbsuMuVTioUMmuv", - "NodeID-6J3LY7ojkK7WCZzmArvxEozaESDMb42hX", - "NodeID-6K9dR5Dx8YkPXzYeNvDRBionRmEo6HGE3", - "NodeID-6KsZqkvobK4vUHJzo2VdwxWMsbHtXCZPb", - "NodeID-6LHDq7hq3PS1xBj7cFQuvxozaM2hJXheF", - "NodeID-6LRbs1K2iPGmhn1EBbX8u2udyPbUt5S5x", - "NodeID-6P9u3TyWn6jh381HSZP2uTyf1JdGBLqHP", - "NodeID-6PS1ECxRbQ5x3wj31utVWecd9Xkgcp8sb", - "NodeID-6PabAb3cYifZm2i5Trr2BCaYyy9TvYYKJ", - "NodeID-6QD1KNQkx6wj142Tv6demd3FYbghQvCM2", - "NodeID-6QpAUeTWNKyVo34r1LrCYpfNtUwUqXNMB", - "NodeID-6SwnPJLH8cWfrJ162JjZekbmzaFpjPcf", - "NodeID-6TG73ofz7EU4keEwv6jt2xLrpaFzqXnYR", - "NodeID-6TwryrqyRkE3evDcGCN1C95TaWzkXicQM", - "NodeID-6TzpKmXTYp2f1ok4rEzEAgP5b87FSQ9G", - "NodeID-6UMb71Emubx62ZEsNBPhhuEzZdqgGpKZY", - "NodeID-6UpNHJdkRQM9TRX1m1wb1sfNX32Ze7ZhA", - "NodeID-6WwTZqp76ms4iEUepaagpeEsf4N4saDGb", - "NodeID-6X1FD9gZjzSfGP7E8v9cxXBo2ofhHLfGq", - "NodeID-6XwiaBfuKwKG761Bc28jDAsiFJ2gDuVgQ", - "NodeID-6YNW6QK3JDpCaEnVNsG5wsNA1SvxT1dhP", - "NodeID-6aZ3KyGBPTcn6NF9K2jpvxTjhhDjks3Ev", - "NodeID-6anRg13mVkUeZmpjf2Mm41sug56BH7Jof", - "NodeID-6cRZQD9AsdBxSPSoHcBfqXeSAwzKNYsBe", - "NodeID-6cem8uPoUwQ6o45VYS3D5mmFFzTuNC2M7", - "NodeID-6eLQBH9yJUPLiZGXToPxQPj2gTWv15Lf7", - "NodeID-6eS6iDVjh54ww1pGHmCAoKiDhkNGi6xTM", - "NodeID-6edspGWTTSWm3N7Zot3kGrEMHPtLrK3VW", - "NodeID-6ff9kZ7ct7e9PvGKBfbMHJ3MJaMPCmyTE", - "NodeID-6gBKuwn1xHG9SmLZKprpSjWACGDUp5k9r", - "NodeID-6gFsNyzYU474fgL7t7x43Efjbak7Vx7Wp", - "NodeID-6gRx5vFhuMTDtaRYP82ZSGuBq7eR5s3jw", - "NodeID-6ghBh6yof5ouMCya2n9fHzhpWouiZFVVj", - "NodeID-6gi5JXkZSZyoZ28CHU6TDtJFVRy4e21W7", - "NodeID-6iLoGX7rEPJW2GZMekiNPEDNZKmsbn3iU", - "NodeID-6mSXCB3r7oeP8Suy1AWroDY2KEF9hT9Mi", - "NodeID-6na5rkzi37wtt5piHV62y11XYfN2kTsTH", - "NodeID-6nssFkEQTjVRoWGdMfkkYJc6wMNYdRg9W", - "NodeID-6o65ccWJmdcMSDkDphL2i9ajLCZRsvAfj", - "NodeID-6oBNaAUr67MFY9Gtu4eis7bsGY1RswvAR", - "NodeID-6p7pSJ2hoYnpRAXUt14cr1tsA5kEm9vXE", - "NodeID-6pCQAcsrwzFfT8sYZeT8cQ7f7aF8S87TM", - "NodeID-6pShVkG6mZsinZNWZr48xvQSuSnmnyh5o", - "NodeID-6pXaVajr1G1nj8Z4rEXisGUajXGcFPh14", - "NodeID-6pm7qiab6Vt5n47MdeNGuzKx5Jy3Pxwu7", - "NodeID-6pzGb1VVyQT4RLChXUQYfhvjLrqEmWiNi", - "NodeID-6qPNz3b5VZpMWkVNjmLmpBrL1sYxr38bs", - "NodeID-6rJMJqgEbTGJCv3hBzDaY3axQ3Fq98yFX", - "NodeID-6rjd7h5dPJwVEytA9zm86ZBfqEfBuSjKi", - "NodeID-6rtV2pPKXyf2Ek7nWnmuzdiXvk2Ma3ynn", - "NodeID-6sLdnpLBDDMG2eEzgdiGjTkne7a1iETEu", - "NodeID-6sywKjSw7tS2qgFAmLSyJR5D6oB2BHT3Z", - "NodeID-6tkBfGVTgfpbaiv5HFX8LpfKdu386tfwr", - "NodeID-6upkG4FRNCoUQ8nz2by26m5vdVSthXCtK", - "NodeID-6w8o4bbNdVLscimLv4X6BA7QuSqX37TFL", - "NodeID-6xPTxaGM5hVHVKKFuC2MjpCL7ZD6xT3wN", - "NodeID-6xQ5oYAQ348ntvsshCMMSd7uduReey2wC", - "NodeID-6xai7EXhzyxCUyHDrtLTYT6uRCNpUfRHB", - "NodeID-6xjnXHhLrLDafewh5t69uRqtHea75RSGv", - "NodeID-6yS1J9HFdHgdX2ruW6XMouQvECDF2Fta4", - "NodeID-6yf4tK8VmAKhQHC7tdQwy5FTw39i9mXVV", - "NodeID-6yi5sG94i8wSHhqFuuUip6RuZGkKDHzxy", - "NodeID-6zcpV968BV1e3BrZoPmcKuoUNRcP6vjxt", - "NodeID-6zytvHVN3xs7VRFG8RBhjWVmcvaYxWHDo", - "NodeID-71ZzUv6td3aKrZG4LhGDDAnjsEcEchwDe", - "NodeID-71taHoSLZsm1Aqe4spXKJvNXw3o7982Hz", - "NodeID-72D6UYvQjfgKuSrSFtMfyCtHq1jZZ2gN6", - "NodeID-72ncx4NEgf4cziN5GPDRhn7i71rgwH1wV", - "NodeID-74oLbJEptxh1cVzvh3QTwaykED3FXjPYK", - "NodeID-75PnenZJE9PQbQycTys2zonb1atGLsbX6", - "NodeID-76GDFDnZW2ihXCsum843HEDmrvcVuMDZ5", - "NodeID-76KcZZBhWfiWuFqrx21KyeBHdXxsaVyX2", - "NodeID-76nqFaqDGakCDcm7kDsgP7GJn2VSM33xh", - "NodeID-77cf68EUcw4pSLJcvjBNNgxUtxNoTHjNX", - "NodeID-77kWbGy45j1Scbvgh5z3zhoUBL1S3qjAi", - "NodeID-7843EeyboY1mZSmdzjqdJodxHycNn7Kv2", - "NodeID-793wJG3RHeLFVCXkNTQxsM1pSUHNyDyMv", - "NodeID-799wg9bHu8gGe83SHdioqQ6hUg8QCYRv3", - "NodeID-79NUUnbkpDfvGzGtq3Q9FArGK9D1Wzpgq", - "NodeID-7AVurguoWJggFMe8WBEBuTzZjmN8AmN8y", - "NodeID-7AnPDxUDnyU4p5YgCpooC6xx1tCfrMHhf", - "NodeID-7BvjRu2P26PSUXWzCSh8LLxLNdSpHEq8f", - "NodeID-7CQwXe5Vnm7hzSQeWDRXqUsGDc5vcPBfZ", - "NodeID-7DR9yUKc8S5d9xwGoaT488hRn9LiHhKTz", - "NodeID-7EEYbCpedmA4bgHnnvhx4zXgMUpKe5Gkd", - "NodeID-7HgUf4o1UiEGh2Z2tWp2erbkn5JaXYYZG", - "NodeID-7HsxnZQnGRWYG5jFVWDX2L26zEAYaUwAP", - "NodeID-7JijGwmqUuditkaCwdcCAr4Xc6AAMy89A", - "NodeID-7KvAj74Y1Aixv1CRWfNMGj73S6qsSGzhg", - "NodeID-7P5SGZLFp95WbF2yv3A9WbQaQDzqfsAFF", - "NodeID-7PUdh6Mzq4NfJR6wpng6cRAYDraESgWCe", - "NodeID-7Pjqo8qr8Gd78Wmzgo5xqF85qcafKQ7W6", - "NodeID-7PsjAayJQ4g5wiQ4QF3qokruC7aSUMqDn", - "NodeID-7TepNNPHs1pGnMS994Pm77YFdSKvghvKm", - "NodeID-7Tv2ubT5xnAXWNRf8X61Eyw7VcU9J1w5b", - "NodeID-7ULxX37k6SSaTX3oF5RdrxL9r5aGZu75M", - "NodeID-7UaxuvJw9C9FytVkUjRCQ3csmDiNzujGW", - "NodeID-7WDMJNKYqJ1yNbPLJrBZubqf6LQrtTw3E", - "NodeID-7XrrK8iL25SJfWrrkyz3gZSo2t5iEadvL", - "NodeID-7a1GnsoFxviSiL8gJyFqrkazv29xY48mr", - "NodeID-7a5FbgWRUJeRWPzyidAyL3ENC8wQDJ1eK", - "NodeID-7aBosQAfHykUE3rmubktp5zZtZmavTzow", - "NodeID-7bnk7Pi7ihTpoyKndMJw53PVM3DJ9QKZ8", - "NodeID-7c866Md3Geveoz9G9XvP1TroT4LKdz5hL", - "NodeID-7cwvfriG4LFWV4iF89E7GhYfLB14hFjMa", - "NodeID-7cyp41vXvj62jBRh7y2j6VjLXhoJ6Hoab", - "NodeID-7fJWXpi4Bj2XgeVXG7Tj3JkNNrGnnJhdp", - "NodeID-7g7qvfKvRXmPZAxhBMfj8XCGuWVVHexHe", - "NodeID-7gLtM9D45daj6WJfqrT6uUje4muznwKwQ", - "NodeID-7gqKK3aZ6m81v2138yfc4fsAdzFHsB3xb", - "NodeID-7gu4gthY5YhpmpUpQvuAy5CDDvDs2yEVt", - "NodeID-7guwrZEeTwM8EZ4eULA3pw1f4ipfYFiLn", - "NodeID-7hQFksPPW1Y5hZukNcQn6bTQjuTZPnj42", - "NodeID-7haZar18iKUdnps7YZEYbJCSwnFw4KMY1", - "NodeID-7hnK4EoWzm7V5qFPqJvpcRQti59au2BD8", - "NodeID-7iFGXSHq1R8MvEM88EkS64rW5z7MwukYk", - "NodeID-7iHpsauHYyQoCjMSZsXJkqXodq7J5eXTR", - "NodeID-7idSkp4X9MwUacdNn32NkE9SXo1XWveLj", - "NodeID-7jqH9PXuyYhoTaaQDAF1eVzLtCVSgmSpz", - "NodeID-7kfCqUsmvGEEfgas81FXNFx833U9xZtWL", - "NodeID-7o1ubnZAYsiV5DUD5R5oDYXkQQvWo69i", - "NodeID-7oHSQLPBV4EzZurguKU4a2FUvPxShuVzf", - "NodeID-7oKBFksJjAcBCNEY3ZcRLQeXLX7iA9dNE", - "NodeID-7oaj9Yf8Uy6PRhqjHyv9oUyLzFMt8DgrM", - "NodeID-7oyvSG1pLLp3zf2ouSAT6rUeehDuQcNtQ", - "NodeID-7p8akVY9Z56XkLykaohLpNGp9sU9PLTvh", - "NodeID-7pDhCWQKNrpCjTL6tB7uNvBUnBQ5amgob", - "NodeID-7qZBqVK1XAPXPqA6jPeDwimDqMTo1ZudW", - "NodeID-7qrESfShxxqXfa35MfBC8D62t6enjm2RC", - "NodeID-7rE4BjdFpwUk2igXEeauKaZT8mCjkt9Hs", - "NodeID-7rXi72Jm76kAKUi6BiyJChnAm9xuKrud9", - "NodeID-7sTpQZFCZVzhLTugv8PKhNE8tdQ394LRo", - "NodeID-7seuWZpGnhEox3dL8T363sghDtCT5UNp4", - "NodeID-7sitbRzmAsrFjKRitC7bub1soEaHXsgbA", - "NodeID-7stntWreGt1wPeFuY9Z8bNURuHxW4JN3D", - "NodeID-7t5yL3rJ5JgME7vxa8em5sUNTPeYfmMop", - "NodeID-7tZXydqQqbjAQaNDK9MNEZFMsSFCp4xJW", - "NodeID-7ts1Uhry9k5qkmpYZNfdivuzj2eBPemKa", - "NodeID-7v2CCw3NVjU9UxBhGzN1jhSmatHKE2mXZ", - "NodeID-7vWb35jCnXGxAhLStVtKKZhWiw1ByhBdT", - "NodeID-7wMUdN6T9awYChEoRgzQ4eg8qZj1BFrne", - "NodeID-7wSVhYSmrwcts5o98Yg863PoHhJWWQcbt", - "NodeID-7wqgzXaTtJLobuBUxbp8yGtQe75TxmaDW", - "NodeID-7wyu3EXASVzsJpRPoqhssRWdmTWa6Fycd", - "NodeID-7x5HbUJqp763SUw8Sz27yU3bKWCdQiqAk", - "NodeID-7xCJtVM3wTprzgDBhXeXCXEUy4NEuqUvi", - "NodeID-7yBDXjCcqHCnfqC8LfQ1oL9Yyx1se2Rj9", - "NodeID-7yUhoXtjqGABwMeSgQG42cWX56r1DkBwh", - "NodeID-7ynNyRtZx8re55eU1CwJ1Ga5cEaRMPJ5s", - "NodeID-7zA1m9YUevKKyKdyJK3snpSiAnXhUG12R", - "NodeID-7zQLzhnMhaj5SbRXVpUUsMP4c4r8yQAD1", - "NodeID-7zVSqXr1f2wcEnMtMRBzMh1VczoEXsu2", - "NodeID-7zeJ5VBLvTF7LvTn1VRZCJfdt5EsWUg3e", - "NodeID-81U2wpq95De12KchbFhatf2fBt6KTFmAr", - "NodeID-84RAL3MngQcrLpLgTgJwtLobhryyt6TiM", - "NodeID-84XTAh1VM9QmfdewNnqFVhz2kbjrFvK4Y", - "NodeID-85QtYSfGWxkvQjbiFJzv8R6ajAutwFS4F", - "NodeID-863ca1dX7NxyiWH6Hf3Bp4ipNokKdzJbp", - "NodeID-86HV89ZFehy2HHmnkpgBuUn6vRxg25if4", - "NodeID-86LjyKDK2eKVUpdesMPWJtvo9gadfW9m3", - "NodeID-86oHZkq55eBsPNFwrFX7kV5w97BPHhtgD", - "NodeID-86rtyxneP9grH5wuqRcQMSZw5mS1vqrKm", - "NodeID-88fsGoe69sPGtRjqe21SK72KrJNezzz5u", - "NodeID-88ik4ovrpTx4dTExqhXhSQ4JwAQnHbuGA", - "NodeID-89ucgJfiRvHtGXynRbta7VcaX6MEcJ7K6", - "NodeID-89zA8HBgsSce4Ut5hzWgfMRKshqooJWdu", - "NodeID-8ALyunjeYV85zBSrD2rjJdQ754z9jasvq", - "NodeID-8DYmrGzmxDPogtQvPR4YjXhRyo2pNDBdT", - "NodeID-8E3UaD6hjNK8aqK2BBUmqPXyrfB19WJJ2", - "NodeID-8Fiuf4Uucg4x3ijMfkyVvYXdfgdBFvsFk", - "NodeID-8Fn8YCu76VUHny7MHQTkm3mPSuGPkVeqn", - "NodeID-8Gct3pDyuCEY5xH1F9RdYjvk9ry23cTtX", - "NodeID-8HHLzk7pF96soZ45bJ1tfHNcSp7moXiTB", - "NodeID-8Hg2J3s2MQVf1GtFLcRpfWjvJZkMesX3z", - "NodeID-8JYJVijgzBsSTK5EUsXitrMEYNGkqeba5", - "NodeID-8Mk5Kpvp3oTpLbRSnwmCJmPbvRwsR48ra", - "NodeID-8Nr7TDSiK215oiNDY17SaDgF5nfty4KUi", - "NodeID-8PmuHd5fRb8VWpTTyNhytQuv3sy83P2jT", - "NodeID-8Q1uX2BfyLbmCCor1t2h9qvn414WXfQ92", - "NodeID-8QKheMcZ1jn5n9RVi5MFBkzGrKjFJNNAX", - "NodeID-8RRm8QkFnJvyuNk9GtXCwniWfHs47b8ni", - "NodeID-8SHAaWWn5qoBCFynwzXdRtFCcMvEkTjAM", - "NodeID-8ST5juiAQzVfXhNAgER1UapEpNowZyMoj", - "NodeID-8SbnHu41g4NFAk7aa8EXpgFSmQ8ZpvX56", - "NodeID-8TArWpFgH3sazEH8qP4gUjtGtFMvjw1aR", - "NodeID-8TubANvEGU3Zkz6nKeRx3ShmHyULLjD89", - "NodeID-8TviTXQLiqxcxkCikPTut9DwifYjFaMcT", - "NodeID-8UynAEU8PuuGetmjiiPcbGmvD3EyycuN6", - "NodeID-8WowWhvPM6hwXBLGkuX7HvwApmXNDCyrH", - "NodeID-8WvUBZyrk6XyF7pvcg3NJZk8jtJGi1W9G", - "NodeID-8Xt57NiwBsGKt3CjYZ1ymKx5h3nHU3vcX", - "NodeID-8Y4i7kpWyv3pvvwJSk4EsGx7frk5mU1Ah", - "NodeID-8YNtmpa8fe2dt12PqDzhDCBtwcQDTXa9p", - "NodeID-8YqEZ2ufMNUFPXyNpUAvLJWRXLKqC6D2H", - "NodeID-8Zvnq1815CaYYegXmuyBD5BVtJnurtpC2", - "NodeID-8byZLbVuVJbedEvsAjZxTTSqorsjz7ThK", - "NodeID-8cKy5FzzP2CHV1rcwdKq62vuYP9yUzYuG", - "NodeID-8dCZ9beUGmAWyCZPwdM8YZ5FDBRPXUxFf", - "NodeID-8dq5Vwc7PzWn5NYNFRkM8TfnYaJpLiPis", - "NodeID-8f27M6Ju9Dnh7YU5pHqpkBLhCmBq9EBBD", - "NodeID-8fLXgVYgby12VunVnSMrRrvcgEijVknbo", - "NodeID-8fq1H8oStMi9BZrEk8qiE8QAV7AtqGnXt", - "NodeID-8gndDR9ULm3ywRNbh3FUveaSyo5g7V3ns", - "NodeID-8iQxXS1Zbm6tGzfp56kpSyUboE5kSNoH7", - "NodeID-8ja1C24FM5FyQgUGjsm4qwpD6shiu71KH", - "NodeID-8mHndwCShG4xau63f5FMJC5r1kDCZNpNi", - "NodeID-8oREeth2haQyVW7Bu1iGgiMe18h5Pqiwp", - "NodeID-8qkeNyB3cbs7LqzP4AB7rHcrcHLAYVDEs", - "NodeID-8rEmSGNj5VW2HUjGYMyynpWTYJuDrMpFE", - "NodeID-8su1eeSjb4emswAx453du7ya3Pp8p2wSe", - "NodeID-8t9KLSgmSQfW668sfoLjVrrur3nDwW7fC", - "NodeID-8vuV1UF3KHF98EdqFyuFAMDJUzwkQWEA7", - "NodeID-8z8rezdB9vXDxBurBeCYnNBfNcD1kVrJP", - "NodeID-91W73TnEik6kseSpBHSAZzsNVRGk8Qfkm", - "NodeID-93LVjgmjMcBmcJSByxYiTuyPNbdVw9q3n", - "NodeID-93bNuNqHUpmiZiT9bvcm4YdRU6ADQnESy", - "NodeID-94CDXgCTFRPKPDmK55UcfG8KqVQfy4QsV", - "NodeID-955GU1MqWL8yXAtoc8AsE7FNx4nGC9JyL", - "NodeID-95rcDYyjGNKckKCF8PKuTyEV1wxkQvP3n", - "NodeID-96tBuFHLkXJwyYug768fE2GDEFmebUUTy", - "NodeID-96tjSzF58iKJUG1hDQve6HJdzjwLNMzFW", - "NodeID-972yzi4wAgqU7RGmcQGED4ueQeBXzccka", - "NodeID-98JuUPhpQBgiY9ozqFTh8rEjx3jL9D3aJ", - "NodeID-99Dk6vNf7RaX4S9e4oAAbuhubzzRnrGxC", - "NodeID-99hQvpQKJi1y7gTjD2icHKYwk1pNMHFhg", - "NodeID-99sqQME296SfcnyYWTmGrLXQJxaGUKAA7", - "NodeID-9ANDYM7So3ZPNwbMMd9xBKUiyJirXN3vF", - "NodeID-9ATz2jx7Vh64A31CcD8PgJw7KLZy92fRT", - "NodeID-9AjYPCvDWKnwzFgRiy7jeTEKmVxK42LSz", - "NodeID-9BCUhY6Q2Eji4J1u6MV9XKnPspciWWdLR", - "NodeID-9Bb6E7B6GMd1MnAuxYVVYF9CSf1XiBCEY", - "NodeID-9CkG9MBNavnw7EVSRsuFr7ws9gascDQy3", - "NodeID-9CnrQBBFSkE2Xzfcz3Tk1e8iauq8iNR88", - "NodeID-9D33RPjZwKx3gV6MVs77z4uPJcKgqy4ns", - "NodeID-9D63iEsgkSKzSz1aBLpELbh47Y7aT5ujj", - "NodeID-9DCqby2EWyUKFsKs1VNH5mX7V9FDkqUnL", - "NodeID-9DmoV3n9Sb1A2aLkYuv9wZV7uPJo5JhpG", - "NodeID-9EMH1m2oZQsbSFvrMzx5YXZWFfqSwjuUx", - "NodeID-9Ef44CXDWWfP63UaLr8XSCsmEWUFY5i2z", - "NodeID-9EizvTJhGPtcwRExBgYySaJMt6syztj2X", - "NodeID-9FZQBRnW2jMU1PW99pqVTnxkPHF2Srfeb", - "NodeID-9G5DhsoBgHjDA3j1FqFXKyEJH8AGPeB67", - "NodeID-9HT8KtMkcxP5aWjmxaVVGBCMZ1r6jGmgz", - "NodeID-9Hp3rH2xzTzDoZj6JgYqhbmTFGVeS1BnL", - "NodeID-9JE3zL1Ud1x5RgSJvqRpyMG6F17dPwAdc", - "NodeID-9KjtB2xC9aehpcYRuqJR4myLGJaq1tVse", - "NodeID-9Lyd45k1mXNkksF2C3nwgCJRX9YY42FT6", - "NodeID-9MCd77R8qxsNg1ajgHqFMsRYCaQ4KpGot", - "NodeID-9NEeo3Ayq5qGodBbMZ1gdCQ4bmGH59BBo", - "NodeID-9P6CxSTDfAi7cRr4LUW4bbdA4F1nK89T1", - "NodeID-9PbbhiQbQitcLLEiVwMCThVLWj2zFsbp3", - "NodeID-9PzVetjSSSY4Xtk3VnNcGzQdEjZSSkR4g", - "NodeID-9S8duheEvrp7gKW4qLLrWVCnC2wvo39w8", - "NodeID-9SQzWXUh9SF4b4qDmYy7p6LcqWSgxtu6o", - "NodeID-9T7NXBFpp8LWCyc58YdKNoowDipdVKAWz", - "NodeID-9TMnzP54UVfmYmYcxAzVuNC9rpVr8zvgB", - "NodeID-9UWtBGvW7G2RVSwcR15MS8gesUvLk6f24", - "NodeID-9UgnxmEX92MdaAFQc7FG9SAfPECeT6Qp3", - "NodeID-9Uis3D51cjQauBaBPnqsvKjKg8Byj6Xwb", - "NodeID-9W3QhxVhg9EncK9438UUepFBrCxdtFp2w", - "NodeID-9W5RaY7LA6so9hGCPGfLezBXMnWNRQb8V", - "NodeID-9YiwE69B2wcvXtEW986YcgQxGg9ctzmKZ", - "NodeID-9Yq2bF3B9p4Lg5czRpYoQULLuEn3nwuhm", - "NodeID-9YqDsggitZTgCi2WnnrKBz3jAcD1S7oin", - "NodeID-9Z7jK8jN5FsTXSqkG1fV2QNG7GktPU8az", - "NodeID-9awX4ceeXavKKmccnAuDU7uvhqGfaEDSS", - "NodeID-9azF97hpcwpzj3t7S9mD4VKY1S5eJDrcW", - "NodeID-9bU9jwHLH6KxcTu8pBbqJQqkHYR4woY7L", - "NodeID-9cEGqGSwjjX23qXbP4vEqva6TwJqH4hAH", - "NodeID-9cazV2uY7efo1f9bjbixH87FFNG5wGyts", - "NodeID-9czFqw5FRq7WhYyf9SBSfq8wsJ1f82m53", - "NodeID-9dN9NU5XCr3WQGYnFjGudKRScQ1HKGmBn", - "NodeID-9eH3Zu7LN7kNwvUy3Am8mkgvvekrkxD6d", - "NodeID-9g6keiiMr9vXhaSNP3oqdxhu42LEZ3pWu", - "NodeID-9hW5Lb3t5JMgP945DB8wHUJP73uLuDLAZ", - "NodeID-9hj2xhiHktPCpcD9koLLH17a1GKoWY7QQ", - "NodeID-9hksERdA8ypkBykmHuch4mw24RR2sg5js", - "NodeID-9iGXJ935QZWkp5j2v6KNSTr8b45a7Xbfs", - "NodeID-9iiCATASsRcosMQ811KpxSMHsGdM38rPJ", - "NodeID-9iuMMyL7LZyUxMK9s735hcRng58bSj3gw", - "NodeID-9izFTRjPnyph3GJu1sp4Cf7zHiwaK7KbS", - "NodeID-9kNp7yMjHnDg1QLQboms9ACgQ7BGu8zpS", - "NodeID-9kgmvmU19mNsTxPS4f2F7ZiSZSwZ7dfGk", - "NodeID-9mtTuxamXQyiePCNyheFEyjr4cAQo4Wbg", - "NodeID-9ntqrySGMSMwqYR8yFdChFdU2ABj5zSEp", - "NodeID-9oP7KmQjtxi7rK5GKmRXFNuNpPmr2vzfw", - "NodeID-9odH3Jbw7uPuRrbaVkVoYeitdzwX6o69A", - "NodeID-9okkd3AwB3eurfQxdP46mcSM5sVhD9jxm", - "NodeID-9opRroLX5zG47LVmyw8hGnQJx6dxmfGsf", - "NodeID-9pBxdzsJRoGFdAjEJzcdWbzKEEkdzyGCr", - "NodeID-9pTnTcJZ714TcKA5ibKwjc4ztbxnt4YR4", - "NodeID-9tAAt3ADXpmStdjfpUKsgKCBowaPjXueE", - "NodeID-9tJaF6mjrwczuEZk3oQRJsB2AzPk7QFHn", - "NodeID-9tLM44jzwQqnsLmQTfhv6Q2GaAEkCdev6", - "NodeID-9tWnniKF15vWEqJa6o2hjmL8p61jq4ZmW", - "NodeID-9u5MGjm2Y2BvQSZBqwDkqjUrqFKffDund", - "NodeID-9ucNhNpdx1QhUnivTY35AtNEVpjY8AAK4", - "NodeID-9wCVwfdLGJe14xss2yjAT8ntowavfe6Cu", - "NodeID-9xTBvp3kCUiUGu8aM8XpBWPf2co3vJTJN", - "NodeID-9yFkNXGSAUgPu3hB4UxkWGhbp7cXBLaJN", - "NodeID-A1rgjFoH8JTHiHWoWYVcDDWC3WKnNFFi1", - "NodeID-A21bAN3Nk96xfoAh8auwqP4uQRbk1xAPz", - "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", - "NodeID-A2aPfvr1t99Nm1K82U2XyWtxse3CNmZ64", - "NodeID-A3azVkFN8rEsnnw7yQoXHDze3gVSSF4YB", - "NodeID-A45ZieXX9VhAjrz2jhACBGYYypn2HEjaS", - "NodeID-A49YH2FmGteFpSV46b9WDxZWDEebAnH4q", - "NodeID-A4amNjJyWX5kd1wNhxZVqDFqWKomCndp2", - "NodeID-A58AWZohmoEPEG2FDjqdT8m5XeUL63FZc", - "NodeID-A5SHWeGWKUiuvPZhRvNAXKyiEnyDhJzdh", - "NodeID-A5y781VL74i4yfFdcMLnjxr2qLbtjaAgi", - "NodeID-A6onFGyJjA37EZ7kYHANMR1PFRT8NmXrF", - "NodeID-A7GwTSd47AcDVqpTVj7YtxtjHREM33EJw", - "NodeID-A8jypu63CWp76STwKdqP6e9hjL675kdiG", - "NodeID-ABHKUic6BDS8Kg95tSWoYv71CXWeuS1Re", - "NodeID-ACB5BBC2RNLSGZVEGkRRQdWg8hqXjnTpM", - "NodeID-ACMpxS8rnwkAA4JfCUm4vNoWQaznNCqGV", - "NodeID-AE67987jikbcv1cjf612huYwFgx7RPAZG", - "NodeID-AEtF29pZDpKEkZ625bg3reDrux4wyMjhh", - "NodeID-AEtKZyYiqnWqzsrwSKEPWrciPHEAn2Q2T", - "NodeID-AFWbdZEPvWxEq6A5SThDPVydUj9FSHjCQ", - "NodeID-AFZVPKaEHwRZgWvcqRpT6mTd4k8xDubGg", - "NodeID-AFnD2mSUo1cB9HSMxGT9hQREHX6V2aCmm", - "NodeID-AFtmZMo4p7AZVenJtT9D2Tbk1od5mrJge", - "NodeID-AG9hZpGAPNtzpPJWKmJHDjyhFppqM16uc", - "NodeID-AGEnkaodYJksMTnwS8LHHD2X7MDQBSMJU", - "NodeID-AGurvCTxa6JFJkk3553Wx8XPtgz6w4xMw", - "NodeID-AHTFPmvMrQBt1hcoGS7HugNCuu15Q5gY6", - "NodeID-AJR4Z9bAx8tom9ygqv3PkpQtdxDV8JeLD", - "NodeID-AMMTYTe6uZR7yGL1AbEMuwYayd4N1J4bL", - "NodeID-ANeoZC7jBSmoDSYVLip5uASJW48GwWLLG", - "NodeID-AQT1i38PMJQxRqjpwrQ98QESW3EJzG3p7", - "NodeID-AQckPm8yWZiWwSAx4FQ44J41Tp4yF4qME", - "NodeID-AR44a1cyPrD8cCNZgyhv7Tc2Lvw3ryhEu", - "NodeID-ARveB1Km8pUjtoTVQL6e27fMHfUyyrjjZ", - "NodeID-ASgm7N2wwZKYc5dZPiHExfDdNcfyZQx3T", - "NodeID-AThE3ad1aiPLKsj1XfmhCsNbai8sMyPc", - "NodeID-AU27Fz35YmQuM6d2pM9HsvLtgwGT5xwnd", - "NodeID-AUeAjRR7q12Pps6Qckyy1PUzFwP34pFij", - "NodeID-AV1uDZqWGSheRS3M6RHUbQJHDGXy6f8Y7", - "NodeID-AVAXg2LFFdkWJjZi4554GBNprWUepqKxm", - "NodeID-AVAXnRLmetkBadrUoqtLSVkohnoEpeSm4", - "NodeID-AVp7QsomV2auUPqPXQesRcuKwxn4JmDRh", - "NodeID-AWLRFc3R7oCqHd6qe95QsEaoBPPTQYpuv", - "NodeID-AWMoYmhjbfpWphJ3nmgxGAPpVFzQbdp1G", - "NodeID-AWirVtsoiwvNdqhqQRwz7vQQEiEyvhq3y", - "NodeID-AX9Fkm7jKPuY9Mit6AyZoS73tFKWvTMF2", - "NodeID-AXPrBC45azzYv7UKCwLYJhidPkKat2veF", - "NodeID-AZPULN7CsYdfSq1zepSS3CZNhxJsU3a4n", - "NodeID-AZfAXX6qyLxVXBUJZPwEgR1iJYwjwozm8", - "NodeID-AZiGXCQ7UJvsVjmBpUMmXAQ12GRj1iaz9", - "NodeID-Aa6HmCaYwZzNoNXRf2xd1aqgtaWdnnryn", - "NodeID-AaVVyiopFyWeLNfshG5eztnEGSUQRDmnn", - "NodeID-AaxT2P4uuPAHb7vAD8mNvjQ3jgyaV7tu9", - "NodeID-Ac4RdT7r2vj7J8s68DB6mpoqPQ9sq6oro", - "NodeID-AcUWiUhdsfAAD4gyVUfQNokZXpDD2SF5J", - "NodeID-AcVHs6PgeipByAajqn3h7PHDk9cZXDZ2K", - "NodeID-AcZuWDkVDZy32y8YSxMVU57sLtkyHbVFQ", - "NodeID-Acigg3i7aU9j7coVrns9SEtyq9dox6cKz", - "NodeID-AdSMHubbQcGeJYMcY9nufaieoYjh57uzp", - "NodeID-AejE54hVtRxSm2e8KW4zUHpBTgHz9fpEw", - "NodeID-AgDYXBZcELb6jPp92Jk2p9qt2R2jbGweF", - "NodeID-AgfJSHN4yaVjgxanEWMfQXKGDNScwrVZL", - "NodeID-AhFT8H88EZjd7K1dhrRPfhatXKuz2iBiY", - "NodeID-Ahq7qT8wG6ufLoM8MrvB5G65SbEfZC85B", - "NodeID-Ahy3pk9UZEeVLzks1BRSqsLL6zvJt4bN4", - "NodeID-AiVA6rmmPhouiy3ERwF7k1eoLTrPErd2p", - "NodeID-Aix93q3XbWsEcoNuuWjYuQM49ZeCX7NLS", - "NodeID-AmFfzQQtUYm1RNuhkQuoG6hzaXpYYbYtE", - "NodeID-AoGM9c6bKC46YpEecEe9tHG5HfcjqPxtb", - "NodeID-AoU4gTzEVKVmopKx7s9hKXBbQ14VYyAcc", - "NodeID-AoYvCZojkKKkDiUjY3Daq5z3FUPrhMAbB", - "NodeID-ApohQPUqvLAFGgH3XobyeDFBHEz7vbS5u", - "NodeID-Aua1pVxQsWLvTTf8bNVw2ZCA2NfogNqiE", - "NodeID-AunfxeXeb5uh5FbxYMr4TtEpbVTPssmmv", - "NodeID-AuqWFe8yzJxPgaZShBZpa3AhEnKT8SmEk", - "NodeID-AvTYuKYvu8oB8dXCbAsLh7nTpCvih4fdd", - "NodeID-AvYo16nRcdMuFmsEps6STb7faiRoCRgHx", - "NodeID-AwBfjtuNZk2Cu8wmQjYsNipqWK6nYMnv2", - "NodeID-AwmHrKdtkhnuEVY5TvbwxVksQ8dWd4a1P", - "NodeID-Ax97guVgJnjpDYiZkHghBpjELMVrbhKLq", - "NodeID-AxSapUskp62c3KkAnzd2WSDammmNXaG53", - "NodeID-AyByRGSrfbDaeW4njEYwCzhsnMyZ2KMcw", - "NodeID-B39dR3Zj4ZtiqSHTPLxck66yqxTZ9pRmK", - "NodeID-B4EU3Tk8BsVczMpkPtJAqS9FSYxNjYNBz", - "NodeID-B4Pubug4ct7TKPRuSAWGqS4Hq79v912VF", - "NodeID-B5MJkFe7GoyrXY3MqrpjMrrTqj9J5oprQ", - "NodeID-B5N5hVfEFbTrG5QGKvXQBGqfvR9GJvSLg", - "NodeID-B6NVZDFoLAErvcUafQ3EzJeynFnGffCQd", - "NodeID-B8RQVdW7nFrVR4Peh6oMfsdK8Muuwfeme", - "NodeID-B8rRoKwovNH4Hv4cgREBqjHcGSCN5Lrcq", - "NodeID-B9dnZzwTmygKPxEP7GvyqDh1F6pQHkmmi", - "NodeID-B9o1a3g4PFp4JWyMJxRv2nvnWHsq1rSvC", - "NodeID-BAePtWtdsqk26YVfucEAJTA9spGpuLf9r", - "NodeID-BBJP3fsJ2sRRbB3umzz8UXAhzrUZJmWqH", - "NodeID-BDFwWjNUNeLYrrfGmYqBMqZSGZQtmCcxx", - "NodeID-BDnEyGooDS9w6bk2Ty7UncMyQ8t1iLLqh", - "NodeID-BFgsRa6TLCKcHZhN9iuufSqRengbXuxQy", - "NodeID-BGEvsCNRi5gr4ga83cVx1E7PTSiBZjyhK", - "NodeID-BHPTN8HM5xA9HNiwUPceNa314kh3YnDpp", - "NodeID-BHsQhBq2NYN4YYB9t9VxoxcL2xkCD4zPj", - "NodeID-BJTip339hEcVzpgyNqzERhfjMc6sUFabj", - "NodeID-BLjWtGBQU3PxgBSMvhiGxHGZ6Scn1gyyB", - "NodeID-BMaQ42mVapxbCcX2RLPRTeRW3th91XdaX", - "NodeID-BPsD5nsuqTKR7ToqUMDFqanYioFnAVo8C", - "NodeID-BQ6uwBhrSU3mwDpguw4rGPXa7kVkk6FyM", - "NodeID-BQEo5Fy1FRKLbX51ejqDd14cuSXJKArH2", - "NodeID-BQpbmskmST3wkcSbypVuFZu7YULXG6pKR", - "NodeID-BQsr3wEWirFH6C81M1LYsYagHXVxXRFSS", - "NodeID-BR8ysKTDMKpwbgH9fsfCdVQWMsniMQBWp", - "NodeID-BRRp1FdWN4PepbmQNUksWPsRJaZ1mFP7q", - "NodeID-BRrFzQrJs8nnmeSZxWwr9yCRcq4U7resP", - "NodeID-BSTCzJUvn8jYqDtsV3aTjRycJHBJi98Zm", - "NodeID-BSornzAY2Y4SmDcQw4Pgsf5zH4Wdv6d1S", - "NodeID-BTUXn6xfxjtA8P4nXYHiwEJpso9Q9t8FZ", - "NodeID-BTybEYu3y8aW54EK9SSivLUYn2fiCosjD", - "NodeID-BURrZL8SidbaotZ1cNxvPxNH5DGvXS7gN", - "NodeID-BVSFJU3T86CWXQxSTc2Y7cHo7nYJx1Jn8", - "NodeID-BXTBUqX8gitUDtVam4fhRWGD1SfeHGoBx", - "NodeID-BYGnq6ZKg5ncN419eBsxd2YQcxoewxfrQ", - "NodeID-BYSrjPkpQsN7YxR2v6ToGhmD6VnpEz9uR", - "NodeID-BaPYDXQYeS9aCFHv76r38gUhYrtfpzq6A", - "NodeID-BaTDuWRvZkEy8gg4FRYmNYXASWL4QKzFD", - "NodeID-BaaUYiEUD9ogi7dDikVZAzaVu5yxAHjGs", - "NodeID-BagXwfWXPpzCt2utVf1P5MTwdQsPnxeaL", - "NodeID-Baof3ssuxMwMHxd3RXpNwiWmRdskL3hLD", - "NodeID-BcfnNieXDpsvkMApb8FcCmGAoQdtyu8jH", - "NodeID-BdD2fp6PXxbSdGshiVrHDzarWpgLFEMF9", - "NodeID-BfeJfXUfFveZPbS5tFaJar7X2uQQ7S7so", - "NodeID-Bg5GpEVehBRU9HDf9e66vXmrRJ39BW1hG", - "NodeID-Bh9vBw87fdqVzMzrFrPiTQqA4irjDP6G4", - "NodeID-BhSpBoma36qXxym3XPxM2E9xisXh2hBmL", - "NodeID-BhbczAQnAARsn5Cwa1onMXLD6j4Uu847F", - "NodeID-BjoNuhod6yNfMJJDJgyfNWWRBUG38ZPCs", - "NodeID-BmKvEFG1hXNQ52rPBTXwQ3ZxEmcCmxXZx", - "NodeID-BmmaSGfGKxQNMsaBSnxvhQdLCNchGEcUo", - "NodeID-BmtQcEcSHhUJzkjKQKJKdF3gQaVtud8s7", - "NodeID-Bn4LPbETjf8D9pZE45abJgcCk5KSQCbo7", - "NodeID-Bn8ZcnL352FHc4utgVPVDjD3o1HfYwtdA", - "NodeID-BoN8r3MqeJiqVcvrQx1VubZMGDQE5pJi7", - "NodeID-Bom5dUsayGwdagVLoNNxe1t1FFDZXGGK", - "NodeID-Bp4nG1LrP7JCg9eSQpfBE91mBSd8biThQ", - "NodeID-BqCmioAapUYdqLL7AuWJqPeRrp4D5a1ag", - "NodeID-BqtSwNPmkfSi5W3Zz7CRffeLmYrUYuEmJ", - "NodeID-Br6QnUhtZGAC4CymYLPRSMCrsNyhLMmH7", - "NodeID-BrexWemEB1Vgpbpnnriy3k8e2CyRvxsPR", - "NodeID-Bsa6pnd8nUhHEQ4v68GJ6fDFwCpz1QSBj", - "NodeID-Bsgdx1HosAzQ5X1M7JmbYngULQ3xjkP2e", - "NodeID-BtcHfm5o3A4WhAmkTm6YPWRhPCChDPLMM", - "NodeID-Btr5hkRibMyYztC9jQg5T3fpKNeYf3Qdq", - "NodeID-BvDJUkrDJotTxgZi96zsEe6iYQBLtz958", - "NodeID-BvpPGydG4inQCbkwRZ3nPMp1zAGToUTxz", - "NodeID-Bw6s9DYKi2V9jRqNmaheGGg2Wz2Dv7DQo", - "NodeID-BwCLnFCE3ipnmkT3V814hGsb6sCRFqScn", - "NodeID-BwsGZ6YpSqF2j3QRRiQJDf9JC4FmCGXq5", - "NodeID-C1oRu2mGfJHUD3UyNCWVJnJ4T6AWXhj5Q", - "NodeID-C3aMR9tsKqTNQra8FbqpFkMgHV5DtuJGx", - "NodeID-C4emGUFHEeCEZgoeMDHZddr5nyZBgEUKf", - "NodeID-C68ijbc3Bz1cdoQv4Mh1TYxrzeGA3PnmG", - "NodeID-C6b58cQGYSqm1FeQyvXKXUgZ3R7Q9D9es", - "NodeID-C6fd6GFYMnbD44LpZR6AuddMDRXTvR5Nn", - "NodeID-C6poeYWySHhDuKWMbckvcny24gTGKEtEK", - "NodeID-C6zVv1ab5JKn2j8DDCGWGai9jgWhmpLVA", - "NodeID-C7VsWUVsE7uFmSgkRQpcjAJWB6gRdm9Pc", - "NodeID-C7YyYDva6rvbpY5GEu2Su653eLBNt49TA", - "NodeID-C8b7aGd2caAe7PgtP2vnJcWta1wUezAAa", - "NodeID-C8zmJazq2HwujDgsjKpmYJsvSuNMD1kwt", - "NodeID-C9Bcji6rXUp22qyWhvYKm4v45hJAkzvpU", - "NodeID-C9CJ3oVhdeLf2Db71JPuzvEUKjy3BdoAA", - "NodeID-C9eHQ7iCCpW7zy7Vk5UJEXd1zwXEdFtS8", - "NodeID-C9eewJtL6WMZi2ce8YoPxhHTCYemhvnKm", - "NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg", - "NodeID-CBPbPrYDbghbAP4RLSCQr7bHQqHWh1c9Y", - "NodeID-CCBWkqmiTdwUCR9ExH1mNSLzvrt9JRKF2", - "NodeID-CCPtDzjuJWjt1VuV3yiHPwQr35qh2rbJN", - "NodeID-CDjuct2YS1o4d14nHtszWmyVUmFjo6AHm", - "NodeID-CEHgpbVVJh676muJTUNKzP3jmZ6Cs2zar", - "NodeID-CF8WKgeNBHxWFmijN7tysmmRSHfJFEKD9", - "NodeID-CFoWfGyYw9HPuDK79fjor9d96S9wLAbpR", - "NodeID-CGrPauwXiEvvY3yLBxR9HM25B8HpNTVfV", - "NodeID-CHxae1CeKzs6DNxur9rHcjSAecpdN1p9Q", - "NodeID-CL3N5kkR7HsmVtKavcuofwQGgMNjppY4N", - "NodeID-CM5KJnEvKQfjFirjbUzHa7WbanH6dLHva", - "NodeID-CMFSQ9wzby52sJqTBeajH2MaJq8HwnZPL", - "NodeID-CNPUVCHqT8Jpjpix7SJfXhh184EjPSsu6", - "NodeID-CNyGDr2EvPqxfybfNLkpGWqMQHiZthJ3Q", - "NodeID-CPWtTaJjKj3uiQnNKeKVk5yKfEiE5mok8", - "NodeID-CPkJH4zTnyhERzo7H1usRiSmMVDeUszm", - "NodeID-CSmSE2veuHYG3dJD9WuqobvsAdJ8iF5pF", - "NodeID-CTry2Hj2aXeA1rfWq1s6pDL8SzaCFGLMC", - "NodeID-CVJCnaM2gVKr6WCmJxKSPjEA6GFtmBknY", - "NodeID-CVXpUPtPZnsEM4mSnJbctBpL6Sgj1rCRt", - "NodeID-CWTULAJzqphbmedDkRpcHuCvGiHARvodz", - "NodeID-CWuWBhX2WaAY1pBTAmLRTGsjX9y3EqWAe", - "NodeID-CY9BmJwkVatHX86Pt3Fkxts1QoKTovyAs", - "NodeID-CYdCC4uTyAmEHW2CNB6oivzBtzqJn55mS", - "NodeID-CZRwtJDY1KeQspzxqmHfSdwvhA8xAeV9K", - "NodeID-CZVcr8ZP7njdQynukR8B1RcCcG9qxSdD5", - "NodeID-CaNQUnkzWJFcsYNhdx4iyRk31McfqtKhX", - "NodeID-CadcH2YHzeVWDSBT2LR9bfqHvMVfH6bTs", - "NodeID-CcNi1r9gNk8NtaNFKShCQdahthUEpZX6R", - "NodeID-CciiJQMXRWQ5967qBS5XncuEiyor1Png1", - "NodeID-Ccx7u3SwfPt52GxWbNc74kjVJvqktTkn8", - "NodeID-CeaG1icxFWcMkTzsqQjpwt82nePJrk5gZ", - "NodeID-CfM5DQx47iD6AWMsFdHGfWUnt97Sbt9n7", - "NodeID-CfT57H9QA59QT6s3QZGi2HZz8TH9i8V3y", - "NodeID-CgXPRNG5FeVSz8qC31u5UDpZ51pJ2mN2X", - "NodeID-CgbgB1UFpUESETV1CVGDM17bE9JA4tVHK", - "NodeID-ChjgtCzFxwhCYQGsUzGHUUTi9nFYrLsXh", - "NodeID-Chk1hvm92LQPActavSVqoEYCmXfQZeFvE", - "NodeID-Chy78FPagNNU7oAj1QWzrdPFjJgZP3Scu", - "NodeID-CiKdcSyNH27re2W17ygscpZ4xG7474E5U", - "NodeID-CjX7mnJM1qasMtuyyxeuKoKy6b9fdSSbE", - "NodeID-CjooWTHxne1o2w1hetMGgDL5Et8JzKMiw", - "NodeID-Ck4VEAv4JTMgnijLQDeGCWST8Zdgxe9Q6", - "NodeID-CkMG3CThWnfAYCYE1MDsFqSU1n4NESoFt", - "NodeID-Cn4ocmPe1Hqo29RyYCC1QXr8b763Wpw92", - "NodeID-CoRQHCd3aSKe7FrhHSUnvNVZzW52xu2YA", - "NodeID-Conr75BBUMBFNXD2VP6gvEbCRihCvjfej", - "NodeID-CpAhCB1gu11mLxBZJfgGLExwwvKobprLQ", - "NodeID-CpS69JexgMfH1sy7a77fiwQgN3c5QtrXa", - "NodeID-Cqc4sovCY4ypZww5envqKgtrvd6zrRPTz", - "NodeID-Crfqdz3qPavSYvQUWSXMawWjUXxnr3Gg5", - "NodeID-CsGzEmegg1sVokBzrSKkMygKy9YCVEzkq", - "NodeID-CskPetRMvtH5Xr6gLa5cwfY4hR34UgkM5", - "NodeID-CuEMaXrtX3tdegH3BPJowHr7cMUyf7P19", - "NodeID-CuF2PsXiuZESJWa5itRLmXWQ66qL1NSE4", - "NodeID-CzW1jKjZwFXgkB2Ria2nNPvah4bMq85bH", - "NodeID-D12qpTYhB3feogxvMBzS1QPvwyKyhRK8G", - "NodeID-D1H3GmiDVvoMsp3foTPmWi9YPXweYv9fn", - "NodeID-D1rgZbjdrevpXXDF1orhAvnUmojVfeZwM", - "NodeID-D2hsJkh6oAf5X9WEuNgbChFvkeUgC99Ns", - "NodeID-D2iAoisJf33uGaaKh9uCUMrEjN9HG5dib", - "NodeID-D3onstuMsGRctDjbksXU6BV3rrCbWHkB9", - "NodeID-D47UrYCDdkfrDrv9gUvYKLUyT44TXYCJZ", - "NodeID-D5aUrNtb3vKUBKYpdapiaGEaBTmUz3Jr2", - "NodeID-D5wkgZDwkAQVpFNYtNZmGUJGnUYRB97RJ", - "NodeID-D5yA7HbEr8AJ4yzwVZXsDtb4xhKkTRz73", - "NodeID-D8vyyYopHECxjFCQ2K4X1sttJjC1B7zva", - "NodeID-D98ujhSFuA5pXc8bnKPPpbP1VNFnfESVk", - "NodeID-D99fW2bCQpU6QCN1pu4UccDLZTQdVEwMj", - "NodeID-DAMYbaM35qcXWvuEKt6spGK6EzVKDJUkT", - "NodeID-DAZNmxJPADAnk53993F5wntS7LUhxNH2i", - "NodeID-DAtCoXfLT6Y83dgJ7FmQg8eR53hz37J79", - "NodeID-DBB8Ve4B6dXejYtFhwcQ8ZMFbmZu3VpSC", - "NodeID-DCUpFFgVWQBseGis77N45cBAZudSbaZyg", - "NodeID-DDzbSLsiD9qMPr9eaUhxwrChfbbXW8Zu1", - "NodeID-DEa3uaa1iztrxytaMqaP3PdydErzjWEgh", - "NodeID-DFDnfBmuJWqEeCxMviw2u93rK5thcetQo", - "NodeID-DFH5SbPENeErMmeys9FcQTMvdKkYrdLU2", - "NodeID-DFUyhAzXyYi3TUaQYBvm5cezyEaREeSYB", - "NodeID-DFuM24ytt31NZquBMCS6X3EHmrbfJXMa8", - "NodeID-DHUX369UfTJb2vVuWSRdJr9s27owdMbkS", - "NodeID-DHpKTzduyCvN3x2G4svUD2T7LZDD1T7nC", - "NodeID-DJ6nZjHBeTwdQiikyuz1foaQ6dWLLYm4u", - "NodeID-DJbw4TrSRu9uovTKqo6w12axPLHWHsjJD", - "NodeID-DKSq9hmU318ceXbU4LBEcSacDPZ5oSNAf", - "NodeID-DKgP4pe8GtAwQ3oVgvHJFG3WexnLjkkSt", - "NodeID-DKxvuUSqd8xtyWejxXC2JvQfP79SAsPvG", - "NodeID-DLFjLpQupsWf5UdaKRFiGELdeY2ViJfwT", - "NodeID-DMn1E4EyXZu8GZGKHV3p1naTmpKkpf4fM", - "NodeID-DN3fqQmgTBvk5JDxKjCFzmbs2XSVXTKny", - "NodeID-DQMJfc9ArkN1gohMBh4SQi4Cmu6EKAPo8", - "NodeID-DQVzByLn57iLrib1MVzoxVsnEksS9jbgb", - "NodeID-DT7ET1yHCTuNMydS4mGod99maQjBFS9MM", - "NodeID-DTzB9kesfKQNYuRBivWhK3iB2aWsuYu6Q", - "NodeID-DUmZowZh6nxKskHUybupqNAhnXVA5yQ1r", - "NodeID-DVh35F3R11HAAxzeSTbk3eR9w2BzPrJQt", - "NodeID-DY2Tk5ZqUir1NpSiTwXVGdETCGGEV8wHe", - "NodeID-DYCS7WSBWdmMx8ioQ4Lq6gfnPtpKmKVB6", - "NodeID-DaKj4jkyyCN4B5zVW65krECqpjxYGUFzX", - "NodeID-Dbf2zdJeUXfi3bFzmjhJTSgyME2o8iEaY", - "NodeID-DcCkk2wqS6L9XpNX41DVN5RZnwgixCYqE", - "NodeID-DceQxAzA4nCGFm9BKa1PEJ4c1zwx3YLuu", - "NodeID-Dcs4UwSwQe7vKaopXi9AcM891ybKatAvp", - "NodeID-Dd6BPwCsmEQaAgx9hpck23LYe1SopA3p9", - "NodeID-DdJNZBekdB5EVLEe2vE9LusaHjbGmsMYh", - "NodeID-Ddm8dYWWMgiZv5dyNWuzgkDprubqB1wkN", - "NodeID-DeT8Fw4Tp875GUQNxfcfKoBSPjKpGi6eR", - "NodeID-DhNYzUwYHPF24Wfz9MmmVyqLBUF6tkEpb", - "NodeID-DhuG2YhqQy26zabyLqTqNr85T9XscsWpY", - "NodeID-Do5ZUHCK8DHm194KGqdcwFc5wWE4fCQ6s", - "NodeID-DoEC8uw9qRNi33EiYrPoK6Vu9pnsH2rnW", - "NodeID-DoTTJmp8cmERizJdYQGFsPVFgZPJxfcis", - "NodeID-DomnwLG65RUJM41RgCJ2tRdR4iZEkVCkk", - "NodeID-Doy4qhTgun22byNDyHxNSRceygqwhwXCn", - "NodeID-DpXBTEP6ZCmm5bgBbv2rb6MzdRovARVhi", - "NodeID-Dpba952dAUnayPmf52GJzQj1PLoqtXahS", - "NodeID-DpwJ1uaLSpSqKu8ZTa7XpmFp5BuBYN4Ns", - "NodeID-DqE45ELtkEn4hSyU58oukvcPg1Ua5UdzV", - "NodeID-DqqpR7tQ3goBbudggakvzYs2K9TzR7daR", - "NodeID-DrijBGc9SonJrGUwex3vXtzzEGW3cB5DY", - "NodeID-Drv1Qh7iJvW3zGBBeRnYfCzk56VCRM2GQ", - "NodeID-Ds3ri3EksrtyjtAJ3RbX8Wku19LRdKTti", - "NodeID-DsMTbudbrnZtFyexvZihGfb9qETaxFBm2", - "NodeID-DsZ2yLdYvfHZptxMZqmHKgs4T5ehRTx35", - "NodeID-DtCpt2Bi6gvmQqwgKE59fanof5F3bepnd", - "NodeID-Du1Ebao2uJG8LukNGcUrzAevtVRhHdtKW", - "NodeID-Du7SAKQLR3j5iK7tGv7NvTSxiEVTfYfeS", - "NodeID-DueWyGi3B9jtKfa9mPoecd4YSDJ1ftF69", - "NodeID-Dv4KWhKB56So4dZNxRRi3J2V74TaUXWMg", - "NodeID-DvCdC1yWp8a9NNLBR7agvTV4YNmJY7zb4", - "NodeID-DvKgKdhkDk6CUf68iqA5Kwaa44RkBa4zN", - "NodeID-DvMo3a7eJYQexjLrR1rykrc1jsNuVwnPn", - "NodeID-DvwWC5ed3j5iG6e4Y5yxAUacPkXvrxLFT", - "NodeID-Dw7tuwxpAmcpvVGp9JzaHAR3REPoJ8f2R", - "NodeID-DwP4ATkTPn52orSSS1FbjjT21TXnXoEnX", - "NodeID-DxdedkGTUuVoRS4VJA1qYXuFU6MerKKyX", - "NodeID-Dy47rtrYr4eiyRTSnbaFi8KZVnR56XrUC", - "NodeID-DyXd5SxgwWWadT9PdEpieSPtjcKxYCMjE", - "NodeID-E1c6FEFavQ1RiaNARpxGx4sWnXAGh2YHN", - "NodeID-E28yXasMLXFQM3f3mQtGWUGh2jEgJATi", - "NodeID-E4KwVKcddwozth12cNvNYApyHhVbvnby6", - "NodeID-E5DL2H2CxUUdxe6TcMW7uTHC5mFujF1eD", - "NodeID-E6GJmPWBnGKad7hPfxCK9GRwsuAKc2MJQ", - "NodeID-E6uwzybtqQ8H7aArfxxVJWVsEcaCPLT7t", - "NodeID-E8rXzDkKySREDECoXPqaPPhQA7QuxL9M2", - "NodeID-E9cBEoCDBGi6qFGcW6bfFoyhWpq6Vc57Q", - "NodeID-EA7WyeKRdVx34ixXFCvfWbv5P9DSNsj1E", - "NodeID-EAdWoKJCXzi2jKAEoETCm89CB3dzyMdAy", - "NodeID-EBF7imfP93Sc4cv3cUAK21maYDvaFMS5j", - "NodeID-EBHJ9gHUbjtNQMnNNcJEsqojFpAbLrnVS", - "NodeID-ECNKxnabxDwevTW7bLgP2Meaid1j8ztVn", - "NodeID-ED4xkYFhZPNNj3WXDQiogcTULeBpDVjSY", - "NodeID-ED9nabFu9bXzdDizCeNytDisKqkdEk83Y", - "NodeID-EEQ4pJQ8FTsFmPi5qEiZDBkKsqCpBRZiT", - "NodeID-EEipCNkeRgfvwiDHbaBdQ2WeRnsRVSH7P", - "NodeID-EFWjQ2CYsraxPFxWVJL87nfqKNsAP2T9q", - "NodeID-EFd4jseGxHxQmYX1ATcJUSZoCnE7z6dFe", - "NodeID-EG6gFe5McNc2EyFzARxuvTApN995FdBZj", - "NodeID-EGKLqBNabvY52737RGARiuGgvu2vHRY6v", - "NodeID-EHJoNS9sgSnjg5gkvKL4AF5vyi8c4qTvg", - "NodeID-EKH5gkuABvZWiZGHvWuZLgGar4Zts6qX6", - "NodeID-ELNdDSKVpamvTWSQvqqBWzuAKFiJLzoT7", - "NodeID-ELjBQTBvaEAMk7Qx7qJNJsEh2DYC4nxUn", - "NodeID-ELx4yRvGiDRcG8r8Tow1LUAhMXkVYVzHo", - "NodeID-EM1NUe17RtPAJ4ofro1qPc8vEfcvEhjZM", - "NodeID-EMETD23g2Bne8CuQKyR8HB15KWomaAuFe", - "NodeID-EMq3MvHvWctiQ5CC2ioXpeyKPsHteXAeR", - "NodeID-EN2aDGGjPAqm4Npzk9wCjCdGfg5hVrWgp", - "NodeID-ENc7M77QRhgtpDojDQY5nqjndjiYCWR4i", - "NodeID-EPqYJkZ7knGWY2TNe4rxRtNgkqc6spyDC", - "NodeID-EQtsYPVt3rHBSJdp2Sss3pm645cpTJkGp", - "NodeID-ERzoQo45TdZFeWHG7JpHVnHbn7ULpTRiV", - "NodeID-ESRpVRqLwts8M93Ly9QPm4ZSdMF4wEpbt", - "NodeID-ESVMWUoEkKz8uAEDfKcEpu5UUCkA6GeyC", - "NodeID-ETwxZVMHXcikZmKsKfjiZuVG84KsZDdqz", - "NodeID-EWNvJxWq2UBBsn2UH35soQugQJn8CVKdS", - "NodeID-EWmdnUhsVGSfZPnbuSodLUTA6ReJcXz8v", - "NodeID-EY4iiXyj2TfoHspEHBHFfBYrHxXESnSN5", - "NodeID-EYDcoNgbX22og1oyEn5s7iH1BYSmR5yF1", - "NodeID-EYgNPuFCT4Qy7YhvsM2s8WKTT74QECvTV", - "NodeID-EZ38CcWHoSyoEfAkDN9zaieJ5Yq64YePY", - "NodeID-EZrxYbBm2ZcoK13eTPf2sdtYuJuSHyaTF", - "NodeID-EaEUnvUyfTr19uMW8g51bvFXfi7r9xL1W", - "NodeID-EbwYUq8FZAK4jf65nZ4dcb5kk5WZ7RBgb", - "NodeID-EcoA7iNFXhc2DwrmWxiEvjvsDvDmQrEKK", - "NodeID-Ed7NMisAoxzWRjxQVrWnBvMShLNcydRa6", - "NodeID-Ee6MdWL7mFKdPAXbJTWZGvwEUsi17869c", - "NodeID-EekL2aJ7TdkbiXDzSsPo5PKyaaQuQqVg7", - "NodeID-EfnXCVeLUtW24v8gwW1VYiNuqDeRPEVYC", - "NodeID-EgzctrMz5jVPbfUEWGufKxf9CXUMLBRGG", - "NodeID-Eht1FjvmFncRbagWk1PGMyE7hVrCS9Acp", - "NodeID-EibWFSUHeLNNjWZrEznmuxH7ZWNsavRgh", - "NodeID-EiyGqDavdQ8dMUtN5wjAezDXAWwVBdSBK", - "NodeID-Ek1pare46s7nXPF9JtsoyM7PcaFnCBms5", - "NodeID-EmPwabyobnM3jYDvQuxZdLBTut5V5pq2n", - "NodeID-EmRTfxEKTLpzTyWJmYTXVxyGr79bsv4Bp", - "NodeID-EmhfRnDPSzpEMhGy3KSC4BWhPdtoxmqqV", - "NodeID-EnANSJ3hrErv6v7ZGSi8p5RCHhdhbGrb", - "NodeID-EnVDmm6dUgePaWbtBem6HcbzptaigBxDe", - "NodeID-Eo31HyvvA1Madeagm6U8CM376cEfgS4Bj", - "NodeID-EoNXC39QyT1eHFPXb5PgvDNigBN8tMeCC", - "NodeID-EooPQfxvcRG9XQpNmbDg85sNzaFDzux6G", - "NodeID-EpU1DGKMMvDRtag9u9G7uwZHRsJF5NodL", - "NodeID-EqBR9F3QBBrTQTN7CDN7sDEUsDGDdMYps", - "NodeID-EqauaQBwVXnpamJvLi84aeZLTQra4GDep", - "NodeID-Ess2uf91CDTfKsLezaTLKqqsWcpEHGvJv", - "NodeID-EtFG3SrbbudeFQCaWRxhwvv28wHpo8VRq", - "NodeID-EvY8p6SYho6VwicRvVasSBBv1MtanH19D", - "NodeID-EvZXX2K2eVEV7n6Y8cnmeSRgj4JhkCVad", - "NodeID-EvdPJG2AAVGCP2s3543KDx1LZ1g5SiH2Y", - "NodeID-EzKkVMd9y6XqzQsvRDLuaaiXqXK8fFipU", - "NodeID-Ezk1hTiN5bogETxygJ5NciRvHXgXvUVVM", - "NodeID-F1JWRVsJ3Wq9eSdNEHvoivQVCsW19r8gT", - "NodeID-F1K4jks15y71PthvXVNks8pgutgBwdHZH", - "NodeID-F1KpunDAMisiGKLX3R6k9uBoJoeLwzJoU", - "NodeID-F1qvuNMn9XBXSjv9iWyyMGfV2PQ2Na7KM", - "NodeID-F3b5mj8PWnMP53hFbfGNxkiXpbK6tPyDU", - "NodeID-F3r4EqguPQgupLCYrTG3SeJSCi5qtc3x4", - "NodeID-F4Q66oFkqCmRnBjDUAh28iXvWx6WxbxJJ", - "NodeID-F4SmFmnXuFBkW5fgFgh5RT2T5w8KseGRN", - "NodeID-F4kKmjMhZJWkYwsWyPSLFxtNcj7BhELmY", - "NodeID-F5sBP4yNA2YXHbD6FJUjsZJ5zhoMqMi6g", - "NodeID-F8HvQKYDbonSeJ3x42Ynb6ibxiJa3FWVL", - "NodeID-F8VWioW7dC64159mMhswhzpkHxnB34cjS", - "NodeID-F8Yq4R4Mx1LHGbQ7g8s3beNB4LGnCUBpv", - "NodeID-FBtCkPRmkfDry8GGpNenBW2fn3fD3qoKn", - "NodeID-FDTRdm7eS7sBuzAnQqMrXUmNiuNHP7VM3", - "NodeID-FDZXWAQeuMzZVq8tv53b1NdiwyJDUHGpB", - "NodeID-FE6WTTtg1FvtgQMZBjjZ1qhZpPq4WoM4m", - "NodeID-FELjhENFRLHTgVrwiKTdL7aSQbU8mBd5Q", - "NodeID-FEUSZzFmjF2JyrniKXksGfRjkQUH5R4eH", - "NodeID-FEsoMJf2VjoRPdnm1Ux7CGg5RrHnAH3VX", - "NodeID-FEtgjYGndfWGzLZELTJJoikpSobjVKTjk", - "NodeID-FFWS6gV9FrKecNWCYJQuyR67t7GY6UiVq", - "NodeID-FGRoKnyYKFWYFMb6Xbocf4hKuyCBENgWM", - "NodeID-FGt2J8WREPFbbTXgVU9YC5NjdERhoMa7E", - "NodeID-FHGwnPLGdU3FBzbwnhayx1sDjxiiyb9sD", - "NodeID-FHHEXLYRNrnQhKFneEwDPX8TZV8WtUpQY", - "NodeID-FJ7WdKoGBkqb78mMGrr3r6kSL45R5Vspp", - "NodeID-FJu9WvWrxTucYcNzEVQj1pHbbS4LaFTnn", - "NodeID-FKCbGm3jmceEEpfSdA4uQUVANpmqFLAty", - "NodeID-FKGhEFYnHUdFadoR2ePvdTTM5Sz8tgjHp", - "NodeID-FLQ8ifj1DwXuRWKShjck624SAgYXVpQzz", - "NodeID-FNfrZNBD1bxGj1VmdgSrEKT8oMePC448e", - "NodeID-FPwgrsmgeX4DSkG4abJ28zZQhjcqirPYi", - "NodeID-FPzqAmcWBR9RZdNggUMtuyWwvuG2RkqrZ", - "NodeID-FQKJ8yATVmwGuy3LN2ExsURDEtZNWgr3v", - "NodeID-FR1WrbXocb3QKywNmjQABt3a159QqRMBe", - "NodeID-FRTCPrh8YwxmR9L1XJWjLuMA1r9SjPrRu", - "NodeID-FS8PXhYXxoo5GoTHoki5Y3Fqk5zzdMY6E", - "NodeID-FUpfjb5sPRnT3XxMbtephYBc1MHZE2RYL", - "NodeID-FVMb2XgKVaeonehFbPMe714kMJ7DRxhpt", - "NodeID-FVgPdpTafzx8jazSNoxvQmJNxoEcAMmxm", - "NodeID-FVgkUobMuUBABuMA2KngEsm2SG9XLGvdW", - "NodeID-FXsyWrGvZZEns2iZr4d2h3pW9piH9ZE5h", - "NodeID-FXzsVMpT3ipDikUzabDtmeLrXW8JYyNZp", - "NodeID-FYv1Lb29SqMpywYXH7yNkcFAzRF2jvm3K", - "NodeID-FZHUwdFr4rndHpmSFXLK9dJwKVcijv4yW", - "NodeID-FapbxinG8eCCXzZQKCjxicKcXijmnKzD3", - "NodeID-Fd4DMc88ELLiTHHSLVZ7L4MB3Z7jbDEAy", - "NodeID-Fe3121hoArBshDTJEEeMeJTNW6HcLXxT1", - "NodeID-FeddPuWb8xtJeuXCDa4CAbjgv3n4PBQXV", - "NodeID-Ff4Fx8mcbfBVZSpMFwQKDUURzufmLjLgS", - "NodeID-Ff4s5gpeGMf5HaBKNxBX1uRxB2hxRx5By", - "NodeID-FfRKiU9BpTzMx2KGmrN4YyiwftTAXZ6FH", - "NodeID-Ffh3UfBYLouumUQgGuFbSTBbD5wLXn7xG", - "NodeID-Fg3L1eo53UWpf3J9Y45PK2ksQ1zyqajHL", - "NodeID-Fh3Yr8SejArPdA3eHfg75sLAt1ypeSpCV", - "NodeID-FhH7R1HX2ipEetm1eH7u9aKfBCtCQyuQM", - "NodeID-FjPxKjpGqPNj8NyEVVdJgGT2bXFVkNyW5", - "NodeID-Fjgs4ALe7yajXjZYmcRAvaQBGrFE61QME", - "NodeID-FjpAr4XXwanzuhLMajEVdm6bwdcGgtZNv", - "NodeID-Fk1hBt9ZyaKiTPjq7MLyvL7Kgd2YMH4ie", - "NodeID-FkHyxMuq6DGNLdQtMKiLzhQQuwjSCqwHj", - "NodeID-FoVyB5QV1hmvAxsNunHRRzonCBJGkLvtj", - "NodeID-FpA1n8w3xHmJ1QK3iDAS49vbLJokejfMA", - "NodeID-FqiffXvatKSLPRhkkc5y2MkALrZ8EFN91", - "NodeID-FrGVKPnD3xVmoMK1RjtbD6evNGk3wrpv7", - "NodeID-FrPwbz7L7qvxbxR63g6CMpWPDEyHiiqrD", - "NodeID-FrTRZzNgZZoHMGvC5t6XtJKAv7E2LvYYU", - "NodeID-FrWaLbhUVQHEzXfeekv6MCbkmLfx74HrP", - "NodeID-FrhMaTxsagqjYCetCyxLxpbcpkN3cjVLH", - "NodeID-FroHhWhFsUAh3s6Y4hjh7mx3E79mBUZGj", - "NodeID-FsqY7xFDE7Cvnxkc1BkpnRbiLXH2tAVha", - "NodeID-FtJRoxeiXq4D4hsM9PCAZkoerJDTqPEW7", - "NodeID-Fugfqxb9NKZ3h7vTe7XsjqqKqxYwSrTsh", - "NodeID-Fv3t2shrpkmvLnvNzcv1rqRKbDAYFnUor", - "NodeID-FvAAKfRTbxB5ANcapWNtQ2VGMFWxX3LCh", - "NodeID-FvFBsrTf6BhCcS1nFPJtRrWZ5Nosb47h6", - "NodeID-FxZHg1hxvYyBWFCHzqQPhFYsXte84UT9A", - "NodeID-FxaeyWwirpBBbBwRgpytNrtR3NY6xTiwT", - "NodeID-FyTHAQeNPFhoDetc7pznBMJ5BRj5s6FJr", - "NodeID-FzJA5i97oBDNiKeePSfHc2t3zt5cRHnjJ", - "NodeID-G1KHG6SL2B9jnfbzdTudhjRPa9hp5tuRQ", - "NodeID-G36seLQVfXnaUgaNobbSWg8anRta2WUwE", - "NodeID-G4dtkvboFCTYpnLyHYMVPq8GLxns99NPq", - "NodeID-G5AGU54ib6jCTc9B3aUC6BVLyhEZUuqYE", - "NodeID-G5QuntEfMZS7A1TPSHN4owEa81C6MAGC2", - "NodeID-G6nXgtucmeKn4nkCp8YTDdM4btVSnW4ad", - "NodeID-G6oS8Nbb74RyJatPe34iwhTUPDqJNtuwD", - "NodeID-G7aPjXRfR2XtrB4PGATDS8NoqxmqZmryS", - "NodeID-G8uVCikgvakai25byQwYx1z56N33unmj", - "NodeID-G8yv8mWQy8FLdFfAhJ4v294T5Z2DWDVEH", - "NodeID-G9aa4VXB19wnUzrmVq2SheaxnKEieUW3S", - "NodeID-G9ucCcZoHdXC6mrVpKVqKzHsMrnoVZLU8", - "NodeID-GAEZpCd2Lg5RSrPtQhGvxw6Kid5tAL6bw", - "NodeID-GBvezLieTFYRqHsd8QzWqH1JUhuwD21mJ", - "NodeID-GCL85wyq71aw2FMRTct2PJ2F4qGQL7WH8", - "NodeID-GD3XH39S9feuK74XEh8AhhNEapSt2hqHo", - "NodeID-GDmLiXrEtmFvBiE2s1ZGDYdZZXdkkLW5F", - "NodeID-GDp4P4Jo84yyVRkL3UTkJDuTNno81BBxN", - "NodeID-GE2jerBVdHtvfKkqfNHwBr2MCkDf6tLir", - "NodeID-GFbG2ARoztCgE1FxUekg5KjEaA1bwThjW", - "NodeID-GGHpri3tVbRgLUEFKqxNivRbegTKBAnyG", - "NodeID-GGfhdfGbqenvgChEXpdngjkKYAByo9di7", - "NodeID-GHBthsGgAzrPLXuXk7vbq4qsc9CvSbwXS", - "NodeID-GHZZWcg26qxY8K9uDLXu6Gc9Gh3P11dK4", - "NodeID-GHd5dmrKvYkAbxii5V7wmJw8sRf4JqYAi", - "NodeID-GHomCXMMRTSPRZrrxEULYPFHHXEhb7qvY", - "NodeID-GKBykzpxeALzYee1fGQjFn6oZiA18W26m", - "NodeID-GL87o4Z7DghVRLf4z6befUxjDoWXZUDqg", - "NodeID-GLSSsNA2oHSaebdYDBQ3u98kvHfH7zjYf", - "NodeID-GMJcCQwhNFDGQy4NAkKM563BMudjmHpXb", - "NodeID-GMoxCucPFt2LPSpTh5hPbDPAp71fiV648", - "NodeID-GNHgGvi7xri6CckDAzmQYL4YgR42WkVsX", - "NodeID-GPYurKNwtkhJ7M7UQoDinFz5P7Rsu9yUo", - "NodeID-GQZBUwNZb7iSYWEyqpyrp6HXG7Z43uhWF", - "NodeID-GR11oP3kLHf82Xbi3H2kewqoM7ydHF5ES", - "NodeID-GRReUAPgHbGdXcv5Btpm4ByGvLrD1NgXG", - "NodeID-GRrpJze5AEaBezaYp5QRtVcLAF6AzdJSy", - "NodeID-GS68HENWev9AWcUrhLqxYvsv2opJBZ7km", - "NodeID-GSgaA47umS1px2ohVjodW9621Ks63xDxD", - "NodeID-GTu4yYzFRv4QGXyyvcorGDUMWjzzMWuqN", - "NodeID-GU7boimY7cxeqdDmnPRyYrwLiRmwiHxhn", - "NodeID-GYAMwLv3XViragqqJUQyTNRcUtoRWbi5F", - "NodeID-GYYGoe6y5TtL8vNBVkvTqk8sPTVVqbGaR", - "NodeID-Gajvbi91pdURX1xzYQ7vzm1qUzNQJEfbG", - "NodeID-GbhKbbABkTdzExgzbbsvCdc4gZe8eHpgP", - "NodeID-Gc1hRnfx1mvhgaUnmymNq9TKwvhFjhEkC", - "NodeID-Ge9DfHbtays3Yfsyr1C2Z6eHSLpmTXQ6H", - "NodeID-Ges52zCMZimxqri3ia1J32mUAKyUsvcpV", - "NodeID-Gey3HmUZyAXuvawThT1McvEjrofAwrGi6", - "NodeID-GfDdBdRqzEKK55gCKqThE2LVxLdLhJY3A", - "NodeID-Gfeb3fWPCSpA4g9edG68NS5aJcYpXn6T3", - "NodeID-Gg8SEQhx4vU2KWzQS8ESCrSpcjzEqQ7kY", - "NodeID-GhG3ac1x2g1Fc4xPWXxXRoTLmMuT2asMV", - "NodeID-GhUSE8wcdouEgd3xeCvmYhmevkdNetfXk", - "NodeID-GiEUKDy7YfYRdxD5rA7t6CgEQxyrWP9sj", - "NodeID-GjYkDpBkCueF4vTkZVdtq3yFiMJha2XpF", - "NodeID-GjjemGsR2kXtPLSwv4oNV3JFt579oJUnn", - "NodeID-GkiJ8CRTibePNf3Y2F7LbGTinHm71HvnF", - "NodeID-Gmitibwg27b6WqHLjqmGiXZAh1kmZVq5P", - "NodeID-GmzoRvWfUdTTUZBmWFM8rswgmwMKkcDAB", - "NodeID-Gn7jLTVPuvdrx6mF5hxSbazRoKPWsM14s", - "NodeID-GnKLq2ipT4D2CMcrrGYndSCuQL58yhCR7", - "NodeID-GpDhyVHYVaL8qXFB2a1QPBsXyUMZjiXLF", - "NodeID-GpEnAaYG182MkURWh8KY4wL5KgWB7cBw8", - "NodeID-Gq6cTyqtHRGHSHELPNdwXCjQJH6vwUkBc", - "NodeID-GqRuMoELZus5EYMwBpiBVtWFDnvLmaJj7", - "NodeID-Gr9xzzL6emX5jWv1LoMKLpCebYR2V2nYs", - "NodeID-GrL4JXttpkikBorzFchuaGhnDTWc8nmEb", - "NodeID-GrkiQsGvbv9PSqJf9r3eE79fUgbZqydmK", - "NodeID-Gs4BSxTpRPxx1ioRz18VUB3kEYVBsDV5T", - "NodeID-GsQoMs5GAL8inkh88XPVJWKMwmJqm5T8N", - "NodeID-GuTDsR1tBFgQUbKqCf7J29yBo8ofudHEZ", - "NodeID-GuWMRuFkQPvPjdnuegSQYDmTMbj3UtPBm", - "NodeID-GujHWE263qNN3MjEYhEeAQdPpQdhHquLJ", - "NodeID-GvEoakPRjaB9jTKup6nAMpFSF3HiEeocP", - "NodeID-GvQdXQD6qFzfAYBvnvxiep7WaXVj2FSnJ", - "NodeID-GwcsDtmQrD8thUHiQWgrpRvhuMjxTqZP6", - "NodeID-GwfPzhzby4Ur8mgdqPDjR3jSTevtmfmY", - "NodeID-Gx4oY9nZmAzJrHUfobrmuK9LrJhwejykC", - "NodeID-GxUaibkyR88sErviW2WK3ukDJsT3DFpoU", - "NodeID-GzSFF2tfNMc7YdJzGeNeNxfSWjDvENJUt", - "NodeID-GzhNocnYWSCziBTP5Jj4xAKn29xDKW9Yr", - "NodeID-H1R3mBHFDeBoQzVYyHzX6RGnVV4nMTrWZ", - "NodeID-H1YSzbspeyANTzErprmBQgV2Crq5hXSW8", - "NodeID-H4mD37NM384RtLGjz5aERQoNCrtGEjgK4", - "NodeID-H94Q5zdkBByZVWvqrB5ByiX4dZdG1J45y", - "NodeID-HCw7S2TVbFPDWNBo1GnFWqJ47f9rDJtt1", - "NodeID-HDXjAjk4rG42HXey7gzQPx6dMBfpWeh5k", - "NodeID-HDmmLUSLtok2sGQEruUsYSMjBeQbUrwpH", - "NodeID-HFFiNVtYmv2YF2WHCZWHSCigo25RxgnFz", - "NodeID-HHV1onrMrN68JdRoKfQGeZphebgRrcADT", - "NodeID-HKskHZG5zu629RsEkScAaGrpfGQABqep7", - "NodeID-HM1vYJWnjWhJkJi8dErcu4p5UDxwUKbp9", - "NodeID-HMFqHmnsaeBGdeg83uXsraRJSH67DNsi6", - "NodeID-HRZAiPM3BaZJpAq9jy3UME2EGsrv1ZMaa", - "NodeID-HRmKWRK8HjqqTKWvYMBNv9hcddSYrhqnF", - "NodeID-HS1PKAMjZczSb5ZQRastn1WG6eJeNmahd", - "NodeID-HTG7W4VHoGJBUTip1gKXzXGtEBhiW1DXT", - "NodeID-HWwYYkiTKnXgYycNN5gXQfxhhA8TZdBvs", - "NodeID-HX7H9nBZX3nZRvLVUxCDBesVX6n8Uv4a", - "NodeID-HYwzPrs3tDR6yyMtKZo22fq8grJsP1DVF", - "NodeID-HZnBEWRUGocZ4HYX8EuMP2YEY94NtySWR", - "NodeID-Ha5u99aoKUdNdTdomp8bQcWHUw8PSF7em", - "NodeID-HaxdTdeEr1sWMRZvXwRN2iotd6RYd9XYM", - "NodeID-Hbf2ZY1Zs1s8KMp3rA1zK36N7zt5fSLkz", - "NodeID-HbmSiec8zTKiPWxaBwStg58a3N5KePhC9", - "NodeID-Hby7B4s5wb697sM4XFN5VusKW7eNyDMg6", - "NodeID-Hcq3gpdMqAEiVwq19E5DZhsjggbkxFx2L", - "NodeID-HdByRj5WVuR7REF2eJDndNyHA94hYhjMp", - "NodeID-HdG8EdGWAy8LR8YPA8hndoa1uwwgGv1si", - "NodeID-Hfa96c7a4xF9vYHuMh3cRsKUHa6YkDsYN", - "NodeID-Hgs8rDmSTASnKigsVfz7k3yZ3DgXP5s1j", - "NodeID-HhEvRMAeXAuXqULRysWKNLK2XZKzYwCnK", - "NodeID-Hhkq3c3UzzX3UpwC2kq9TcbJdguht164A", - "NodeID-HiFv1DpKXkAAfJ1NHWVqQoojjznibZXHP", - "NodeID-HkE9eyj5U8saYexeGWuPcQQbiu5MyRHHa", - "NodeID-HkEQ2sJogxEps4tmqFRDuVG9hyfxe8vMg", - "NodeID-HkpgaE4YB9Z7KmueQ2mz2cZFyfttvo6GP", - "NodeID-Hn7YWxiVC9JufWW5n8u1mvaYgNgqWG8VT", - "NodeID-HnCFvKLXEVsT1fJtMxCnkNj5fs9ExEugv", - "NodeID-HoC4UxP4UuJyda7MZs5jUkZRk8Rfj3pzD", - "NodeID-Hp82btBefk1ffBD7d1qtoBL3DuuNUv6qa", - "NodeID-HpMSfYT2ox1vkr1hFNMwmdWuq8QWhvH2u", - "NodeID-Hq2aEQ2RYhEo7BkVR83c78n6wbVLPrbqJ", - "NodeID-Hq5vdoGnZLMfasw4ykMzdM6PhUFDmp7FL", - "NodeID-HqPSHk6fxtJW1EsF9Y8RPH7KvPvdRpnzy", - "NodeID-Hr78Fy8uDYiRYocRYHXp4eLCYeb8x5UuM", - "NodeID-HrGKtuSRaRj9b4CNy2JeLfv1WAULmhwtF", - "NodeID-HrPfqGPogaKpTTcBhNBhmYfLRHZhiMWyR", - "NodeID-HsBEx3L71EHWSXaE6gvk2VsNntFEZsxqc", - "NodeID-HsSzvb9mMLFcidMWoQYXwHrnG2gZKQtPC", - "NodeID-HuPCfRaLN2cXoXDYyi8GYvjATLDmNJMHs", - "NodeID-HvmgHvMoe15ks8rbGXHyKHvJWDyN5yAGU", - "NodeID-HvxZoKdC58RkD4ZVTYwjVZ3TsiQoTESEP", - "NodeID-Hw7wL2of6tnqntucHPpca6xnnTYZCvBRL", - "NodeID-HwD5fu2NCooHXCPc2GMuNHrhfsThpsQYY", - "NodeID-HwSpUzHSq3ZQC5H6sL9xyze8r9APmFunH", - "NodeID-HwTU12fiGyZoyqaShTAFgTadY2w4DnazT", - "NodeID-Hxx8vTs8kH3stQWgPw1XdHKqpbuD2nMRi", - "NodeID-Hy2aSw3vVNwwQhKas9ETUxtfZgcefsPZD", - "NodeID-HysvJteG6zyScbEu5WKiqAetFXHNrnJHA", - "NodeID-HzSHrBKrycaSu3FMCLwd4WfPrQF2n61tG", - "NodeID-Hzfy8c2s9PyC7CPiUB1PmPckWYs7nj9Tm", - "NodeID-Hzwoqn1Vmj46T1HZzEUNG9kb633SLLHxZ", - "NodeID-J1CD2Nw1eX7iNUVw3iXjFJkUgrSm9qbm6", - "NodeID-J2RTGUXRNDSx2kBU8w7Am6Y7k3LABR5iU", - "NodeID-J7GwUKfHXhxTqgFbuQd4us6yKYdwahHHx", - "NodeID-J7PV3mKZgSJRDy3atopJhh15Y1TqYsySk", - "NodeID-J7PjfVJgpLL3mBMUwpicPqiqDFAmNWhKA", - "NodeID-J7gmHAAEPkSPbNeurMqhg6bknPXWgJgS2", - "NodeID-J7n7bUvog8Zdgj4bCNxRzjzrSKAirk7vi", - "NodeID-J7vWeKgzhtKNy14NLT82Vkz5N6L9sqB38", - "NodeID-JAkZxmCTCkBmscBpSisz5xPFDWcrBbkUC", - "NodeID-JAqrskRRwjmmU8fRp6RAf5wDoEtjXFyXu", - "NodeID-JCT5WWZVaKqcMNDXuuYm3Gpgah9TpKevV", - "NodeID-JDH5gzcB2DTfbEokaFU7EvpLN7E1RHzpH", - "NodeID-JDYxVGLrUb8SHwuu5jZBXNC9rqYWd29PG", - "NodeID-JE8niwmtgpDARKNUqTEdXPQY41uHtb1PN", - "NodeID-JFMBphfETbxfarEkQBHw1RSpfoFhdhUSR", - "NodeID-JGVF16zbVcXqH8ysCQdK2ap38DfHk8ie3", - "NodeID-JH744d6NN5DbtYR3fwuonjNGqUNwhYG5V", - "NodeID-JKCgdbWtCa8BreNP3xftfUuoWGXoy8hWX", - "NodeID-JKxZwnEvK2MAsL9SQ46fyCnTo1ZDkz22D", - "NodeID-JPSnjdvcPjD2NQNaTgC8YP6dhcGeKhse8", - "NodeID-JPvThCax26E5wEh4HSpjhfbfGn8LnvGx8", - "NodeID-JQb8aC4ny7Np8CVAasacpby9moWWzZXzT", - "NodeID-JR96tvzbG8L6xdoGLUWUWhQiGkCfNFP7z", - "NodeID-JR9oQgVHfNBybNVMm64AB2AGvHFCfaaxA", - "NodeID-JRCLnbo62xRaNLhNeNd3HzSHK4dW5iMx4", - "NodeID-JReo9xxdEAX82pAt3berdoi59Pn9km8nV", - "NodeID-JSKsSxV74dyp94CvBKqEKUcEEKBXyNbge", - "NodeID-JUncQvtGY9EVfsfHNHrdsiv4kRfAQSsvu", - "NodeID-JVRaZNCXjBjKqsmrd8grSR9LjFDr1zcgo", - "NodeID-JWBfuYPeFXRkuL1AeW6p2fquqoQTVJsV2", - "NodeID-JWwGze2HXQq7THFQj5zWRmBa5XaMj55jZ", - "NodeID-JYoS8akGmcoeLq4kxpxfsPJxwi3UWeXu2", - "NodeID-JZg54UPtzhHhXoVkX4r6WSTc74cAgdFjY", - "NodeID-JZoTeECdroSJ8sDK3nwpeBz2cYCEPPjiu", - "NodeID-JaS7Df16bwZUSL87wersMaXez7836EH2X", - "NodeID-JbXcSSwYvmnwD85nw8Yro79xaNuAJKxqp", - "NodeID-JbsnKEwxa9J6arKtZ52j4obF7FwvH634k", - "NodeID-JbyG4cewqSwjatqGtg7mDYbcvb299Cb8Z", - "NodeID-JcVg17s5KwKNv2yJtYfBjEFfB6GdHDmXN", - "NodeID-Je9mYMihjzv2oDF3ebvzDKs96zfaXDLHF", - "NodeID-JfXzxLA38XSz8EfYiWDUvsz6Tu8xwhdkF", - "NodeID-Jfx9FcVMQuy1FXGd53EuigXnCEgRQUUMg", - "NodeID-JgEayrUnvk1tvMFS5Qvr6LPNSE9wNYNik", - "NodeID-JgdYonZgwW2LRYGMwcDcHywQ4GmvjJoe2", - "NodeID-JgfyD94R76Wj1KBXWkGpnsSAXLM6f6dnN", - "NodeID-JkjTJNKyJwjEfxdfgQhvrUuf9x3ovpQBs", - "NodeID-Jmvu5u8svgTa716m6xBEcrB6wweP9tX5h", - "NodeID-JnREhSP5nvBcrCY1L3it6odDaHKZDryA6", - "NodeID-Jp4dLMTHd6huttS1jZhqNnBN9ZMNmTmWC", - "NodeID-Jpad4xARtJKgtzo199VoEaGbmYdBYbN39", - "NodeID-JqHkFFzz1tYoGHzPuTsueqF1yKifPiBEG", - "NodeID-JqXD8Tsj1nKXCBEp65ESmFhBrEhPL4WCs", - "NodeID-Jr2wjVqKeLpnyK23Y4EgDpCBf1HJ8XpJg", - "NodeID-JrHvS97Avz8uqX3E1RgG6mCSaiedjWf5E", - "NodeID-JwiikR8FhmnYxxGjywAZeJMFjxfpfD3L3", - "NodeID-JxJxzCNp5c2p447FF24jEDPdHkbB2mhJY", - "NodeID-JxxUAnbxUYQXzTQ8eNeE4jWQt9fTzWd8o", - "NodeID-JyCGTjJaPELmLZdtn5J1HwKHZzki6Ae9W", - "NodeID-JyomXASU2NoPhoGGzQtiVKUAHFpm3NeU7", - "NodeID-Jz2nuAFAfyvgni96rviZWsXxyYYBgSmXf", - "NodeID-Jz9EUhGBC19bzUE7kurEPyoKTRjVMgi3v", - "NodeID-K1E6w1DSaHzZky2aUM4qyQfPYMxF6Mixi", - "NodeID-K2fyNZcrWA4DBUNyFme4pNshAgSw2YSSL", - "NodeID-K3gyeR7GXuuf4coJXD4CxviWpRopysX4j", - "NodeID-K3unRwiJFD4p6dXDHJcdeQn6CaoFiqo2", - "NodeID-K3wvYyc46fLE7sSy3G81uta4wDKVkdKbZ", - "NodeID-K484QXg69NxbC2BUsB7Bgc511t22E6MAs", - "NodeID-K5J2aanpMN3PJLmYT7amdzSGygetejuPQ", - "NodeID-K5ecmXoCnxQPFTwrDxqL63kfdh8X4Z3oJ", - "NodeID-K6qqr2J2JcYZnSMRSqpbVv5ysZfnwMreQ", - "NodeID-K7ZsFPBybHPuD3YbzBpp1fe9QTj81WYSU", - "NodeID-K8EaudGE2PS93rgD6aayqS4dPRfrseWdi", - "NodeID-K8tzccU8StAHuSZfS5trxHKbvA17wixN2", - "NodeID-K8zr3RfHUQuupNJdPDKnbhFhwcD3TTbuD", - "NodeID-KALbip9YkRerN81YxU32ySYk5PbGrkysz", - "NodeID-KAjUQ36dNGmMpw35iavX7i8Cr5XGXwby7", - "NodeID-KB1wcvduXXXkTUw97gWchLs4oXbQK8Gwk", - "NodeID-KB5e5rq9ioGR5uicmKdmgjR5hU7iRUFTz", - "NodeID-KBcYcnQmw47qpb49rKtRr5tZgsxnsdkrZ", - "NodeID-KBvpDcnJ9ztfqA4jiAoMwARqfDaS91xqx", - "NodeID-KC9tasJTftYR2SYdNcPRF6XJGng6gBYcw", - "NodeID-KCQARVq1pjYw31EPSaW9571giKoFH498X", - "NodeID-KCX4L5dr83TbmBnE4UeFtzGeE2NSLskt8", - "NodeID-KDHVpdM7PeMtoVm2mmNNXjFfs93cABSut", - "NodeID-KFhoZ7aZMtAReBrb8KgcKG322q27akhN4", - "NodeID-KGYVGbz1pbyuJpujtJAkXhSY3AtLqBG2Z", - "NodeID-KH8r5RoMBBpy4XHHb9DMrbMLc2a1WJKWC", - "NodeID-KH9WnxfcrJLod4JWXHxESehVTAqE5DoLy", - "NodeID-KHRscCPBynyUHXSz4nXrxmFmoMgUPZBTn", - "NodeID-KHaBbtVbSMHmkqs5SKsdCPCgRbouNcwy1", - "NodeID-KHqznMCanU1tA9DcNLBwJQ7zUkRHC9yDW", - "NodeID-KJLkmhbvSYUqdMybmRScnyo7aDY6X2mYa", - "NodeID-KJfoYJrDRXdmLaaaaRMjNbNKAwqSj3pWT", - "NodeID-KK6ifknXca7VGbqB3d5ccUzKta1zJiVM7", - "NodeID-KKz1wXitLQWsfKSSUPE5JL6Wxw35S2218", - "NodeID-KLPimX5rN51nsSg9UQQahoRvKapDLD1pc", - "NodeID-KLiUDfG672VocEHwbAwGxxFdCHovg1Zp5", - "NodeID-KLsfWtM1cJLWNG21LdwPxaLk83pZo99oV", - "NodeID-KNLkh3KVKFFhBWujmcZ5P3p2fJc3BbdNA", - "NodeID-KNPCT1vLFcbVsFvLzgQqrbCS2kvEyZKBz", - "NodeID-KNm1ZqZXdAMJxggBGJkSs7A4tSwYLAjEb", - "NodeID-KQfghSuT1CskYLvgrQAt6oxUQU7ask2QS", - "NodeID-KQfmZVTmDMvuSEW2kts1rmVNmspyzUwVq", - "NodeID-KRhtytNVPjiSeZMJrqqE1vdHTCoMTHCer", - "NodeID-KU58LYgLuboacvuaNQ1T3VZMSdcTxzFfH", - "NodeID-KUgJ4Tiwfx9di8h6oPCkTEcrBBDiDq4hg", - "NodeID-KVB8F5Gy8adXA2zCg3i3m3qJ23NoCDDiA", - "NodeID-KVF3A8uB916AuexeZWS6eeeMdK2ep2vi2", - "NodeID-KXKwcGbqgdKb5ksmyB13p4oP1r8jmsPTW", - "NodeID-KXizASmXqFZsywyF2n41NEs5y6MBbJaa6", - "NodeID-KXuvoHe9KgzW6KfVNHXW4CUNunzWDDC4M", - "NodeID-KZLSjb8umvkj4nUVdARnY55NBKQcYfVV8", - "NodeID-KZiZi4sS44KZjmGtkeF6r1vs2MNN7p2kZ", - "NodeID-KZnxZckzgz9eQWzB3iuvM5GC2QdJLE5yv", - "NodeID-KbqaQBQVzCb44wByiZX4ZChg7CtmX1pVK", - "NodeID-KdEdrTAZpr9rdfqcpXjJxEbHC1oSWnvZP", - "NodeID-KdxMzeB5ubHBCbk8SqgesC4BAUx7fCT6q", - "NodeID-Keh97V9b6k4QvYt4JewbkabSmGoQ4sA3Q", - "NodeID-KfPXTUa3haWHCr1z91ULmY9Pit4VwUQ9C", - "NodeID-Kfqu9wo9FhcXG1jK9nVwbTrBV3d3kzmKR", - "NodeID-KhvVVixdSrBD6u9q25YYNbayxBnNsw9h", - "NodeID-Kk1UZNLJiyf57AL7vYPHntjPYLBdmTyu6", - "NodeID-KkCG4Sktn8zxkaFRV9bi5RaJxZNu1XyMq", - "NodeID-KkZX7xaSAUZ2sGBwpGWLSfLRER4pzR8Fs", - "NodeID-KqKMF5JYhxjkMVpYWQz8zTiv1N1qm2nSf", - "NodeID-KqmFvyCFfsaTcs2XDquCerCfWx3S6Zhj9", - "NodeID-KriCxu39kfZ99PrLwzX2pDUf2Uh8V796m", - "NodeID-KsSwTshRyF2xV75YDNXcEB5psLaBFHKfr", - "NodeID-KsUkk3D4hSKJGM1WBmeu1yj8Ab7h512X1", - "NodeID-KtJJDa5PVQYChXaNd1fKVmF5LSsBB8NHP", - "NodeID-KtJLagoYnWfw2oBnRki63NcguiGjuA2Cr", - "NodeID-KtKf9AuKyBvofsQE7Jn4eAzAndKHu1f4M", - "NodeID-KtSsjRubDzNuGP6FsXphHmtjWx62KCqvf", - "NodeID-KuGgrUTz4ki5oYkE91wHSdXgGL2Gb5fju", - "NodeID-KuStLqzCMZmLv3NigAtKPt2BEE12q71wQ", - "NodeID-KvBcQpCDXbb3w8x7ktMhsx6rCq8eSYcd3", - "NodeID-KvN79EtxbHdT86o7w9GBQEVeRWZ5woAJx", - "NodeID-KxLfzAQyjR1At4rPWmWYGueRUkxSfbVBF", - "NodeID-KzbTvxZgKCWpKcL62Y2HbB54uuDVNTCSo", - "NodeID-L1RcwxtQjb72GiCABuonnV3PWFZKPTV4P", - "NodeID-L1u2bQdMywnBLHVkrMiAoTSCYJTGSwE9k", - "NodeID-L2zTrwT5JitNvBTbC8L8N8i3ANQ1KyNd7", - "NodeID-L3JrbBLmihsqtaXAPXg7acKQbGa9tjhEc", - "NodeID-L3SyWrZH6uorqgExkkmGuXPx9neqELqXA", - "NodeID-L9D4FZhAGu8xGd6LL6Kn4ZqfpXuXSxTXJ", - "NodeID-L9HsJPQ9TF5aXjdx3KnQrh1eWaHJaNXNj", - "NodeID-LBA1YYYBbxwYMMAA9odGhR69d9SCbyq8v", - "NodeID-LCQBGoE9MtECsDjNLohwAP6L4rXDbSooL", - "NodeID-LCRMLuFKUYvcdAemtKiudy1XNM9oMN5Wv", - "NodeID-LCVUCE4bvtPopRuYvoWwTopRScmpLHTcg", - "NodeID-LCvxVSwts7BQAS5mVuXH8XYGuVJZSRtCn", - "NodeID-LDgwboNU4iVyy5MQgArg2rcDPssiAe6jT", - "NodeID-LDv41AQj1469CJsYDux9cLZepfaAWKzCr", - "NodeID-LF7ktpNDXo1fjHYN6MYHnitMPrHwN3pup", - "NodeID-LFNBojkAbg1az3ys8htBJHmyQ96hYhFzP", - "NodeID-LFg6CHJ6gQKNjcCMoz97BdDwqTH9JDUbG", - "NodeID-LGPn5jkr3MueEHLLt71wCRire43N5rp5u", - "NodeID-LGrCunBRJPWSqZLEw2QTHruuQtZai5P64", - "NodeID-LJBZ5j8beyjdcnVdNk5fwtThNn4LokYpV", - "NodeID-LKbxWKUAE7s5dtGWhm4Cr8hsosDxLsNzu", - "NodeID-LL3tKdbQ9qCDRMm4cif2pGsxGDXsNNzBp", - "NodeID-LLVMxBRYjgvczhD9u9RJDSmZ48bbXdWx5", - "NodeID-LN7tsaTsJaPDTJHjUPUX4ePk2HFBWZVh9", - "NodeID-LP9FxV6iBCayBiupHa4QiPxtqDWNoBoVx", - "NodeID-LPf42gVqz97N6bogZGXJNTWhgBABEe4qE", - "NodeID-LQP4aci528q8z4KMe8Ug3Gh1aHj4yojPX", - "NodeID-LQhwkBnuj2vjE786WcgsGneFVWcjiH6KA", - "NodeID-LRBqzoj2mB8eD4AHE2oCTBziNdssTfxuf", - "NodeID-LTM3DRAzRtWoWHVtB58s5CohXKYexiqVp", - "NodeID-LUFJGzAfqkmUaTDBVScjvdWtrruDkbFvr", - "NodeID-LUhB7mVaTMnkYLQsqf2RV2PUerJfsq2wW", - "NodeID-LUqMj414dv39Z5SNRXRb3bz9YhLJ2oWrS", - "NodeID-LVqsakFrQLyqNiChxcYqsBzKaKFRMiBsN", - "NodeID-LXCSfcmd7p7LroJzJtYoSAhbsawe47CNk", - "NodeID-LXVb4LZEU53c7XCk2v4bU2qacG7ux5dUB", - "NodeID-LXpULpbU1A4AobEzCSBy6wYLEbogwsMK1", - "NodeID-LYXB7GQj7vd4Ju3y6fMnX43wkAKJoEN9b", - "NodeID-LZMN1BDS3u6pe7T5Umjuhg1Z1MahXkK9C", - "NodeID-Lai2VTTYk897ae9uq6cGk9FbhKD1KHvFS", - "NodeID-Lb2X2hJpi6krux6aRpYSG7xcNvCXNg6M7", - "NodeID-LbAkNKxyv3kCs1C2ngkb91STbKpYHKs1q", - "NodeID-LcBGn2kscipZRgqhKqDCA5dq4WmHuuvai", - "NodeID-LcG4rUqdBPdrnBuNQ543C2pHVwfknyMJJ", - "NodeID-LcNseW1dfEL8FnXQB5HidFpzNu452vuGc", - "NodeID-Le5rVEBBPdgYEcEJpvYeKo36hRs75WE5S", - "NodeID-LeZUTECdpTLux94oAXKruxYgz5ppx7tfr", - "NodeID-LeesBWnR4x3zWaDmYTPQHmNhsMwm6KqWK", - "NodeID-Lf7b2RCtkb9mYi2Y5kZ3mJvJNc6MEjVnC", - "NodeID-Lga7mB6EfqgSJv4VTPaUwDjEtq6utiNQH", - "NodeID-Lgjda988AdujVYMYdwuEM4Tc8aopF6DRk", - "NodeID-LhLiUsJSSSpW8SrXCT319enhrYDybuG3H", - "NodeID-LhjS7bvahdBn2BomUUBHHFNbnzLRjri6D", - "NodeID-LhkzuEyUkHR9SW4cMxB55QQRbbGF83zzc", - "NodeID-LjxLvskdhxQ5jAhBKSzKrxU9NQD1DPuKR", - "NodeID-LkDLSLrAW1E7Sga1zng17L1AqrtkyWTGg", - "NodeID-LkTbz4orQbSz9hQsjyY743JUA2v1vPjAf", - "NodeID-LmZ33PJKkQqueDDzPnmVSyHMgFFmaADrb", - "NodeID-LmvNsnX956Es8bWDXqaVm4UTQ5wHC3uf7", - "NodeID-Ln3NxH8SbGS4CukCp9Hs3q7ijKfGqneXz", - "NodeID-LnR5bqTLkmeGjsDKiPdJNSbRPr4pjAURR", - "NodeID-LqLgyDEyMbd1uXfRa6kf8EPjnRhpF4KCF", - "NodeID-LqqUzQs77BPhtbXR7jFBsaNRxdLdfLSnT", - "NodeID-Ltq93eHazD1AtdGNuWb739t4fyvnRLryC", - "NodeID-LvKMfPzfWT1VfAPLef6denZ8hTwSAFMGY", - "NodeID-LvWcDhi9d75T8dwerYcQRoVWD6yDtywFN", - "NodeID-LvpYyT4UY4UAgP4quynTFzffYmjoxqZtR", - "NodeID-LwiNyRJeqRfAGS5phAQvvKhX9xj8LbQ86", - "NodeID-LxrJtyQXpdweZH7LR3ujcEQZJ9VDTW3tC", - "NodeID-LydNf31SmNLztbKL7iNsHXPhnKxz7g3Cw", - "NodeID-LzEWm3dhVaGJeHA3ZzzjaRaAVWVeL4Bi3", - "NodeID-M17yakji8RzPBFJNPXnksjoeabg7BXUJH", - "NodeID-M1SrBrn1szYR6jQJkyrJzd6YXsbAeWSnj", - "NodeID-M1Zsz7o9AiDgUqA6KFE8hrCkvybN6EqcP", - "NodeID-M33qUGE35HbVRppTTMY1qyyfK5T52id2a", - "NodeID-M3VrNcHHd3LGpwm6U6Gw1vfuJHoJzfG7g", - "NodeID-M4AhBqhjwLxGixtjxaLvenUpTe8mxNfhg", - "NodeID-M4FXQatkpbrCWRwdf381tfifDzXz34XUS", - "NodeID-M4ojoWJoEmsVD3vf7KxZ2BnfR5Ue2wr41", - "NodeID-M4psvzu2dS7hQ8gHgCUzXfipVKuFEsoFU", - "NodeID-M51d2sDyE92NjgRaiTnSjSLaG3U9eJ3BD", - "NodeID-M5wUvCymq18DUFjXk9s2UCZmyWzgo9ZtJ", - "NodeID-M64wor3rGStFTBWuzvkGPYYsWUu2dX7S2", - "NodeID-M6tt22qVLnGoaYY4aVUXTpKCCCEiupNHA", - "NodeID-M77VJM2GfeAzueJ6DjumoM5enZma86Zop", - "NodeID-M7GC8ZPn3JACK7sxBXqzeoNW6Q2XZeCpM", - "NodeID-M96ypSznK7ECF4EGd5KfxcxCiboyAZnAQ", - "NodeID-M9LeDgEaTfEN1qnEtLw3CXBwjh2VcGbeG", - "NodeID-M9Q4Fc2StCtFCofjppsy6DC7JDGmtRfUA", - "NodeID-MAg11ijmoZunT94rEdvxhmQToJzgH4bYj", - "NodeID-MBuKQwYxNAttaiugN4eMt1aV7vhLUo7Qh", - "NodeID-MBucJmfSNuMy7CiXWb9Zzd1Gf1yCoKwGy", - "NodeID-MBy2Rde5LJyWunzffJ9FfBj3BVNg1haib", - "NodeID-MEnWKkj5iUC3Z2rNhKuDTm5EVDu2ZUZZo", - "NodeID-MFp5wwuKzSfCNESpdD3avbZBkZ3KMkEeK", - "NodeID-MGJcpxBEXDn2Yk94uTXQwxgmYtuX6Ky99", - "NodeID-MHBrAomZpJhaYjqWKWXSS3YusVo7afBn6", - "NodeID-MJvk5Su2t8dFhcGe6z58Fx8A2QAAZTMGd", - "NodeID-MK6HYMwXj3k3HZfzjdegdnd9p9LQ1dk8x", - "NodeID-MKfE4StupLg6ts5v7u6Drs7HhFf1rHjEj", - "NodeID-MLRgfkWbezKNtcH2ghSyE5J3C4Rcxg5Sy", - "NodeID-MLkE5eQrTGa4BoQSR9QLEZKQB9yPJEnuN", - "NodeID-MMemzZih83vtU6TRK5oiJt6bJpNSWm1uE", - "NodeID-MN3pkk9h9anNMuCpUuXPVxGKw1rUw177u", - "NodeID-MNm7zKhCHwqQ3a3oqqEqDSXM9uVFMcEA7", - "NodeID-MP8NsoqJxPMUfCbw1izND6n4i5pTJJkhS", - "NodeID-MPLzWkWAbT3937j7U1uWfxdTMg3iw3BqY", - "NodeID-MSbDAksgjGPoKE4azGEgvrDj1EK2GG8T7", - "NodeID-MSrtdRQ9bEWLhi5d8YLQtnB9E2biVkkrJ", - "NodeID-MTEbgxTNBdL6GWh8SdQMfMXvEU1jC9aws", - "NodeID-MTQbFuBcjcQ7TuVQjvoXC7hiWAWPkouzA", - "NodeID-MTdVMzfENtZAEGdji5EGgiLsLkG3hV9D3", - "NodeID-MTmtdGgEg6gSEVhG5ShyfReR8ubtcZhbb", - "NodeID-MV2a235PcwYscp7qq8N9M4pYQBqMnfZ6T", - "NodeID-MVRcFZmxaMJWedF4oVqsxT2YYkX3kSuGG", - "NodeID-MVUMPzSBAtrHwTD5SZSNPRVTLkYnDPDz4", - "NodeID-MVayMsZd2VrMvEwFMDreTrauJHGBZu3Xa", - "NodeID-MWqZRLNFJzDPKnEuUHJSpEg56ejrzY56V", - "NodeID-MWwstjwXDrzkd3Zqnfaoa9vWtCpb32Fhd", - "NodeID-MXNBsr8xSHE9CKfmyzvBYyEzxAbLuHTAn", - "NodeID-MXxYFnzdP24DpJmdtUKqzMEN7nh69aYqD", - "NodeID-MZV1PpqVuFPa56t7TmfA8VVdXxDSHnQW7", - "NodeID-MZxjrRvxrjvAdaz6pDS82v65xLwckmiti", - "NodeID-Ma3Ztm2A48bCVjfiSmoZS5MKNzKVTRN7j", - "NodeID-Mb528V8a2cdddEYWmxh7ThDGQoQWhMt73", - "NodeID-McTi7BY4csWEnBAb5B9Z2ojNSk21Nt4NK", - "NodeID-MdQZNCCZN5gTEMVaJkSekNYCZkvp5xp4L", - "NodeID-Mdpo4kYtg8eqn61AhjTrZ51exnHLJmcpA", - "NodeID-Mf3rZ5w3aEtM1bzRBwFqhZYZMwks6FYF5", - "NodeID-MfVDQRZ6jSUmke5aofBuNXruEQunxZ5F7", - "NodeID-MgLEPkYaWQD6XqbvRRMk6CfMWe3Zw3P7S", - "NodeID-MikkG849wcdpBdeUJ2HTV2gTEDfeXWseg", - "NodeID-Mm8qGQPb5tHF96ENH1MuYsYwhA5Nj2DHj", - "NodeID-MmTfUacXsPdKryR3WkVteMqoFvyxEdYf4", - "NodeID-Mn2isVXFR85bfjMHPM1DT8EY8wig7YhTW", - "NodeID-MnQoJXMCgPk3zxKQ7kkYdmoZwj2dcDcmb", - "NodeID-Moej2WBv9BCw1pnPGsm31GYvfyY5BHZCD", - "NodeID-Moz5Jcjj2JoDgay9ScwcRDQReSqX8sjyz", - "NodeID-Mq7hjS5ySKApHMKCGw16YFo1tW7xA5DXm", - "NodeID-Mrh4UKAifNZtd8RJXqokDzajQnAsZuw8Q", - "NodeID-Mss1z2VZYsNSa4LyqD99vXeNd8h3hUMDA", - "NodeID-MtJWp4WidtWe1jzPf5u8hFtxMy6TCmaRX", - "NodeID-MtiHM2m6jKECmfTDBcfCut99JHzFm91T5", - "NodeID-Mu35k31HAXFbEp1SqJr1uUrue9nwqVFe6", - "NodeID-MuEFvXvbZ964sk1rdQKWNtUc5PJAGkWeL", - "NodeID-MvfTRb81PAx9AHYxbz5xACaoG84PM7YQe", - "NodeID-MwZ3XEbAdDciHW65MpvfPjiyS9D68hiKz", - "NodeID-MyaTMxwSKbtrFRRypqr1nWKJ3EK6di3dF", - "NodeID-MyeSQZnEZDzTfFFQvxZ5qqfqVDwg15NPB", - "NodeID-N1aFXom4C5ALmH33bXHuRpPBo7Nwqeu8t", - "NodeID-N21EWyi4Y5D8MNapwZ5tXs9D5A3rrfPi1", - "NodeID-N2nTLuaVwKk8EF3NBsSygCVmpGHwNz2Nz", - "NodeID-N2t1CAS75972obgtRPHwVanMnRF1rRo1B", - "NodeID-N35BjCN6ARikprxERf4WiMeUnh2ZsfwJJ", - "NodeID-N3WnyXmV89jbtQgmjqpoxBxpi5Rah86az", - "NodeID-N3e9W3EngjabGnTZVqyZwunVcbCdrY5Qy", - "NodeID-N4eXezpVzti1ssWvyQKqkuGB15dJNJsp5", - "NodeID-N4r8sLfeDVa2c9eDFpE4wuxJccUku3LKu", - "NodeID-N4vaumNTt2kixxUTtWEBgy4vwsxnuahc2", - "NodeID-N5FWBAn5j1UVxb3nH45N9DyXEAaeZiU4q", - "NodeID-N6c8ZxrQwMWWMGn3GVbZvW3GwC6PyWYMz", - "NodeID-N6z9WSBMoSxLSRtdPDz8jZvasAskYcCrd", - "NodeID-N7FjoUy3LrDi1kSYeaBwZjja6H2Y2NLsN", - "NodeID-N7WPJ9DXvEx8xLJdtDswNh1JdNmCKejSq", - "NodeID-N7iZFQdtUfPRcWGs8DB3JQRZt3Pq33eoZ", - "NodeID-N8MfE7gFMQUdH3wirj6HXkYZeeKd13xAx", - "NodeID-N8tijV4qwWMep4STmLzWJEkqbg6bSdCmn", - "NodeID-N95GoeyiprvxNj6E3G8QvYg3gpQ7x8NKE", - "NodeID-N9S6JJT2VKRZ48vA5vtWgboDnfzXXycQn", - "NodeID-N9c2YTRzGpRNp2J6qyPEEiAvyrViL4cGH", - "NodeID-N9qur4q5HCDb7xK6b89peZ5dKJxEWPdFm", - "NodeID-NAFCCsFtU8WXbgpgbciz6zUzwnRZAE99L", - "NodeID-NBjvikZcadcyCJ2hEJsUn9EcCjys5hav9", - "NodeID-NCVrEpmYjJBHqj9vx9r5usFiMd1PooCfZ", - "NodeID-NDMPc8h9L6keJw8F82NBobc874zZ6bDa6", - "NodeID-NEeK7hrVjQUHCwFQVMTmUaVDr33EH6WAw", - "NodeID-NGspMWkA7FgT6DnDghg4B95pQ468j7DK8", - "NodeID-NGxhFFwufwUSXGHjxdCUZW1hNpodfTrmj", - "NodeID-NHBv1LqcCdrcwatzQ9pGbGXPZQTi462Ur", - "NodeID-NHEESrJJNnyCPn5c5Uyp9EZYHCCkZwzuW", - "NodeID-NJZWC8HxGtLkxjQk5F9KSG44WC3gCm8a9", - "NodeID-NJaSwZPtuiN9TxaFLVF2sk3eNNHGm2UC9", - "NodeID-NKStfwoiZwBnZEFka1rqT54AiZ4CN3ksi", - "NodeID-NLBgQfsmCGFzXDehvwvmzjyfmkWQndx9L", - "NodeID-NMfBW4PDVkVZhJzJa6SiCDZ4M7wAkXbAc", - "NodeID-NN5j35c8DsuMydM5icoxhKePqc7AjwH1K", - "NodeID-NN6iut3SAWZqM56kbg8EhtpTU2NkMJgWV", - "NodeID-NNWrYMQgNFRNbvwAUA8grXiAVVE9VEyV6", - "NodeID-NNrbnhLBjgzBvhi3JXK48ckVFcg6FXVnn", - "NodeID-NNyxDSovcVYmXHacSM8aK2pg67oPjkRrE", - "NodeID-NPexpo2AXQ7RZC3wCKugj9q4y599pSfrb", - "NodeID-NSAi8z5XtoagdADeMNAPuWxfZpzUxacYB", - "NodeID-NSHmxWXYXAvHLdHqNyKZjP8MgSSu1dNnW", - "NodeID-NST51yBNtgVkXWuofyacbR1MbqYJEYdor", - "NodeID-NSUM9tzmeZ1DujarhTwjXAcnCeAH273v3", - "NodeID-NSngpSyxjXz3ErfjsFoc6CpfVPLxApJen", - "NodeID-NTTNYBYdkf3n5U4zrZknt1nst9rHzpuCj", - "NodeID-NTvJb2gZdvYU2kaMUrMbtu79KUMgyJNPW", - "NodeID-NUur4HBKXj8GS5TX11jZhtPHLH6zMa6L5", - "NodeID-NVSSRYMjjYyMkUpt7AHXWnKNTTJCd8UbS", - "NodeID-NVkHd9WCbVAr79r3gtA7AmKBkVkNL9EXb", - "NodeID-NWwQRYczsB8gf2tiiLLrk1foSgNUyrFLe", - "NodeID-NYjgvA2mJy4kTCQeEHnSuycnu5Kgo9gEq", - "NodeID-NZEnXQpa55wAhwpcUZFgSAREXW1FLdkzQ", - "NodeID-NZGsXrgoEuExZdJn8WxmyrLt4Cxb7LFyD", - "NodeID-NaGEfmLttvK5r93aqaoxLKoADVcs2HASy", - "NodeID-NcPHhZ4wgGywviLVxEQ6s2q5NZm6Wgrqb", - "NodeID-NcSLm9skkUrfA9mKGjdtmT163iDjqAw6H", - "NodeID-NcZtrWEjPY7XDT5PHgZbwXLCW3LGBjxui", - "NodeID-NdpTU44ZgiACprPmr9evdh4NS6Knz1PfR", - "NodeID-NfgHajZM47C3CaAXFa1B2YrwZmc4EdSgk", - "NodeID-Nfz4ZGQ8ZPvNQ3yHoRNMT7aTCiFYjMnSA", - "NodeID-NgkksDCWH73BnfgN2ALUBykc2kftsquff", - "NodeID-NhL9H8VSfhrktdjmQQ3P47wYXzRfQwBiy", - "NodeID-NiW2qTm2fSKHGuMqeo1twtM8j7LoAGzHR", - "NodeID-NkYLNRp4S6exbWamVvMzUUpXvHeVEzLR6", - "NodeID-Nom39tjDi1Vf51VxuaZvJiDeQHwbyg6MU", - "NodeID-NovHTxGVasNU2y33YPwmQ39DbYDkXiEfe", - "NodeID-Nr584bLpGgbCUbZFSBaBz3Xum5wpca9Ym", - "NodeID-NrVSfY4zCbPjYTe4XPjmQB7qLJhYW3V6h", - "NodeID-Nrs246dXUZmALw7a2HRTANx6U1LeawsKq", - "NodeID-NsVdtyjprgWXLsvmuWvYe749tx3tdbY55", - "NodeID-Nsdn6eemD7KUpKEaGYjYFuJjxC36c3qXC", - "NodeID-NtDMBzQGPnp7suCbyCMcdE2CFU4JXcvwX", - "NodeID-NtX4Q64xT4Yad8wdhQ4erSG6mi3DPUwzX", - "NodeID-NtgR3kDx7Mm2szCiDTs3rtWaqUDWRMDyY", - "NodeID-NuJhcXgmQMbFJwm9yTTmdvGN86qygnXwP", - "NodeID-NuXW8S95Hvv2eq6JoY1qCDmK1h8yuAAt3", - "NodeID-NudTZgq7DKGQsY1Gkt1v3ZG7pgaWbbBuj", - "NodeID-NvsbNmirter6SLhta1kkvoEjcgvaHxEt9", - "NodeID-Nwr26Q5CPcRfSHQKgQ5y3ayVPgjziWkkT", - "NodeID-NxgyyDw6YGHprTJjZv7qh9X1yoj3yZN7u", - "NodeID-Nz93c8UB78eEVVtfxpcecxHmiy2gZ4iAi", - "NodeID-NzQnRDwTYZJPwYMcDkyNGCnhH7S1HQZgy", - "NodeID-Nza7rHanhSFgJ6m9D8fFWgrx7fqbxp7q9", - "NodeID-NzaVh4SaZh7zaT5uFmHyAT99zRbQhzvvd", - "NodeID-P2EM7MDMhKVo4LLgSqtxYSyc39wfPe2TL", - "NodeID-P2Jp7sd5mv4ZGBqThYfjHkz1EyJUXoMcE", - "NodeID-P2xEUig1YeBTwrUF3Xj52pxaNH6gSHjsb", - "NodeID-P3EhUmKXJ5F2BiZw1TwNftAC1y4XyGufz", - "NodeID-P3budG9yRu9ph2UedCGdf3KaLQKQLehy2", - "NodeID-P4tSY1ZLb4q2xTdYGXCkgwXWeQN7mUUWq", - "NodeID-P5hTsAQgfSLJumMDVDK2773U4gjyPtYnr", - "NodeID-P5q5numCvCNo6GmD8vhDqq1tU25Yok4Ky", - "NodeID-P6M41urqadxF7NBcxEHNFxKkGPkHjC95v", - "NodeID-P9FGdfCp7sHRcUwHERp2hzo98ifUaCZ5x", - "NodeID-P9kf9VSRrgD8B1MQKMsjravHvMHVxvoaZ", - "NodeID-PDZYy4rfhPZWskL32EMt45zuLD2rWjDLs", - "NodeID-PERaNX2PDtAr8zkXgbZvwXHfjq4VKtbew", - "NodeID-PF9fY3h6ZMMqPmTZZUwc7wyLnZ1rSoz5u", - "NodeID-PGonFPDqHgyAWCFaoLxQvAQEz6uJYzZpW", - "NodeID-PH5DLzGXEhe6RMHgod3CH9T3s3WVfQm8Z", - "NodeID-PJA7yH2ZVtccSj4RrB94a8MtHboS9xozZ", - "NodeID-PKiUH3xw8SmVNVJsAqFV1mXwDXToFVATi", - "NodeID-PL7xq98yQ9kTYyGDvVQg3efowKeHug3HN", - "NodeID-PLs2JZXeTtfZvYx4DJqkA3sKXz8ynvKLM", - "NodeID-PPH8k8RGmrTuc6Dun92atkbDkgs3sj6ws", - "NodeID-PPYetyVA4dk3bYdNtvTsy5Cqg4L31EUze", - "NodeID-PPoo9VFqdSWsrZZHrnrBBfi3uE2cw9JgW", - "NodeID-PRxbx3LZSnwvLqFa5audJBsSqAJe9rmsP", - "NodeID-PT45awwLjTTiEqvFufS4nCkVN7wtEsDmf", - "NodeID-PUw5p37RZKVjpK8kxBa12TBtZZdhykGUP", - "NodeID-PVm9UudEC7N6HJ3jus5KJ1Rufck88g1Dt", - "NodeID-PY3QRSGTdYzmPTQEwrH2AmYUMBnrcge9Y", - "NodeID-PY5kT7pHUEZPmh2QK5k6w3H6pKhFGUfq1", - "NodeID-PYFkkThWT79Sc7QqHijAc1yZjSqfXu6Eb", - "NodeID-PYJbbkTHqyuowa3EKkkxeYxRcXUhxehkF", - "NodeID-PYecKsWbPTayLsHDdopKjB1Mw5NP3kDUJ", - "NodeID-PYmftFnrKf6y9k6kXXuB5GWwjLtkP7sLB", - "NodeID-PYwMEam56vM4Nix3AG1vufHZbMvdv8zwy", - "NodeID-PZ66baswBL8xsSHaFVG2Yx7qH8MkBfXSK", - "NodeID-PZvapthv5iRB7txuVNTrKCo2fWovBExLh", - "NodeID-PaSvEqWq5ZESHSuNGTZeQL6sybzsQzoZ5", - "NodeID-PcDGg5a4P3XK1E7PXS5YedYL7vi8vSXvB", - "NodeID-PcN5Zh5GNvUJnoiaqkvRvMYBo4oAMDvTs", - "NodeID-PczCXQXPxNgeKy3P4jtAt1ycvrjvghVw1", - "NodeID-Pd7Hexv94PQNVnEbYXWUttEAAybG34Yiy", - "NodeID-Pe1pUMoFAts11s2kA3F7EPmzLyZwj6Msv", - "NodeID-Pe5xmD9DhTrSCDykMqFdG8CazG3QyJxos", - "NodeID-PfY5X2GWsSaj8y6usEji4HZmokHHdWsqi", - "NodeID-Pfj9qXo6LGR3goGzcLSJsCZwYNFFndV75", - "NodeID-PhB7iV3nDxiotJnAMetF6puzg6fxTqZCP", - "NodeID-PhDmCZH4R8VFjVzQLRBquKMVss5sKukw3", - "NodeID-Phds7RN13xWBmpe9MTPhJde3hajVpUB38", - "NodeID-PmH5X1xavW8PjgvkW1u4K9qTHAbMx36hq", - "NodeID-PmJQ7UjZo5db9XL494EbbEufAbYxqWswU", - "NodeID-PnuVZDXvdSNRbC92ibq5w1FtPvbTFvwmM", - "NodeID-PqPwxtYAt6AmikigAwkRzTQCaeMqPvpff", - "NodeID-PtG5NyNK2mGku7fSkRDAUyaZwtj5hcbFV", - "NodeID-PuF1sG8hh4CLLznER6vf4d1o6bWZc5Vof", - "NodeID-PuYX3u6gfLje9bt6fCDFHkSwqaL8VSpv6", - "NodeID-Puv7ksUTmwsxqEx7XLikRicKtKss6QNNi", - "NodeID-Pv5X1dBk1wfZJwRqm8Aj9QecxvA87r31j", - "NodeID-PvssbRjYWsCmvck5umz9V2qMRXMHPpz9W", - "NodeID-PxXndSoasDvvx9ax2h9bWGb9iF3LcR11h", - "NodeID-PxmdCJV62VecySivang3vVymEBwjPQeTm", - "NodeID-PzEsAB7RCHTFwHszw3yfs99GshYm6Qs5b", - "NodeID-PzQafFPgbCLkvMgrP7nh7aCG1eKypdNi2", - "NodeID-Q2NiN9VSKEYK11GMMFZm1r9vYQ2D7srq1", - "NodeID-Q44XVjVEhgxacoq2ETj7yLBuUra9ru2BA", - "NodeID-Q4mUNVKvwEHF3tkxQcCYbrQA8XWdybLzv", - "NodeID-Q5rNbr5yFwotdbeRPGeTagHP1hbHYuaJg", - "NodeID-Q5xvrPQSjHhJX8eLKbBnZMWbS648NqnsZ", - "NodeID-Q6ZLZ1EifMyNd6evH83FJrVGyauaUSP9S", - "NodeID-QBowbP1jz8zA86CtSzRwsFsxr5q1rY6pB", - "NodeID-QCfTXZ1cdPt5XT1jiJfycHKTFo6Yg164L", - "NodeID-QCkFTaWJg5ixVhZoNbePxzs9HWrTutVy4", - "NodeID-QDLrtBngMA6mFveLNZTXxKQVEYx518fG8", - "NodeID-QDfLjUuR9D5a6G5ZAQdPPbggJxtLnbPj3", - "NodeID-QHX9w6oLs8zjHdBvbzx1ZadHvy9aUNLr5", - "NodeID-QHa12bzXnupukwvFdWkRrRzRkC1Cz9nXd", - "NodeID-QJMNxwTLjdg9C1vY2BKNtapWUuoeCgHFj", - "NodeID-QKGoUvqcgormCoMj6yPw9isY7DX9H4mdd", - "NodeID-QKdEYKG21HJ5DCQQaotjG4rJmcTgjno7f", - "NodeID-QKfhLAkwYPwAZNKTanfuNfmm7cYRTzfYo", - "NodeID-QKn4ujiEcP1n8iFbEJqNsKZUYbUG4fHAc", - "NodeID-QL7j3UxnxJz2HUn6jNdqH7gqcGX5XcPug", - "NodeID-QLC3sD3RU2SkeWhSrzM8tfb5QF3XYgDgr", - "NodeID-QmTPCR33deSWVwZ4Ri2jUw6cDAhoUwZP", - "NodeID-SWPRmNkYP7vP1y1EKnuH78QZNyJ2ZpZM", - "NodeID-TgaMGAEpkXKAisumnnmzzRzVkexbSkB7", - "NodeID-UC1qmKMoMcfShU6idcreEAsxSHs3BDBj", - "NodeID-V3fYZv2vHtLB5gQF548JRnSyk4tZfZ2o", - "NodeID-V5R4XjWDtjs8Zi2g3TRNzngnGJiXm2ic", - "NodeID-VEhPJXs67q8rs8hifAfBxYUgE1s8YKfz", - "NodeID-WAHX8MXekynX6xZSFiSewY9Qxnhq5HZh", - "NodeID-WRz6mTt6LCdSSvuHdqsrBYxi4hdfecTW", - "NodeID-XYAkZN1GfMwcYRRyGLiZsGV2thZbqDGT", - "NodeID-YdCKQdXecSPWqABWcRtPZvBaLd3MPPR8", - "NodeID-ZVLPagHUUrQ2vB7mjsWQ44wNGf5SVKKW", - "NodeID-ZwShn4JT1Bg91QphD3VBLryA88GFnAg5", - "NodeID-aFRSyUykQjScZiWASVqmdTGzBfV9KKj1", - "NodeID-bx2UN8z5nfLMTFphQqnYeyngQnccL6tN", - "NodeID-cme6KToKFLCwqj27F7a7Ys9iC4cLrqMz", - "NodeID-duaNgYtghtCRzj2rkiRDDs51BPX8CCjn", - "NodeID-fr4FFtJ5PF5UZpyA3RyoxhNks6Yfhu7u", - "NodeID-i9uQjR8P5Wzd1wTLeALkZ2oXqKjMKQbs", - "NodeID-iTKqsK6Qhjj9RT2ZA9PVAC96FTiDvK7k", - "NodeID-jB3tEp5oBcHYRLLmNaMgP4v59dyr1a9E", - "NodeID-jjTi6fViUUkPwZQbE9N8Bm7AThmVyjGW", - "NodeID-jz1mR5zZukizoZEZ1Wa17h18Kou1Rfzt", - "NodeID-kCLme7NNnAVrbQGZadzgWwtoPJpkQcJR", - "NodeID-kXTWkRtur8X9vchkcXAiG6qD8PDogo2N", - "NodeID-kZNuQMHhydefgnwjYX1fhHMpRNAs9my1", - "NodeID-krdJFoXmC68zd4pSFCwMnCM4dhiR8gnq", - "NodeID-mEbcN58z2esHFnnXHeR3T2UTfsR5H6WJ", - "NodeID-mfUNFSM9ak3NuCvaiFCtcmEcHF9ptfrU", - "NodeID-mwty8tviuGBvDEG8e6vTQByDZN2MKnNo", - "NodeID-mzhghLeMzv8qrRrK76wABwrf3LrL6mP1", - "NodeID-nJm8Ltnf7MDCiuP3PzU4hv3RqXXKmeqd", - "NodeID-oZyu1tEJrBeFkquoqZ5rYpvsEAkfFiwD", - "NodeID-rKCpkJKNAZeE8sKEHduq8Co7GwrAdTJb", - "NodeID-rS4TWt8iuAbQTsg6ez6u5tXvUzicRzuq", - "NodeID-rU9hLEWJCxRksiPuEYm2qqof6uwWEDeo", - "NodeID-rroLHLixQkZMTsTnePdWhDrGpWenYX7t", - "NodeID-sAyLfHTC8ZQRn5HtfjNKxXDbnZTaJUqa", - "NodeID-tHkVEqdhWPdX2vJGbqDWebw2VPrho4Aq", - "NodeID-uhGb1JoQ5sv9oJaECWYN7H5PabwxehN2", - "NodeID-vV5S1LUtAxCWq9ASiDSjZpX88y2WcFGM", - "NodeID-vrzTEabKUgCBXYg3oHFwJFkR1Np6Avh5", - "NodeID-w6kJAMpdT4hB9jE4NnEfBm47PzD1UXfW", - "NodeID-xHLKdNkbh94JMSFp2vU7fbwEA712vub7", - "NodeID-xQU1Ntg4uYkkSgXivV2ELwr8s8FovRCS", - "NodeID-xVVbmFL3eww4dmBkgQ2akBxcnEy4VyLh", - "NodeID-z3Z8s8xoYQhN8A1fmNZcQx9CyXN6zxJz", - "NodeID-z3rX3CnWLi5KBXQ8nVB4W8NnLNdUBcPD", - "NodeID-zbFM8qH7MnQ8uo6rm4tZaq6vhbF4cpgt" - ] + "fuji": [ + "NodeID-11112jHXqNowaUzgEwjMAdiKRm57b5cM", + "NodeID-15uUYVJH5xM396PKH5d9GTjGErkciLdBx", + "NodeID-1REAt4C9SQUo17pseGmHL2oNUdpkBkrB", + "NodeID-22hnv3WsLkax27PmQdYJrVRDJVm17XCCX", + "NodeID-23GCcht221hDaKdtH8BhSLpUrugsfRAY6", + "NodeID-24WK7qiKXAumya1kKEktwj2ubBbRyq5UW", + "NodeID-24nupT8dLucgRn2HuYGzqUZEbkfKRaUnX", + "NodeID-26yNpVkHNGxboUshTXtFAy76yYLmWa7bU", + "NodeID-27n6vtWe35N6JmbpVQKfeVqy7KJ874tFU", + "NodeID-29tGiEe2rxuoHJgjEZ4sDytQAivwjJmaC", + "NodeID-2Bxm4MQUKqq7yMtHLWsfYpKqRAfSterR2", + "NodeID-2CDAbZAYzHv4imG3sC9hBx9WGMzJdAJeX", + "NodeID-2CVgPTjtmaxSSjKuZXUwrgG4cPapmEgmD", + "NodeID-2D9EnSs4qEtZVPB2kxUX2xEATUUgXX3Nh", + "NodeID-2GKxWMGx19NvTSorxibapih9DcuRx6WzV", + "NodeID-2GXYggxghp56hz5zkdSvtVXEQ3AZB1gGM", + "NodeID-2Gp8ZuzK92tZDzLknZxmsm48RvppFYSqc", + "NodeID-2JGdGihFqGFcKEZEUswXDSWwaBJcU797P", + "NodeID-2MrvT4zf7GNN32eeGizM34s6UaX9SuZsx", + "NodeID-2PPDjKZvz1RTRiKQaojA4vsrno6N8mWuh", + "NodeID-2PfNAhAG7nypsyDRHzPwZaZsDcj1jA6rU", + "NodeID-2Pvoq8Stniirtie17djAh3ys7rUxn21F5", + "NodeID-2Ty5YxnuVTUkPX8SPMcS1b1qfE3sMbcRV", + "NodeID-2bRcmz6BF39s7bMoG7wWPWST73LWcaAUp", + "NodeID-2cU7F76JcCHXcsY6L8pMeHQBxwXqMumNC", + "NodeID-2cu2JVaQDucg81tff1W4PBeZ5oMUG3vj6", + "NodeID-2ebMFnGycbMsnxJ3VV2WLhJSQPLQUSJgk", + "NodeID-2kwc3kKwtfgTQ7aPahndbHAer236maSBH", + "NodeID-2m38qc95mhHXtrhjyGbe7r2NhniqHHJRB", + "NodeID-2mMkmzYVHw4YWojaAuAHpNoEz3mqyEbBJ", + "NodeID-2n8rK9kL8N7y1P6hyKu5ZwrMFUX1NEXG8", + "NodeID-2pV9ukRgk7eBJR9Ab5DSZqU3uZSfA9TvM", + "NodeID-2vtBaWPqDCi1rzQWdmcSXG3R2hJbnpMvg", + "NodeID-2wejWSTCbLboLdsgu9YAUeT2h5bnpzcNc", + "NodeID-2ywA5crdZzPPV41rXRPkPktyRKHHSCdEZ", + "NodeID-31NFpxN7VniDZbDDNkvvZaFuuNhDJyYro", + "NodeID-33PdW8ge5VAHD98Bmxy6kYhm992Mhnu8x", + "NodeID-345wyACGatmkic8wWga8Tr4qxoeuoiZvQ", + "NodeID-34qTBTrvhsF3MQDuwdNUDHBvj982Wm6NV", + "NodeID-34sJYzSaqAD8GSoK1WVguqLgdg9uVotGH", + "NodeID-36e7GjwMCYr1d9tDUgUyz9swewgNhKArs", + "NodeID-36ktMvm5GFTkfTAd5pPw7zpAXZG174Fvo", + "NodeID-37fc7hgUGsXKxPx3rMYyBdHatNpKRb8z2", + "NodeID-3932bao9oUnjfwGwWgsBk96M8rBhgQdeG", + "NodeID-39V1962v35f5Rs1NsaCskg84uaMqyxeAs", + "NodeID-39w4saojjUihKVNHJiQuSwugYbiGraXGU", + "NodeID-3DgkJ24cK9scEWQnoa7BwgP6YpB9ibccJ", + "NodeID-3FQZUAfKMJVzV5opV1DC3EpEYiZ5aYJQm", + "NodeID-3FYxUrCrACjqdBYFc8SnTzJ7Xq9fY3i2G", + "NodeID-3FaY3uSPkatMS3HUWXDeq6WuYyFPrHoj1", + "NodeID-3HNtqQ9HQftuHD8gApoDTLMH78z33P4Ze", + "NodeID-3KSEXMHijPpZbUHHgpqubFvjA2N4GJ6MC", + "NodeID-3KixTZkLBUqrDDeaaEpXaTTiU4Qan9xdC", + "NodeID-3M7L6w9a1G7o6ywAuY47HTnuGaMPZKQWx", + "NodeID-3M8ZqnsX6DDFkxVUnBzcKgVxce8vFLf68", + "NodeID-3NghhwXzgEMZNnjpJGiYrrpfCMNYCtbsf", + "NodeID-3PjPmpuCghoVT7AJRb8qTjyZ6DtCPuURp", + "NodeID-3QKhsmp2cj4eJ1hYecqQ6UAPYGTfZhWfr", + "NodeID-3RGiNDT55RwAQARCjrKgFc1hjdjVVchDR", + "NodeID-3RaFvh85MNRXdUmsjMPjvfNHmdbrSn9kx", + "NodeID-3U18hPBaGyELh3ZFEBPsvidFv5gP2Pv38", + "NodeID-3UhYTVhNbwBBALPyvwhRiGmgJts3obFvr", + "NodeID-3VWnZNViBP2b56QBY7pNJSLzN2rkTyqnK", + "NodeID-3Z6K13A3BogE9oMPg81vWgfitgvN1kCRh", + "NodeID-3bqNW8gEe1uwQus6dr8uux2g227tnXB5A", + "NodeID-3d2VDPUTpXd97ukrx9Faepmb79wzFicQZ", + "NodeID-3dahoBAqDyB1vskabnMHPy47zg8gJ9tD4", + "NodeID-3hdUZJo43ZTmFe6KdYxaPS92tqbR9woqw", + "NodeID-3jFnB85bDiJ8f1G8EgptsZMENJfGCeBVD", + "NodeID-3jbJ1eh1i8iqQKsrMjcG5WzAmPhkFU1Ds", + "NodeID-3kuuAaJKZWFYp4dy8rcrBWVkV4LDb86hE", + "NodeID-3nhpqPqAz8og2A2DBeVjb4fmFK1d2rRvQ", + "NodeID-3oFxfDPzWo4YhvYzswCMzLrcJwx2UKkwV", + "NodeID-3ry1arUtntKBQ4shFYgF9VB6AbGRHnPwe", + "NodeID-3tJhpEC14rjctSoh7ZN6TXAijmrMvjRNf", + "NodeID-3uK65P4yQGns5wVB9Bv955dHP2rRiXzFF", + "NodeID-3uRhwbfSajPyvWGaNSJyjhDKGPACGqHz4", + "NodeID-3um9mPx53CkfV1KSDdYkdrv6tEVR2E8vg", + "NodeID-3uq87hQvpuXWoqpmPhLRWavFpqzGDZbn1", + "NodeID-3vtMDZ9Eqs3AzwNbqudMoxuUXyi97MKut", + "NodeID-41cr9VeX852rtHrELWnHthUV4Bbm75WBY", + "NodeID-468yx2KFJV9M7uNiTXJrbqyFGeQxgiBfh", + "NodeID-4B4rc5vdD1758JSBYL1xyvE5NHGzz6xzH", + "NodeID-4CWTbdvgXHY1CLXqQNAp22nJDo5nAmts6", + "NodeID-4DDjS32CM5oK7tbba8iNnXv7VWJsrynDu", + "NodeID-4H2NGT5zSc5Tt5KHTciLXVHW3CVofDmuG", + "NodeID-4JwxRwRY8LgeSdDLNargL9NBEBUuvTk9v", + "NodeID-4KKUrWvuKKEwNQWvZj7x6NDhUEan1m44C", + "NodeID-4KXitMCoE9p2BHA6VzXtaTxLoEjNDo2Pt", + "NodeID-4LJNqmxdSigcw9wnGcd8nRP7Z4XZrEMyt", + "NodeID-4QBwET5o8kUhvt9xArhir4d3R25CtmZho", + "NodeID-4RApHGzbpwtrUEbL9BpkV8AfdCzr1ciCj", + "NodeID-4SdtN4zCP8h3ZEymEfGxJRocAu5hrwphC", + "NodeID-4TJyt2f7zGuusjc1yXcBJnkNvDMAJ9py4", + "NodeID-4WP36nX46eS27wcRsW1agg7bzpNDonEf6", + "NodeID-4ZrTre1sS8qxndZvsMNzBGm3MxxWBpbJb", + "NodeID-4aAK5LmtRsrAGnZgHTWXcK8EwrtxEk26Q", + "NodeID-4aQfCERvSk5sn9SJfzGZtb4ea6UQtxXNf", + "NodeID-4aa1L1AKqdG76yQ7Y3eGYV1wProfTVjc9", + "NodeID-4bPd6dgavJ9sggrbTMou3jkjcJ6Ng9L43", + "NodeID-4bo3ptnJcE25b9YSZvzUYxkXipqptKGer", + "NodeID-4dNvbt8gNJWXtTMA8BARk8haL8agc8emC", + "NodeID-4eruhJFiLfkgmeKrG9udZthPCvGpyyw9d", + "NodeID-4jkdfkuyACE6K5YV3YtbCieZazm6Gjjat", + "NodeID-4kMv27g3A6x2RMkiJjiK73zmAxvPDmbct", + "NodeID-4kSPhc76z8Nxfta8gjxHDCHcNx7TrNSLX", + "NodeID-4syxSZ2LPcCeE96VL1HsY3fx3AYnnGfsi", + "NodeID-4t94JpNNhRT9v6uoUWFY5G4jKmNqV6BQh", + "NodeID-4tsmKt9tHvMocmyHe9oKD1PkAa67iHn4k", + "NodeID-4wL6VGogpJKy7EB69BxaRi1R7sg4npMxV", + "NodeID-4wnwAREi6cY2vYccTktFC1gCEJfxwMJrU", + "NodeID-4xKQvNdSepnCAUZ5JMvqNxanaUQ4Qn22k", + "NodeID-4xpmwNTMoAxA4XGPyrBzas5Vnu1Beykmw", + "NodeID-4xyPSDPrx6wecMnPu754XG6hnb2HYCYLz", + "NodeID-52UrdjqkYxmkasCeLaH2jkHMXEYayFn61", + "NodeID-53BzXzD64f4CrJQZJmn5VWhwwys1cpzGU", + "NodeID-53QuyRVXP99F83s85cp7Fe8Aax8KAFQct", + "NodeID-54RagM4VF5VNeKWoVV5UNHJfM6ccHtBob", + "NodeID-54WkEbocc1ACvV6N6Qu4NVDGHGfpFhBzr", + "NodeID-59HRzrFCmhEmUJAncPdXZ5H1NrreBQR6e", + "NodeID-5KtwUENNLTnfjAeVWpED9jq2TeCPZjTxU", + "NodeID-5LtxGcaXocgCfx5qn2uMKiLnoJZi8Q11P", + "NodeID-5M11QQFMk3iqV8g6QoRiDNSDwR2XsQSe7", + "NodeID-5RHueEiTPCFb2T8YuDid94rJtr31UvnYW", + "NodeID-5T4381mMgVqnW1b6y9ddyHBfYAqaB8C8b", + "NodeID-5TcM4MkRoE7Vhnv9kcawSwpVSiTPDDBKw", + "NodeID-5UVT7fNKF22XkWXMxCDvGHZW2auLgxprr", + "NodeID-5Vd1XuN87ZgjBzpGL5NDhVPbmaqzd4YfU", + "NodeID-5WPHvkgxcwSE3XhuLf3rVNU3crqoF1BJ2", + "NodeID-5XgY2PdtB5DdELR3CzSt4U5gpC7XEUNVp", + "NodeID-5ZKjaekNVNoi6xaEEuKLQ6ZbYMQk4wA2u", + "NodeID-5aXqEaEkJH58WjMzuw6h8i7b16SNHq5uD", + "NodeID-5aqkYoNRpwJ3EhBvc8uF3626mzfiUsxdG", + "NodeID-5bGeKYsDjDfMwPAipVDPk5rYX5b8vc1aN", + "NodeID-5ewkSj3RxqMG7shRumy4USF5ibHMaFAJY", + "NodeID-5fvPxB3edzXX3Eb5x5r7tbknoxqKyELtf", + "NodeID-5ivzLGz96pAJWd3o83x4JWHTpWZoHJvc9", + "NodeID-5kGqjBKnQ9gEm6gBXieWvP9oGZoFXPA8e", + "NodeID-5naAivQLhjbpVw35YGaD4HJwXTwuDufXA", + "NodeID-5oRZWHEqipzXDnScB5UgPP5cUqfgPa9GR", + "NodeID-5q6drRMuNYp3hfZokxgB2m5NxBoFZXc6X", + "NodeID-5rLsXFYvpZqjWfXkPouCUAmXc3Xcvebvn", + "NodeID-5rZ6LbEm6o3baUxVyV4GV21sPD4QqjPk1", + "NodeID-5tqDUvtVzpChaPgXcrXjuRRS5EJU648en", + "NodeID-5vCs6XJWRNTLpAkQP2HK8fwprGb1v86Q9", + "NodeID-5ztQ9vcGysCVPY56bfht1GsxV6Xce6tJ2", + "NodeID-653BnnF1HfEQY9APtAu7V23FNEmRMBGDW", + "NodeID-678Z9gkWVfFoAAnRJBEtgSm6Th6TUhsMa", + "NodeID-67tGW3yXGqnDVnEwEAwVv84yZtm1AiZPA", + "NodeID-6DjE25mD9X5AXWf8xpfgJ5tK94SFq11Vw", + "NodeID-6DxE723urFNy3H7SyMMs76ZLRYx6bDJdz", + "NodeID-6FgfGS3McpD27X8hdC7ZgQVhs6DoKvBzq", + "NodeID-6Kgqv9SV42oRBk2KNSRwFfJwsLBia49De", + "NodeID-6KtZFnJUHfu92NNRdgdea9ZA5mjbADDBR", + "NodeID-6LZ6k2VRSdaF4qLHgfjER6gjVjrjDEAmm", + "NodeID-6MnjianNNDMpLNhCnirZsw47aGGkkfCZd", + "NodeID-6N15qNZphbUdxRSfThfDbbFpgDdJvoHrR", + "NodeID-6NHaJnvJtHSbdtJHzdDesKdj3Wu9mAuNh", + "NodeID-6Powgn3qZ8HZGmHUeQ7b1acypxzXhA9Lq", + "NodeID-6Pq5DKB1kzJjvnc8KPNSDYfMCsUGJxCyZ", + "NodeID-6TrmPJiRneiG2ztDxBPWQAxAqv976ZJmU", + "NodeID-6Uh985Lx96QQZ6LmbqJF1j4CxLu4ZCcd7", + "NodeID-6W4LCoXP8T2QYRGWcAcpNftMYyHcVuKCF", + "NodeID-6YPFxT3358wbWFW6zHTnVtUYYedASEnVu", + "NodeID-6ZmBHXTqjknJoZtXbnJ6x7af863rXDTwx", + "NodeID-6edspGWTTSWm3N7Zot3kGrEMHPtLrK3VW", + "NodeID-6f4T9BgmXJVJBNTwAj2giidTU7WiomG8G", + "NodeID-6gVjCexoCvwXqApW3YVLnQSjsCUjbSDYx", + "NodeID-6iky1tgQsZupgN75GcSjFyJxC7a3rUc3D", + "NodeID-6pMsJc16h9YF2mMY5VkZu8rDS5Qco23fC", + "NodeID-6qzz3HV9nEmVLrDKGo9L5k94BZksKgwXL", + "NodeID-6tWHHU9uVWAf46qTYTsnTnVZJeL65hwgR", + "NodeID-6tkEtqzyUzqkPZ1KGH8XS9ZTasYGk68iq", + "NodeID-6uRAYA8LDmiD4se1Ve9fBSRrjNi5TZjw7", + "NodeID-6uicgS3fAizqshZgZPrNqm66YieUeZkbj", + "NodeID-6voVgdj8tVSWrgprYtrQYyidN8myXQUXj", + "NodeID-6xEvEA7hcEAnqaXW7R9RFZSkdsAniHPad", + "NodeID-6z161fCLZDJjvLNSPXCK1bAxkK6gjiDXc", + "NodeID-6z3AiSaoYsmFgjqsc1w8rPx4vGaA3Bni3", + "NodeID-77ebv49H9yRLLiUC46Hm9H371wXYNZNjL", + "NodeID-79idCdyu498QoEFzvqKBbWFsXECKSYbpb", + "NodeID-79u7mCRHvc9q5piSciiTphM8H1TDEq4Ab", + "NodeID-7A8w1M4GpWHy8UMwQkARRoB9a67Rod7yR", + "NodeID-7BPqDUFt9F5Vs9eqZiBYXmnaeC5UtZ2U", + "NodeID-7DYhQRawvQ3hoDTfytAa5KHeMTUM7buBN", + "NodeID-7EexMiaXNY1HYVV7gWdXtsiKh8j9gW1Fy", + "NodeID-7FXaqpRJgAPGWAUPs1UunagASkxPZps2D", + "NodeID-7GM3ww9CL3uXtZuK6nSpdKJmEbiiyYgu2", + "NodeID-7H5yeX5kkfdUBFCHLbDfDRxqWCDoFrCcL", + "NodeID-7HvCZsgMXsCTjddz7cYNpKrGxK1i1SxMr", + "NodeID-7L9oKJx6AsgGfG2GR8qQ7ndbKBVxqV9At", + "NodeID-7NenT29nACMVLj8K685mBLodfp6GehVy7", + "NodeID-7QjQJHgVxMFBZzNG6n7ULTeaa7dAbd1U9", + "NodeID-7SKSvUU5xyRiTJxsKsoeXnLa6idNEtZ19", + "NodeID-7Uq7GYJHYNh6LxFinWQpyB4ZitqDkUC6E", + "NodeID-7XRaRs6shZG5VVVoaKeUxdJfbPmuVU4CB", + "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", + "NodeID-7YJB8mcHCRmzsrrkxxpvqjyQH4cCEBXQq", + "NodeID-7b3i18ygt1A2gPpXKeEfAuC3ekHB5J4DP", + "NodeID-7cukmtqdCLDWG6N8BJswwKidxe5iGyVvm", + "NodeID-7dCZydYmPM846KqjhL9b4gRT1C7MDFFxG", + "NodeID-7dZ86Yv4Md2dwhHPpJNyuh83LjKNKvw44", + "NodeID-7eR9d4bjMsTgpwCbvXz4ynETmbXiQrJ1X", + "NodeID-7epJ8SkPeY9rL49JY8ELYJSduMt6eEnAk", + "NodeID-7fi9HdQSPQbnDrSjiVBUAAy5YfisSweEk", + "NodeID-7kVsskXDhAQ2grucq8sUwJARmtqsTmw9a", + "NodeID-7kfKeW5gRRVj7XgsssdWaKNU4AvC8dLiG", + "NodeID-7peBGoPt8rGfPUEeH1VCqnKyMFJg9y6z", + "NodeID-7rxhbsWmUqQ74N3FqoeUo1jpEspkEPeuL", + "NodeID-7uXxUx1VAs3NUs2J472MdQ4V9xVNKZHxN", + "NodeID-7yTMMzMTd1Fuct5tTeCB34HoZ9kLdKCpF", + "NodeID-7zbpDafC5Rxm6ZMXqSrz9D28ZdC4WV7Hp", + "NodeID-83qSEo3NEDrRoNYzJJY4RUBM79cSz4zVR", + "NodeID-84KbQHSDnojrmyuZjWM6hrM2vgPtMWt3", + "NodeID-84KbQHSDnojroCVY7vQ7u9Tx7pUonPaS", + "NodeID-89GQ3qi4bif58ovQnQAehtccU8Jbynozk", + "NodeID-89UCR1CsPzzEHuknxhJHKxuFPNCyPz7Bu", + "NodeID-8Bh3X1LH6uW1q2USKQeu11PAozaSMgEjr", + "NodeID-8CgGmdahNXvmuhyK7NziR9zTEMiArgrrr", + "NodeID-8DLjsnc2R3mm64NJ5puhrgisrLXHXihKc", + "NodeID-8F62HdqXVhqGTySVZ7HyQbEyFDMo33iKd", + "NodeID-8JC2wNQkExELqhtzoGnyBcC7b5Su1C9ju", + "NodeID-8JtmUUx6NHGVACFTReQbFxx1mWMJTdsWb", + "NodeID-8JvHG2u3R6DLSBpv55rHhNvj7MCbeWRGL", + "NodeID-8L6pLG9PQ3XUhsWHT7E2VGuW1S5mgs6LG", + "NodeID-8Lf1apT2CuoLpsqF3sHd5DQCRQ4cs8oYX", + "NodeID-8LjNUkzYVge7UvJkrJmaCYyWvmRb4oxoA", + "NodeID-8MXE4VNHGfx5d5NM7zVeU4KU8kZVs17VG", + "NodeID-8PvUVsNyrXj2SpTyrfxM7AcgjWU4xCufs", + "NodeID-8WJr4wGhcXChCXKXQpSidvTW5RiCQzX64", + "NodeID-8XhZkWckQGKgzhv3XSmUeM3NSrskD4bew", + "NodeID-8YHqGprPt4vva7TqVbzTtVFRv38BmpDUD", + "NodeID-8bVFU3U2PpHCwavsvzfMTE54cir79cmPr", + "NodeID-8boFLW2GXq6DxBRTxAguJ9N6dBYmBd2Ld", + "NodeID-8byCCMYn6aaNs4sQmwemcQfMwrnxBDA7U", + "NodeID-8eZ8eW3Q2Kf6YV1wEVCaFpEsRMm2vfmqy", + "NodeID-8efhLH97RLg7fodqvk16qQbscnGQtV5CP", + "NodeID-8ftKdL6NkAz7K2yUJwNuhZJVLrNiz5qjN", + "NodeID-8gYpz72F1GBoTwufD9FfjESwKAnRRYnwt", + "NodeID-8hqGf72EsTsRTWpP1kxGJkbzeJjnosiDM", + "NodeID-8i9eqbVxzf2KtQkBPiX2BvZujYza6fDe9", + "NodeID-8jUnxLxkowHFhDrEZ1FmucLDC62c3xJVi", + "NodeID-8miY3PqR6f9C6GDr6WFqAwpqqVFheJhrP", + "NodeID-8nCutCx3GgDYrNL1ancH4ZsE5tXHRYj2Z", + "NodeID-8nXdZLTjc3FLaPGbS41WXt3Qwa3JvKaHF", + "NodeID-8pDV7WK6kEp4mw2kupK1bSXTsShiZamE4", + "NodeID-8qNPJ4cmRiqaM7LA9v9tishQvkqqHLCeY", + "NodeID-8qTXyZZtMFdVqfEvr1nhnCJgh1i4ZGqqz", + "NodeID-8rLtFc9Ds7Liw6mF9vz51fmHfxFqDuCvF", + "NodeID-8rcfydaHitUhBWcUuDxf5p24p4qwfvucw", + "NodeID-8tpPNhuBrXw8KKqJjrsxUwVqsgdgbuoc5", + "NodeID-8vGhAbGtfHhi1nNg8A1Jof4ivgLCRdU8M", + "NodeID-93n7QZ5J8s1hej9LEVKX8g8yV8g9FvqCY", + "NodeID-96B6wPgw4HKySZk2C65c33YzzNx5VGmE4", + "NodeID-96ugvCFSQ4Df84uPhPwqHQNRCxVvkpxep", + "NodeID-97jPS9hQkuWC7DhEchgwC2aUN75oto4XL", + "NodeID-989RjLGtpnUjDHGD9mqxgyHLcXfnsaw4H", + "NodeID-9B3HLkYWERnM5daHNb6XaX8on8WP3XiGE", + "NodeID-9DQ6UMDYYWZccC5MRmT2xqE5TaMZUDbLN", + "NodeID-9DnRjykQ4ZdyebJ3FeoqKBBjJcbMC4nsV", + "NodeID-9FKZ4X9iEb3aBqmqzBHsu9kXmhn6aUhzd", + "NodeID-9HUatTvqyEsDD4bUaocsDGpVeePh7KEdE", + "NodeID-9KhiEguiCdK9KGCsfwkWY7M4VLvM5dbuo", + "NodeID-9NsPTteByFVHbn26rvU9NjjLjRKKCR84g", + "NodeID-9QhM9oKKXbAV5xtfARnyKXM97L7nwvGSu", + "NodeID-9TCq8np31pHjjhGaHtLjs6ptYYPEt3LGb", + "NodeID-9X4SMAESCQz8H32PMq4wrSafx6sAUv6oN", + "NodeID-9Xp5yzoLDUuCzUdaU6uFxXTjUYjwoCvPp", + "NodeID-9YzkgDFxmnRQxV4M8E7cuWPd5HukCaQkt", + "NodeID-9bk3GQD8qBvHfFTFaBCBURupAKLQEYg6", + "NodeID-9c5whzpb1QstunxbQ9PGqKQLanAU32Wnu", + "NodeID-9cQwDnPkD4Km3rQFvyJuWD5GUCMYrPHkk", + "NodeID-9dqCQXBAv1AdbNPrR4HCbRDgDjMebHk61", + "NodeID-9j9p75hBtn6rMES3TuWrGc7Q7tQZrfWf5", + "NodeID-9jTrqaVKZpevKsGoiixjVSAc8b2Md18RA", + "NodeID-9jpUT6Zjmsi2MjU8xBh5MWWR2rmTHuurM", + "NodeID-9yrLEmUoyFvZ6MVwrtsXr82LpFExgsfim", + "NodeID-A1SAHmXVC3D7dn67LPmWgd8bMvoNKgqTj", + "NodeID-A1YeC21gHYrEf4HBdRvxFheviXct4MUQ", + "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", + "NodeID-A2Z8m7egVLhKf1Qj14uvXadhExM5zrB7p", + "NodeID-A3Y24F5vNuDy3L2pLwmvZG8s976nCQ5Mj", + "NodeID-A7az7ffBywSGhgSGvwC2WbUgNxcQSiJD8", + "NodeID-A8VrzZuMjMGkFce5zqSQ4nbSwUMwNmnHt", + "NodeID-AAvXsy99V6dtcjwvweVC6FRWRk4fxwhjZ", + "NodeID-ABCBD3w6GosyujRHjEAXfbRkU14YxX1Af", + "NodeID-ACQt5KkctKfdLSNB6bfu7dVzmsyqpm3z2", + "NodeID-AHnXYg7f19R1MMmtt8D2yNejuBwha5i8Y", + "NodeID-ANZVxnoYnsWdzBUQePUsXHC1pVSdsGNca", + "NodeID-APKTqeD7UsfjYqfYBtDGaDCwLpr3ECVBN", + "NodeID-APhFyzYExri3n5GtDz7ytXCgbt8x5NAud", + "NodeID-AUFGUsjF8DR9cPfh4kLWCjtwdKyop1Y6H", + "NodeID-AYWEvPkJB7nePGujP9zWkHjrL76ppQqYK", + "NodeID-AZsVs7FHdKmNfjDDesfRY5w9J3bJd2e9j", + "NodeID-AeQY8TMBdDVVUgvsgRtZjFkArRybvbANS", + "NodeID-Ahtb1pwX6ugZfmb8ioJrBRWkPqg762Ed4", + "NodeID-Amf3N6UZZ5Q4PukDPttqqMDrkjYyu7Qfq", + "NodeID-AnJkYoj9mvGqv1A7WBujia17Hq1rDZp4Y", + "NodeID-AnZdc4zkKTSkYUDUByvX6u3HJP2MU53Pq", + "NodeID-AohNLSFbhRMHRdF9CPe72epbRtYPeZwjB", + "NodeID-AqXr2RXWtX9FcPndqPZmEDHqfd8Rm5cxq", + "NodeID-Ar9txpfoVW1LxzfYpQ1itPWpjq8b3c3s2", + "NodeID-AuyddbmFnAXCgeN388tMWzvAYu3nMzi4m", + "NodeID-B1SoG2eCceT7YhdRq8EdcuVZgcXeWB5VD", + "NodeID-B1jRRwEACvv92YJWyZrWwQn8DaAhEQA8K", + "NodeID-B3KbeQXjwDat2ySJrVppBxRrTxb7RwRjy", + "NodeID-B3si8iQ5MxJDRnwMBJyVt6puzici5tufY", + "NodeID-B5EdUCfcqnnHKgYzZfoVE3BBabQt165y", + "NodeID-B6GaYh7RRopBAkQJGiMeMZAsAbHXyYi6e", + "NodeID-B7R5mup1BGypqosat4fvCxWXGgziRaZgB", + "NodeID-B8SLANqFYZnUqfnWMuJjsjfzcN8Fxs9rp", + "NodeID-B8vH6dfELDJgPjYVMK5hjrRQkUMFFW7i2", + "NodeID-BBt17ZXGPvov135835zT6BBAa6uTwriQi", + "NodeID-BFa1padLXBj7VHa2JYvYGzcTBPQGjPhUy", + "NodeID-BHM9wtsHVPmqKbfmqqHTvTCiM4YXoRSvs", + "NodeID-BJjQb2PFLPiHsvejL2Q3yX28nqRxGxEqA", + "NodeID-BNYwWBYAidDqYiJYKhRahibQxPuG6hGvp", + "NodeID-BQTWT6W3Ke4PUweoYHThhuQgerhuAFVZH", + "NodeID-BSE4qod6VYM7Xxeausg2UzgxZqMmTTWnU", + "NodeID-BVXicWEU3ULP9aBsmRT82PLJMCXfdXDMp", + "NodeID-BWhTVK8YDrRmK6NeoLDn8oSk7pGu9386L", + "NodeID-BZq3oJcE1Unw1rYTB86B1q56x2VYQ7PwD", + "NodeID-Ba4X4hJ4bz51Hm1L6M4rRhu9JwniJgyUx", + "NodeID-BbDHoP1Th9LSr8iEuoHktCF38MQ6Wx5Ws", + "NodeID-Bd7EUL6WhVm1wF5bVNefWxHYsg8q2ttuh", + "NodeID-BdhYSwf3LW3bBqt3235WS6Cw7P5GYDFSV", + "NodeID-BdpT6z1FRz6vjEQp7Cb7nRFUgvcquBXT2", + "NodeID-BemmZ7Y5HLGHSz2kUjmPUDD7bbJDebVd4", + "NodeID-Bevezp7VTbNs4wGiiB115f8NrBwuRa79F", + "NodeID-BffXkmzM8EwrBZgpqFp9pwgE9DbDgYKG2", + "NodeID-Bgskmf8PocRPgtHgnAYKUgyifo9qD3Y5g", + "NodeID-Bh1NKhN5t6MBcHvY7XuGhLK14q7FwQjmf", + "NodeID-BhmBgAcV8WiNyrVUdDYJ9CVi7TvjPfJV", + "NodeID-Bk8Etvn1q5cEbZcn4y9QjbXoEAPwsHxB", + "NodeID-BmkswdTypyATT3xP9as8BeUCyq2sGScBD", + "NodeID-BrYXghQSu6KKGjuzhs3nrkcB46Wc2yYHy", + "NodeID-Bvr4dL7pK3FHqXvPs3X21y6QaZS86g4z4", + "NodeID-C2Yoi9vTGPppDhpFMx8J1XvKJv3CY2x8n", + "NodeID-C34t8rtehJ2BXMkok68K7ZuUZEk9ryJrA", + "NodeID-C7E4ym1BsDbraGxymND3zGYHmo8SJfMRb", + "NodeID-CA74JxFwV5BeRMCesYQruxjiKw4ofkEKQ", + "NodeID-CBy6ZLEwBBuYFtVDDvz8Wra2AfeAd96fs", + "NodeID-CCDSFhaQAuXWpiLviESSUPJmWUUTVxdGj", + "NodeID-CCPjVQc87Ka7nbXVBN5cVtGTfTzPVnEyb", + "NodeID-CET8PwdAu6Q2Cx7iqHrfdSyo4WEnkoxFr", + "NodeID-CEzYD3rFjsGtKFu7JLGpD7rMcGRNJFLGB", + "NodeID-CKZg819tz5CXMxMtrRfKS8XxVURFDuHVB", + "NodeID-CMSgVPNXC5R1kL19KHCNgbbRTeStUWPJA", + "NodeID-CMaW3TiXtNHzPGm7xzjkJvE8fthGibhAv", + "NodeID-CNK8vDPGbKfS3YSptRPPN4VYUEpoNH4Vz", + "NodeID-CNp6HLV3F1RnbBF977E93KReTXTkZ4t32", + "NodeID-CT2Fqk6d8eYAx627aYB8HAr7VjWHZYPQc", + "NodeID-CTtkcXvVdhpNp6f97LEUXPwsRD3A2ZHqP", + "NodeID-CU8Tq3pP9QniPeYWagh3TKDFccbvfwDkw", + "NodeID-CYKruAjwH1BmV3m37sXNuprbr7dGQuJwG", + "NodeID-CZP8JG4BKdDyiktxg3D2ZYgREHtFhqzjH", + "NodeID-CZmZ9xpCzkWqjAyS7L4htzh5Lg6kf1k18", + "NodeID-CaHFWxHNLv1R4R9oGHMQR7n2vKy95LTei", + "NodeID-CafHoeCqCjg8fWufaorRqFe3iX8s7z6A8", + "NodeID-CcS3n2j4CEaQCEnY39qaBDZajeZaXkRGU", + "NodeID-CduWdu3Gv7bsqAxnsdTCWuuMEyLYQqchX", + "NodeID-CehvZ1zrpo5HAb7K2sDiQcrks1Cn4d5Ew", + "NodeID-CfN57fb8f1jS3NWKsYSxfsHf2Lo8HUFSY", + "NodeID-CfdN2fVKKjDBRjqMLsxZNSaSKFdBgpMmr", + "NodeID-Ch8GJYTFsdPRzMVyWgVJTVV8MsHvbS4h6", + "NodeID-CipRaLt4Ym8yKegs45dpeEscA2x5w29Q9", + "NodeID-CkS5zL9rUsJkYHgSMtoYF7yBwBCV6Gn3X", + "NodeID-CkWijvSj2dEenuJeXu5fyJcxc5Wtg1feo", + "NodeID-CoKgGkWBUGouNZTqKCYLBNJ9dw4yJXUEW", + "NodeID-CpLDjTHrAuB8p3G42uRtGhnGKJ5YzGkFa", + "NodeID-Cq8kbEVqteYEqfNNW1CJSkrG7S16GiZ3u", + "NodeID-CqDq4nGVYJoSgKVpZpyutzkZPfcugTdjG", + "NodeID-CqGy1ZUkq4ZTznvsvzwwXtQiu8gBT3eYW", + "NodeID-CvFCEpXymDz9A2EftqnJmCNi8qVHxwKXq", + "NodeID-CwcD65rnKwedLNcsc98MZK6RghPMptEyo", + "NodeID-CyQc7xjJ2gJtCQNL6RVMEJf1KysJXG6QF", + "NodeID-CyS27tGGmcmxeKhCuCwhT4GwiZGBE8QEb", + "NodeID-CzBZTXGcxZqfB7UiN9ALzssfyHMWbMKH6", + "NodeID-D3BkKn3N6chukRSZN3yr6zQvu4DgCSvp2", + "NodeID-D3x6QzTaTdXxkMXYFx1MDc3T224H2Pmh6", + "NodeID-D6MxfVN4395J9jSmuPHDueQJue4Gitwns", + "NodeID-D7jdvPnW8XX3Yz1k4YYKCZxaY1FF7x6at", + "NodeID-D8bHw3BUjyGycV3dDTknNp1p6w8LHkNhh", + "NodeID-DE5iNyHAPisnXpaf8e16diJWL5y33VB7u", + "NodeID-DJHKfhFKe4QjX6AY7tyj2VTjZrpxUWUyQ", + "NodeID-DMbbEVaCyas1EXR5ubg2naKgEBmVerPne", + "NodeID-DQ4PJvysogwgzru7R8oDiRLv6qoF7Wwxc", + "NodeID-DSCwZSNFHcZFg5kbWrbbMHJNdpLUAuWB5", + "NodeID-DUNsbAcHScpFE2uwBQ2o3SPZ46C2svMqq", + "NodeID-DV4fFyxuvwUUUQbTKuc9bYnRibVixtSDs", + "NodeID-DVQevoevYh5pYSNCwoGpn3QnqewfibCJP", + "NodeID-DVZ7ffBkVkXDbpjGPEqwyYQgvcHhuTynj", + "NodeID-Da1yBnfJmUsS366wMN9b2Kzw3EL3WMdkC", + "NodeID-DdhG9cNQmDpPwWSpEW9u6T7PNCc9GKv2S", + "NodeID-DeeVioFXeoXx718FkbAk2unyikBN8iLJo", + "NodeID-DfWyvyBF7XF33B9kkSiXYcJyzxRBATXN", + "NodeID-Dh1JnVoEMU5zEQtvR6LHPVsyw6AGqbLuG", + "NodeID-DhQSUszPR4zHoxF2Cicx3pCUnjrfsewnp", + "NodeID-DnyNinbTZWYSyoekJ1xMmh8TxQCw9kHdz", + "NodeID-DonmTGabi4TZjWH1ue6W9GnHB9ZSjTrqG", + "NodeID-DpwRt5xkd3rKici9ikuo9aEH4AMfzsT7E", + "NodeID-DqogihFFxTyKaUTqmjDt1Fh82hWwkeq9v", + "NodeID-Dr3k3Xb2uFHqztcbVtAbbfhtrwYjsRysu", + "NodeID-Drb1UM6uo69KiAy8tyD2QXv3JUGU9exaz", + "NodeID-Ds4BPVEDoEPu9wHT5rk7ry8vWaHoY4cDo", + "NodeID-DuXPSVSZUeEJA8QP9QV4Vt2G3y3WbPvRx", + "NodeID-DxV8FsH9amd8cjQhEboKZerAPsBR94maA", + "NodeID-Dyd6GY1EnBTGi9WEMvFo7kkjsZBWWRDo7", + "NodeID-DzyJouyxaQRYYyfYEvTaWrB4uaPTTKn2V", + "NodeID-E1tni7wFcu9CizXdckfgxo9dhUwR3243v", + "NodeID-E24tDGQ6uRbTZaFCpqnUgZdWq2Y9YX4qy", + "NodeID-E6CBZzykpEJSqKyNjDdFeLvDN1AmZccWY", + "NodeID-E7Cm2d6wVhaA4Q7AnuRg2S3sD6noReX91", + "NodeID-E7e5wZQb8QYEKYd1BrRrszjPxUaAQNaY7", + "NodeID-E8dfbZCzX8VXgXYmjnA58GorajNrNcpFL", + "NodeID-ECmPviPvgqFc4iXFi3soN1xpXnUUDHjoG", + "NodeID-EDESh4DfZFC15i613pMtWniQ9arbBZRnL", + "NodeID-EEuQumHSHr2hV4C5S2FNL8LVofD2Wvqyi", + "NodeID-EGzKzc9RU6HGCzBe8nK2qY6mVs6WqroBg", + "NodeID-EHV8d1ezFyoA8DMzTU3WZXfVR95R7v1cv", + "NodeID-ENMu41b1avXe4yRxmF1uzymNJP9Xf4jcy", + "NodeID-ER95YbfDrVih5Ja8F81ac1RZ3Bk8h6dTj", + "NodeID-ESYYcZZMJkLzC9raPoRvH4rUeErh6YF7P", + "NodeID-EThtNJN89zd1cGjVPyThdEwHknvV6XeML", + "NodeID-EXuaP8HAE4anxXGR4QJX2em2nfEiTR9tz", + "NodeID-EYEsr6Srmjn4XM8DijPFLFT3Hf7fsDMHA", + "NodeID-EdSG1Dy4kqqaDJRn3kSAdM7RVSdW5eyyz", + "NodeID-EdbD6AHYPYNqv4X9KMUA4RBkuHnd54E9a", + "NodeID-EfGKSr1JxRXofvpSo1kABnyjuyJWLr19K", + "NodeID-Ej578hCdtGtaSQUMQFkPkoXVHHByJJzZM", + "NodeID-Ej5WQFmSCm27bZuRPoK6PeFe5tMURCgdG", + "NodeID-EjSCX6FJvzVA1gaja4cWqfaXEkZeAgnQb", + "NodeID-EjvGBJ65yHcJMwV5RhDJBEcKb1QP4Du1L", + "NodeID-EqJ1JGnx7zPAEvGy9JRgytDDTrsPtZUet", + "NodeID-Et4ic8Ew2HhDqKzb4Zx68SMbC8mCLUWzi", + "NodeID-EtBgBdH22chVR1fzZZPky3jzUZDTigCbV", + "NodeID-EtUZs6wf6j5kZMUuABEzUY7Z16Ja9DtoM", + "NodeID-EuQ17UhJAMCCPKo6qhEkeiEgeyNQk3vLt", + "NodeID-EzGaipqomyK9UKx9DBHV6Ky3y68hoknrF", + "NodeID-EzN4q9mU6TVFkND6oghbdLAUqDacE9Czp", + "NodeID-F19vhTXhznYNp6pAvaUmUpj4VWq7qjUyP", + "NodeID-F3c4DfFS8crrJUyExRhgaMiXtZrn3TuP", + "NodeID-F6AdvbZj7E2JZDfG9WhafyQeFAqiU3geT", + "NodeID-F9kHeXw8eoxEMpKVCi7yCUwYGry5zPURy", + "NodeID-FDXS1jxwngimMxWwdysC5N1dNZVPZ9GQ2", + "NodeID-FGA3erWUCbD9rUBXy1Ea2rzp4xas5zLgW", + "NodeID-FPZ87ZH95TeFm1su82QJRX8PCJi4oBAoJ", + "NodeID-FQ4TUmX7RFf84qxGPBdmPkrUCzCVoWuVR", + "NodeID-FQuy4XRiNwdHunxKvAEsSG7N2oTFvcKiJ", + "NodeID-FSDQT7qCdqgxZZq4AnFDcMpxukPrXUoyL", + "NodeID-FT27zhjAL6HYVkfBHoWk8FQ3pCt4xyVsA", + "NodeID-FTtpSNGEGH4HiQbi99qcgwGsgHthwMUGZ", + "NodeID-FXLBpf4W1QenLua7FMGTKqvk2Anobbi4m", + "NodeID-FYD28utCsypYL6THXnyT8bTW9syP4WQrm", + "NodeID-FaADDvJH51EAP4vhJEKCEfCtgpUUnTNX6", + "NodeID-FamFBmBfwGwjn7fKpbaWjzcnTiGNfmgWN", + "NodeID-Fc8JvkNuUmo9oSy8jXiNXUczUM2q3jWrS", + "NodeID-FcG6viphauzUYhxsCtbaJUKqirYqp8YbK", + "NodeID-Fcz43yNkFRu3jL97vjLi3ZkpmeAcVR8La", + "NodeID-FdcqnJ1bwv976Ft4RibXmD5DTeWSnMzS5", + "NodeID-FehvGhfc73qH6s4zTdiKrNA4WmSMbCW4X", + "NodeID-FesGqwKq7z5nPFHa5iwZctHE5EZV9Lpdq", + "NodeID-FfiosnkKYLrMKoUpNTuFZz6gY5kb9cPb2", + "NodeID-Ffr1YgeWw3h2Ct9dY7V3u79ScrAbhSUUz", + "NodeID-FfxNCp6tZxTpj1JxA8GGVTtJWowqKDmvY", + "NodeID-FgvaeMrL2GqxSBV9R2hkLL7jH29vhBeao", + "NodeID-FkbkPTVMLbZZJKFHYUKZTt1Z3quNUurV", + "NodeID-FnQRH8p5JrhLRUT9wK2rtEc17EtN8Tcb1", + "NodeID-FnsrF37UrgFtzoEKNxyAV7wN516SwqFVN", + "NodeID-FqAXbqQUVaXS6z6jTaLPZGivbLnHf3G7q", + "NodeID-FsBU6yEVf9ZVEhuFy5sRixYwio3LRN9Ey", + "NodeID-FvMWujr57hToQPSfGsd2exqaFBdZzJBTk", + "NodeID-FxgVB4Wwgg4dZ5WTkkBp9EbwJhAgwZgWd", + "NodeID-FynRLYTNZroGso229UyxpxsjqmQqJgAQF", + "NodeID-G1MJv3mVMjo2SueWzr6rvn1gWyAvgTXrQ", + "NodeID-G3axaqp4Grtc2S6LD3qhFR3wN1NEZRuGx", + "NodeID-G3h4X9o4Rk71ijtpEdsQpjWCM46GNCXPk", + "NodeID-G4Za1ZuLLinkM5skf1LZqAWqKs3P5xs7F", + "NodeID-G5p6Hn8XFSQJKH1YzA5iS53rgDfCCE7a6", + "NodeID-G6g8fYiCrp6ZNryP3Ni2fJKysDxHbaafU", + "NodeID-G7fjDTJ9DH2P3ckC4VqKvH9q9Zqsv9b6b", + "NodeID-GDZpG8cVCndUcnoHiub4XPM5WR2hF7tmk", + "NodeID-GEC1zVazREQmLUpj1fF2qvuATpRvMgf62", + "NodeID-GHvQsCAUehhZi5psMeBxDfKHuoVGfRoDt", + "NodeID-GJsdSRahtgdsTBjr3jbew5uqTXLcjJkG9", + "NodeID-GK8GSuLrw6jk9CVZ7ryAjSTm3pFEmeVF8", + "NodeID-GNJqrL7nMYPaYXcrSSfsY7ffe5JAzTRGh", + "NodeID-GPc1Si7SQ6oAEfP8MzQ3cFN3fsAtkwC6i", + "NodeID-GQTbQ8qJYwBEhQEa92V1yjHzeVyjTDKFP", + "NodeID-GR5Hc9oEi2AvNBAoUaQDZtWEYz73jP6jq", + "NodeID-GTgPUiVqjBX1UAFmdDmBoyHuiRhTPrZen", + "NodeID-GTx2HdjpdzYuQEpjrKnuuvXDzd8XPBxBG", + "NodeID-GWRSuAdKF4LjKSgEYFXR1crtjov8vnW4a", + "NodeID-GXtJyspnxHxzLWWyUqJ3xgXNidoxwAtdw", + "NodeID-GYXpBJh1SYjG9heFSV51NVhJHh5LindGx", + "NodeID-Ga88DP7f7F12ePN3LEYUGge9kjKi3qHP5", + "NodeID-GbUcqW9qSUuKZPMJ89qL5YJWDfAuUjdq5", + "NodeID-GgDJXjd35ewugJyG9tonbjBEKVZambFAb", + "NodeID-GhLyXd9aVH4xujx9SzC9oy2JcQQ5amXuC", + "NodeID-GhsAAVi8nXhvLS1Xv4ast3EbcL4BDU8NK", + "NodeID-GiAS7J8Aiuj2iBAnKT2wmnxWWqp1QLd2v", + "NodeID-GkiKRa6ww4zJqXKQUcqHXnGaRKD6JNoYx", + "NodeID-GoVFrxwF41mzpVyt6Pb8K83ynj3q2U1CV", + "NodeID-Gohrw1ApuWhwFwUbCLKjS6hbijukerjuo", + "NodeID-GrL2hD5CdKU4CE8fbN97kVH5DpztHMLPX", + "NodeID-GsGzZFRypbZdhosjortCTbGCHiMGAifhw", + "NodeID-GsoJqaJe9SBrouxVCtSriYE64e2cQB4NP", + "NodeID-GsufzM4GKTutEFEAkDunS2wkhjdUPUvCu", + "NodeID-GtJaZR21ZmzB8CcPYXVA2Ks6Qgb26upj5", + "NodeID-H5Kcdpnye7iumF8ad4EHEFxvYzPAg4o89", + "NodeID-H5yv8taAdDWeCGNSLzdM1u2FA9cavk8ka", + "NodeID-H6FuMzUuGxjcko4hoBhPaZ56F4pheS2Sj", + "NodeID-H6Y7aEKkKz5HeWp4nE7nKHR4PUksjBuke", + "NodeID-H7Wq3A1RJsb5skBd9iy8zY37yW72zrNLy", + "NodeID-HB5cY5e67mzjNwrcqucGAxh7SyNMWLY2z", + "NodeID-HBkBmNgoiab6dDBZ3d7Atiq8ja9achxwV", + "NodeID-HD9qhGtz18TdEbLeuMhn4ZXNCxvdvQTwy", + "NodeID-HDcjsGMHLaLgJFoQYmi4CBsbjMKPacuP6", + "NodeID-HEdbAzR9GLht5p6b47J214UhdshCDX9TP", + "NodeID-HFEef35BkgqRBYiQ2ou5JhsyB8LHRtyuo", + "NodeID-HGZ8ae74J3odT8ESreAdCtdnvWG1J4X5n", + "NodeID-HHXxANboEXufRMuSFBHgc5dbpk67L7XPV", + "NodeID-HHcVpHweLyANYAB3UoDYrBQLDznFeS42j", + "NodeID-HM73QztvPuGikaADwnjpaJ1iKWAABuQon", + "NodeID-HME2ASYZmCcpRRpKQRsCLPJ83ZkWDBkQ5", + "NodeID-HPpKmAyrXsouQTaxMJR2YFgSDVV8BA5xP", + "NodeID-HQ4mk1kjeNvfsan5qrmynaMhQLCsQ4pYv", + "NodeID-HThbCMfRbs6nVRR1ySihYtWLraLZw8x16", + "NodeID-HTkPf7hwzrLyDDjAZAqMNQh9oF4B9iebY", + "NodeID-HVYnT9MUfcK8sFV9tRirmkppWiNmFWQya", + "NodeID-HXdPaFvKy2oaDKcd1ufP7cjUuRLk4T3cQ", + "NodeID-HYDf2HUkHFDiUKYmort7tjUFLq3253dHc", + "NodeID-HbH45yH52gVWeFe91A873QBG8a1uGBD3S", + "NodeID-Hcg9iX24FKp1zumDpJbXF4vPzkbcHBDhw", + "NodeID-HcrXuRruPjFEdc3snCR9wqxbh87sNCJWj", + "NodeID-HeWWhU8g5KQBNFaVdwnj2TZLvBVuke7kB", + "NodeID-Hfm8gpD4DpCz4KTzt2osJPfFvu7az3qiD", + "NodeID-HiX1MqbbJLeV96jrYH6uTkuWr7ofbiAHy", + "NodeID-HkyME9tYN3G6DR9bvrha6XWNB3kYaDJbq", + "NodeID-Hm1uax9QMFjwNrrAmriWVQVcChyfmrqFB", + "NodeID-Hn6ji4ie91SEhmpgs7PZzDajaMZoH3eZg", + "NodeID-HnZNJY2KscixbVi58em86faLMY1BbT5Zf", + "NodeID-HwYioQttyXRmGzdGAfNcZ8cAkrhfCqSuj", + "NodeID-HyWNPsQZyve88fbwmxgUzq8FnNfE6wR9E", + "NodeID-J3s61uikXhXGVxC8ffsgbctVLV1Mbvxz6", + "NodeID-J7EzGdbSy8EFrQM9bBJXdLfwCoRHtXok3", + "NodeID-J7yqAsDbJ9jXTg3dbszqUoJMgUwDgnmyn", + "NodeID-JAyKNPqtqsmjizdEWgTy8C8dM1tgZ7XNz", + "NodeID-JBWVRVMqqTR9sYFQqESA1V9YQNoi8oa1b", + "NodeID-JBiRdFNc9he8ivyGkdAzH9WaL4GKHoQG4", + "NodeID-JHQyndxosLrdixA6TjB6bexisQxCuQkgR", + "NodeID-JHVmPLfE3YrKdBozJM5MEn1BzgMJzUyPz", + "NodeID-JLw6tbjnhJZLhEq5jnWsrxRgP3AEbxAtT", + "NodeID-JMoiLcTY2t9P94nTXfm68pYq7LMQ4fdFt", + "NodeID-JNRTA7Q6t5azWZrT3qaVeeXnT4vH73zDF", + "NodeID-JPvPvJLYDc89thb7UhqrqhndNCHGggxbM", + "NodeID-JQGMqAo4i7uXuS49vgaZDeJedDRp6oyuH", + "NodeID-JSNDtZdthVnHjSt7NY3HWd1ub4gw1pKez", + "NodeID-JXw6V9Bwidgc7c2aCZEebHDRT2FuWzBLu", + "NodeID-JYJRG5ZYgd6kuQ6RvqHMs9CGh8RkyEpvv", + "NodeID-JgQWdp2K5yq7Bj2Z3TfGDP8GYAmeqtUQX", + "NodeID-JhWkuVZGeJ42FLktoMVoiGuoaepWjxyqx", + "NodeID-JjvzhxnLHLUQ5HjVRkvG827ivbLXPwA9u", + "NodeID-JkadBNex6QYkFN6MRMjrRq8LHn6jp6qKk", + "NodeID-JnVy96b53CKBAPiqJTRTK7FnPxRk15gZ", + "NodeID-Jni7c9DhGu4aMvU4axvH8jfnKLmi5iaCo", + "NodeID-JqPCvrvnKgNEKdsKfCnhVcaP9KJ3GWPq8", + "NodeID-JrKGcbdnCzXUijeLiwzJZQNX48Cyrs9Yx", + "NodeID-JtgzXwsBLsJh6HWQGWfszrCCxpCnnzdwc", + "NodeID-JvyHfY99GqXXWUsSaoeEEZZ64LQpMCUMU", + "NodeID-JyE4P8f4cTryNV8DCz2M81bMtGhFFHexG", + "NodeID-JyRud4d7Sp77cjoXiuaThBsUVrSFEHgMQ", + "NodeID-JzcJLa8bXBPBg75VVXUHh4fqgmhx8N83h", + "NodeID-K2tnczAaPNak4WDoHs7thRxztKDc3LgoH", + "NodeID-K7X83JX64HEzj4xSLF8MZWNNtUbQmwnn7", + "NodeID-KEkCHDs3iiF5U9xaKSVg6xzDU27oe6bBp", + "NodeID-KEkeqcndUcaWVXNjNCXUUbX3gUepXqvCm", + "NodeID-KFerpW79qQ1whckFbjUvuP7eLwtXEHndV", + "NodeID-KGfpnGi2LiRyTFfeq866B4skCpo5xuwFp", + "NodeID-KKMxwJXjz4iB6G1VopYYst5W9VJ7dE5RH", + "NodeID-KNGEydgzXRZzNcibfSDGfQwZBUHaA91ij", + "NodeID-KPi6dGARXc6A8vMjKuA8troteNsArT2nB", + "NodeID-KRibmCkicP8FkeGM5Xm9yykNcrED2sjaK", + "NodeID-KRvfLaiAUDLBEixkmdTDf43nNppas96Mg", + "NodeID-KTnhPkucgchw74sGCrkpuCUmv5y2Nwnnz", + "NodeID-KUVib5Ye7nrnA7RdKWz9nv8q7gZuCZwp6", + "NodeID-KYr2Ldd1YHibJx38nkQ1vfqzRmsc41Gzu", + "NodeID-KcC4UA5WXJtgRBdhtEnECqxyNcxh6bsno", + "NodeID-KeNHPP5bXbGV25Ujjp6cYfExVzQrmCfkq", + "NodeID-Ked7WpBzVYe4DthczsGV3CCYpEvj2F2bD", + "NodeID-KerQSdj93DReMZFcDxqCVqs37jwEQb1Ji", + "NodeID-KfWrRxNQACEGRqPw7RNkpn2AYh5kPbCFt", + "NodeID-KjKVvgJ71tiwHGwqBmhQLKGqrNeQBpqeR", + "NodeID-KmzXj1CfPzG2WoTJiXr2DACTksgeQARJp", + "NodeID-Kn1JzoTMNzKS67fuEtcLU73dUTCdjoomR", + "NodeID-KpdyakxPD8mdLHV7XDYjrtUZ6BG4rXRKu", + "NodeID-KrZPkFHQnZWqdSC76pXRvnPVXBC7PyWWZ", + "NodeID-Kskhj6CSMxyA3Y6VsjrjGUDGZdMXTMjjv", + "NodeID-Ksmvwp6BpSszz917AjDWG9mHqi2cdXVW2", + "NodeID-KuvxfizxywPLkup6RtzmaJcCECjBrSACL", + "NodeID-KyP1LyscPyThYCEbN1KXekaeNgCtUgFhq", + "NodeID-Kzj2Jr4XWUdVhLkRsaYC5WH3tKVKyqX8x", + "NodeID-L1UD9fwiT1VtFUVX7en9Pnz4EcLTwAvwP", + "NodeID-L2LTo1cbHtyqkZfgKpPdo861Lgz8WmJzj", + "NodeID-L2kZ947yAuzugQaduZPJdysWRqxxsT2Ak", + "NodeID-L3eNEFiZPrdiToXvDvcR2Yepk9p23NK7X", + "NodeID-L5SLiTDbpJAgt4VFJ7CtVscaYcLk4L8jT", + "NodeID-L9Md43FWvJz6gQJ2eAS1QVigXSecSM7LC", + "NodeID-LCXfgTWLmmxazX8C3JuRbvpzmzqjzT3xe", + "NodeID-LDKGrAwCoz5Tdhu4tVDjqFFQsR7nKqNHz", + "NodeID-LE9q4y22nKHCv1gHSJfUyYY1qXcziLkFx", + "NodeID-LGGrrgqBdzT3smcojPh7nTKiPRu4Q8G9g", + "NodeID-LJH9JffagSPthZ4adGRjHByXFytPdrmmc", + "NodeID-LLH3HuzG4eaxJYYMiZTpQPVJNuEAZEaa4", + "NodeID-LQE7F5TjyfGV3HqrzAwYYAjdeUZzp4Fzh", + "NodeID-LQwRLm4cbJ7T2kxcxp4uXCU5XD8DFrE1C", + "NodeID-LRPi25wApvsNUuUFwwQtUMyuUNgrhmZPG", + "NodeID-LRZMF1NjDo4neYWtbA1vRD6P7rmLKu3RL", + "NodeID-LSsApoxv5refjrydswTevcdtddK4LU392", + "NodeID-LUMxSYFmov1nDn7KZE1Z4RmT1EYgTCu3v", + "NodeID-LVSzcr2TXAjTTNbEi8Nxfjwk3GQyZo2s9", + "NodeID-LX75T9BwhW85T9Vz9mxvUEQhFqR1688Qn", + "NodeID-LZMzeFFuZvg2fL3JYoAGd8sChmBncgPA2", + "NodeID-LZYJZxAqgn28K3g2crJtGgr5mW9mo7NFc", + "NodeID-La8YHdyQZHuaaoEb6ww2BznRa1N4c54J3", + "NodeID-LaidvDiaEiYSxKhqPsJx3ST2PQKFidmY8", + "NodeID-Lb7Ez9LWTXUeKRUMgHX4JJtg4WNh31JUS", + "NodeID-LbijL9cqXkmq2Q8oQYYGs8LmcSRhnrDWJ", + "NodeID-Le4BWsZM3dAuMXTDL4rkcRZBTyHpC9zzq", + "NodeID-LegbVf6qaMKcsXPnLStkdc1JVktmmiDxy", + "NodeID-Lf75GiFUq2psqfd3e6GkMNuVEYx9BUuuT", + "NodeID-Li2RswwproDXoFXPtrc4LvVWLxC1osx1C", + "NodeID-LkER3oCznkUE1mTaRsugitboTtBSxNF7o", + "NodeID-LkcSuyM6DZa1ZMWDpybe6VJVD1RjNF3JW", + "NodeID-LkdxkfYhg6nSw1EEUxDUSYPXPwmr2cUet", + "NodeID-LmzaWSmdA8jM4hfYjsEZ9QJnHZP9K7nET", + "NodeID-Lpb442HkX5sNFDeKcf5zXZJ349cuqiWdg", + "NodeID-LsgAS4nCNrjL4gxPmTSDmNu2ywWrPwvVK", + "NodeID-LtUqKXZBqZj37HCNQGqjaor6TZVBVF51x", + "NodeID-LyaNgPqgHTrKSiLdEpp1JPF3Qkv1k6n1B", + "NodeID-M1745j4YUixszHoRfPq52DpyQ4TSiM8pL", + "NodeID-MEEDgr35ZZm61jCzguAYDqFipBGrEnMtP", + "NodeID-MEe8K9JFZHtovv515bNciv3YGC3jci3yN", + "NodeID-MGkAX1DhKPPUudKPgP9qu2bCh3h2KY2ea", + "NodeID-MKaR86DivZF1UA77gwUtRjHp6ddUHBr6T", + "NodeID-MLHMrE994WwHxKqF6tf6E6DF4SuQyeP2Q", + "NodeID-MMiSVwiACfxkyURcAYV2EXUShAYpmpkWJ", + "NodeID-MMsdXcGMAN1RgytS3EfsEFzF9opLeEryY", + "NodeID-MPw5DtJq8yeFFuEj9LrhiM6p6hhdTXBsd", + "NodeID-MSF7z6rWEhimnDUJwwaGTiuWxkQEjT1Di", + "NodeID-MT8bs75x9ZZYTCC2G3FdBfSiSPmW5nste", + "NodeID-MViNUVT7MHKe7jS91EtfJixZG1nDowv9y", + "NodeID-MXwySzKc2JDDg2GLR8NsmHXDQ3XJcWFtT", + "NodeID-MZxyHcXmSRh6uLruUmgBEhXRxYge4rooz", + "NodeID-MbibpFmGwGXAL1yPQVDvJfjL5GgbGqDEJ", + "NodeID-McsVE9skuHHM3ebcFwWLhzXvhpT2Dc8Z8", + "NodeID-Md59LZThQ9xsihEFmbgv4SVktSuQkXnN6", + "NodeID-MeDZKLP7y9ydHRVixZ54yxZQzWqS8YvG", + "NodeID-MeZyN4H2yUfvu3KuiTFDh7KLctHWni9tF", + "NodeID-MiMhJNePYcQNGrAVsXRYEKXQ8AA85Nhb9", + "NodeID-Mj7LRrnqPK2UPrAKYHY3aNSDpshsM9tXP", + "NodeID-MjFgGwGpHSsvyJPk7d5XRhWWyihttVLNU", + "NodeID-Mn5pQf8vkLQtic9W6beXzE592Gyctr4qo", + "NodeID-Mn9484xnB1NnnrfPfeJ9UrdakNXdD1B85", + "NodeID-MnAL4QmHAqYihdL8Ad61AY5NuKAtYjz9j", + "NodeID-MnBVormBXdmpzuFUVFX7XVdwoMHEbH2bV", + "NodeID-MnNiFH3NJLWYsH1MU7C4U6fXdzhqtZW6a", + "NodeID-MoW5hERQWaaaZDvy2g3LDHqUNqkf7Bjo6", + "NodeID-MtR3HLYP88Xmsd8whwWHRvijdAuWsPsBA", + "NodeID-MucxfzaqiKNQCznykW8XPPM7JZFPVEbhF", + "NodeID-MvxNcbGGUifjjh41nnrm7RRsTqmU75mH1", + "NodeID-Mw9wURaGBAXkgbpX5fkipsmoqnWXXxzdF", + "NodeID-MwBo6z1rpGZqbD9xuo3ByvcKTw55D4393", + "NodeID-MxsyPb1TKJzaTxyVvEvYqmkYfAH2NKED4", + "NodeID-MySLmc7236dztdt3jA5znemeaSHWGCg8x", + "NodeID-MzpGqPgcjmT5ALuCnZXbociRiWJTQyncW", + "NodeID-MzqqzQwU5BGCTTTj7FTEG8eGK35Sp4jrB", + "NodeID-N1dQ3zWTgcpnxDqejNYLevSQQPGNZSgvg", + "NodeID-N2vaQwWF6MeLWTT8Y9pBKV2oGjKVxZ6K2", + "NodeID-N59JVgQCpF5cRt4e6zKQUBgDkgyNH5GAa", + "NodeID-N5gc5soT3Gpr98NKpqvQQG2SgGrVPL64w", + "NodeID-NEeaczgsLrh5DKparo914eAz4SHCNrCSn", + "NodeID-NF3dhwiiGHc1MoT85T7MwWk2xLF9zpgeh", + "NodeID-NGCgVZpeUaJXdjVq2moRRha8tM8tfYEcc", + "NodeID-NHkrKzwkkva75HTqd1RDWBdH7tRe9FAFo", + "NodeID-NHv8CEWXzT8z8A4xDU9qDVp9yGfM9SZVo", + "NodeID-NK38Y3Y1gg3duKmwEmPURY5ngYLYb1yAq", + "NodeID-NL8ivcdpDokN2c2XB36iBbqTP2dmtDN2z", + "NodeID-NQxiZFkiHvPMdFnVQer5K3mPJPxctBefD", + "NodeID-NRhg5SrvPn8CvtisAdgFXA1QkLoPsqRdp", + "NodeID-NTELjonQCqJzT1QFvRdvMSDtJ2qwnqXGR", + "NodeID-NTvmKq2wmTvqoccqpxW7fQd1iGCiGhAsj", + "NodeID-NYrHxv8EfFjM2wnsvXSickbq6XEqwwB34", + "NodeID-NZeTWb3Ri5eR3tim5hAntmiwEWoLVdkDE", + "NodeID-NZfe5jh36pdgmAN4yX3MgafwUFmvMTCXW", + "NodeID-NctFDTRfjWrT5cfC831NNBA12XCLmoLTC", + "NodeID-NhqNSzgKY5HahcosTxbcB887htZgzcrjS", + "NodeID-NjPTsac32vTLnYBmz95TLBmMZZyy68Y8t", + "NodeID-NmGx6qD19PwiQRPwJq5fxfoKc4QUaSYPc", + "NodeID-NmUiTVDryDrut41qnwaNrBref4FMfn9Wg", + "NodeID-NpagUxt6KQiwPch9Sd4osv8kD1TZnkjdk", + "NodeID-NtyTVeUSdkNrAEQo3vPLzrqhQfrYg8f7Q", + "NodeID-NwkffS9VYtwYH1pDJ3xMD5ZKKt3ZAqCW2", + "NodeID-PA9LANCKQbk9Un8Wv4SbBXoDCW4bP9yLk", + "NodeID-PB6nGgZqX8ccEvyEutDiasS8ndhnrakdf", + "NodeID-PCuSoYTWTcZwQUZW41HpW3VaU5ogsAGER", + "NodeID-PEdsT2FKxpXiemSctvHry8gbZJC6bJrF7", + "NodeID-PEsmPuBRtjpBRnaV6gTrTxTFehVUtjDf7", + "NodeID-PGhVwQYM5eidnACK7jQ5ZkL1CnFpKTAm3", + "NodeID-PHiFH2SQRhBFnaNsLVZX179np4y8gjmk5", + "NodeID-PKSwUUGdADabw5br1MosKrSPyyeYdRKAu", + "NodeID-PMYYkxDpE7RPrtmACDaHi6RESLwhoHcYw", + "NodeID-PNXWeCUduveVZYuHRf9Mi6b4suVMJsxSK", + "NodeID-PPCdQBpQ5THZzWrbKAHTdwj5fcx2x3wBs", + "NodeID-PQRNvZxSZi598GNxbH6joNaUPgxaD5Yaa", + "NodeID-PWko2VpWPb748ARPENzdAfak6NZ6pYG1D", + "NodeID-PWnPrE1Sckzuoj4Di5zBwrRc5q8UYGm7j", + "NodeID-PWxEYBRBbKai9U3t8jgfb2SA8uAECKvju", + "NodeID-PYXgapX8Yi28W2Xib9oNDxuaaLkZ1gZ42", + "NodeID-PZATpKoYGFhHosyUfecJXUAzbXiMVEWcr", + "NodeID-PZCSrsorCsvyTxkt2aq1yCMXPxEUm5PGF", + "NodeID-PcZGZ4CzwJ8NEGsL7ccQEgAGZ7AU6jtBc", + "NodeID-Pd7rHrBk8hJyD5uCRcG3uWC3ZwPGtTohm", + "NodeID-PgBvqpbMQzJk61yoN346xxrnrHad8y8LB", + "NodeID-PgXSBGwW6cNMwQv8P7kYXVr5AkJWs7i5R", + "NodeID-PgheFFDtZftKj9mNpEvH27zeQ6c6qvoep", + "NodeID-Pm3TC3M1pWDFhwa79YRqHGzG9Sjvgcdtd", + "NodeID-Pn9jFroHyLVfDmsEruHABa73mpbnSU5RN", + "NodeID-PnZAZuzfg7xchQ3qbCMAtg4bAW9XSx1Jx", + "NodeID-PoyWPaU4f25ev8h5KQYWrnTdGMiN9scHK", + "NodeID-PpR5kKTZTpF2VstAXn4BwNKHeNEvo3LiA", + "NodeID-PqKQwU5B1hzz11kW9BE4G642BMB6xrdnz", + "NodeID-PqZJgjNLDbeqmSg7hMWU8R1a5HCEjbBP9", + "NodeID-Pr6ZsMxfFr6uyMyZeN95ZJ1yHqGrDhqRP", + "NodeID-PrZZEFnhrsgdbWr7hZYBw1vTpLpkntFLv", + "NodeID-PtHsgZydMzwYNT3GcUXmaKptmScFwJkZY", + "NodeID-PvST69voCJeusKj2UGoFvK1UJxuZYWjmZ", + "NodeID-PzPoTUQaErAzPd5EBdRzJeNSFr1kVMX3h", + "NodeID-Q2J1vGj5FvVz5rDST2nC2saG1BeDofUbY", + "NodeID-Q5Jk89SmFTSnxonorozufMhqnyY1RiUQx", + "NodeID-Q5XuPs5dhsQRuGJebnzStvyF7GKWt9JVp", + "NodeID-Q6uYpvGDEJUUqgN1eiiKNkDCfbPCjB11s", + "NodeID-Q7e8iAC8sdAhnhPuegkFchun2yHo7UAC7", + "NodeID-Q7y45kPeb692xEHNUXA5rCdZgDqvQtHtF", + "NodeID-QAnYYbuWU1PfEqVFgZQz9EHKEWd8fky9z", + "NodeID-QBtEYnbWGX5PtbsD1cd37Jx4eATeJoDuA", + "NodeID-QE8ipEQ1Sc56Fa15G6HdCfUFk9SpFRBjM", + "NodeID-QFG9ZiXr7boyFonB2D5B4MLfPHRgQDwLd", + "NodeID-QGGJXjdsv7EKVKy1EG5Hq9GzeFcNFMbMh", + "NodeID-QKheyKgFVkDyMxLcnoUHregsKHFuzuR6h", + "NodeID-SCtrKtb5k75f8KUnTPj2gBsq6yrxpmk3", + "NodeID-SvkCVFNKhd5VEo8Hgdky2TyxZ4J18NpV", + "NodeID-TJvKKLYAycYi23bnFiSFpq9pZBNktyer", + "NodeID-UCaJK1qXng91C24jExSCkRhqE8hSCXWW", + "NodeID-UujvYYJGbxFXh357EMppUFsXzPKvU3sN", + "NodeID-WqHQbG5MYQAYBRzjJV3qqy263mbz6iko", + "NodeID-ZYrkX7KzmDHfRzUhtVu7B1EYy1dCbbQZ", + "NodeID-a4kVGB6zfhfHgz3JpoLY7Yqr6aXM9BRv", + "NodeID-bQd33gr3fvRae95TLYkF6LcuyqrJeKK2", + "NodeID-bpSs3H78Q6kdMPHyy1WAYGdVXhVMmuWg", + "NodeID-c6NmA1sCyFvKV6NeKBndEykD3a5Y3Svc", + "NodeID-cCZxQ6nBdNcPMpKdKHHxm5kjwfR3caTk", + "NodeID-dFaWdTjZH3FryPCs2MTiivJuia52711h", + "NodeID-ei9CM9pS3ePsg2UYUrdRRALKr61jyJav", + "NodeID-fJcYnNFYcnf9Tn4sLVPSyKnpFr7yivMH", + "NodeID-ftRqiSfcMstsADKTtMnHGX8svv95tPXn", + "NodeID-hArafGhY2HFTbwaaVh1CSCUCUCiJ2Vfb", + "NodeID-hpZLLFfwLit3Az5SDfXAtgCsErQfdQ9A", + "NodeID-jRBYRTWyowM2FUvfyZkg8cmhtKwqRYb3", + "NodeID-kCqLujZC9JuZp7sqe3vhffxgMgVwq7bu", + "NodeID-mce4CCkKp1Vx9ck6FwtjQVbTyUSvKe1V", + "NodeID-mwGVBwDPG11rSWCjYwYyqBJJxM3ZEoPj", + "NodeID-oRUBcQ7Lsrxi2S5bmWGD5CF69e2x8mct", + "NodeID-pCZeP48M5cMxycWR5QFfUumPgwKEXPFY", + "NodeID-pQCdCxnzPybSowJ8aNuu3o1w7e7QCVNH", + "NodeID-tFgE4qqgLiivtexeoojvJgSk7eHv1HRU", + "NodeID-tkLPZudEk3RpVG2DLq5jfZS4KHLJf27E", + "NodeID-vDc7LhjzpkqnPoFNMisr4BvijCQKe2oQ", + "NodeID-vZMp41xfebyKTCjNNT8wq6bm2u2xo46B", + "NodeID-wvLAxGEDoLcPaTWzEkmV1n7ipXFiWAA1", + "NodeID-yJAXXBzvB3sTVciXpoyku7uWuvhPnnqa", + "NodeID-z7b2btT1NfrouM5xCJPescQW1QxWLq2v" + ], + "mainnet": [ + "NodeID-12dyQ7nhRzsNSiFzEoW1RWK819Zkssf5g", + "NodeID-13XrVPjS5dVxBKaweeG94SjY1Q6yeM4EJ", + "NodeID-1431VdHCWJgM15Wcg3zaSBYbpXGTSd7Hu", + "NodeID-158YgSNVidjeFx76vtQ5SxWq8B1F3ai1E", + "NodeID-15AuPME9h4AS8CAEDsokNE5KMjLovnphr", + "NodeID-1A1GTyMcDcassSiTBZFVuoXs7AS5HcHu", + "NodeID-1Z67stQzn6v2hi1wD1Zd7nooPoqJE4es", + "NodeID-1aA7BtLfTX4SRXaWR8HttP4z2UapE1R9", + "NodeID-21TUfex3GmhmusTHmp5SDUQTEaCkaXwH9", + "NodeID-22jB4hF45iUrVhqiHvbDETRgpHKJdirY3", + "NodeID-22k7HZj3D9DSAD7ujyvvuYn8XzWuwA1Hi", + "NodeID-22wjev1roSt8jieZ4SW8rJLG3YiWyvbV3", + "NodeID-23NsVPT7XuxbAmisVH2LFwXAN1JsGvCjb", + "NodeID-23Po1dKrXFmpQaRafo1ZEdv8qbHC7i1yi", + "NodeID-23Xaok4Hr7SgTcCjjMnVsYJaN5cSZLR3Z", + "NodeID-23jyZenUu8Fm26ebdyXEEVH6PDoEXJ9j2", + "NodeID-24gzuDUUhGEsAGbxhMZNJJ2x5G1wDVHEo", + "NodeID-25GWqcvqc8m2ZT5ULNWfan5SEJNFBZMcw", + "NodeID-25RzatyYmpsm3QbYj9QdSWqdFQLKxdMR3", + "NodeID-25vUwC2XTURgqbtYripLhP7V6HPrkji96", + "NodeID-26VN5FUvCmFWEhHm2k85hHn4rDqyKsV3W", + "NodeID-28wbL4a2ozWTgYXt7NekGT12h5wp6UyKg", + "NodeID-2A2CytyzFR1r5m81cfUPL4BR2MAAp5U3g", + "NodeID-2BSvxuZFVVSpjrezuABMPvC6cLMwH8TT8", + "NodeID-2Bct3bqbgyNctwUahjFDCF3siViyVBiuJ", + "NodeID-2BjnggzgeiPAgrSmpzf3Hd1r4DTan3Rdo", + "NodeID-2Bq98e7Q94vVWipc5tv9jCL4aMxL7pjxr", + "NodeID-2EH9c6NwjHLZLWC2Ah3vekv3XUwcup62L", + "NodeID-2F2gRAyyVkaNC7jtPzJ4zgcQh64QyMkvx", + "NodeID-2HvkjoRiMzEcZgpWKNAruLKNv9r7Lb2pv", + "NodeID-2HwdM25EpGSt2M2BDaYREmGJrbYNudMma", + "NodeID-2KSietvSEq4mX2C8p1DAT83RTJPykxUqN", + "NodeID-2KfgS6P7vf9L55fMRTbHPgS4ugVSDW3nj", + "NodeID-2L2wFDTAv9Ti1wpqbFzqLbTa87dMw7QQM", + "NodeID-2PZiqgTALZcdU1TUvQeypFARYEgjkQZPg", + "NodeID-2Q8DS1hgPgsaMB1y8VqmxeworYJ2h2Ubt", + "NodeID-2THa3uLP7oEvBj19k4E4jm1tCpT4muhYi", + "NodeID-2UXMFjdXTw96iQHNL23PxH2hcLJUxnWic", + "NodeID-2VJfSPqaevBmiJKSVDnw7GBwsdfgA1XuM", + "NodeID-2WfvcQumS36rdyubDSioc8B5YinToKAaf", + "NodeID-2ZtHY1RPNrq1y5YuJLaCShK617g6CjRsU", + "NodeID-2aCXkeemxpBXiFui8BX1tVpyVsvhoZCU8", + "NodeID-2aSKmf99roSwDq7MChQ5pvmCKoS1qbcHS", + "NodeID-2bRK9nCjngVig5fMFjLhVgqf18L7dbTj6", + "NodeID-2cH1ggEZ8Z6CoKoQsEeZudUy5kEihW4T2", + "NodeID-2dsDfPgPdjhqMfDHskgiwDcqkqhhG6f7H", + "NodeID-2eBu8RjbvCFTZMcxu1oh2oKtfHT7V4zyM", + "NodeID-2eJ2XJDpUagguhE9wKFR9JUxYNaBk49Ko", + "NodeID-2eraCsE3WijaEnkcFX77hbK494TneHXkY", + "NodeID-2ff3RLJaMK5VdQ4jnXELc9yas4iKoKuLG", + "NodeID-2hoNSdthtVU9RE6g4VJ7Y6tGdWm3s1PKN", + "NodeID-2iVvryG4GyPR5XBQebYMMVTFYfsNKy9oB", + "NodeID-2iWqUM3VWvrcTLyXi2KgBLVhunMvFW7vY", + "NodeID-2iY9tRvYLGjeGtjnUGyGbMz7uoaBdZR58", + "NodeID-2itoUKTyTyhGLyN1sYKNiyKHG2UkDGjgk", + "NodeID-2jnJ9jJrW2EULmCCNnZz88HHCAQYo1Bja", + "NodeID-2mWa8ytKEtviCNwmHfSPmDvkTGPLH3kf7", + "NodeID-2nfH8Mmj5ZY6Tx5oD8ebst7prrEmbS4Ex", + "NodeID-2pC9PZWbWLdaxTuXX3zvh4xZ4WobwiExr", + "NodeID-2pNQqfaBqMqwWgeJiqPbmHZk1cUtWcjqb", + "NodeID-2sNYafYrpqSjsGspW2emjd6TqNTtWz74S", + "NodeID-2sspVTzGYqTkeiQeBsdFKv57gWpLg6Efg", + "NodeID-2vPh5nJm68PNyauc2ot6LJgubxBaJbBkV", + "NodeID-2vbdREFyZitz6LvSBca5gCe3eCPHZGq3b", + "NodeID-2ves7JhkWUcLfPWWtKVgh7uvJogz8HLnR", + "NodeID-2wWroHMggzJvKh6t3tdPtJTTP9DNmdc4K", + "NodeID-2xWeMjBPrnJejBo1vFiyNZzy2FcquZnae", + "NodeID-2yC7fWX23kGjCd7ytqGzQQcRJf7xaj1N1", + "NodeID-2yZivvmC5XD2M6CwcVVBdPGGgU3MNta1o", + "NodeID-2yrtwg1pRGi9jB6ayaXgpNbMTeGHUyofw", + "NodeID-2zzp8nVwqw7ssQsMXniESwjwpZYMzeFsa", + "NodeID-32JAXT6PVdHqpvDuXXHfWrFLXg8oZGqiv", + "NodeID-32aVnE9HYv1FesKKbvvUh1ZvFU3ARNtR2", + "NodeID-32dhPQyEQArm4ybXTxAvAAWAap7DkZAPh", + "NodeID-33Ztk39cwheRHZbWLMyrNFUea7y7VoaWW", + "NodeID-33miCHPn9eN8H9Yi4bCzEaL9Sc5BLeKMg", + "NodeID-33sja4uJHmJ3fpDDu5byuG6V8icdSAke7", + "NodeID-34QP8d17f1XjB778dCTCsBfjL3T4PeMAf", + "NodeID-35rq6ZWsLWs3coxC38LACEayLh99jxMav", + "NodeID-36Vywf4J2tu9gA8xJCxZjwi2JABWSF7qo", + "NodeID-36i6jQQTfB6Z8NXFPQJsY3FVukaSGKTDp", + "NodeID-37Aec6FfbDxVtjLNUv3bTsaXWaw5EGUrM", + "NodeID-37ZMQ9ZZ4e7ZD1kmRg1WSTpRrEPSQ5LGT", + "NodeID-39ZN7XxaD4si7XdTrhiaPJfQqusjzLP9M", + "NodeID-3A2diR9QLdWU77zW1sS39tAb1rSYexhSG", + "NodeID-3AUVAzMqQ66svzG1H7JVgURhUQHU8Y3r7", + "NodeID-3BmiiYjMNvspTqKKo4fXJWbjDbaaWRNXE", + "NodeID-3CHc7PuHw5sGxtSVjujpHRxgiFDSFfucK", + "NodeID-3DwhPYMEQABuocceWDAZEpi8GMcLyvTYy", + "NodeID-3DyUWkRptB3CRUVHk39Ni6Dpr6QvGWXwA", + "NodeID-3EzewMeb8MrVyWam8FhnHPHPoKsT7ERXM", + "NodeID-3FhRFK6UxSfMED5EkK7jZT84pFZy9f17D", + "NodeID-3HLAgdaA61zPrTx5yQ7Cc6waKWidsiqMT", + "NodeID-3HvUXQy1siDNUBGWMYxwMfjufh8mxLtQY", + "NodeID-3JSPJv6xHFBekjausg4m8e5JP7UXSPWj4", + "NodeID-3K3PUAqo3cKxRoQyYto1EsXtuTHoDZ2B6", + "NodeID-3KAxYX7JeLQgm1fwzVqbzjow6eNzSS9Aa", + "NodeID-3KX9tgCEQcTHbC8W9yY4zY32Cj3ET9MNQ", + "NodeID-3KyemFW2jou47TCfoJG4YQhtCDd6Si64q", + "NodeID-3M5i35f5u99QbBn6fP1FzeAto7NA4TFKt", + "NodeID-3MFu1eLpGRrRcWksHJLBuk516Vk5PoYgC", + "NodeID-3NJgvio7B47MB7BZWm31LHzbPWVdkEiEP", + "NodeID-3NXS6ZAzHeqV7w4saG4vXxAd4tcbpmxfk", + "NodeID-3PJY4Rpb5BRR3xSUvuU5Dj3cyHcAmzfjD", + "NodeID-3QvnmD9KrJt7BcoYytWfCsCD83TmKo16d", + "NodeID-3ShFK7JbJ2LN2gFT2W4iXp4N2NVuP4vZC", + "NodeID-3TWEGuLyjvyKYLQqXNvQ7GQqSNoSQrviN", + "NodeID-3U6UcmBu6WVCgodXYsH72VwVKpgE4XomQ", + "NodeID-3U945Ju6EUzVaiA25ea2BvaapV111iqcW", + "NodeID-3V8B3h9bS1cQerQMF47sw8Tr9jmJz4uHG", + "NodeID-3ViTS5vVn4uLoQQ5d7Qs8mF5eYvgQcLQe", + "NodeID-3WH62agC9m63q5SmAyPvhhLygsUjboQe3", + "NodeID-3YkLrm1D9MqZ6K4YTwaQkt1NBb6wP9Ldx", + "NodeID-3Zbddv2qkn6gWAfd12ysNN7N9EsDTjc9v", + "NodeID-3b2dLL4mSiGK2gx9pmML5n2Za4T9pLHe3", + "NodeID-3bciNCJdZcW5k8jMtHujT6msFbGMotkSF", + "NodeID-3dan8fxgCWWJZpNUkrBBEw1vhL8E85h4i", + "NodeID-3douD9GDP69zSq1eMzRAYfKCUVtjEEUCt", + "NodeID-3fntmpjeW5JhEgbVfKT9fy8xeaMg4tquo", + "NodeID-3fuaS8gCD4cWtgZDCLrffU17gfHUNHX8Y", + "NodeID-3iXKmHPAMgJa7z7pGcPpMC6pAmx8fjM1q", + "NodeID-3iknBWGJowmNu2d63Qv7mRM52xoQ3mCoB", + "NodeID-3ir9ZQxz7rrTVDcfieFUHcaVNVhV4ysUR", + "NodeID-3izZtcg2iecpF5rEkQF7Mwofd4puVGZwz", + "NodeID-3kGMSCRnasr5CjsgNm1D8FbZnY4C5iNRE", + "NodeID-3kTMjX1jJvdH2S94GHLi6Qxy1DKyLhuc3", + "NodeID-3kUUeZB7umtaENekUfWxa1bxrAU2eq1AD", + "NodeID-3kpT5aLGx1dFdDY1Dfn3qPH3qYkoj9dWy", + "NodeID-3mvtMQ554k7VbrbYFUaNZR4JmeCoggD5P", + "NodeID-3nuVL5JFrrumBeA3xqAk7BqTkRpu5mJsh", + "NodeID-3oJ5XYknQTmDrwTkBxLx4DCuFgFKFP2h6", + "NodeID-3oaegcGaKyncpiWQCzEVd7vN1Vcsue3Wc", + "NodeID-3p3GjN8gxjGNpFCEKyErnWoXJGENDdj7W", + "NodeID-3p3zJHazEyiVrhRXKL6jJds5esWnwzbW4", + "NodeID-3pSYSkZy99npP3NS1UfES7beUM1y84EjP", + "NodeID-3pfvvxwJWQb1w7KrtGfGhd9ZtLZhrBrBc", + "NodeID-3qUq9jKXL43HwdMEov6KBsnCjcvWXmAoF", + "NodeID-3rw6bDxFFNVoRnZmBAnTV4ZEXnkjooVq4", + "NodeID-3tTQWaeudKziFWpbmzbawLJTunDsQnjnu", + "NodeID-3tjM63VDvTaHkhzxWxV3zrnJjAfHFAgfC", + "NodeID-3txc7u47G8EyCyD5aSZdTxeVdhAWSbpoa", + "NodeID-3vkjzH23PgBPmHixW9xpdUD9vndf6ffBZ", + "NodeID-3wd8cyGCDmhuoZYWmNDab2FhAVpnKYKJE", + "NodeID-3xmutK2VUntMTYcAL5F8A8AYuDcyeAZ4K", + "NodeID-3xtitFQ6k29E476KCq7a6CoZtDmUgKqmQ", + "NodeID-3yiw3g5Rer7repmzoJaATJpkf7GnWD5j9", + "NodeID-419QFcweSxfj2ZgxFMR619CkMNupjpAW4", + "NodeID-41CFoAtQx8Bqivuq3tkg5oqnj6WpBz32S", + "NodeID-42kmqmMDkmMyw2q6gS1uLi4wiXdC2NLwW", + "NodeID-43AKDBv1R4hvnt9bjDFA4SEcwFMzZqpXX", + "NodeID-43LKNkQ9avhKgVj7KrHXjq1bYi6mvxQ2C", + "NodeID-45hNv286MEyVSjGrtiYLt3qqnj8G7FecS", + "NodeID-45kFbHHYtgXEXEy53LCaLMBE8CA5XEdKL", + "NodeID-45p6WjZk3E9Je9Sw4q4SvEaagbYF7Jsud", + "NodeID-47pbycgGRRWtAB4FZ5fJZApoeG4nzv41U", + "NodeID-49LTjmBTcdjMyD33u7gKkfREPqEhhfPaj", + "NodeID-49tGSAiEbwhRcTvnu2EaskxZPiPb9Lv2T", + "NodeID-4ALu7Jfcp5S7S4BXnQgGXMZ3rm3fQkxNR", + "NodeID-4AW19ZAJMCyr64UKfFAUhZXuZDtVshQ36", + "NodeID-4AWHc6b817tKesbKJ22EAEsJa4GkrDuNE", + "NodeID-4BQYSFMqtFcjNgwS1bQgLnzvoKqqMx18E", + "NodeID-4CJDfSDWT9X3hTosPsgui1ZRkBNRhX6jV", + "NodeID-4CL8XnuYqfVVLxRre5C5A1dpRv3cZN2Zs", + "NodeID-4DHwFAw2xZ8HuSu3jFzMU9cXvNhUHCkZ9", + "NodeID-4G6U36ehMMYjJ3C9gzLmYRzQFho8c4U4w", + "NodeID-4GFFG65jrNUU3X6vsZKgUhmz5iCG21nyS", + "NodeID-4GcMxoKhvXDebqgeZq2zKWPgQZF5aDPm4", + "NodeID-4GkgAWZzSWHi3hZZLjLGes5HwuJ5FXDuj", + "NodeID-4JcnzK8FQKGHGMt5EQHRWgBVxxdA4sFy7", + "NodeID-4K6rXew2J41T5LTWmTi8AjMbUFsidXGpE", + "NodeID-4MqtiVkCYGD4TmoBhH3b6a6UTGNrPhvvW", + "NodeID-4PKUhJMxeL5C7A5epar2X5TAAzXLqH44r", + "NodeID-4PTYheMTMhPZvYhJJ1Hj2FwCZSR6rSWsr", + "NodeID-4Q7EdeK1p9JkHULo5nZ9KVwgWYjDjDf9F", + "NodeID-4QRHMt4aejVDLqY1VNmSXnLxaQiZoZbej", + "NodeID-4R4zmBEWqY3dCtKHmvDd56Dupq97UAwtP", + "NodeID-4RV8eRbw9andBLK2og4rtt3W7txBmSuxA", + "NodeID-4RVd14QquiKdEXitdrnTuZiYpaBY1W6QM", + "NodeID-4S2uvFvPmHh2Q4f2To1XznG2HMsyohuA1", + "NodeID-4S5sLovGppHvP9uv4v6jZHV7JtASRpUUk", + "NodeID-4S6TMWiPdBW55NS9ZU95y4aHTBjUqr2eh", + "NodeID-4SkHqMZLGsjBmMXF7Dnpg7tYESgo9zAC8", + "NodeID-4SvFyvJPHPYvkMnJqBaNcwr5yuU8sCsem", + "NodeID-4TSV8FnyRHrVAmPALXfvLnGaHGspS5W2R", + "NodeID-4TaEnGcWM77nvEityjYDxB4zYdLQ6LiZ1", + "NodeID-4Ubqsj2vfwdGUUYNg1jtYpkYNNLugNBQ9", + "NodeID-4V2KBeNd58jdBXej3ohL8E5d1bNTTp4tT", + "NodeID-4WGNJ4vv6bH3FLCJgovqn3D7RCJ8rKBDR", + "NodeID-4Wt44Y2AAuuD8iRvFfh1va5K7p7v697my", + "NodeID-4Xw1ekhVqhHqzZ4pLTPtofbTZxpkvcQNi", + "NodeID-4YLHgpase4iRi6a4wH6c2jUMdWsKr74j6", + "NodeID-4YYQc96D2kyeXh2z5Eb9U2owhPXKPJgS5", + "NodeID-4aLF7SfieaFRqFtLBKo6eeEbQbpVYVjoX", + "NodeID-4abzhcVga2Mc1BJYEfypmRVtVctYwsvpx", + "NodeID-4bKCgF7VcG9ZtcfMwAVFfBJoh2xDgvz1j", + "NodeID-4bajtcpjERHRChiaYpovKU8XE5qAE4usY", + "NodeID-4btZGj8TmrycK22kwgBK5wJEFighAFWiZ", + "NodeID-4cJyBoufFfiMShtRhcd6WGTYdvUCE3Ai4", + "NodeID-4cuTK1XYjm1VMTitd4MPBcwZ7LYyiqjfd", + "NodeID-4cw926TqMXDNo7QyraCShjWMXNSCDZqMQ", + "NodeID-4cwQT5hvhnhgYM7kJia4MK5kT8XLVZSNz", + "NodeID-4dJTYbWkF82oeT3gYAjoVNNbaga2zXsy4", + "NodeID-4dNrRsASZXHs7XdZ1sPuj6kKWs5bdqHZ9", + "NodeID-4e1C32U5TBUFuQpykL6rSw46RijbjdwRz", + "NodeID-4eaj7e8pXaR1TSuCF5n7tKDCHPPemZGky", + "NodeID-4edDKb3xKovZjTSuFbhNzJZ3Y9KTAzDaQ", + "NodeID-4fK92LkTyEUzPoDW44Bo9b5YvL5kJ7369", + "NodeID-4fwq4Tcz2ERoDWDzcow2JNmT2KaxtJrjY", + "NodeID-4gTwepTF5fcacXB7gdYZLTtfSFsYh4faj", + "NodeID-4givb8yw6262YETrNnm4hTSRPeK4qEBfk", + "NodeID-4iabwkRVrx3KWgYgFuDAR23EZna6rjKxc", + "NodeID-4jvscnKzJyMUpbsZzfoaZVHd2ez6Vj5ad", + "NodeID-4k9FLLYj63sJNrrGycj6MTRm6JqyacEav", + "NodeID-4kCLS16Wy73nt1Zm54jFZsL7Msrv3UCeJ", + "NodeID-4m1TLqY9ob5u23YrJx9zWDj11dz6DmV19", + "NodeID-4nc9Pi32BZwWxcM21U95mVHsbExbPSmkq", + "NodeID-4o17gdHmyD1dWGxwez5KqKdyLDfiYmPX9", + "NodeID-4oA58fddyvuKuRtqanZtp8V1Sz9mbr6sS", + "NodeID-4ocksMuoXQXnBH9XPRnH8j5x48cLLpFmC", + "NodeID-4ofBXitDMQ6QZi83yvPjCYn5LG6HBwqSn", + "NodeID-4pZqGB9JdyanFMVQEeq5VZ6YG9yZNsCF8", + "NodeID-4ppYtgngzEnrgBZ7JUVw8bTbaBD76efcR", + "NodeID-4qzj4sLxsLnmhhktyTyR3BWXu8nXTABnY", + "NodeID-4rqntan9eh1AmkCW7RNKwzVVB1r6hhnxc", + "NodeID-4soc4KzELnfnTLLw4FTgpEefZpE6aSQbw", + "NodeID-4ttQXnMSk443JHiMCRaoHBjjLArwEWbya", + "NodeID-4uHXbHesQbAzcDBRqaFyJ5kpgovHpU576", + "NodeID-4ux8p7PdNGBzrcwYE9U3gHF8ehb882VGp", + "NodeID-519R4edrXr2qJBZnFX7X9dJvo2JjJcesT", + "NodeID-51wXjrXuQkpHqgnyZ6pgQVbiBwTWgVQZi", + "NodeID-5517ZjCrBhnLs1aqw2YVqRopDnAu5z8FT", + "NodeID-56PBmfRBSmT2sYsPLiBPKVq2fQUVGEg9g", + "NodeID-56RnA8AJBddFSt2rrGu5WmsZF8qW4zNeP", + "NodeID-57VYS3UDdnkurTnK9WVzfpNT4H4V2fCmT", + "NodeID-57o8JLPG29tydZsDVGuD8iBZ3rVorYeoB", + "NodeID-57vP1ZP91HztWSRTHurGdrMSw3TWHYumo", + "NodeID-599kjqvHr1rEhyvT2mFA2whFJZS2Yoexg", + "NodeID-5A3vbPTyhDj14bLRCBs75HvsjMJ1h32FT", + "NodeID-5AzNzec73Pth9Acw6jVd2BYZWyY5KjV6y", + "NodeID-5B2Uyysf1nWcRbiCYdKwXzevVF5a7sN6T", + "NodeID-5C4VhhoWhTJ2LewfxQNvM6AKk1o5oHS3o", + "NodeID-5C5QEUprYutWMbxYicmQd8dUFhc4eh6TW", + "NodeID-5CDfrTrcGndVpY6qtuWsKWLm3j93GXyey", + "NodeID-5CwgaeHgQgWbeaMB2ERYZ1ntrhKCmSs5D", + "NodeID-5EuG66om4jxQDK8hRFyq89SsMqfdvESew", + "NodeID-5F6HiZ34F4oRtMX8PZoJcfvQiH7K9mGSs", + "NodeID-5HkCsXm4TQUb9uXxM6Cjy1WzvuDSspPui", + "NodeID-5KGMoDk3pwPz5LgQ8FTJ5jJXJFnJ9CuRc", + "NodeID-5L14VfdhVJvi4GowA2zgqj78bGriVMLxr", + "NodeID-5LGFWx2kfwMZXpyG52FkRtrfYfVRimjh5", + "NodeID-5PMCtewYFfdxWmE5gcxuZeXAQAxHqMhu3", + "NodeID-5PMGUqdapvGYEATmbQ48hMJTwcYyKFNDg", + "NodeID-5PeQVPLrJH9xiSQZ8hcmeXWtUzhcArEhQ", + "NodeID-5Pg156uQvovbZQ3F6JKUiyAg5MrdFseMP", + "NodeID-5PvfcnfPd3MLnpq4MujxvBQHPwtdjYk8s", + "NodeID-5PxpmHkfB3gNh3spZWuzEKis3DJ8WKxLt", + "NodeID-5Q8GBt1GY6fUToWZ9txSGzWr8QTDUXKJF", + "NodeID-5QzeGmasNDHSxzxBqiUQ9TBPqkkwzJWGe", + "NodeID-5RuEXmu7SJpf8bwuY17UpMpoEsGZRWnuj", + "NodeID-5S729stbM7nFyWHdsoBeFzo5NMUXaTrjR", + "NodeID-5SmDUGU8WwZkvxKMnjwKAYvfa9w2qEe1U", + "NodeID-5UW1pHAXDJi1tRFfGSEgujuExMztq6sCc", + "NodeID-5WCpR3DKFt9665Wj9jDCTdncLNX7AbzfK", + "NodeID-5YX9uqiPm6hmJEmDy2fUyvFEjvSvSbiWE", + "NodeID-5ZXpg581dpjG8AdoJgTDeXXLnxrQc9Wtd", + "NodeID-5aCHiSvLejirNRt8Xgw6SNzd1dDq3XviL", + "NodeID-5aQHgP4cTuyentoPz9KK3y2anCBYyG7tG", + "NodeID-5aiXb9CdCDJ6vRmJ6reLPehKFeKvdnHxy", + "NodeID-5bJYpPDsUq3JpGJrFjVRtr1GybXQDP1M1", + "NodeID-5bNomTz89SyKffJWnEZGXXdwvSnZanVTS", + "NodeID-5cL4dSEdWWKnzZxvg1rqen4M31YeZhFkf", + "NodeID-5dP5pp3AQeD9GbRPbhuyXfFcNsU8RsgmM", + "NodeID-5eFuL1vXb4NSxW4ZF16WZsJM3gyjS7i2Z", + "NodeID-5eVCCzU5VQXhj2iqpqneRxTUNSD8aCJki", + "NodeID-5eogZcASu4bDhWxMuUF6h7VFK5SCt3msp", + "NodeID-5gcdejFBQ3wMPFpo7qKUKBREJ8w3PRTM1", + "NodeID-5gmMRqNob9UjcgroCKH67bQb9PVwtnoeD", + "NodeID-5h3GjwRs4cndBMxxfRpuDMyrX9SF9dPoe", + "NodeID-5hNGcpQHUrBDd19vV5QcugACUAmwiWU3D", + "NodeID-5hSVoN9CgKTxGVj2M3pXBDBYtfZkjQF1D", + "NodeID-5idht8398Yg1AqYyBkTQf2kN7zFK1J7Qn", + "NodeID-5mmVqScHrzTiSa2WVjo99g2yzL83EBS6W", + "NodeID-5nWWPwUZPzdTJYGXJoWxzWj3Xm63vLL7p", + "NodeID-5naWZjifbRQdBoW5bDtAcvuFjKr3k6G2o", + "NodeID-5o4eWuhvE9cmScEoZHr8ngGebxa94rFLo", + "NodeID-5ppnn5JSeWMAznssuPMJujyJhzHkXHN8E", + "NodeID-5qr8okF4mnAB2JhAvaJuwqMGXN3gi9QXD", + "NodeID-5qxuSbJfb3xqgNQ2pFycD4ybuEH3ATg66", + "NodeID-5tUAsBWWmhHrLnjmieom6twf8YREwfosQ", + "NodeID-5uYQ6R4WF7kmGfraM9LtsUJG2CDmh78Lf", + "NodeID-5wCTAXLJSc5i9RpksPG5fFZXemq4dm2A6", + "NodeID-5wQr9SafAyQ6BKMjtTomLB7Bc4tg8iYD4", + "NodeID-5wUKLtxUEckPyuzLQSozcPmqVzMRx6v7j", + "NodeID-5wf3A9TPUALDHaRhufq3Ry4jfH3cA9SEe", + "NodeID-5xEL4zcSuMjZCEzY3WhQ81Sb1Pw4E5VL8", + "NodeID-5xhFgBpc99AjBEXqfzNAG3W8mX8vnmXWZ", + "NodeID-5yYNsLs1TZoj93f27GD1CBr424tZJVpVh", + "NodeID-5zENHPe3oP2SdU13oTAvxZA2cEupejYhD", + "NodeID-5zP7p1nk2KnAL4SHvgFWcF9Xei3Q13CC3", + "NodeID-5zWQQHoMSd29NfKUMziBuccvtt2aahnHH", + "NodeID-5ztBWB4caxbw121xfsXc9JqsknrwxrRob", + "NodeID-61nHqrF65PzDx4SeUmaxrdbBLHNxGfv1z", + "NodeID-61rJbupdhGqaumerueZFVVJT4Sbp4fciN", + "NodeID-62XYpHtuv92hHhJJXVd4wxJqPFv9rbWA8", + "NodeID-62hEBGiabBK34vV52kGT64T6S9QVcdMVN", + "NodeID-63JGDZZtRyCMUiGmqQcL2rxXx4MrbNzNt", + "NodeID-643Sjdbh4n7krQXPSNbSK491xfVbh3hqy", + "NodeID-64Y4Dq4dwfnhTjNnZEFjCexmc2Wwi1fyM", + "NodeID-64Zz8dh68ypXYWaUcfkXDm9UuG9VNXrk8", + "NodeID-65KSgMC8R7CjSQoyBc85UMjW9YZ1cTKke", + "NodeID-65zy7gGi1v2US2tkBFfjpwuDoWVPjPsZW", + "NodeID-68ZngAKzsRbzQMq4CpuZ41J7AgCDEijPp", + "NodeID-69vkfdsq14i5HZSd6m2kUwRAu59ePbeWw", + "NodeID-6AKFYXuxWErAD6nqqFkPnbwHzXB1JC4VW", + "NodeID-6AXAfsfvp25QX5Tff6Ag6ERLXQ577wurM", + "NodeID-6Aed6k5Zj6vffgNdvr29Z9VcdDxk5PoMq", + "NodeID-6CGouDLcYyiuBY9xEi4rEaHCoBzH6UQrS", + "NodeID-6DX3ppjVpWsV8EUihpbRh73K5dGXBSmGr", + "NodeID-6DqFjxDUK7nh68zrFDE7iHfVsXvoM5yzt", + "NodeID-6ETncdUXndB43iT4LijRYLHF711gWeAgJ", + "NodeID-6Ef219qf1xYjFL5SCFQo29ZYKDrcNi6xT", + "NodeID-6F2LZ5hykkwmnRYYabqHH19MnzknJ7rij", + "NodeID-6FSSZuuLEZ4sHJZGfpY4Wuz8M3qnK6ec5", + "NodeID-6FWuMoDyCe1gsmeQj2RsGBmYv1hoGUbzs", + "NodeID-6GEno5sempCQdCZvTEuPZpDLqVvpN2JEB", + "NodeID-6GuJTV6P89ZgzzYM1CJbsuMuVTioUMmuv", + "NodeID-6J3LY7ojkK7WCZzmArvxEozaESDMb42hX", + "NodeID-6K9dR5Dx8YkPXzYeNvDRBionRmEo6HGE3", + "NodeID-6KsZqkvobK4vUHJzo2VdwxWMsbHtXCZPb", + "NodeID-6LHDq7hq3PS1xBj7cFQuvxozaM2hJXheF", + "NodeID-6LRbs1K2iPGmhn1EBbX8u2udyPbUt5S5x", + "NodeID-6P9u3TyWn6jh381HSZP2uTyf1JdGBLqHP", + "NodeID-6PS1ECxRbQ5x3wj31utVWecd9Xkgcp8sb", + "NodeID-6PabAb3cYifZm2i5Trr2BCaYyy9TvYYKJ", + "NodeID-6QD1KNQkx6wj142Tv6demd3FYbghQvCM2", + "NodeID-6QpAUeTWNKyVo34r1LrCYpfNtUwUqXNMB", + "NodeID-6SwnPJLH8cWfrJ162JjZekbmzaFpjPcf", + "NodeID-6TG73ofz7EU4keEwv6jt2xLrpaFzqXnYR", + "NodeID-6TwryrqyRkE3evDcGCN1C95TaWzkXicQM", + "NodeID-6TzpKmXTYp2f1ok4rEzEAgP5b87FSQ9G", + "NodeID-6UMb71Emubx62ZEsNBPhhuEzZdqgGpKZY", + "NodeID-6UpNHJdkRQM9TRX1m1wb1sfNX32Ze7ZhA", + "NodeID-6WwTZqp76ms4iEUepaagpeEsf4N4saDGb", + "NodeID-6X1FD9gZjzSfGP7E8v9cxXBo2ofhHLfGq", + "NodeID-6XwiaBfuKwKG761Bc28jDAsiFJ2gDuVgQ", + "NodeID-6YNW6QK3JDpCaEnVNsG5wsNA1SvxT1dhP", + "NodeID-6aZ3KyGBPTcn6NF9K2jpvxTjhhDjks3Ev", + "NodeID-6anRg13mVkUeZmpjf2Mm41sug56BH7Jof", + "NodeID-6cRZQD9AsdBxSPSoHcBfqXeSAwzKNYsBe", + "NodeID-6cem8uPoUwQ6o45VYS3D5mmFFzTuNC2M7", + "NodeID-6eLQBH9yJUPLiZGXToPxQPj2gTWv15Lf7", + "NodeID-6eS6iDVjh54ww1pGHmCAoKiDhkNGi6xTM", + "NodeID-6edspGWTTSWm3N7Zot3kGrEMHPtLrK3VW", + "NodeID-6ff9kZ7ct7e9PvGKBfbMHJ3MJaMPCmyTE", + "NodeID-6gBKuwn1xHG9SmLZKprpSjWACGDUp5k9r", + "NodeID-6gFsNyzYU474fgL7t7x43Efjbak7Vx7Wp", + "NodeID-6gRx5vFhuMTDtaRYP82ZSGuBq7eR5s3jw", + "NodeID-6ghBh6yof5ouMCya2n9fHzhpWouiZFVVj", + "NodeID-6gi5JXkZSZyoZ28CHU6TDtJFVRy4e21W7", + "NodeID-6iLoGX7rEPJW2GZMekiNPEDNZKmsbn3iU", + "NodeID-6mSXCB3r7oeP8Suy1AWroDY2KEF9hT9Mi", + "NodeID-6na5rkzi37wtt5piHV62y11XYfN2kTsTH", + "NodeID-6nssFkEQTjVRoWGdMfkkYJc6wMNYdRg9W", + "NodeID-6o65ccWJmdcMSDkDphL2i9ajLCZRsvAfj", + "NodeID-6oBNaAUr67MFY9Gtu4eis7bsGY1RswvAR", + "NodeID-6p7pSJ2hoYnpRAXUt14cr1tsA5kEm9vXE", + "NodeID-6pCQAcsrwzFfT8sYZeT8cQ7f7aF8S87TM", + "NodeID-6pShVkG6mZsinZNWZr48xvQSuSnmnyh5o", + "NodeID-6pXaVajr1G1nj8Z4rEXisGUajXGcFPh14", + "NodeID-6pm7qiab6Vt5n47MdeNGuzKx5Jy3Pxwu7", + "NodeID-6pzGb1VVyQT4RLChXUQYfhvjLrqEmWiNi", + "NodeID-6qPNz3b5VZpMWkVNjmLmpBrL1sYxr38bs", + "NodeID-6rJMJqgEbTGJCv3hBzDaY3axQ3Fq98yFX", + "NodeID-6rjd7h5dPJwVEytA9zm86ZBfqEfBuSjKi", + "NodeID-6rtV2pPKXyf2Ek7nWnmuzdiXvk2Ma3ynn", + "NodeID-6sLdnpLBDDMG2eEzgdiGjTkne7a1iETEu", + "NodeID-6sywKjSw7tS2qgFAmLSyJR5D6oB2BHT3Z", + "NodeID-6tkBfGVTgfpbaiv5HFX8LpfKdu386tfwr", + "NodeID-6upkG4FRNCoUQ8nz2by26m5vdVSthXCtK", + "NodeID-6w8o4bbNdVLscimLv4X6BA7QuSqX37TFL", + "NodeID-6xPTxaGM5hVHVKKFuC2MjpCL7ZD6xT3wN", + "NodeID-6xQ5oYAQ348ntvsshCMMSd7uduReey2wC", + "NodeID-6xai7EXhzyxCUyHDrtLTYT6uRCNpUfRHB", + "NodeID-6xjnXHhLrLDafewh5t69uRqtHea75RSGv", + "NodeID-6yS1J9HFdHgdX2ruW6XMouQvECDF2Fta4", + "NodeID-6yf4tK8VmAKhQHC7tdQwy5FTw39i9mXVV", + "NodeID-6yi5sG94i8wSHhqFuuUip6RuZGkKDHzxy", + "NodeID-6zcpV968BV1e3BrZoPmcKuoUNRcP6vjxt", + "NodeID-6zytvHVN3xs7VRFG8RBhjWVmcvaYxWHDo", + "NodeID-71ZzUv6td3aKrZG4LhGDDAnjsEcEchwDe", + "NodeID-71taHoSLZsm1Aqe4spXKJvNXw3o7982Hz", + "NodeID-72D6UYvQjfgKuSrSFtMfyCtHq1jZZ2gN6", + "NodeID-72ncx4NEgf4cziN5GPDRhn7i71rgwH1wV", + "NodeID-74oLbJEptxh1cVzvh3QTwaykED3FXjPYK", + "NodeID-75PnenZJE9PQbQycTys2zonb1atGLsbX6", + "NodeID-76GDFDnZW2ihXCsum843HEDmrvcVuMDZ5", + "NodeID-76KcZZBhWfiWuFqrx21KyeBHdXxsaVyX2", + "NodeID-76nqFaqDGakCDcm7kDsgP7GJn2VSM33xh", + "NodeID-77cf68EUcw4pSLJcvjBNNgxUtxNoTHjNX", + "NodeID-77kWbGy45j1Scbvgh5z3zhoUBL1S3qjAi", + "NodeID-7843EeyboY1mZSmdzjqdJodxHycNn7Kv2", + "NodeID-793wJG3RHeLFVCXkNTQxsM1pSUHNyDyMv", + "NodeID-799wg9bHu8gGe83SHdioqQ6hUg8QCYRv3", + "NodeID-79NUUnbkpDfvGzGtq3Q9FArGK9D1Wzpgq", + "NodeID-7AVurguoWJggFMe8WBEBuTzZjmN8AmN8y", + "NodeID-7AnPDxUDnyU4p5YgCpooC6xx1tCfrMHhf", + "NodeID-7BvjRu2P26PSUXWzCSh8LLxLNdSpHEq8f", + "NodeID-7CQwXe5Vnm7hzSQeWDRXqUsGDc5vcPBfZ", + "NodeID-7DR9yUKc8S5d9xwGoaT488hRn9LiHhKTz", + "NodeID-7EEYbCpedmA4bgHnnvhx4zXgMUpKe5Gkd", + "NodeID-7HgUf4o1UiEGh2Z2tWp2erbkn5JaXYYZG", + "NodeID-7HsxnZQnGRWYG5jFVWDX2L26zEAYaUwAP", + "NodeID-7JijGwmqUuditkaCwdcCAr4Xc6AAMy89A", + "NodeID-7KKSDmFVJ4YXsdcnxjDnV4girXR32yRni", + "NodeID-7KvAj74Y1Aixv1CRWfNMGj73S6qsSGzhg", + "NodeID-7P5SGZLFp95WbF2yv3A9WbQaQDzqfsAFF", + "NodeID-7PUdh6Mzq4NfJR6wpng6cRAYDraESgWCe", + "NodeID-7Pjqo8qr8Gd78Wmzgo5xqF85qcafKQ7W6", + "NodeID-7PsjAayJQ4g5wiQ4QF3qokruC7aSUMqDn", + "NodeID-7TepNNPHs1pGnMS994Pm77YFdSKvghvKm", + "NodeID-7Tv2ubT5xnAXWNRf8X61Eyw7VcU9J1w5b", + "NodeID-7ULxX37k6SSaTX3oF5RdrxL9r5aGZu75M", + "NodeID-7UaxuvJw9C9FytVkUjRCQ3csmDiNzujGW", + "NodeID-7WDMJNKYqJ1yNbPLJrBZubqf6LQrtTw3E", + "NodeID-7XrrK8iL25SJfWrrkyz3gZSo2t5iEadvL", + "NodeID-7a1GnsoFxviSiL8gJyFqrkazv29xY48mr", + "NodeID-7a5FbgWRUJeRWPzyidAyL3ENC8wQDJ1eK", + "NodeID-7aBosQAfHykUE3rmubktp5zZtZmavTzow", + "NodeID-7bnk7Pi7ihTpoyKndMJw53PVM3DJ9QKZ8", + "NodeID-7c866Md3Geveoz9G9XvP1TroT4LKdz5hL", + "NodeID-7cwvfriG4LFWV4iF89E7GhYfLB14hFjMa", + "NodeID-7cyp41vXvj62jBRh7y2j6VjLXhoJ6Hoab", + "NodeID-7fJWXpi4Bj2XgeVXG7Tj3JkNNrGnnJhdp", + "NodeID-7g7qvfKvRXmPZAxhBMfj8XCGuWVVHexHe", + "NodeID-7gLtM9D45daj6WJfqrT6uUje4muznwKwQ", + "NodeID-7gqKK3aZ6m81v2138yfc4fsAdzFHsB3xb", + "NodeID-7gu4gthY5YhpmpUpQvuAy5CDDvDs2yEVt", + "NodeID-7guwrZEeTwM8EZ4eULA3pw1f4ipfYFiLn", + "NodeID-7hQFksPPW1Y5hZukNcQn6bTQjuTZPnj42", + "NodeID-7haZar18iKUdnps7YZEYbJCSwnFw4KMY1", + "NodeID-7hnK4EoWzm7V5qFPqJvpcRQti59au2BD8", + "NodeID-7iFGXSHq1R8MvEM88EkS64rW5z7MwukYk", + "NodeID-7iHpsauHYyQoCjMSZsXJkqXodq7J5eXTR", + "NodeID-7idSkp4X9MwUacdNn32NkE9SXo1XWveLj", + "NodeID-7jqH9PXuyYhoTaaQDAF1eVzLtCVSgmSpz", + "NodeID-7kfCqUsmvGEEfgas81FXNFx833U9xZtWL", + "NodeID-7o1ubnZAYsiV5DUD5R5oDYXkQQvWo69i", + "NodeID-7oHSQLPBV4EzZurguKU4a2FUvPxShuVzf", + "NodeID-7oKBFksJjAcBCNEY3ZcRLQeXLX7iA9dNE", + "NodeID-7oaj9Yf8Uy6PRhqjHyv9oUyLzFMt8DgrM", + "NodeID-7oyvSG1pLLp3zf2ouSAT6rUeehDuQcNtQ", + "NodeID-7p8akVY9Z56XkLykaohLpNGp9sU9PLTvh", + "NodeID-7pDhCWQKNrpCjTL6tB7uNvBUnBQ5amgob", + "NodeID-7qZBqVK1XAPXPqA6jPeDwimDqMTo1ZudW", + "NodeID-7qrESfShxxqXfa35MfBC8D62t6enjm2RC", + "NodeID-7rE4BjdFpwUk2igXEeauKaZT8mCjkt9Hs", + "NodeID-7rXi72Jm76kAKUi6BiyJChnAm9xuKrud9", + "NodeID-7sTpQZFCZVzhLTugv8PKhNE8tdQ394LRo", + "NodeID-7seuWZpGnhEox3dL8T363sghDtCT5UNp4", + "NodeID-7sitbRzmAsrFjKRitC7bub1soEaHXsgbA", + "NodeID-7stntWreGt1wPeFuY9Z8bNURuHxW4JN3D", + "NodeID-7t5yL3rJ5JgME7vxa8em5sUNTPeYfmMop", + "NodeID-7tZXydqQqbjAQaNDK9MNEZFMsSFCp4xJW", + "NodeID-7ts1Uhry9k5qkmpYZNfdivuzj2eBPemKa", + "NodeID-7v2CCw3NVjU9UxBhGzN1jhSmatHKE2mXZ", + "NodeID-7vWb35jCnXGxAhLStVtKKZhWiw1ByhBdT", + "NodeID-7wMUdN6T9awYChEoRgzQ4eg8qZj1BFrne", + "NodeID-7wSVhYSmrwcts5o98Yg863PoHhJWWQcbt", + "NodeID-7wqgzXaTtJLobuBUxbp8yGtQe75TxmaDW", + "NodeID-7wyu3EXASVzsJpRPoqhssRWdmTWa6Fycd", + "NodeID-7x5HbUJqp763SUw8Sz27yU3bKWCdQiqAk", + "NodeID-7xCJtVM3wTprzgDBhXeXCXEUy4NEuqUvi", + "NodeID-7yBDXjCcqHCnfqC8LfQ1oL9Yyx1se2Rj9", + "NodeID-7yUhoXtjqGABwMeSgQG42cWX56r1DkBwh", + "NodeID-7ynNyRtZx8re55eU1CwJ1Ga5cEaRMPJ5s", + "NodeID-7zA1m9YUevKKyKdyJK3snpSiAnXhUG12R", + "NodeID-7zQLzhnMhaj5SbRXVpUUsMP4c4r8yQAD1", + "NodeID-7zVSqXr1f2wcEnMtMRBzMh1VczoEXsu2", + "NodeID-7zeJ5VBLvTF7LvTn1VRZCJfdt5EsWUg3e", + "NodeID-81U2wpq95De12KchbFhatf2fBt6KTFmAr", + "NodeID-84RAL3MngQcrLpLgTgJwtLobhryyt6TiM", + "NodeID-84XTAh1VM9QmfdewNnqFVhz2kbjrFvK4Y", + "NodeID-85QtYSfGWxkvQjbiFJzv8R6ajAutwFS4F", + "NodeID-863ca1dX7NxyiWH6Hf3Bp4ipNokKdzJbp", + "NodeID-86HV89ZFehy2HHmnkpgBuUn6vRxg25if4", + "NodeID-86LjyKDK2eKVUpdesMPWJtvo9gadfW9m3", + "NodeID-86oHZkq55eBsPNFwrFX7kV5w97BPHhtgD", + "NodeID-86rtyxneP9grH5wuqRcQMSZw5mS1vqrKm", + "NodeID-88fsGoe69sPGtRjqe21SK72KrJNezzz5u", + "NodeID-88ik4ovrpTx4dTExqhXhSQ4JwAQnHbuGA", + "NodeID-89ucgJfiRvHtGXynRbta7VcaX6MEcJ7K6", + "NodeID-89zA8HBgsSce4Ut5hzWgfMRKshqooJWdu", + "NodeID-8ALyunjeYV85zBSrD2rjJdQ754z9jasvq", + "NodeID-8DYmrGzmxDPogtQvPR4YjXhRyo2pNDBdT", + "NodeID-8E3UaD6hjNK8aqK2BBUmqPXyrfB19WJJ2", + "NodeID-8Fiuf4Uucg4x3ijMfkyVvYXdfgdBFvsFk", + "NodeID-8Fn8YCu76VUHny7MHQTkm3mPSuGPkVeqn", + "NodeID-8Gct3pDyuCEY5xH1F9RdYjvk9ry23cTtX", + "NodeID-8HHLzk7pF96soZ45bJ1tfHNcSp7moXiTB", + "NodeID-8Hg2J3s2MQVf1GtFLcRpfWjvJZkMesX3z", + "NodeID-8JYJVijgzBsSTK5EUsXitrMEYNGkqeba5", + "NodeID-8Mk5Kpvp3oTpLbRSnwmCJmPbvRwsR48ra", + "NodeID-8Nr7TDSiK215oiNDY17SaDgF5nfty4KUi", + "NodeID-8PmuHd5fRb8VWpTTyNhytQuv3sy83P2jT", + "NodeID-8Q1uX2BfyLbmCCor1t2h9qvn414WXfQ92", + "NodeID-8QKheMcZ1jn5n9RVi5MFBkzGrKjFJNNAX", + "NodeID-8RRm8QkFnJvyuNk9GtXCwniWfHs47b8ni", + "NodeID-8SHAaWWn5qoBCFynwzXdRtFCcMvEkTjAM", + "NodeID-8ST5juiAQzVfXhNAgER1UapEpNowZyMoj", + "NodeID-8SbnHu41g4NFAk7aa8EXpgFSmQ8ZpvX56", + "NodeID-8TArWpFgH3sazEH8qP4gUjtGtFMvjw1aR", + "NodeID-8TubANvEGU3Zkz6nKeRx3ShmHyULLjD89", + "NodeID-8TviTXQLiqxcxkCikPTut9DwifYjFaMcT", + "NodeID-8UynAEU8PuuGetmjiiPcbGmvD3EyycuN6", + "NodeID-8WowWhvPM6hwXBLGkuX7HvwApmXNDCyrH", + "NodeID-8WvUBZyrk6XyF7pvcg3NJZk8jtJGi1W9G", + "NodeID-8Xt57NiwBsGKt3CjYZ1ymKx5h3nHU3vcX", + "NodeID-8Y4i7kpWyv3pvvwJSk4EsGx7frk5mU1Ah", + "NodeID-8YNtmpa8fe2dt12PqDzhDCBtwcQDTXa9p", + "NodeID-8YqEZ2ufMNUFPXyNpUAvLJWRXLKqC6D2H", + "NodeID-8Zvnq1815CaYYegXmuyBD5BVtJnurtpC2", + "NodeID-8byZLbVuVJbedEvsAjZxTTSqorsjz7ThK", + "NodeID-8cKy5FzzP2CHV1rcwdKq62vuYP9yUzYuG", + "NodeID-8dCZ9beUGmAWyCZPwdM8YZ5FDBRPXUxFf", + "NodeID-8dq5Vwc7PzWn5NYNFRkM8TfnYaJpLiPis", + "NodeID-8f27M6Ju9Dnh7YU5pHqpkBLhCmBq9EBBD", + "NodeID-8fLXgVYgby12VunVnSMrRrvcgEijVknbo", + "NodeID-8fq1H8oStMi9BZrEk8qiE8QAV7AtqGnXt", + "NodeID-8gndDR9ULm3ywRNbh3FUveaSyo5g7V3ns", + "NodeID-8iQxXS1Zbm6tGzfp56kpSyUboE5kSNoH7", + "NodeID-8ja1C24FM5FyQgUGjsm4qwpD6shiu71KH", + "NodeID-8mHndwCShG4xau63f5FMJC5r1kDCZNpNi", + "NodeID-8oREeth2haQyVW7Bu1iGgiMe18h5Pqiwp", + "NodeID-8qkeNyB3cbs7LqzP4AB7rHcrcHLAYVDEs", + "NodeID-8rEmSGNj5VW2HUjGYMyynpWTYJuDrMpFE", + "NodeID-8su1eeSjb4emswAx453du7ya3Pp8p2wSe", + "NodeID-8t9KLSgmSQfW668sfoLjVrrur3nDwW7fC", + "NodeID-8vuV1UF3KHF98EdqFyuFAMDJUzwkQWEA7", + "NodeID-8z8rezdB9vXDxBurBeCYnNBfNcD1kVrJP", + "NodeID-91W73TnEik6kseSpBHSAZzsNVRGk8Qfkm", + "NodeID-93LVjgmjMcBmcJSByxYiTuyPNbdVw9q3n", + "NodeID-93bNuNqHUpmiZiT9bvcm4YdRU6ADQnESy", + "NodeID-94CDXgCTFRPKPDmK55UcfG8KqVQfy4QsV", + "NodeID-955GU1MqWL8yXAtoc8AsE7FNx4nGC9JyL", + "NodeID-95rcDYyjGNKckKCF8PKuTyEV1wxkQvP3n", + "NodeID-96tBuFHLkXJwyYug768fE2GDEFmebUUTy", + "NodeID-96tjSzF58iKJUG1hDQve6HJdzjwLNMzFW", + "NodeID-972yzi4wAgqU7RGmcQGED4ueQeBXzccka", + "NodeID-98JuUPhpQBgiY9ozqFTh8rEjx3jL9D3aJ", + "NodeID-99Dk6vNf7RaX4S9e4oAAbuhubzzRnrGxC", + "NodeID-99hQvpQKJi1y7gTjD2icHKYwk1pNMHFhg", + "NodeID-99sqQME296SfcnyYWTmGrLXQJxaGUKAA7", + "NodeID-9ANDYM7So3ZPNwbMMd9xBKUiyJirXN3vF", + "NodeID-9ATz2jx7Vh64A31CcD8PgJw7KLZy92fRT", + "NodeID-9AjYPCvDWKnwzFgRiy7jeTEKmVxK42LSz", + "NodeID-9BCUhY6Q2Eji4J1u6MV9XKnPspciWWdLR", + "NodeID-9Bb6E7B6GMd1MnAuxYVVYF9CSf1XiBCEY", + "NodeID-9CkG9MBNavnw7EVSRsuFr7ws9gascDQy3", + "NodeID-9CnrQBBFSkE2Xzfcz3Tk1e8iauq8iNR88", + "NodeID-9D33RPjZwKx3gV6MVs77z4uPJcKgqy4ns", + "NodeID-9D63iEsgkSKzSz1aBLpELbh47Y7aT5ujj", + "NodeID-9DCqby2EWyUKFsKs1VNH5mX7V9FDkqUnL", + "NodeID-9DmoV3n9Sb1A2aLkYuv9wZV7uPJo5JhpG", + "NodeID-9EMH1m2oZQsbSFvrMzx5YXZWFfqSwjuUx", + "NodeID-9Ef44CXDWWfP63UaLr8XSCsmEWUFY5i2z", + "NodeID-9EizvTJhGPtcwRExBgYySaJMt6syztj2X", + "NodeID-9FZQBRnW2jMU1PW99pqVTnxkPHF2Srfeb", + "NodeID-9G5DhsoBgHjDA3j1FqFXKyEJH8AGPeB67", + "NodeID-9HT8KtMkcxP5aWjmxaVVGBCMZ1r6jGmgz", + "NodeID-9Hp3rH2xzTzDoZj6JgYqhbmTFGVeS1BnL", + "NodeID-9JE3zL1Ud1x5RgSJvqRpyMG6F17dPwAdc", + "NodeID-9KjtB2xC9aehpcYRuqJR4myLGJaq1tVse", + "NodeID-9Lyd45k1mXNkksF2C3nwgCJRX9YY42FT6", + "NodeID-9MCd77R8qxsNg1ajgHqFMsRYCaQ4KpGot", + "NodeID-9NEeo3Ayq5qGodBbMZ1gdCQ4bmGH59BBo", + "NodeID-9P6CxSTDfAi7cRr4LUW4bbdA4F1nK89T1", + "NodeID-9PbbhiQbQitcLLEiVwMCThVLWj2zFsbp3", + "NodeID-9PzVetjSSSY4Xtk3VnNcGzQdEjZSSkR4g", + "NodeID-9S8duheEvrp7gKW4qLLrWVCnC2wvo39w8", + "NodeID-9SQzWXUh9SF4b4qDmYy7p6LcqWSgxtu6o", + "NodeID-9T7NXBFpp8LWCyc58YdKNoowDipdVKAWz", + "NodeID-9TMnzP54UVfmYmYcxAzVuNC9rpVr8zvgB", + "NodeID-9UWtBGvW7G2RVSwcR15MS8gesUvLk6f24", + "NodeID-9UgnxmEX92MdaAFQc7FG9SAfPECeT6Qp3", + "NodeID-9Uis3D51cjQauBaBPnqsvKjKg8Byj6Xwb", + "NodeID-9W3QhxVhg9EncK9438UUepFBrCxdtFp2w", + "NodeID-9W5RaY7LA6so9hGCPGfLezBXMnWNRQb8V", + "NodeID-9YiwE69B2wcvXtEW986YcgQxGg9ctzmKZ", + "NodeID-9Yq2bF3B9p4Lg5czRpYoQULLuEn3nwuhm", + "NodeID-9YqDsggitZTgCi2WnnrKBz3jAcD1S7oin", + "NodeID-9Z7jK8jN5FsTXSqkG1fV2QNG7GktPU8az", + "NodeID-9awX4ceeXavKKmccnAuDU7uvhqGfaEDSS", + "NodeID-9azF97hpcwpzj3t7S9mD4VKY1S5eJDrcW", + "NodeID-9bU9jwHLH6KxcTu8pBbqJQqkHYR4woY7L", + "NodeID-9cEGqGSwjjX23qXbP4vEqva6TwJqH4hAH", + "NodeID-9cazV2uY7efo1f9bjbixH87FFNG5wGyts", + "NodeID-9czFqw5FRq7WhYyf9SBSfq8wsJ1f82m53", + "NodeID-9dN9NU5XCr3WQGYnFjGudKRScQ1HKGmBn", + "NodeID-9eH3Zu7LN7kNwvUy3Am8mkgvvekrkxD6d", + "NodeID-9g6keiiMr9vXhaSNP3oqdxhu42LEZ3pWu", + "NodeID-9hW5Lb3t5JMgP945DB8wHUJP73uLuDLAZ", + "NodeID-9hj2xhiHktPCpcD9koLLH17a1GKoWY7QQ", + "NodeID-9hksERdA8ypkBykmHuch4mw24RR2sg5js", + "NodeID-9iGXJ935QZWkp5j2v6KNSTr8b45a7Xbfs", + "NodeID-9iiCATASsRcosMQ811KpxSMHsGdM38rPJ", + "NodeID-9iuMMyL7LZyUxMK9s735hcRng58bSj3gw", + "NodeID-9izFTRjPnyph3GJu1sp4Cf7zHiwaK7KbS", + "NodeID-9kNp7yMjHnDg1QLQboms9ACgQ7BGu8zpS", + "NodeID-9kgmvmU19mNsTxPS4f2F7ZiSZSwZ7dfGk", + "NodeID-9mtTuxamXQyiePCNyheFEyjr4cAQo4Wbg", + "NodeID-9ntqrySGMSMwqYR8yFdChFdU2ABj5zSEp", + "NodeID-9oP7KmQjtxi7rK5GKmRXFNuNpPmr2vzfw", + "NodeID-9odH3Jbw7uPuRrbaVkVoYeitdzwX6o69A", + "NodeID-9okkd3AwB3eurfQxdP46mcSM5sVhD9jxm", + "NodeID-9opRroLX5zG47LVmyw8hGnQJx6dxmfGsf", + "NodeID-9pBxdzsJRoGFdAjEJzcdWbzKEEkdzyGCr", + "NodeID-9pTnTcJZ714TcKA5ibKwjc4ztbxnt4YR4", + "NodeID-9tAAt3ADXpmStdjfpUKsgKCBowaPjXueE", + "NodeID-9tJaF6mjrwczuEZk3oQRJsB2AzPk7QFHn", + "NodeID-9tLM44jzwQqnsLmQTfhv6Q2GaAEkCdev6", + "NodeID-9tWnniKF15vWEqJa6o2hjmL8p61jq4ZmW", + "NodeID-9u5MGjm2Y2BvQSZBqwDkqjUrqFKffDund", + "NodeID-9ucNhNpdx1QhUnivTY35AtNEVpjY8AAK4", + "NodeID-9wCVwfdLGJe14xss2yjAT8ntowavfe6Cu", + "NodeID-9xTBvp3kCUiUGu8aM8XpBWPf2co3vJTJN", + "NodeID-9yFkNXGSAUgPu3hB4UxkWGhbp7cXBLaJN", + "NodeID-A1rgjFoH8JTHiHWoWYVcDDWC3WKnNFFi1", + "NodeID-A21bAN3Nk96xfoAh8auwqP4uQRbk1xAPz", + "NodeID-A29C9b97WqpgPBZS8Kh4NEvf7RLRm1cdZ", + "NodeID-A2aPfvr1t99Nm1K82U2XyWtxse3CNmZ64", + "NodeID-A3azVkFN8rEsnnw7yQoXHDze3gVSSF4YB", + "NodeID-A45ZieXX9VhAjrz2jhACBGYYypn2HEjaS", + "NodeID-A49YH2FmGteFpSV46b9WDxZWDEebAnH4q", + "NodeID-A4amNjJyWX5kd1wNhxZVqDFqWKomCndp2", + "NodeID-A58AWZohmoEPEG2FDjqdT8m5XeUL63FZc", + "NodeID-A5SHWeGWKUiuvPZhRvNAXKyiEnyDhJzdh", + "NodeID-A5y781VL74i4yfFdcMLnjxr2qLbtjaAgi", + "NodeID-A6onFGyJjA37EZ7kYHANMR1PFRT8NmXrF", + "NodeID-A7GwTSd47AcDVqpTVj7YtxtjHREM33EJw", + "NodeID-A8jypu63CWp76STwKdqP6e9hjL675kdiG", + "NodeID-ABHKUic6BDS8Kg95tSWoYv71CXWeuS1Re", + "NodeID-ACB5BBC2RNLSGZVEGkRRQdWg8hqXjnTpM", + "NodeID-ACMpxS8rnwkAA4JfCUm4vNoWQaznNCqGV", + "NodeID-AE67987jikbcv1cjf612huYwFgx7RPAZG", + "NodeID-AEtF29pZDpKEkZ625bg3reDrux4wyMjhh", + "NodeID-AEtKZyYiqnWqzsrwSKEPWrciPHEAn2Q2T", + "NodeID-AFWbdZEPvWxEq6A5SThDPVydUj9FSHjCQ", + "NodeID-AFZVPKaEHwRZgWvcqRpT6mTd4k8xDubGg", + "NodeID-AFnD2mSUo1cB9HSMxGT9hQREHX6V2aCmm", + "NodeID-AFtmZMo4p7AZVenJtT9D2Tbk1od5mrJge", + "NodeID-AG9hZpGAPNtzpPJWKmJHDjyhFppqM16uc", + "NodeID-AGEnkaodYJksMTnwS8LHHD2X7MDQBSMJU", + "NodeID-AGurvCTxa6JFJkk3553Wx8XPtgz6w4xMw", + "NodeID-AHTFPmvMrQBt1hcoGS7HugNCuu15Q5gY6", + "NodeID-AJR4Z9bAx8tom9ygqv3PkpQtdxDV8JeLD", + "NodeID-AMMTYTe6uZR7yGL1AbEMuwYayd4N1J4bL", + "NodeID-ANeoZC7jBSmoDSYVLip5uASJW48GwWLLG", + "NodeID-AQT1i38PMJQxRqjpwrQ98QESW3EJzG3p7", + "NodeID-AQckPm8yWZiWwSAx4FQ44J41Tp4yF4qME", + "NodeID-AR44a1cyPrD8cCNZgyhv7Tc2Lvw3ryhEu", + "NodeID-ARveB1Km8pUjtoTVQL6e27fMHfUyyrjjZ", + "NodeID-ASgm7N2wwZKYc5dZPiHExfDdNcfyZQx3T", + "NodeID-AThE3ad1aiPLKsj1XfmhCsNbai8sMyPc", + "NodeID-AU27Fz35YmQuM6d2pM9HsvLtgwGT5xwnd", + "NodeID-AUeAjRR7q12Pps6Qckyy1PUzFwP34pFij", + "NodeID-AV1uDZqWGSheRS3M6RHUbQJHDGXy6f8Y7", + "NodeID-AVAXg2LFFdkWJjZi4554GBNprWUepqKxm", + "NodeID-AVAXnRLmetkBadrUoqtLSVkohnoEpeSm4", + "NodeID-AVp7QsomV2auUPqPXQesRcuKwxn4JmDRh", + "NodeID-AWLRFc3R7oCqHd6qe95QsEaoBPPTQYpuv", + "NodeID-AWMoYmhjbfpWphJ3nmgxGAPpVFzQbdp1G", + "NodeID-AWirVtsoiwvNdqhqQRwz7vQQEiEyvhq3y", + "NodeID-AX9Fkm7jKPuY9Mit6AyZoS73tFKWvTMF2", + "NodeID-AXPrBC45azzYv7UKCwLYJhidPkKat2veF", + "NodeID-AZPULN7CsYdfSq1zepSS3CZNhxJsU3a4n", + "NodeID-AZfAXX6qyLxVXBUJZPwEgR1iJYwjwozm8", + "NodeID-AZiGXCQ7UJvsVjmBpUMmXAQ12GRj1iaz9", + "NodeID-Aa6HmCaYwZzNoNXRf2xd1aqgtaWdnnryn", + "NodeID-AaVVyiopFyWeLNfshG5eztnEGSUQRDmnn", + "NodeID-AaxT2P4uuPAHb7vAD8mNvjQ3jgyaV7tu9", + "NodeID-Ac4RdT7r2vj7J8s68DB6mpoqPQ9sq6oro", + "NodeID-AcUWiUhdsfAAD4gyVUfQNokZXpDD2SF5J", + "NodeID-AcVHs6PgeipByAajqn3h7PHDk9cZXDZ2K", + "NodeID-AcZuWDkVDZy32y8YSxMVU57sLtkyHbVFQ", + "NodeID-Acigg3i7aU9j7coVrns9SEtyq9dox6cKz", + "NodeID-AdSMHubbQcGeJYMcY9nufaieoYjh57uzp", + "NodeID-AejE54hVtRxSm2e8KW4zUHpBTgHz9fpEw", + "NodeID-AgDYXBZcELb6jPp92Jk2p9qt2R2jbGweF", + "NodeID-AgfJSHN4yaVjgxanEWMfQXKGDNScwrVZL", + "NodeID-AhFT8H88EZjd7K1dhrRPfhatXKuz2iBiY", + "NodeID-Ahq7qT8wG6ufLoM8MrvB5G65SbEfZC85B", + "NodeID-Ahy3pk9UZEeVLzks1BRSqsLL6zvJt4bN4", + "NodeID-AiVA6rmmPhouiy3ERwF7k1eoLTrPErd2p", + "NodeID-Aix93q3XbWsEcoNuuWjYuQM49ZeCX7NLS", + "NodeID-AmFfzQQtUYm1RNuhkQuoG6hzaXpYYbYtE", + "NodeID-AoGM9c6bKC46YpEecEe9tHG5HfcjqPxtb", + "NodeID-AoU4gTzEVKVmopKx7s9hKXBbQ14VYyAcc", + "NodeID-AoYvCZojkKKkDiUjY3Daq5z3FUPrhMAbB", + "NodeID-ApohQPUqvLAFGgH3XobyeDFBHEz7vbS5u", + "NodeID-Aua1pVxQsWLvTTf8bNVw2ZCA2NfogNqiE", + "NodeID-AunfxeXeb5uh5FbxYMr4TtEpbVTPssmmv", + "NodeID-AuqWFe8yzJxPgaZShBZpa3AhEnKT8SmEk", + "NodeID-AvTYuKYvu8oB8dXCbAsLh7nTpCvih4fdd", + "NodeID-AvYo16nRcdMuFmsEps6STb7faiRoCRgHx", + "NodeID-AwBfjtuNZk2Cu8wmQjYsNipqWK6nYMnv2", + "NodeID-AwmHrKdtkhnuEVY5TvbwxVksQ8dWd4a1P", + "NodeID-Ax97guVgJnjpDYiZkHghBpjELMVrbhKLq", + "NodeID-AxSapUskp62c3KkAnzd2WSDammmNXaG53", + "NodeID-AyByRGSrfbDaeW4njEYwCzhsnMyZ2KMcw", + "NodeID-B39dR3Zj4ZtiqSHTPLxck66yqxTZ9pRmK", + "NodeID-B4EU3Tk8BsVczMpkPtJAqS9FSYxNjYNBz", + "NodeID-B4Pubug4ct7TKPRuSAWGqS4Hq79v912VF", + "NodeID-B5MJkFe7GoyrXY3MqrpjMrrTqj9J5oprQ", + "NodeID-B5N5hVfEFbTrG5QGKvXQBGqfvR9GJvSLg", + "NodeID-B6NVZDFoLAErvcUafQ3EzJeynFnGffCQd", + "NodeID-B8RQVdW7nFrVR4Peh6oMfsdK8Muuwfeme", + "NodeID-B8rRoKwovNH4Hv4cgREBqjHcGSCN5Lrcq", + "NodeID-B9dnZzwTmygKPxEP7GvyqDh1F6pQHkmmi", + "NodeID-B9o1a3g4PFp4JWyMJxRv2nvnWHsq1rSvC", + "NodeID-BAePtWtdsqk26YVfucEAJTA9spGpuLf9r", + "NodeID-BBJP3fsJ2sRRbB3umzz8UXAhzrUZJmWqH", + "NodeID-BDFwWjNUNeLYrrfGmYqBMqZSGZQtmCcxx", + "NodeID-BDnEyGooDS9w6bk2Ty7UncMyQ8t1iLLqh", + "NodeID-BFgsRa6TLCKcHZhN9iuufSqRengbXuxQy", + "NodeID-BGEvsCNRi5gr4ga83cVx1E7PTSiBZjyhK", + "NodeID-BHPTN8HM5xA9HNiwUPceNa314kh3YnDpp", + "NodeID-BHsQhBq2NYN4YYB9t9VxoxcL2xkCD4zPj", + "NodeID-BJTip339hEcVzpgyNqzERhfjMc6sUFabj", + "NodeID-BLjWtGBQU3PxgBSMvhiGxHGZ6Scn1gyyB", + "NodeID-BMaQ42mVapxbCcX2RLPRTeRW3th91XdaX", + "NodeID-BPsD5nsuqTKR7ToqUMDFqanYioFnAVo8C", + "NodeID-BQ6uwBhrSU3mwDpguw4rGPXa7kVkk6FyM", + "NodeID-BQEo5Fy1FRKLbX51ejqDd14cuSXJKArH2", + "NodeID-BQpbmskmST3wkcSbypVuFZu7YULXG6pKR", + "NodeID-BQsr3wEWirFH6C81M1LYsYagHXVxXRFSS", + "NodeID-BR8ysKTDMKpwbgH9fsfCdVQWMsniMQBWp", + "NodeID-BRRp1FdWN4PepbmQNUksWPsRJaZ1mFP7q", + "NodeID-BRrFzQrJs8nnmeSZxWwr9yCRcq4U7resP", + "NodeID-BSTCzJUvn8jYqDtsV3aTjRycJHBJi98Zm", + "NodeID-BSornzAY2Y4SmDcQw4Pgsf5zH4Wdv6d1S", + "NodeID-BTUXn6xfxjtA8P4nXYHiwEJpso9Q9t8FZ", + "NodeID-BTybEYu3y8aW54EK9SSivLUYn2fiCosjD", + "NodeID-BURrZL8SidbaotZ1cNxvPxNH5DGvXS7gN", + "NodeID-BVSFJU3T86CWXQxSTc2Y7cHo7nYJx1Jn8", + "NodeID-BXTBUqX8gitUDtVam4fhRWGD1SfeHGoBx", + "NodeID-BYGnq6ZKg5ncN419eBsxd2YQcxoewxfrQ", + "NodeID-BYSrjPkpQsN7YxR2v6ToGhmD6VnpEz9uR", + "NodeID-BaPYDXQYeS9aCFHv76r38gUhYrtfpzq6A", + "NodeID-BaTDuWRvZkEy8gg4FRYmNYXASWL4QKzFD", + "NodeID-BaaUYiEUD9ogi7dDikVZAzaVu5yxAHjGs", + "NodeID-BagXwfWXPpzCt2utVf1P5MTwdQsPnxeaL", + "NodeID-Baof3ssuxMwMHxd3RXpNwiWmRdskL3hLD", + "NodeID-BcfnNieXDpsvkMApb8FcCmGAoQdtyu8jH", + "NodeID-BdD2fp6PXxbSdGshiVrHDzarWpgLFEMF9", + "NodeID-BfeJfXUfFveZPbS5tFaJar7X2uQQ7S7so", + "NodeID-Bg5GpEVehBRU9HDf9e66vXmrRJ39BW1hG", + "NodeID-Bh9vBw87fdqVzMzrFrPiTQqA4irjDP6G4", + "NodeID-BhSpBoma36qXxym3XPxM2E9xisXh2hBmL", + "NodeID-BhbczAQnAARsn5Cwa1onMXLD6j4Uu847F", + "NodeID-BjoNuhod6yNfMJJDJgyfNWWRBUG38ZPCs", + "NodeID-BmKvEFG1hXNQ52rPBTXwQ3ZxEmcCmxXZx", + "NodeID-BmmaSGfGKxQNMsaBSnxvhQdLCNchGEcUo", + "NodeID-BmtQcEcSHhUJzkjKQKJKdF3gQaVtud8s7", + "NodeID-Bn4LPbETjf8D9pZE45abJgcCk5KSQCbo7", + "NodeID-Bn8ZcnL352FHc4utgVPVDjD3o1HfYwtdA", + "NodeID-BoN8r3MqeJiqVcvrQx1VubZMGDQE5pJi7", + "NodeID-Bom5dUsayGwdagVLoNNxe1t1FFDZXGGK", + "NodeID-Bp4nG1LrP7JCg9eSQpfBE91mBSd8biThQ", + "NodeID-BqCmioAapUYdqLL7AuWJqPeRrp4D5a1ag", + "NodeID-BqtSwNPmkfSi5W3Zz7CRffeLmYrUYuEmJ", + "NodeID-Br6QnUhtZGAC4CymYLPRSMCrsNyhLMmH7", + "NodeID-BrexWemEB1Vgpbpnnriy3k8e2CyRvxsPR", + "NodeID-Bsa6pnd8nUhHEQ4v68GJ6fDFwCpz1QSBj", + "NodeID-Bsgdx1HosAzQ5X1M7JmbYngULQ3xjkP2e", + "NodeID-BtcHfm5o3A4WhAmkTm6YPWRhPCChDPLMM", + "NodeID-Btr5hkRibMyYztC9jQg5T3fpKNeYf3Qdq", + "NodeID-BvDJUkrDJotTxgZi96zsEe6iYQBLtz958", + "NodeID-BvpPGydG4inQCbkwRZ3nPMp1zAGToUTxz", + "NodeID-Bw6s9DYKi2V9jRqNmaheGGg2Wz2Dv7DQo", + "NodeID-BwCLnFCE3ipnmkT3V814hGsb6sCRFqScn", + "NodeID-BwsGZ6YpSqF2j3QRRiQJDf9JC4FmCGXq5", + "NodeID-C1oRu2mGfJHUD3UyNCWVJnJ4T6AWXhj5Q", + "NodeID-C3aMR9tsKqTNQra8FbqpFkMgHV5DtuJGx", + "NodeID-C4emGUFHEeCEZgoeMDHZddr5nyZBgEUKf", + "NodeID-C68ijbc3Bz1cdoQv4Mh1TYxrzeGA3PnmG", + "NodeID-C6b58cQGYSqm1FeQyvXKXUgZ3R7Q9D9es", + "NodeID-C6fd6GFYMnbD44LpZR6AuddMDRXTvR5Nn", + "NodeID-C6poeYWySHhDuKWMbckvcny24gTGKEtEK", + "NodeID-C6zVv1ab5JKn2j8DDCGWGai9jgWhmpLVA", + "NodeID-C7VsWUVsE7uFmSgkRQpcjAJWB6gRdm9Pc", + "NodeID-C7YyYDva6rvbpY5GEu2Su653eLBNt49TA", + "NodeID-C8b7aGd2caAe7PgtP2vnJcWta1wUezAAa", + "NodeID-C8zmJazq2HwujDgsjKpmYJsvSuNMD1kwt", + "NodeID-C9Bcji6rXUp22qyWhvYKm4v45hJAkzvpU", + "NodeID-C9CJ3oVhdeLf2Db71JPuzvEUKjy3BdoAA", + "NodeID-C9eHQ7iCCpW7zy7Vk5UJEXd1zwXEdFtS8", + "NodeID-C9eewJtL6WMZi2ce8YoPxhHTCYemhvnKm", + "NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg", + "NodeID-CBPbPrYDbghbAP4RLSCQr7bHQqHWh1c9Y", + "NodeID-CCBWkqmiTdwUCR9ExH1mNSLzvrt9JRKF2", + "NodeID-CCPtDzjuJWjt1VuV3yiHPwQr35qh2rbJN", + "NodeID-CDjuct2YS1o4d14nHtszWmyVUmFjo6AHm", + "NodeID-CEHgpbVVJh676muJTUNKzP3jmZ6Cs2zar", + "NodeID-CF8WKgeNBHxWFmijN7tysmmRSHfJFEKD9", + "NodeID-CFoWfGyYw9HPuDK79fjor9d96S9wLAbpR", + "NodeID-CGrPauwXiEvvY3yLBxR9HM25B8HpNTVfV", + "NodeID-CHxae1CeKzs6DNxur9rHcjSAecpdN1p9Q", + "NodeID-CL3N5kkR7HsmVtKavcuofwQGgMNjppY4N", + "NodeID-CM5KJnEvKQfjFirjbUzHa7WbanH6dLHva", + "NodeID-CMFSQ9wzby52sJqTBeajH2MaJq8HwnZPL", + "NodeID-CNPUVCHqT8Jpjpix7SJfXhh184EjPSsu6", + "NodeID-CNyGDr2EvPqxfybfNLkpGWqMQHiZthJ3Q", + "NodeID-CPWtTaJjKj3uiQnNKeKVk5yKfEiE5mok8", + "NodeID-CPkJH4zTnyhERzo7H1usRiSmMVDeUszm", + "NodeID-CSmSE2veuHYG3dJD9WuqobvsAdJ8iF5pF", + "NodeID-CTry2Hj2aXeA1rfWq1s6pDL8SzaCFGLMC", + "NodeID-CVJCnaM2gVKr6WCmJxKSPjEA6GFtmBknY", + "NodeID-CVXpUPtPZnsEM4mSnJbctBpL6Sgj1rCRt", + "NodeID-CWTULAJzqphbmedDkRpcHuCvGiHARvodz", + "NodeID-CWuWBhX2WaAY1pBTAmLRTGsjX9y3EqWAe", + "NodeID-CY9BmJwkVatHX86Pt3Fkxts1QoKTovyAs", + "NodeID-CYdCC4uTyAmEHW2CNB6oivzBtzqJn55mS", + "NodeID-CZRwtJDY1KeQspzxqmHfSdwvhA8xAeV9K", + "NodeID-CZVcr8ZP7njdQynukR8B1RcCcG9qxSdD5", + "NodeID-CaNQUnkzWJFcsYNhdx4iyRk31McfqtKhX", + "NodeID-CadcH2YHzeVWDSBT2LR9bfqHvMVfH6bTs", + "NodeID-CcNi1r9gNk8NtaNFKShCQdahthUEpZX6R", + "NodeID-CciiJQMXRWQ5967qBS5XncuEiyor1Png1", + "NodeID-Ccx7u3SwfPt52GxWbNc74kjVJvqktTkn8", + "NodeID-CeaG1icxFWcMkTzsqQjpwt82nePJrk5gZ", + "NodeID-CfM5DQx47iD6AWMsFdHGfWUnt97Sbt9n7", + "NodeID-CfT57H9QA59QT6s3QZGi2HZz8TH9i8V3y", + "NodeID-CgXPRNG5FeVSz8qC31u5UDpZ51pJ2mN2X", + "NodeID-CgbgB1UFpUESETV1CVGDM17bE9JA4tVHK", + "NodeID-ChjgtCzFxwhCYQGsUzGHUUTi9nFYrLsXh", + "NodeID-Chk1hvm92LQPActavSVqoEYCmXfQZeFvE", + "NodeID-Chy78FPagNNU7oAj1QWzrdPFjJgZP3Scu", + "NodeID-CiKdcSyNH27re2W17ygscpZ4xG7474E5U", + "NodeID-CjX7mnJM1qasMtuyyxeuKoKy6b9fdSSbE", + "NodeID-CjooWTHxne1o2w1hetMGgDL5Et8JzKMiw", + "NodeID-Ck4VEAv4JTMgnijLQDeGCWST8Zdgxe9Q6", + "NodeID-CkMG3CThWnfAYCYE1MDsFqSU1n4NESoFt", + "NodeID-Cn4ocmPe1Hqo29RyYCC1QXr8b763Wpw92", + "NodeID-CoRQHCd3aSKe7FrhHSUnvNVZzW52xu2YA", + "NodeID-Conr75BBUMBFNXD2VP6gvEbCRihCvjfej", + "NodeID-CpAhCB1gu11mLxBZJfgGLExwwvKobprLQ", + "NodeID-CpS69JexgMfH1sy7a77fiwQgN3c5QtrXa", + "NodeID-Cqc4sovCY4ypZww5envqKgtrvd6zrRPTz", + "NodeID-Crfqdz3qPavSYvQUWSXMawWjUXxnr3Gg5", + "NodeID-CsGzEmegg1sVokBzrSKkMygKy9YCVEzkq", + "NodeID-CskPetRMvtH5Xr6gLa5cwfY4hR34UgkM5", + "NodeID-CuEMaXrtX3tdegH3BPJowHr7cMUyf7P19", + "NodeID-CuF2PsXiuZESJWa5itRLmXWQ66qL1NSE4", + "NodeID-CzW1jKjZwFXgkB2Ria2nNPvah4bMq85bH", + "NodeID-D12qpTYhB3feogxvMBzS1QPvwyKyhRK8G", + "NodeID-D1H3GmiDVvoMsp3foTPmWi9YPXweYv9fn", + "NodeID-D1rgZbjdrevpXXDF1orhAvnUmojVfeZwM", + "NodeID-D2hsJkh6oAf5X9WEuNgbChFvkeUgC99Ns", + "NodeID-D2iAoisJf33uGaaKh9uCUMrEjN9HG5dib", + "NodeID-D3onstuMsGRctDjbksXU6BV3rrCbWHkB9", + "NodeID-D47UrYCDdkfrDrv9gUvYKLUyT44TXYCJZ", + "NodeID-D5aUrNtb3vKUBKYpdapiaGEaBTmUz3Jr2", + "NodeID-D5wkgZDwkAQVpFNYtNZmGUJGnUYRB97RJ", + "NodeID-D5yA7HbEr8AJ4yzwVZXsDtb4xhKkTRz73", + "NodeID-D8vyyYopHECxjFCQ2K4X1sttJjC1B7zva", + "NodeID-D98ujhSFuA5pXc8bnKPPpbP1VNFnfESVk", + "NodeID-D99fW2bCQpU6QCN1pu4UccDLZTQdVEwMj", + "NodeID-DAMYbaM35qcXWvuEKt6spGK6EzVKDJUkT", + "NodeID-DAZNmxJPADAnk53993F5wntS7LUhxNH2i", + "NodeID-DAtCoXfLT6Y83dgJ7FmQg8eR53hz37J79", + "NodeID-DBB8Ve4B6dXejYtFhwcQ8ZMFbmZu3VpSC", + "NodeID-DCUpFFgVWQBseGis77N45cBAZudSbaZyg", + "NodeID-DDzbSLsiD9qMPr9eaUhxwrChfbbXW8Zu1", + "NodeID-DEa3uaa1iztrxytaMqaP3PdydErzjWEgh", + "NodeID-DFDnfBmuJWqEeCxMviw2u93rK5thcetQo", + "NodeID-DFH5SbPENeErMmeys9FcQTMvdKkYrdLU2", + "NodeID-DFUyhAzXyYi3TUaQYBvm5cezyEaREeSYB", + "NodeID-DFuM24ytt31NZquBMCS6X3EHmrbfJXMa8", + "NodeID-DHUX369UfTJb2vVuWSRdJr9s27owdMbkS", + "NodeID-DHpKTzduyCvN3x2G4svUD2T7LZDD1T7nC", + "NodeID-DJ6nZjHBeTwdQiikyuz1foaQ6dWLLYm4u", + "NodeID-DJbw4TrSRu9uovTKqo6w12axPLHWHsjJD", + "NodeID-DKSq9hmU318ceXbU4LBEcSacDPZ5oSNAf", + "NodeID-DKgP4pe8GtAwQ3oVgvHJFG3WexnLjkkSt", + "NodeID-DKxvuUSqd8xtyWejxXC2JvQfP79SAsPvG", + "NodeID-DLFjLpQupsWf5UdaKRFiGELdeY2ViJfwT", + "NodeID-DMn1E4EyXZu8GZGKHV3p1naTmpKkpf4fM", + "NodeID-DN3fqQmgTBvk5JDxKjCFzmbs2XSVXTKny", + "NodeID-DQMJfc9ArkN1gohMBh4SQi4Cmu6EKAPo8", + "NodeID-DQVzByLn57iLrib1MVzoxVsnEksS9jbgb", + "NodeID-DT7ET1yHCTuNMydS4mGod99maQjBFS9MM", + "NodeID-DTzB9kesfKQNYuRBivWhK3iB2aWsuYu6Q", + "NodeID-DUmZowZh6nxKskHUybupqNAhnXVA5yQ1r", + "NodeID-DVh35F3R11HAAxzeSTbk3eR9w2BzPrJQt", + "NodeID-DY2Tk5ZqUir1NpSiTwXVGdETCGGEV8wHe", + "NodeID-DYCS7WSBWdmMx8ioQ4Lq6gfnPtpKmKVB6", + "NodeID-DaKj4jkyyCN4B5zVW65krECqpjxYGUFzX", + "NodeID-Dbf2zdJeUXfi3bFzmjhJTSgyME2o8iEaY", + "NodeID-DcCkk2wqS6L9XpNX41DVN5RZnwgixCYqE", + "NodeID-DceQxAzA4nCGFm9BKa1PEJ4c1zwx3YLuu", + "NodeID-Dcs4UwSwQe7vKaopXi9AcM891ybKatAvp", + "NodeID-Dd6BPwCsmEQaAgx9hpck23LYe1SopA3p9", + "NodeID-DdJNZBekdB5EVLEe2vE9LusaHjbGmsMYh", + "NodeID-Ddm8dYWWMgiZv5dyNWuzgkDprubqB1wkN", + "NodeID-DeT8Fw4Tp875GUQNxfcfKoBSPjKpGi6eR", + "NodeID-DhNYzUwYHPF24Wfz9MmmVyqLBUF6tkEpb", + "NodeID-DhuG2YhqQy26zabyLqTqNr85T9XscsWpY", + "NodeID-Do5ZUHCK8DHm194KGqdcwFc5wWE4fCQ6s", + "NodeID-DoEC8uw9qRNi33EiYrPoK6Vu9pnsH2rnW", + "NodeID-DoTTJmp8cmERizJdYQGFsPVFgZPJxfcis", + "NodeID-DomnwLG65RUJM41RgCJ2tRdR4iZEkVCkk", + "NodeID-Doy4qhTgun22byNDyHxNSRceygqwhwXCn", + "NodeID-DpXBTEP6ZCmm5bgBbv2rb6MzdRovARVhi", + "NodeID-Dpba952dAUnayPmf52GJzQj1PLoqtXahS", + "NodeID-DpwJ1uaLSpSqKu8ZTa7XpmFp5BuBYN4Ns", + "NodeID-DqE45ELtkEn4hSyU58oukvcPg1Ua5UdzV", + "NodeID-DqqpR7tQ3goBbudggakvzYs2K9TzR7daR", + "NodeID-DrijBGc9SonJrGUwex3vXtzzEGW3cB5DY", + "NodeID-Drv1Qh7iJvW3zGBBeRnYfCzk56VCRM2GQ", + "NodeID-Ds3ri3EksrtyjtAJ3RbX8Wku19LRdKTti", + "NodeID-DsMTbudbrnZtFyexvZihGfb9qETaxFBm2", + "NodeID-DsZ2yLdYvfHZptxMZqmHKgs4T5ehRTx35", + "NodeID-DtCpt2Bi6gvmQqwgKE59fanof5F3bepnd", + "NodeID-Du1Ebao2uJG8LukNGcUrzAevtVRhHdtKW", + "NodeID-Du7SAKQLR3j5iK7tGv7NvTSxiEVTfYfeS", + "NodeID-DueWyGi3B9jtKfa9mPoecd4YSDJ1ftF69", + "NodeID-Dv4KWhKB56So4dZNxRRi3J2V74TaUXWMg", + "NodeID-DvCdC1yWp8a9NNLBR7agvTV4YNmJY7zb4", + "NodeID-DvKgKdhkDk6CUf68iqA5Kwaa44RkBa4zN", + "NodeID-DvMo3a7eJYQexjLrR1rykrc1jsNuVwnPn", + "NodeID-DvwWC5ed3j5iG6e4Y5yxAUacPkXvrxLFT", + "NodeID-Dw7tuwxpAmcpvVGp9JzaHAR3REPoJ8f2R", + "NodeID-DwP4ATkTPn52orSSS1FbjjT21TXnXoEnX", + "NodeID-DxdedkGTUuVoRS4VJA1qYXuFU6MerKKyX", + "NodeID-Dy47rtrYr4eiyRTSnbaFi8KZVnR56XrUC", + "NodeID-DyXd5SxgwWWadT9PdEpieSPtjcKxYCMjE", + "NodeID-E1c6FEFavQ1RiaNARpxGx4sWnXAGh2YHN", + "NodeID-E28yXasMLXFQM3f3mQtGWUGh2jEgJATi", + "NodeID-E4KwVKcddwozth12cNvNYApyHhVbvnby6", + "NodeID-E5DL2H2CxUUdxe6TcMW7uTHC5mFujF1eD", + "NodeID-E6GJmPWBnGKad7hPfxCK9GRwsuAKc2MJQ", + "NodeID-E6uwzybtqQ8H7aArfxxVJWVsEcaCPLT7t", + "NodeID-E8rXzDkKySREDECoXPqaPPhQA7QuxL9M2", + "NodeID-E9cBEoCDBGi6qFGcW6bfFoyhWpq6Vc57Q", + "NodeID-EA7WyeKRdVx34ixXFCvfWbv5P9DSNsj1E", + "NodeID-EAdWoKJCXzi2jKAEoETCm89CB3dzyMdAy", + "NodeID-EBF7imfP93Sc4cv3cUAK21maYDvaFMS5j", + "NodeID-EBHJ9gHUbjtNQMnNNcJEsqojFpAbLrnVS", + "NodeID-ECNKxnabxDwevTW7bLgP2Meaid1j8ztVn", + "NodeID-ED4xkYFhZPNNj3WXDQiogcTULeBpDVjSY", + "NodeID-ED9nabFu9bXzdDizCeNytDisKqkdEk83Y", + "NodeID-EEQ4pJQ8FTsFmPi5qEiZDBkKsqCpBRZiT", + "NodeID-EEipCNkeRgfvwiDHbaBdQ2WeRnsRVSH7P", + "NodeID-EFWjQ2CYsraxPFxWVJL87nfqKNsAP2T9q", + "NodeID-EFd4jseGxHxQmYX1ATcJUSZoCnE7z6dFe", + "NodeID-EG6gFe5McNc2EyFzARxuvTApN995FdBZj", + "NodeID-EGKLqBNabvY52737RGARiuGgvu2vHRY6v", + "NodeID-EHJoNS9sgSnjg5gkvKL4AF5vyi8c4qTvg", + "NodeID-EKH5gkuABvZWiZGHvWuZLgGar4Zts6qX6", + "NodeID-ELNdDSKVpamvTWSQvqqBWzuAKFiJLzoT7", + "NodeID-ELjBQTBvaEAMk7Qx7qJNJsEh2DYC4nxUn", + "NodeID-ELx4yRvGiDRcG8r8Tow1LUAhMXkVYVzHo", + "NodeID-EM1NUe17RtPAJ4ofro1qPc8vEfcvEhjZM", + "NodeID-EMETD23g2Bne8CuQKyR8HB15KWomaAuFe", + "NodeID-EMq3MvHvWctiQ5CC2ioXpeyKPsHteXAeR", + "NodeID-EN2aDGGjPAqm4Npzk9wCjCdGfg5hVrWgp", + "NodeID-ENc7M77QRhgtpDojDQY5nqjndjiYCWR4i", + "NodeID-EPqYJkZ7knGWY2TNe4rxRtNgkqc6spyDC", + "NodeID-EQtsYPVt3rHBSJdp2Sss3pm645cpTJkGp", + "NodeID-ERzoQo45TdZFeWHG7JpHVnHbn7ULpTRiV", + "NodeID-ESRpVRqLwts8M93Ly9QPm4ZSdMF4wEpbt", + "NodeID-ESVMWUoEkKz8uAEDfKcEpu5UUCkA6GeyC", + "NodeID-ETwxZVMHXcikZmKsKfjiZuVG84KsZDdqz", + "NodeID-EWNvJxWq2UBBsn2UH35soQugQJn8CVKdS", + "NodeID-EWmdnUhsVGSfZPnbuSodLUTA6ReJcXz8v", + "NodeID-EY4iiXyj2TfoHspEHBHFfBYrHxXESnSN5", + "NodeID-EYDcoNgbX22og1oyEn5s7iH1BYSmR5yF1", + "NodeID-EYgNPuFCT4Qy7YhvsM2s8WKTT74QECvTV", + "NodeID-EZ38CcWHoSyoEfAkDN9zaieJ5Yq64YePY", + "NodeID-EZrxYbBm2ZcoK13eTPf2sdtYuJuSHyaTF", + "NodeID-EaEUnvUyfTr19uMW8g51bvFXfi7r9xL1W", + "NodeID-EbwYUq8FZAK4jf65nZ4dcb5kk5WZ7RBgb", + "NodeID-EcoA7iNFXhc2DwrmWxiEvjvsDvDmQrEKK", + "NodeID-Ed7NMisAoxzWRjxQVrWnBvMShLNcydRa6", + "NodeID-Ee6MdWL7mFKdPAXbJTWZGvwEUsi17869c", + "NodeID-EekL2aJ7TdkbiXDzSsPo5PKyaaQuQqVg7", + "NodeID-EfnXCVeLUtW24v8gwW1VYiNuqDeRPEVYC", + "NodeID-EgzctrMz5jVPbfUEWGufKxf9CXUMLBRGG", + "NodeID-Eht1FjvmFncRbagWk1PGMyE7hVrCS9Acp", + "NodeID-EibWFSUHeLNNjWZrEznmuxH7ZWNsavRgh", + "NodeID-EiyGqDavdQ8dMUtN5wjAezDXAWwVBdSBK", + "NodeID-Ek1pare46s7nXPF9JtsoyM7PcaFnCBms5", + "NodeID-EmPwabyobnM3jYDvQuxZdLBTut5V5pq2n", + "NodeID-EmRTfxEKTLpzTyWJmYTXVxyGr79bsv4Bp", + "NodeID-EmhfRnDPSzpEMhGy3KSC4BWhPdtoxmqqV", + "NodeID-EnANSJ3hrErv6v7ZGSi8p5RCHhdhbGrb", + "NodeID-EnVDmm6dUgePaWbtBem6HcbzptaigBxDe", + "NodeID-Eo31HyvvA1Madeagm6U8CM376cEfgS4Bj", + "NodeID-EoNXC39QyT1eHFPXb5PgvDNigBN8tMeCC", + "NodeID-EooPQfxvcRG9XQpNmbDg85sNzaFDzux6G", + "NodeID-EpU1DGKMMvDRtag9u9G7uwZHRsJF5NodL", + "NodeID-EqBR9F3QBBrTQTN7CDN7sDEUsDGDdMYps", + "NodeID-EqauaQBwVXnpamJvLi84aeZLTQra4GDep", + "NodeID-Ess2uf91CDTfKsLezaTLKqqsWcpEHGvJv", + "NodeID-EtFG3SrbbudeFQCaWRxhwvv28wHpo8VRq", + "NodeID-EvY8p6SYho6VwicRvVasSBBv1MtanH19D", + "NodeID-EvZXX2K2eVEV7n6Y8cnmeSRgj4JhkCVad", + "NodeID-EvdPJG2AAVGCP2s3543KDx1LZ1g5SiH2Y", + "NodeID-EzKkVMd9y6XqzQsvRDLuaaiXqXK8fFipU", + "NodeID-Ezk1hTiN5bogETxygJ5NciRvHXgXvUVVM", + "NodeID-F1JWRVsJ3Wq9eSdNEHvoivQVCsW19r8gT", + "NodeID-F1K4jks15y71PthvXVNks8pgutgBwdHZH", + "NodeID-F1KpunDAMisiGKLX3R6k9uBoJoeLwzJoU", + "NodeID-F1qvuNMn9XBXSjv9iWyyMGfV2PQ2Na7KM", + "NodeID-F3b5mj8PWnMP53hFbfGNxkiXpbK6tPyDU", + "NodeID-F3r4EqguPQgupLCYrTG3SeJSCi5qtc3x4", + "NodeID-F4Q66oFkqCmRnBjDUAh28iXvWx6WxbxJJ", + "NodeID-F4SmFmnXuFBkW5fgFgh5RT2T5w8KseGRN", + "NodeID-F4kKmjMhZJWkYwsWyPSLFxtNcj7BhELmY", + "NodeID-F5sBP4yNA2YXHbD6FJUjsZJ5zhoMqMi6g", + "NodeID-F8HvQKYDbonSeJ3x42Ynb6ibxiJa3FWVL", + "NodeID-F8VWioW7dC64159mMhswhzpkHxnB34cjS", + "NodeID-F8Yq4R4Mx1LHGbQ7g8s3beNB4LGnCUBpv", + "NodeID-FBtCkPRmkfDry8GGpNenBW2fn3fD3qoKn", + "NodeID-FDTRdm7eS7sBuzAnQqMrXUmNiuNHP7VM3", + "NodeID-FDZXWAQeuMzZVq8tv53b1NdiwyJDUHGpB", + "NodeID-FE6WTTtg1FvtgQMZBjjZ1qhZpPq4WoM4m", + "NodeID-FELjhENFRLHTgVrwiKTdL7aSQbU8mBd5Q", + "NodeID-FEUSZzFmjF2JyrniKXksGfRjkQUH5R4eH", + "NodeID-FEsoMJf2VjoRPdnm1Ux7CGg5RrHnAH3VX", + "NodeID-FEtgjYGndfWGzLZELTJJoikpSobjVKTjk", + "NodeID-FFWS6gV9FrKecNWCYJQuyR67t7GY6UiVq", + "NodeID-FGRoKnyYKFWYFMb6Xbocf4hKuyCBENgWM", + "NodeID-FGt2J8WREPFbbTXgVU9YC5NjdERhoMa7E", + "NodeID-FHGwnPLGdU3FBzbwnhayx1sDjxiiyb9sD", + "NodeID-FHHEXLYRNrnQhKFneEwDPX8TZV8WtUpQY", + "NodeID-FJ7WdKoGBkqb78mMGrr3r6kSL45R5Vspp", + "NodeID-FJu9WvWrxTucYcNzEVQj1pHbbS4LaFTnn", + "NodeID-FKCbGm3jmceEEpfSdA4uQUVANpmqFLAty", + "NodeID-FKGhEFYnHUdFadoR2ePvdTTM5Sz8tgjHp", + "NodeID-FLQ8ifj1DwXuRWKShjck624SAgYXVpQzz", + "NodeID-FNfrZNBD1bxGj1VmdgSrEKT8oMePC448e", + "NodeID-FPwgrsmgeX4DSkG4abJ28zZQhjcqirPYi", + "NodeID-FPzqAmcWBR9RZdNggUMtuyWwvuG2RkqrZ", + "NodeID-FQKJ8yATVmwGuy3LN2ExsURDEtZNWgr3v", + "NodeID-FR1WrbXocb3QKywNmjQABt3a159QqRMBe", + "NodeID-FRTCPrh8YwxmR9L1XJWjLuMA1r9SjPrRu", + "NodeID-FS8PXhYXxoo5GoTHoki5Y3Fqk5zzdMY6E", + "NodeID-FUpfjb5sPRnT3XxMbtephYBc1MHZE2RYL", + "NodeID-FVMb2XgKVaeonehFbPMe714kMJ7DRxhpt", + "NodeID-FVgPdpTafzx8jazSNoxvQmJNxoEcAMmxm", + "NodeID-FVgkUobMuUBABuMA2KngEsm2SG9XLGvdW", + "NodeID-FXsyWrGvZZEns2iZr4d2h3pW9piH9ZE5h", + "NodeID-FXzsVMpT3ipDikUzabDtmeLrXW8JYyNZp", + "NodeID-FYv1Lb29SqMpywYXH7yNkcFAzRF2jvm3K", + "NodeID-FZHUwdFr4rndHpmSFXLK9dJwKVcijv4yW", + "NodeID-FapbxinG8eCCXzZQKCjxicKcXijmnKzD3", + "NodeID-Fd4DMc88ELLiTHHSLVZ7L4MB3Z7jbDEAy", + "NodeID-Fe3121hoArBshDTJEEeMeJTNW6HcLXxT1", + "NodeID-FeddPuWb8xtJeuXCDa4CAbjgv3n4PBQXV", + "NodeID-Ff4Fx8mcbfBVZSpMFwQKDUURzufmLjLgS", + "NodeID-Ff4s5gpeGMf5HaBKNxBX1uRxB2hxRx5By", + "NodeID-FfRKiU9BpTzMx2KGmrN4YyiwftTAXZ6FH", + "NodeID-Ffh3UfBYLouumUQgGuFbSTBbD5wLXn7xG", + "NodeID-Fg3L1eo53UWpf3J9Y45PK2ksQ1zyqajHL", + "NodeID-Fh3Yr8SejArPdA3eHfg75sLAt1ypeSpCV", + "NodeID-FhH7R1HX2ipEetm1eH7u9aKfBCtCQyuQM", + "NodeID-FjPxKjpGqPNj8NyEVVdJgGT2bXFVkNyW5", + "NodeID-Fjgs4ALe7yajXjZYmcRAvaQBGrFE61QME", + "NodeID-FjpAr4XXwanzuhLMajEVdm6bwdcGgtZNv", + "NodeID-Fk1hBt9ZyaKiTPjq7MLyvL7Kgd2YMH4ie", + "NodeID-FkHyxMuq6DGNLdQtMKiLzhQQuwjSCqwHj", + "NodeID-FoVyB5QV1hmvAxsNunHRRzonCBJGkLvtj", + "NodeID-FpA1n8w3xHmJ1QK3iDAS49vbLJokejfMA", + "NodeID-FqiffXvatKSLPRhkkc5y2MkALrZ8EFN91", + "NodeID-FrGVKPnD3xVmoMK1RjtbD6evNGk3wrpv7", + "NodeID-FrPwbz7L7qvxbxR63g6CMpWPDEyHiiqrD", + "NodeID-FrTRZzNgZZoHMGvC5t6XtJKAv7E2LvYYU", + "NodeID-FrWaLbhUVQHEzXfeekv6MCbkmLfx74HrP", + "NodeID-FrhMaTxsagqjYCetCyxLxpbcpkN3cjVLH", + "NodeID-FroHhWhFsUAh3s6Y4hjh7mx3E79mBUZGj", + "NodeID-FsqY7xFDE7Cvnxkc1BkpnRbiLXH2tAVha", + "NodeID-FtJRoxeiXq4D4hsM9PCAZkoerJDTqPEW7", + "NodeID-Fugfqxb9NKZ3h7vTe7XsjqqKqxYwSrTsh", + "NodeID-Fv3t2shrpkmvLnvNzcv1rqRKbDAYFnUor", + "NodeID-FvAAKfRTbxB5ANcapWNtQ2VGMFWxX3LCh", + "NodeID-FvFBsrTf6BhCcS1nFPJtRrWZ5Nosb47h6", + "NodeID-FxZHg1hxvYyBWFCHzqQPhFYsXte84UT9A", + "NodeID-FxaeyWwirpBBbBwRgpytNrtR3NY6xTiwT", + "NodeID-FyTHAQeNPFhoDetc7pznBMJ5BRj5s6FJr", + "NodeID-FzJA5i97oBDNiKeePSfHc2t3zt5cRHnjJ", + "NodeID-G1KHG6SL2B9jnfbzdTudhjRPa9hp5tuRQ", + "NodeID-G36seLQVfXnaUgaNobbSWg8anRta2WUwE", + "NodeID-G4dtkvboFCTYpnLyHYMVPq8GLxns99NPq", + "NodeID-G5AGU54ib6jCTc9B3aUC6BVLyhEZUuqYE", + "NodeID-G5QuntEfMZS7A1TPSHN4owEa81C6MAGC2", + "NodeID-G6nXgtucmeKn4nkCp8YTDdM4btVSnW4ad", + "NodeID-G6oS8Nbb74RyJatPe34iwhTUPDqJNtuwD", + "NodeID-G7aPjXRfR2XtrB4PGATDS8NoqxmqZmryS", + "NodeID-G8uVCikgvakai25byQwYx1z56N33unmj", + "NodeID-G8yv8mWQy8FLdFfAhJ4v294T5Z2DWDVEH", + "NodeID-G9aa4VXB19wnUzrmVq2SheaxnKEieUW3S", + "NodeID-G9ucCcZoHdXC6mrVpKVqKzHsMrnoVZLU8", + "NodeID-GAEZpCd2Lg5RSrPtQhGvxw6Kid5tAL6bw", + "NodeID-GBvezLieTFYRqHsd8QzWqH1JUhuwD21mJ", + "NodeID-GCL85wyq71aw2FMRTct2PJ2F4qGQL7WH8", + "NodeID-GD3XH39S9feuK74XEh8AhhNEapSt2hqHo", + "NodeID-GDmLiXrEtmFvBiE2s1ZGDYdZZXdkkLW5F", + "NodeID-GDp4P4Jo84yyVRkL3UTkJDuTNno81BBxN", + "NodeID-GE2jerBVdHtvfKkqfNHwBr2MCkDf6tLir", + "NodeID-GFbG2ARoztCgE1FxUekg5KjEaA1bwThjW", + "NodeID-GGHpri3tVbRgLUEFKqxNivRbegTKBAnyG", + "NodeID-GGfhdfGbqenvgChEXpdngjkKYAByo9di7", + "NodeID-GHBthsGgAzrPLXuXk7vbq4qsc9CvSbwXS", + "NodeID-GHZZWcg26qxY8K9uDLXu6Gc9Gh3P11dK4", + "NodeID-GHd5dmrKvYkAbxii5V7wmJw8sRf4JqYAi", + "NodeID-GHomCXMMRTSPRZrrxEULYPFHHXEhb7qvY", + "NodeID-GKBykzpxeALzYee1fGQjFn6oZiA18W26m", + "NodeID-GL87o4Z7DghVRLf4z6befUxjDoWXZUDqg", + "NodeID-GLSSsNA2oHSaebdYDBQ3u98kvHfH7zjYf", + "NodeID-GMJcCQwhNFDGQy4NAkKM563BMudjmHpXb", + "NodeID-GMoxCucPFt2LPSpTh5hPbDPAp71fiV648", + "NodeID-GNHgGvi7xri6CckDAzmQYL4YgR42WkVsX", + "NodeID-GPYurKNwtkhJ7M7UQoDinFz5P7Rsu9yUo", + "NodeID-GQZBUwNZb7iSYWEyqpyrp6HXG7Z43uhWF", + "NodeID-GR11oP3kLHf82Xbi3H2kewqoM7ydHF5ES", + "NodeID-GRReUAPgHbGdXcv5Btpm4ByGvLrD1NgXG", + "NodeID-GRrpJze5AEaBezaYp5QRtVcLAF6AzdJSy", + "NodeID-GS68HENWev9AWcUrhLqxYvsv2opJBZ7km", + "NodeID-GSgaA47umS1px2ohVjodW9621Ks63xDxD", + "NodeID-GTu4yYzFRv4QGXyyvcorGDUMWjzzMWuqN", + "NodeID-GU7boimY7cxeqdDmnPRyYrwLiRmwiHxhn", + "NodeID-GYAMwLv3XViragqqJUQyTNRcUtoRWbi5F", + "NodeID-GYYGoe6y5TtL8vNBVkvTqk8sPTVVqbGaR", + "NodeID-Gajvbi91pdURX1xzYQ7vzm1qUzNQJEfbG", + "NodeID-GbhKbbABkTdzExgzbbsvCdc4gZe8eHpgP", + "NodeID-Gc1hRnfx1mvhgaUnmymNq9TKwvhFjhEkC", + "NodeID-Ge9DfHbtays3Yfsyr1C2Z6eHSLpmTXQ6H", + "NodeID-Ges52zCMZimxqri3ia1J32mUAKyUsvcpV", + "NodeID-Gey3HmUZyAXuvawThT1McvEjrofAwrGi6", + "NodeID-GfDdBdRqzEKK55gCKqThE2LVxLdLhJY3A", + "NodeID-Gfeb3fWPCSpA4g9edG68NS5aJcYpXn6T3", + "NodeID-Gg8SEQhx4vU2KWzQS8ESCrSpcjzEqQ7kY", + "NodeID-GhG3ac1x2g1Fc4xPWXxXRoTLmMuT2asMV", + "NodeID-GhUSE8wcdouEgd3xeCvmYhmevkdNetfXk", + "NodeID-GiEUKDy7YfYRdxD5rA7t6CgEQxyrWP9sj", + "NodeID-GjYkDpBkCueF4vTkZVdtq3yFiMJha2XpF", + "NodeID-GjjemGsR2kXtPLSwv4oNV3JFt579oJUnn", + "NodeID-GkiJ8CRTibePNf3Y2F7LbGTinHm71HvnF", + "NodeID-Gmitibwg27b6WqHLjqmGiXZAh1kmZVq5P", + "NodeID-GmzoRvWfUdTTUZBmWFM8rswgmwMKkcDAB", + "NodeID-Gn7jLTVPuvdrx6mF5hxSbazRoKPWsM14s", + "NodeID-GnKLq2ipT4D2CMcrrGYndSCuQL58yhCR7", + "NodeID-GpDhyVHYVaL8qXFB2a1QPBsXyUMZjiXLF", + "NodeID-GpEnAaYG182MkURWh8KY4wL5KgWB7cBw8", + "NodeID-Gq6cTyqtHRGHSHELPNdwXCjQJH6vwUkBc", + "NodeID-GqRuMoELZus5EYMwBpiBVtWFDnvLmaJj7", + "NodeID-Gr9xzzL6emX5jWv1LoMKLpCebYR2V2nYs", + "NodeID-GrL4JXttpkikBorzFchuaGhnDTWc8nmEb", + "NodeID-GrkiQsGvbv9PSqJf9r3eE79fUgbZqydmK", + "NodeID-Gs4BSxTpRPxx1ioRz18VUB3kEYVBsDV5T", + "NodeID-GsQoMs5GAL8inkh88XPVJWKMwmJqm5T8N", + "NodeID-GuTDsR1tBFgQUbKqCf7J29yBo8ofudHEZ", + "NodeID-GuWMRuFkQPvPjdnuegSQYDmTMbj3UtPBm", + "NodeID-GujHWE263qNN3MjEYhEeAQdPpQdhHquLJ", + "NodeID-GvEoakPRjaB9jTKup6nAMpFSF3HiEeocP", + "NodeID-GvQdXQD6qFzfAYBvnvxiep7WaXVj2FSnJ", + "NodeID-GwcsDtmQrD8thUHiQWgrpRvhuMjxTqZP6", + "NodeID-GwfPzhzby4Ur8mgdqPDjR3jSTevtmfmY", + "NodeID-Gx4oY9nZmAzJrHUfobrmuK9LrJhwejykC", + "NodeID-GxUaibkyR88sErviW2WK3ukDJsT3DFpoU", + "NodeID-GzSFF2tfNMc7YdJzGeNeNxfSWjDvENJUt", + "NodeID-GzhNocnYWSCziBTP5Jj4xAKn29xDKW9Yr", + "NodeID-H1R3mBHFDeBoQzVYyHzX6RGnVV4nMTrWZ", + "NodeID-H1YSzbspeyANTzErprmBQgV2Crq5hXSW8", + "NodeID-H4mD37NM384RtLGjz5aERQoNCrtGEjgK4", + "NodeID-H94Q5zdkBByZVWvqrB5ByiX4dZdG1J45y", + "NodeID-HCw7S2TVbFPDWNBo1GnFWqJ47f9rDJtt1", + "NodeID-HDXjAjk4rG42HXey7gzQPx6dMBfpWeh5k", + "NodeID-HDmmLUSLtok2sGQEruUsYSMjBeQbUrwpH", + "NodeID-HFFiNVtYmv2YF2WHCZWHSCigo25RxgnFz", + "NodeID-HHV1onrMrN68JdRoKfQGeZphebgRrcADT", + "NodeID-HKskHZG5zu629RsEkScAaGrpfGQABqep7", + "NodeID-HM1vYJWnjWhJkJi8dErcu4p5UDxwUKbp9", + "NodeID-HMFqHmnsaeBGdeg83uXsraRJSH67DNsi6", + "NodeID-HRZAiPM3BaZJpAq9jy3UME2EGsrv1ZMaa", + "NodeID-HRmKWRK8HjqqTKWvYMBNv9hcddSYrhqnF", + "NodeID-HS1PKAMjZczSb5ZQRastn1WG6eJeNmahd", + "NodeID-HTG7W4VHoGJBUTip1gKXzXGtEBhiW1DXT", + "NodeID-HWwYYkiTKnXgYycNN5gXQfxhhA8TZdBvs", + "NodeID-HX7H9nBZX3nZRvLVUxCDBesVX6n8Uv4a", + "NodeID-HYwzPrs3tDR6yyMtKZo22fq8grJsP1DVF", + "NodeID-HZnBEWRUGocZ4HYX8EuMP2YEY94NtySWR", + "NodeID-Ha5u99aoKUdNdTdomp8bQcWHUw8PSF7em", + "NodeID-HaxdTdeEr1sWMRZvXwRN2iotd6RYd9XYM", + "NodeID-Hbf2ZY1Zs1s8KMp3rA1zK36N7zt5fSLkz", + "NodeID-HbmSiec8zTKiPWxaBwStg58a3N5KePhC9", + "NodeID-Hby7B4s5wb697sM4XFN5VusKW7eNyDMg6", + "NodeID-Hcq3gpdMqAEiVwq19E5DZhsjggbkxFx2L", + "NodeID-HdByRj5WVuR7REF2eJDndNyHA94hYhjMp", + "NodeID-HdG8EdGWAy8LR8YPA8hndoa1uwwgGv1si", + "NodeID-Hfa96c7a4xF9vYHuMh3cRsKUHa6YkDsYN", + "NodeID-Hgs8rDmSTASnKigsVfz7k3yZ3DgXP5s1j", + "NodeID-HhEvRMAeXAuXqULRysWKNLK2XZKzYwCnK", + "NodeID-Hhkq3c3UzzX3UpwC2kq9TcbJdguht164A", + "NodeID-HiFv1DpKXkAAfJ1NHWVqQoojjznibZXHP", + "NodeID-HkE9eyj5U8saYexeGWuPcQQbiu5MyRHHa", + "NodeID-HkEQ2sJogxEps4tmqFRDuVG9hyfxe8vMg", + "NodeID-HkpgaE4YB9Z7KmueQ2mz2cZFyfttvo6GP", + "NodeID-Hn7YWxiVC9JufWW5n8u1mvaYgNgqWG8VT", + "NodeID-HnCFvKLXEVsT1fJtMxCnkNj5fs9ExEugv", + "NodeID-HoC4UxP4UuJyda7MZs5jUkZRk8Rfj3pzD", + "NodeID-Hp82btBefk1ffBD7d1qtoBL3DuuNUv6qa", + "NodeID-HpMSfYT2ox1vkr1hFNMwmdWuq8QWhvH2u", + "NodeID-Hq2aEQ2RYhEo7BkVR83c78n6wbVLPrbqJ", + "NodeID-Hq5vdoGnZLMfasw4ykMzdM6PhUFDmp7FL", + "NodeID-HqPSHk6fxtJW1EsF9Y8RPH7KvPvdRpnzy", + "NodeID-Hr78Fy8uDYiRYocRYHXp4eLCYeb8x5UuM", + "NodeID-HrGKtuSRaRj9b4CNy2JeLfv1WAULmhwtF", + "NodeID-HrPfqGPogaKpTTcBhNBhmYfLRHZhiMWyR", + "NodeID-HsBEx3L71EHWSXaE6gvk2VsNntFEZsxqc", + "NodeID-HsSzvb9mMLFcidMWoQYXwHrnG2gZKQtPC", + "NodeID-HuPCfRaLN2cXoXDYyi8GYvjATLDmNJMHs", + "NodeID-HvmgHvMoe15ks8rbGXHyKHvJWDyN5yAGU", + "NodeID-HvxZoKdC58RkD4ZVTYwjVZ3TsiQoTESEP", + "NodeID-Hw7wL2of6tnqntucHPpca6xnnTYZCvBRL", + "NodeID-HwD5fu2NCooHXCPc2GMuNHrhfsThpsQYY", + "NodeID-HwSpUzHSq3ZQC5H6sL9xyze8r9APmFunH", + "NodeID-HwTU12fiGyZoyqaShTAFgTadY2w4DnazT", + "NodeID-Hxx8vTs8kH3stQWgPw1XdHKqpbuD2nMRi", + "NodeID-Hy2aSw3vVNwwQhKas9ETUxtfZgcefsPZD", + "NodeID-HysvJteG6zyScbEu5WKiqAetFXHNrnJHA", + "NodeID-HzSHrBKrycaSu3FMCLwd4WfPrQF2n61tG", + "NodeID-Hzfy8c2s9PyC7CPiUB1PmPckWYs7nj9Tm", + "NodeID-Hzwoqn1Vmj46T1HZzEUNG9kb633SLLHxZ", + "NodeID-J1CD2Nw1eX7iNUVw3iXjFJkUgrSm9qbm6", + "NodeID-J2RTGUXRNDSx2kBU8w7Am6Y7k3LABR5iU", + "NodeID-J7GwUKfHXhxTqgFbuQd4us6yKYdwahHHx", + "NodeID-J7PV3mKZgSJRDy3atopJhh15Y1TqYsySk", + "NodeID-J7PjfVJgpLL3mBMUwpicPqiqDFAmNWhKA", + "NodeID-J7gmHAAEPkSPbNeurMqhg6bknPXWgJgS2", + "NodeID-J7n7bUvog8Zdgj4bCNxRzjzrSKAirk7vi", + "NodeID-J7vWeKgzhtKNy14NLT82Vkz5N6L9sqB38", + "NodeID-JAkZxmCTCkBmscBpSisz5xPFDWcrBbkUC", + "NodeID-JAqrskRRwjmmU8fRp6RAf5wDoEtjXFyXu", + "NodeID-JCT5WWZVaKqcMNDXuuYm3Gpgah9TpKevV", + "NodeID-JDH5gzcB2DTfbEokaFU7EvpLN7E1RHzpH", + "NodeID-JDYxVGLrUb8SHwuu5jZBXNC9rqYWd29PG", + "NodeID-JE8niwmtgpDARKNUqTEdXPQY41uHtb1PN", + "NodeID-JFMBphfETbxfarEkQBHw1RSpfoFhdhUSR", + "NodeID-JGVF16zbVcXqH8ysCQdK2ap38DfHk8ie3", + "NodeID-JH744d6NN5DbtYR3fwuonjNGqUNwhYG5V", + "NodeID-JKCgdbWtCa8BreNP3xftfUuoWGXoy8hWX", + "NodeID-JKxZwnEvK2MAsL9SQ46fyCnTo1ZDkz22D", + "NodeID-JPSnjdvcPjD2NQNaTgC8YP6dhcGeKhse8", + "NodeID-JPvThCax26E5wEh4HSpjhfbfGn8LnvGx8", + "NodeID-JQb8aC4ny7Np8CVAasacpby9moWWzZXzT", + "NodeID-JR96tvzbG8L6xdoGLUWUWhQiGkCfNFP7z", + "NodeID-JR9oQgVHfNBybNVMm64AB2AGvHFCfaaxA", + "NodeID-JRCLnbo62xRaNLhNeNd3HzSHK4dW5iMx4", + "NodeID-JReo9xxdEAX82pAt3berdoi59Pn9km8nV", + "NodeID-JSKsSxV74dyp94CvBKqEKUcEEKBXyNbge", + "NodeID-JUncQvtGY9EVfsfHNHrdsiv4kRfAQSsvu", + "NodeID-JVRaZNCXjBjKqsmrd8grSR9LjFDr1zcgo", + "NodeID-JWBfuYPeFXRkuL1AeW6p2fquqoQTVJsV2", + "NodeID-JWwGze2HXQq7THFQj5zWRmBa5XaMj55jZ", + "NodeID-JYoS8akGmcoeLq4kxpxfsPJxwi3UWeXu2", + "NodeID-JZg54UPtzhHhXoVkX4r6WSTc74cAgdFjY", + "NodeID-JZoTeECdroSJ8sDK3nwpeBz2cYCEPPjiu", + "NodeID-JaS7Df16bwZUSL87wersMaXez7836EH2X", + "NodeID-JbXcSSwYvmnwD85nw8Yro79xaNuAJKxqp", + "NodeID-JbsnKEwxa9J6arKtZ52j4obF7FwvH634k", + "NodeID-JbyG4cewqSwjatqGtg7mDYbcvb299Cb8Z", + "NodeID-JcVg17s5KwKNv2yJtYfBjEFfB6GdHDmXN", + "NodeID-Je9mYMihjzv2oDF3ebvzDKs96zfaXDLHF", + "NodeID-JfXzxLA38XSz8EfYiWDUvsz6Tu8xwhdkF", + "NodeID-Jfx9FcVMQuy1FXGd53EuigXnCEgRQUUMg", + "NodeID-JgEayrUnvk1tvMFS5Qvr6LPNSE9wNYNik", + "NodeID-JgdYonZgwW2LRYGMwcDcHywQ4GmvjJoe2", + "NodeID-JgfyD94R76Wj1KBXWkGpnsSAXLM6f6dnN", + "NodeID-JkjTJNKyJwjEfxdfgQhvrUuf9x3ovpQBs", + "NodeID-Jmvu5u8svgTa716m6xBEcrB6wweP9tX5h", + "NodeID-JnREhSP5nvBcrCY1L3it6odDaHKZDryA6", + "NodeID-Jp4dLMTHd6huttS1jZhqNnBN9ZMNmTmWC", + "NodeID-Jpad4xARtJKgtzo199VoEaGbmYdBYbN39", + "NodeID-JqHkFFzz1tYoGHzPuTsueqF1yKifPiBEG", + "NodeID-JqXD8Tsj1nKXCBEp65ESmFhBrEhPL4WCs", + "NodeID-Jr2wjVqKeLpnyK23Y4EgDpCBf1HJ8XpJg", + "NodeID-JrHvS97Avz8uqX3E1RgG6mCSaiedjWf5E", + "NodeID-JwiikR8FhmnYxxGjywAZeJMFjxfpfD3L3", + "NodeID-JxJxzCNp5c2p447FF24jEDPdHkbB2mhJY", + "NodeID-JxxUAnbxUYQXzTQ8eNeE4jWQt9fTzWd8o", + "NodeID-JyCGTjJaPELmLZdtn5J1HwKHZzki6Ae9W", + "NodeID-JyomXASU2NoPhoGGzQtiVKUAHFpm3NeU7", + "NodeID-Jz2nuAFAfyvgni96rviZWsXxyYYBgSmXf", + "NodeID-Jz9EUhGBC19bzUE7kurEPyoKTRjVMgi3v", + "NodeID-K1E6w1DSaHzZky2aUM4qyQfPYMxF6Mixi", + "NodeID-K2fyNZcrWA4DBUNyFme4pNshAgSw2YSSL", + "NodeID-K3gyeR7GXuuf4coJXD4CxviWpRopysX4j", + "NodeID-K3unRwiJFD4p6dXDHJcdeQn6CaoFiqo2", + "NodeID-K3wvYyc46fLE7sSy3G81uta4wDKVkdKbZ", + "NodeID-K484QXg69NxbC2BUsB7Bgc511t22E6MAs", + "NodeID-K5J2aanpMN3PJLmYT7amdzSGygetejuPQ", + "NodeID-K5ecmXoCnxQPFTwrDxqL63kfdh8X4Z3oJ", + "NodeID-K6qqr2J2JcYZnSMRSqpbVv5ysZfnwMreQ", + "NodeID-K7ZsFPBybHPuD3YbzBpp1fe9QTj81WYSU", + "NodeID-K8EaudGE2PS93rgD6aayqS4dPRfrseWdi", + "NodeID-K8tzccU8StAHuSZfS5trxHKbvA17wixN2", + "NodeID-K8zr3RfHUQuupNJdPDKnbhFhwcD3TTbuD", + "NodeID-KALbip9YkRerN81YxU32ySYk5PbGrkysz", + "NodeID-KAjUQ36dNGmMpw35iavX7i8Cr5XGXwby7", + "NodeID-KB1wcvduXXXkTUw97gWchLs4oXbQK8Gwk", + "NodeID-KB5e5rq9ioGR5uicmKdmgjR5hU7iRUFTz", + "NodeID-KBcYcnQmw47qpb49rKtRr5tZgsxnsdkrZ", + "NodeID-KBvpDcnJ9ztfqA4jiAoMwARqfDaS91xqx", + "NodeID-KC9tasJTftYR2SYdNcPRF6XJGng6gBYcw", + "NodeID-KCQARVq1pjYw31EPSaW9571giKoFH498X", + "NodeID-KCX4L5dr83TbmBnE4UeFtzGeE2NSLskt8", + "NodeID-KDHVpdM7PeMtoVm2mmNNXjFfs93cABSut", + "NodeID-KFhoZ7aZMtAReBrb8KgcKG322q27akhN4", + "NodeID-KGYVGbz1pbyuJpujtJAkXhSY3AtLqBG2Z", + "NodeID-KH8r5RoMBBpy4XHHb9DMrbMLc2a1WJKWC", + "NodeID-KH9WnxfcrJLod4JWXHxESehVTAqE5DoLy", + "NodeID-KHRscCPBynyUHXSz4nXrxmFmoMgUPZBTn", + "NodeID-KHaBbtVbSMHmkqs5SKsdCPCgRbouNcwy1", + "NodeID-KHqznMCanU1tA9DcNLBwJQ7zUkRHC9yDW", + "NodeID-KJLkmhbvSYUqdMybmRScnyo7aDY6X2mYa", + "NodeID-KJfoYJrDRXdmLaaaaRMjNbNKAwqSj3pWT", + "NodeID-KK6ifknXca7VGbqB3d5ccUzKta1zJiVM7", + "NodeID-KKz1wXitLQWsfKSSUPE5JL6Wxw35S2218", + "NodeID-KLPimX5rN51nsSg9UQQahoRvKapDLD1pc", + "NodeID-KLiUDfG672VocEHwbAwGxxFdCHovg1Zp5", + "NodeID-KLsfWtM1cJLWNG21LdwPxaLk83pZo99oV", + "NodeID-KNLkh3KVKFFhBWujmcZ5P3p2fJc3BbdNA", + "NodeID-KNPCT1vLFcbVsFvLzgQqrbCS2kvEyZKBz", + "NodeID-KNm1ZqZXdAMJxggBGJkSs7A4tSwYLAjEb", + "NodeID-KQfghSuT1CskYLvgrQAt6oxUQU7ask2QS", + "NodeID-KQfmZVTmDMvuSEW2kts1rmVNmspyzUwVq", + "NodeID-KRhtytNVPjiSeZMJrqqE1vdHTCoMTHCer", + "NodeID-KU58LYgLuboacvuaNQ1T3VZMSdcTxzFfH", + "NodeID-KUgJ4Tiwfx9di8h6oPCkTEcrBBDiDq4hg", + "NodeID-KVB8F5Gy8adXA2zCg3i3m3qJ23NoCDDiA", + "NodeID-KVF3A8uB916AuexeZWS6eeeMdK2ep2vi2", + "NodeID-KXKwcGbqgdKb5ksmyB13p4oP1r8jmsPTW", + "NodeID-KXizASmXqFZsywyF2n41NEs5y6MBbJaa6", + "NodeID-KXuvoHe9KgzW6KfVNHXW4CUNunzWDDC4M", + "NodeID-KZLSjb8umvkj4nUVdARnY55NBKQcYfVV8", + "NodeID-KZiZi4sS44KZjmGtkeF6r1vs2MNN7p2kZ", + "NodeID-KZnxZckzgz9eQWzB3iuvM5GC2QdJLE5yv", + "NodeID-KbqaQBQVzCb44wByiZX4ZChg7CtmX1pVK", + "NodeID-KdEdrTAZpr9rdfqcpXjJxEbHC1oSWnvZP", + "NodeID-KdxMzeB5ubHBCbk8SqgesC4BAUx7fCT6q", + "NodeID-Keh97V9b6k4QvYt4JewbkabSmGoQ4sA3Q", + "NodeID-KfPXTUa3haWHCr1z91ULmY9Pit4VwUQ9C", + "NodeID-Kfqu9wo9FhcXG1jK9nVwbTrBV3d3kzmKR", + "NodeID-KhvVVixdSrBD6u9q25YYNbayxBnNsw9h", + "NodeID-Kk1UZNLJiyf57AL7vYPHntjPYLBdmTyu6", + "NodeID-KkCG4Sktn8zxkaFRV9bi5RaJxZNu1XyMq", + "NodeID-KkZX7xaSAUZ2sGBwpGWLSfLRER4pzR8Fs", + "NodeID-KqKMF5JYhxjkMVpYWQz8zTiv1N1qm2nSf", + "NodeID-KqmFvyCFfsaTcs2XDquCerCfWx3S6Zhj9", + "NodeID-KriCxu39kfZ99PrLwzX2pDUf2Uh8V796m", + "NodeID-KsSwTshRyF2xV75YDNXcEB5psLaBFHKfr", + "NodeID-KsUkk3D4hSKJGM1WBmeu1yj8Ab7h512X1", + "NodeID-KtJJDa5PVQYChXaNd1fKVmF5LSsBB8NHP", + "NodeID-KtJLagoYnWfw2oBnRki63NcguiGjuA2Cr", + "NodeID-KtKf9AuKyBvofsQE7Jn4eAzAndKHu1f4M", + "NodeID-KtSsjRubDzNuGP6FsXphHmtjWx62KCqvf", + "NodeID-KuGgrUTz4ki5oYkE91wHSdXgGL2Gb5fju", + "NodeID-KuStLqzCMZmLv3NigAtKPt2BEE12q71wQ", + "NodeID-KvBcQpCDXbb3w8x7ktMhsx6rCq8eSYcd3", + "NodeID-KvN79EtxbHdT86o7w9GBQEVeRWZ5woAJx", + "NodeID-KxLfzAQyjR1At4rPWmWYGueRUkxSfbVBF", + "NodeID-KzbTvxZgKCWpKcL62Y2HbB54uuDVNTCSo", + "NodeID-L1RcwxtQjb72GiCABuonnV3PWFZKPTV4P", + "NodeID-L1u2bQdMywnBLHVkrMiAoTSCYJTGSwE9k", + "NodeID-L2zTrwT5JitNvBTbC8L8N8i3ANQ1KyNd7", + "NodeID-L3JrbBLmihsqtaXAPXg7acKQbGa9tjhEc", + "NodeID-L3SyWrZH6uorqgExkkmGuXPx9neqELqXA", + "NodeID-L9D4FZhAGu8xGd6LL6Kn4ZqfpXuXSxTXJ", + "NodeID-L9HsJPQ9TF5aXjdx3KnQrh1eWaHJaNXNj", + "NodeID-LBA1YYYBbxwYMMAA9odGhR69d9SCbyq8v", + "NodeID-LCQBGoE9MtECsDjNLohwAP6L4rXDbSooL", + "NodeID-LCRMLuFKUYvcdAemtKiudy1XNM9oMN5Wv", + "NodeID-LCVUCE4bvtPopRuYvoWwTopRScmpLHTcg", + "NodeID-LCvxVSwts7BQAS5mVuXH8XYGuVJZSRtCn", + "NodeID-LDgwboNU4iVyy5MQgArg2rcDPssiAe6jT", + "NodeID-LDv41AQj1469CJsYDux9cLZepfaAWKzCr", + "NodeID-LF7ktpNDXo1fjHYN6MYHnitMPrHwN3pup", + "NodeID-LFNBojkAbg1az3ys8htBJHmyQ96hYhFzP", + "NodeID-LFg6CHJ6gQKNjcCMoz97BdDwqTH9JDUbG", + "NodeID-LGPn5jkr3MueEHLLt71wCRire43N5rp5u", + "NodeID-LGrCunBRJPWSqZLEw2QTHruuQtZai5P64", + "NodeID-LJBZ5j8beyjdcnVdNk5fwtThNn4LokYpV", + "NodeID-LKbxWKUAE7s5dtGWhm4Cr8hsosDxLsNzu", + "NodeID-LL3tKdbQ9qCDRMm4cif2pGsxGDXsNNzBp", + "NodeID-LLVMxBRYjgvczhD9u9RJDSmZ48bbXdWx5", + "NodeID-LN7tsaTsJaPDTJHjUPUX4ePk2HFBWZVh9", + "NodeID-LP9FxV6iBCayBiupHa4QiPxtqDWNoBoVx", + "NodeID-LPf42gVqz97N6bogZGXJNTWhgBABEe4qE", + "NodeID-LQP4aci528q8z4KMe8Ug3Gh1aHj4yojPX", + "NodeID-LQhwkBnuj2vjE786WcgsGneFVWcjiH6KA", + "NodeID-LRBqzoj2mB8eD4AHE2oCTBziNdssTfxuf", + "NodeID-LTM3DRAzRtWoWHVtB58s5CohXKYexiqVp", + "NodeID-LUFJGzAfqkmUaTDBVScjvdWtrruDkbFvr", + "NodeID-LUhB7mVaTMnkYLQsqf2RV2PUerJfsq2wW", + "NodeID-LUqMj414dv39Z5SNRXRb3bz9YhLJ2oWrS", + "NodeID-LVqsakFrQLyqNiChxcYqsBzKaKFRMiBsN", + "NodeID-LXCSfcmd7p7LroJzJtYoSAhbsawe47CNk", + "NodeID-LXVb4LZEU53c7XCk2v4bU2qacG7ux5dUB", + "NodeID-LXpULpbU1A4AobEzCSBy6wYLEbogwsMK1", + "NodeID-LYXB7GQj7vd4Ju3y6fMnX43wkAKJoEN9b", + "NodeID-LZMN1BDS3u6pe7T5Umjuhg1Z1MahXkK9C", + "NodeID-Lai2VTTYk897ae9uq6cGk9FbhKD1KHvFS", + "NodeID-Lb2X2hJpi6krux6aRpYSG7xcNvCXNg6M7", + "NodeID-LbAkNKxyv3kCs1C2ngkb91STbKpYHKs1q", + "NodeID-LcBGn2kscipZRgqhKqDCA5dq4WmHuuvai", + "NodeID-LcG4rUqdBPdrnBuNQ543C2pHVwfknyMJJ", + "NodeID-LcNseW1dfEL8FnXQB5HidFpzNu452vuGc", + "NodeID-Le5rVEBBPdgYEcEJpvYeKo36hRs75WE5S", + "NodeID-LeZUTECdpTLux94oAXKruxYgz5ppx7tfr", + "NodeID-LeesBWnR4x3zWaDmYTPQHmNhsMwm6KqWK", + "NodeID-Lf7b2RCtkb9mYi2Y5kZ3mJvJNc6MEjVnC", + "NodeID-Lga7mB6EfqgSJv4VTPaUwDjEtq6utiNQH", + "NodeID-Lgjda988AdujVYMYdwuEM4Tc8aopF6DRk", + "NodeID-LhLiUsJSSSpW8SrXCT319enhrYDybuG3H", + "NodeID-LhjS7bvahdBn2BomUUBHHFNbnzLRjri6D", + "NodeID-LhkzuEyUkHR9SW4cMxB55QQRbbGF83zzc", + "NodeID-LjxLvskdhxQ5jAhBKSzKrxU9NQD1DPuKR", + "NodeID-LkDLSLrAW1E7Sga1zng17L1AqrtkyWTGg", + "NodeID-LkTbz4orQbSz9hQsjyY743JUA2v1vPjAf", + "NodeID-LmZ33PJKkQqueDDzPnmVSyHMgFFmaADrb", + "NodeID-LmvNsnX956Es8bWDXqaVm4UTQ5wHC3uf7", + "NodeID-Ln3NxH8SbGS4CukCp9Hs3q7ijKfGqneXz", + "NodeID-LnR5bqTLkmeGjsDKiPdJNSbRPr4pjAURR", + "NodeID-LqLgyDEyMbd1uXfRa6kf8EPjnRhpF4KCF", + "NodeID-LqqUzQs77BPhtbXR7jFBsaNRxdLdfLSnT", + "NodeID-Ltq93eHazD1AtdGNuWb739t4fyvnRLryC", + "NodeID-LvKMfPzfWT1VfAPLef6denZ8hTwSAFMGY", + "NodeID-LvWcDhi9d75T8dwerYcQRoVWD6yDtywFN", + "NodeID-LvpYyT4UY4UAgP4quynTFzffYmjoxqZtR", + "NodeID-LwiNyRJeqRfAGS5phAQvvKhX9xj8LbQ86", + "NodeID-LxrJtyQXpdweZH7LR3ujcEQZJ9VDTW3tC", + "NodeID-LydNf31SmNLztbKL7iNsHXPhnKxz7g3Cw", + "NodeID-LzEWm3dhVaGJeHA3ZzzjaRaAVWVeL4Bi3", + "NodeID-M17yakji8RzPBFJNPXnksjoeabg7BXUJH", + "NodeID-M1SrBrn1szYR6jQJkyrJzd6YXsbAeWSnj", + "NodeID-M1Zsz7o9AiDgUqA6KFE8hrCkvybN6EqcP", + "NodeID-M33qUGE35HbVRppTTMY1qyyfK5T52id2a", + "NodeID-M3VrNcHHd3LGpwm6U6Gw1vfuJHoJzfG7g", + "NodeID-M4AhBqhjwLxGixtjxaLvenUpTe8mxNfhg", + "NodeID-M4FXQatkpbrCWRwdf381tfifDzXz34XUS", + "NodeID-M4ojoWJoEmsVD3vf7KxZ2BnfR5Ue2wr41", + "NodeID-M4psvzu2dS7hQ8gHgCUzXfipVKuFEsoFU", + "NodeID-M51d2sDyE92NjgRaiTnSjSLaG3U9eJ3BD", + "NodeID-M5wUvCymq18DUFjXk9s2UCZmyWzgo9ZtJ", + "NodeID-M64wor3rGStFTBWuzvkGPYYsWUu2dX7S2", + "NodeID-M6tt22qVLnGoaYY4aVUXTpKCCCEiupNHA", + "NodeID-M77VJM2GfeAzueJ6DjumoM5enZma86Zop", + "NodeID-M7GC8ZPn3JACK7sxBXqzeoNW6Q2XZeCpM", + "NodeID-M96ypSznK7ECF4EGd5KfxcxCiboyAZnAQ", + "NodeID-M9LeDgEaTfEN1qnEtLw3CXBwjh2VcGbeG", + "NodeID-M9Q4Fc2StCtFCofjppsy6DC7JDGmtRfUA", + "NodeID-MAg11ijmoZunT94rEdvxhmQToJzgH4bYj", + "NodeID-MBuKQwYxNAttaiugN4eMt1aV7vhLUo7Qh", + "NodeID-MBucJmfSNuMy7CiXWb9Zzd1Gf1yCoKwGy", + "NodeID-MBy2Rde5LJyWunzffJ9FfBj3BVNg1haib", + "NodeID-MEnWKkj5iUC3Z2rNhKuDTm5EVDu2ZUZZo", + "NodeID-MFp5wwuKzSfCNESpdD3avbZBkZ3KMkEeK", + "NodeID-MGJcpxBEXDn2Yk94uTXQwxgmYtuX6Ky99", + "NodeID-MHBrAomZpJhaYjqWKWXSS3YusVo7afBn6", + "NodeID-MJvk5Su2t8dFhcGe6z58Fx8A2QAAZTMGd", + "NodeID-MK6HYMwXj3k3HZfzjdegdnd9p9LQ1dk8x", + "NodeID-MKfE4StupLg6ts5v7u6Drs7HhFf1rHjEj", + "NodeID-MLRgfkWbezKNtcH2ghSyE5J3C4Rcxg5Sy", + "NodeID-MLkE5eQrTGa4BoQSR9QLEZKQB9yPJEnuN", + "NodeID-MMemzZih83vtU6TRK5oiJt6bJpNSWm1uE", + "NodeID-MN3pkk9h9anNMuCpUuXPVxGKw1rUw177u", + "NodeID-MNm7zKhCHwqQ3a3oqqEqDSXM9uVFMcEA7", + "NodeID-MP8NsoqJxPMUfCbw1izND6n4i5pTJJkhS", + "NodeID-MPLzWkWAbT3937j7U1uWfxdTMg3iw3BqY", + "NodeID-MSbDAksgjGPoKE4azGEgvrDj1EK2GG8T7", + "NodeID-MSrtdRQ9bEWLhi5d8YLQtnB9E2biVkkrJ", + "NodeID-MTEbgxTNBdL6GWh8SdQMfMXvEU1jC9aws", + "NodeID-MTQbFuBcjcQ7TuVQjvoXC7hiWAWPkouzA", + "NodeID-MTdVMzfENtZAEGdji5EGgiLsLkG3hV9D3", + "NodeID-MTmtdGgEg6gSEVhG5ShyfReR8ubtcZhbb", + "NodeID-MV2a235PcwYscp7qq8N9M4pYQBqMnfZ6T", + "NodeID-MVRcFZmxaMJWedF4oVqsxT2YYkX3kSuGG", + "NodeID-MVUMPzSBAtrHwTD5SZSNPRVTLkYnDPDz4", + "NodeID-MVayMsZd2VrMvEwFMDreTrauJHGBZu3Xa", + "NodeID-MWqZRLNFJzDPKnEuUHJSpEg56ejrzY56V", + "NodeID-MWwstjwXDrzkd3Zqnfaoa9vWtCpb32Fhd", + "NodeID-MXNBsr8xSHE9CKfmyzvBYyEzxAbLuHTAn", + "NodeID-MXxYFnzdP24DpJmdtUKqzMEN7nh69aYqD", + "NodeID-MZV1PpqVuFPa56t7TmfA8VVdXxDSHnQW7", + "NodeID-MZxjrRvxrjvAdaz6pDS82v65xLwckmiti", + "NodeID-Ma3Ztm2A48bCVjfiSmoZS5MKNzKVTRN7j", + "NodeID-Mb528V8a2cdddEYWmxh7ThDGQoQWhMt73", + "NodeID-McTi7BY4csWEnBAb5B9Z2ojNSk21Nt4NK", + "NodeID-MdQZNCCZN5gTEMVaJkSekNYCZkvp5xp4L", + "NodeID-Mdpo4kYtg8eqn61AhjTrZ51exnHLJmcpA", + "NodeID-Mf3rZ5w3aEtM1bzRBwFqhZYZMwks6FYF5", + "NodeID-MfVDQRZ6jSUmke5aofBuNXruEQunxZ5F7", + "NodeID-MgLEPkYaWQD6XqbvRRMk6CfMWe3Zw3P7S", + "NodeID-MikkG849wcdpBdeUJ2HTV2gTEDfeXWseg", + "NodeID-Mm8qGQPb5tHF96ENH1MuYsYwhA5Nj2DHj", + "NodeID-MmTfUacXsPdKryR3WkVteMqoFvyxEdYf4", + "NodeID-Mn2isVXFR85bfjMHPM1DT8EY8wig7YhTW", + "NodeID-MnQoJXMCgPk3zxKQ7kkYdmoZwj2dcDcmb", + "NodeID-Moej2WBv9BCw1pnPGsm31GYvfyY5BHZCD", + "NodeID-Moz5Jcjj2JoDgay9ScwcRDQReSqX8sjyz", + "NodeID-Mq7hjS5ySKApHMKCGw16YFo1tW7xA5DXm", + "NodeID-Mrh4UKAifNZtd8RJXqokDzajQnAsZuw8Q", + "NodeID-Mss1z2VZYsNSa4LyqD99vXeNd8h3hUMDA", + "NodeID-MtJWp4WidtWe1jzPf5u8hFtxMy6TCmaRX", + "NodeID-MtiHM2m6jKECmfTDBcfCut99JHzFm91T5", + "NodeID-Mu35k31HAXFbEp1SqJr1uUrue9nwqVFe6", + "NodeID-MuEFvXvbZ964sk1rdQKWNtUc5PJAGkWeL", + "NodeID-MvfTRb81PAx9AHYxbz5xACaoG84PM7YQe", + "NodeID-MwZ3XEbAdDciHW65MpvfPjiyS9D68hiKz", + "NodeID-MyaTMxwSKbtrFRRypqr1nWKJ3EK6di3dF", + "NodeID-MyeSQZnEZDzTfFFQvxZ5qqfqVDwg15NPB", + "NodeID-N1aFXom4C5ALmH33bXHuRpPBo7Nwqeu8t", + "NodeID-N21EWyi4Y5D8MNapwZ5tXs9D5A3rrfPi1", + "NodeID-N2nTLuaVwKk8EF3NBsSygCVmpGHwNz2Nz", + "NodeID-N2t1CAS75972obgtRPHwVanMnRF1rRo1B", + "NodeID-N35BjCN6ARikprxERf4WiMeUnh2ZsfwJJ", + "NodeID-N3WnyXmV89jbtQgmjqpoxBxpi5Rah86az", + "NodeID-N3e9W3EngjabGnTZVqyZwunVcbCdrY5Qy", + "NodeID-N4eXezpVzti1ssWvyQKqkuGB15dJNJsp5", + "NodeID-N4r8sLfeDVa2c9eDFpE4wuxJccUku3LKu", + "NodeID-N4vaumNTt2kixxUTtWEBgy4vwsxnuahc2", + "NodeID-N5FWBAn5j1UVxb3nH45N9DyXEAaeZiU4q", + "NodeID-N6c8ZxrQwMWWMGn3GVbZvW3GwC6PyWYMz", + "NodeID-N6z9WSBMoSxLSRtdPDz8jZvasAskYcCrd", + "NodeID-N7FjoUy3LrDi1kSYeaBwZjja6H2Y2NLsN", + "NodeID-N7WPJ9DXvEx8xLJdtDswNh1JdNmCKejSq", + "NodeID-N7iZFQdtUfPRcWGs8DB3JQRZt3Pq33eoZ", + "NodeID-N8MfE7gFMQUdH3wirj6HXkYZeeKd13xAx", + "NodeID-N8tijV4qwWMep4STmLzWJEkqbg6bSdCmn", + "NodeID-N95GoeyiprvxNj6E3G8QvYg3gpQ7x8NKE", + "NodeID-N9S6JJT2VKRZ48vA5vtWgboDnfzXXycQn", + "NodeID-N9c2YTRzGpRNp2J6qyPEEiAvyrViL4cGH", + "NodeID-N9qur4q5HCDb7xK6b89peZ5dKJxEWPdFm", + "NodeID-NAFCCsFtU8WXbgpgbciz6zUzwnRZAE99L", + "NodeID-NBjvikZcadcyCJ2hEJsUn9EcCjys5hav9", + "NodeID-NCVrEpmYjJBHqj9vx9r5usFiMd1PooCfZ", + "NodeID-NDMPc8h9L6keJw8F82NBobc874zZ6bDa6", + "NodeID-NEeK7hrVjQUHCwFQVMTmUaVDr33EH6WAw", + "NodeID-NGspMWkA7FgT6DnDghg4B95pQ468j7DK8", + "NodeID-NGxhFFwufwUSXGHjxdCUZW1hNpodfTrmj", + "NodeID-NHBv1LqcCdrcwatzQ9pGbGXPZQTi462Ur", + "NodeID-NHEESrJJNnyCPn5c5Uyp9EZYHCCkZwzuW", + "NodeID-NJZWC8HxGtLkxjQk5F9KSG44WC3gCm8a9", + "NodeID-NJaSwZPtuiN9TxaFLVF2sk3eNNHGm2UC9", + "NodeID-NKStfwoiZwBnZEFka1rqT54AiZ4CN3ksi", + "NodeID-NLBgQfsmCGFzXDehvwvmzjyfmkWQndx9L", + "NodeID-NMfBW4PDVkVZhJzJa6SiCDZ4M7wAkXbAc", + "NodeID-NN5j35c8DsuMydM5icoxhKePqc7AjwH1K", + "NodeID-NN6iut3SAWZqM56kbg8EhtpTU2NkMJgWV", + "NodeID-NNWrYMQgNFRNbvwAUA8grXiAVVE9VEyV6", + "NodeID-NNrbnhLBjgzBvhi3JXK48ckVFcg6FXVnn", + "NodeID-NNyxDSovcVYmXHacSM8aK2pg67oPjkRrE", + "NodeID-NPexpo2AXQ7RZC3wCKugj9q4y599pSfrb", + "NodeID-NSAi8z5XtoagdADeMNAPuWxfZpzUxacYB", + "NodeID-NSHmxWXYXAvHLdHqNyKZjP8MgSSu1dNnW", + "NodeID-NST51yBNtgVkXWuofyacbR1MbqYJEYdor", + "NodeID-NSUM9tzmeZ1DujarhTwjXAcnCeAH273v3", + "NodeID-NSngpSyxjXz3ErfjsFoc6CpfVPLxApJen", + "NodeID-NTTNYBYdkf3n5U4zrZknt1nst9rHzpuCj", + "NodeID-NTvJb2gZdvYU2kaMUrMbtu79KUMgyJNPW", + "NodeID-NUur4HBKXj8GS5TX11jZhtPHLH6zMa6L5", + "NodeID-NVSSRYMjjYyMkUpt7AHXWnKNTTJCd8UbS", + "NodeID-NVkHd9WCbVAr79r3gtA7AmKBkVkNL9EXb", + "NodeID-NWwQRYczsB8gf2tiiLLrk1foSgNUyrFLe", + "NodeID-NYjgvA2mJy4kTCQeEHnSuycnu5Kgo9gEq", + "NodeID-NZEnXQpa55wAhwpcUZFgSAREXW1FLdkzQ", + "NodeID-NZGsXrgoEuExZdJn8WxmyrLt4Cxb7LFyD", + "NodeID-NaGEfmLttvK5r93aqaoxLKoADVcs2HASy", + "NodeID-NcPHhZ4wgGywviLVxEQ6s2q5NZm6Wgrqb", + "NodeID-NcSLm9skkUrfA9mKGjdtmT163iDjqAw6H", + "NodeID-NcZtrWEjPY7XDT5PHgZbwXLCW3LGBjxui", + "NodeID-NdpTU44ZgiACprPmr9evdh4NS6Knz1PfR", + "NodeID-NfgHajZM47C3CaAXFa1B2YrwZmc4EdSgk", + "NodeID-Nfz4ZGQ8ZPvNQ3yHoRNMT7aTCiFYjMnSA", + "NodeID-NgkksDCWH73BnfgN2ALUBykc2kftsquff", + "NodeID-NhL9H8VSfhrktdjmQQ3P47wYXzRfQwBiy", + "NodeID-NiW2qTm2fSKHGuMqeo1twtM8j7LoAGzHR", + "NodeID-NkYLNRp4S6exbWamVvMzUUpXvHeVEzLR6", + "NodeID-Nom39tjDi1Vf51VxuaZvJiDeQHwbyg6MU", + "NodeID-NovHTxGVasNU2y33YPwmQ39DbYDkXiEfe", + "NodeID-Nr584bLpGgbCUbZFSBaBz3Xum5wpca9Ym", + "NodeID-NrVSfY4zCbPjYTe4XPjmQB7qLJhYW3V6h", + "NodeID-Nrs246dXUZmALw7a2HRTANx6U1LeawsKq", + "NodeID-NsVdtyjprgWXLsvmuWvYe749tx3tdbY55", + "NodeID-Nsdn6eemD7KUpKEaGYjYFuJjxC36c3qXC", + "NodeID-NtDMBzQGPnp7suCbyCMcdE2CFU4JXcvwX", + "NodeID-NtX4Q64xT4Yad8wdhQ4erSG6mi3DPUwzX", + "NodeID-NtgR3kDx7Mm2szCiDTs3rtWaqUDWRMDyY", + "NodeID-NuJhcXgmQMbFJwm9yTTmdvGN86qygnXwP", + "NodeID-NuXW8S95Hvv2eq6JoY1qCDmK1h8yuAAt3", + "NodeID-NudTZgq7DKGQsY1Gkt1v3ZG7pgaWbbBuj", + "NodeID-NvsbNmirter6SLhta1kkvoEjcgvaHxEt9", + "NodeID-Nwr26Q5CPcRfSHQKgQ5y3ayVPgjziWkkT", + "NodeID-NxgyyDw6YGHprTJjZv7qh9X1yoj3yZN7u", + "NodeID-Nz93c8UB78eEVVtfxpcecxHmiy2gZ4iAi", + "NodeID-NzQnRDwTYZJPwYMcDkyNGCnhH7S1HQZgy", + "NodeID-Nza7rHanhSFgJ6m9D8fFWgrx7fqbxp7q9", + "NodeID-NzaVh4SaZh7zaT5uFmHyAT99zRbQhzvvd", + "NodeID-P2EM7MDMhKVo4LLgSqtxYSyc39wfPe2TL", + "NodeID-P2Jp7sd5mv4ZGBqThYfjHkz1EyJUXoMcE", + "NodeID-P2xEUig1YeBTwrUF3Xj52pxaNH6gSHjsb", + "NodeID-P3EhUmKXJ5F2BiZw1TwNftAC1y4XyGufz", + "NodeID-P3budG9yRu9ph2UedCGdf3KaLQKQLehy2", + "NodeID-P4tSY1ZLb4q2xTdYGXCkgwXWeQN7mUUWq", + "NodeID-P5hTsAQgfSLJumMDVDK2773U4gjyPtYnr", + "NodeID-P5q5numCvCNo6GmD8vhDqq1tU25Yok4Ky", + "NodeID-P6M41urqadxF7NBcxEHNFxKkGPkHjC95v", + "NodeID-P9FGdfCp7sHRcUwHERp2hzo98ifUaCZ5x", + "NodeID-P9kf9VSRrgD8B1MQKMsjravHvMHVxvoaZ", + "NodeID-PDZYy4rfhPZWskL32EMt45zuLD2rWjDLs", + "NodeID-PERaNX2PDtAr8zkXgbZvwXHfjq4VKtbew", + "NodeID-PF9fY3h6ZMMqPmTZZUwc7wyLnZ1rSoz5u", + "NodeID-PGonFPDqHgyAWCFaoLxQvAQEz6uJYzZpW", + "NodeID-PH5DLzGXEhe6RMHgod3CH9T3s3WVfQm8Z", + "NodeID-PJA7yH2ZVtccSj4RrB94a8MtHboS9xozZ", + "NodeID-PKiUH3xw8SmVNVJsAqFV1mXwDXToFVATi", + "NodeID-PL7xq98yQ9kTYyGDvVQg3efowKeHug3HN", + "NodeID-PLs2JZXeTtfZvYx4DJqkA3sKXz8ynvKLM", + "NodeID-PPH8k8RGmrTuc6Dun92atkbDkgs3sj6ws", + "NodeID-PPYetyVA4dk3bYdNtvTsy5Cqg4L31EUze", + "NodeID-PPoo9VFqdSWsrZZHrnrBBfi3uE2cw9JgW", + "NodeID-PRxbx3LZSnwvLqFa5audJBsSqAJe9rmsP", + "NodeID-PT45awwLjTTiEqvFufS4nCkVN7wtEsDmf", + "NodeID-PUw5p37RZKVjpK8kxBa12TBtZZdhykGUP", + "NodeID-PVm9UudEC7N6HJ3jus5KJ1Rufck88g1Dt", + "NodeID-PY3QRSGTdYzmPTQEwrH2AmYUMBnrcge9Y", + "NodeID-PY5kT7pHUEZPmh2QK5k6w3H6pKhFGUfq1", + "NodeID-PYFkkThWT79Sc7QqHijAc1yZjSqfXu6Eb", + "NodeID-PYJbbkTHqyuowa3EKkkxeYxRcXUhxehkF", + "NodeID-PYecKsWbPTayLsHDdopKjB1Mw5NP3kDUJ", + "NodeID-PYmftFnrKf6y9k6kXXuB5GWwjLtkP7sLB", + "NodeID-PYwMEam56vM4Nix3AG1vufHZbMvdv8zwy", + "NodeID-PZ66baswBL8xsSHaFVG2Yx7qH8MkBfXSK", + "NodeID-PZvapthv5iRB7txuVNTrKCo2fWovBExLh", + "NodeID-PaSvEqWq5ZESHSuNGTZeQL6sybzsQzoZ5", + "NodeID-PcDGg5a4P3XK1E7PXS5YedYL7vi8vSXvB", + "NodeID-PcN5Zh5GNvUJnoiaqkvRvMYBo4oAMDvTs", + "NodeID-PczCXQXPxNgeKy3P4jtAt1ycvrjvghVw1", + "NodeID-Pd7Hexv94PQNVnEbYXWUttEAAybG34Yiy", + "NodeID-Pe1pUMoFAts11s2kA3F7EPmzLyZwj6Msv", + "NodeID-Pe5xmD9DhTrSCDykMqFdG8CazG3QyJxos", + "NodeID-PfY5X2GWsSaj8y6usEji4HZmokHHdWsqi", + "NodeID-Pfj9qXo6LGR3goGzcLSJsCZwYNFFndV75", + "NodeID-PhB7iV3nDxiotJnAMetF6puzg6fxTqZCP", + "NodeID-PhDmCZH4R8VFjVzQLRBquKMVss5sKukw3", + "NodeID-Phds7RN13xWBmpe9MTPhJde3hajVpUB38", + "NodeID-PmH5X1xavW8PjgvkW1u4K9qTHAbMx36hq", + "NodeID-PmJQ7UjZo5db9XL494EbbEufAbYxqWswU", + "NodeID-PnuVZDXvdSNRbC92ibq5w1FtPvbTFvwmM", + "NodeID-PqPwxtYAt6AmikigAwkRzTQCaeMqPvpff", + "NodeID-PtG5NyNK2mGku7fSkRDAUyaZwtj5hcbFV", + "NodeID-PuF1sG8hh4CLLznER6vf4d1o6bWZc5Vof", + "NodeID-PuYX3u6gfLje9bt6fCDFHkSwqaL8VSpv6", + "NodeID-Puv7ksUTmwsxqEx7XLikRicKtKss6QNNi", + "NodeID-Pv5X1dBk1wfZJwRqm8Aj9QecxvA87r31j", + "NodeID-PvssbRjYWsCmvck5umz9V2qMRXMHPpz9W", + "NodeID-PxXndSoasDvvx9ax2h9bWGb9iF3LcR11h", + "NodeID-PxmdCJV62VecySivang3vVymEBwjPQeTm", + "NodeID-PzEsAB7RCHTFwHszw3yfs99GshYm6Qs5b", + "NodeID-PzQafFPgbCLkvMgrP7nh7aCG1eKypdNi2", + "NodeID-Q2NiN9VSKEYK11GMMFZm1r9vYQ2D7srq1", + "NodeID-Q44XVjVEhgxacoq2ETj7yLBuUra9ru2BA", + "NodeID-Q4mUNVKvwEHF3tkxQcCYbrQA8XWdybLzv", + "NodeID-Q5rNbr5yFwotdbeRPGeTagHP1hbHYuaJg", + "NodeID-Q5xvrPQSjHhJX8eLKbBnZMWbS648NqnsZ", + "NodeID-Q6ZLZ1EifMyNd6evH83FJrVGyauaUSP9S", + "NodeID-QBowbP1jz8zA86CtSzRwsFsxr5q1rY6pB", + "NodeID-QCfTXZ1cdPt5XT1jiJfycHKTFo6Yg164L", + "NodeID-QCkFTaWJg5ixVhZoNbePxzs9HWrTutVy4", + "NodeID-QDLrtBngMA6mFveLNZTXxKQVEYx518fG8", + "NodeID-QDfLjUuR9D5a6G5ZAQdPPbggJxtLnbPj3", + "NodeID-QHX9w6oLs8zjHdBvbzx1ZadHvy9aUNLr5", + "NodeID-QHa12bzXnupukwvFdWkRrRzRkC1Cz9nXd", + "NodeID-QJMNxwTLjdg9C1vY2BKNtapWUuoeCgHFj", + "NodeID-QKGoUvqcgormCoMj6yPw9isY7DX9H4mdd", + "NodeID-QKdEYKG21HJ5DCQQaotjG4rJmcTgjno7f", + "NodeID-QKfhLAkwYPwAZNKTanfuNfmm7cYRTzfYo", + "NodeID-QKn4ujiEcP1n8iFbEJqNsKZUYbUG4fHAc", + "NodeID-QL7j3UxnxJz2HUn6jNdqH7gqcGX5XcPug", + "NodeID-QLC3sD3RU2SkeWhSrzM8tfb5QF3XYgDgr", + "NodeID-QmTPCR33deSWVwZ4Ri2jUw6cDAhoUwZP", + "NodeID-SWPRmNkYP7vP1y1EKnuH78QZNyJ2ZpZM", + "NodeID-TgaMGAEpkXKAisumnnmzzRzVkexbSkB7", + "NodeID-UC1qmKMoMcfShU6idcreEAsxSHs3BDBj", + "NodeID-V3fYZv2vHtLB5gQF548JRnSyk4tZfZ2o", + "NodeID-V5R4XjWDtjs8Zi2g3TRNzngnGJiXm2ic", + "NodeID-VEhPJXs67q8rs8hifAfBxYUgE1s8YKfz", + "NodeID-WAHX8MXekynX6xZSFiSewY9Qxnhq5HZh", + "NodeID-WRz6mTt6LCdSSvuHdqsrBYxi4hdfecTW", + "NodeID-XYAkZN1GfMwcYRRyGLiZsGV2thZbqDGT", + "NodeID-YdCKQdXecSPWqABWcRtPZvBaLd3MPPR8", + "NodeID-ZVLPagHUUrQ2vB7mjsWQ44wNGf5SVKKW", + "NodeID-ZwShn4JT1Bg91QphD3VBLryA88GFnAg5", + "NodeID-aFRSyUykQjScZiWASVqmdTGzBfV9KKj1", + "NodeID-bx2UN8z5nfLMTFphQqnYeyngQnccL6tN", + "NodeID-cme6KToKFLCwqj27F7a7Ys9iC4cLrqMz", + "NodeID-duaNgYtghtCRzj2rkiRDDs51BPX8CCjn", + "NodeID-fr4FFtJ5PF5UZpyA3RyoxhNks6Yfhu7u", + "NodeID-i9uQjR8P5Wzd1wTLeALkZ2oXqKjMKQbs", + "NodeID-iTKqsK6Qhjj9RT2ZA9PVAC96FTiDvK7k", + "NodeID-jB3tEp5oBcHYRLLmNaMgP4v59dyr1a9E", + "NodeID-jjTi6fViUUkPwZQbE9N8Bm7AThmVyjGW", + "NodeID-jz1mR5zZukizoZEZ1Wa17h18Kou1Rfzt", + "NodeID-kCLme7NNnAVrbQGZadzgWwtoPJpkQcJR", + "NodeID-kXTWkRtur8X9vchkcXAiG6qD8PDogo2N", + "NodeID-kZNuQMHhydefgnwjYX1fhHMpRNAs9my1", + "NodeID-krdJFoXmC68zd4pSFCwMnCM4dhiR8gnq", + "NodeID-mEbcN58z2esHFnnXHeR3T2UTfsR5H6WJ", + "NodeID-mfUNFSM9ak3NuCvaiFCtcmEcHF9ptfrU", + "NodeID-mwty8tviuGBvDEG8e6vTQByDZN2MKnNo", + "NodeID-mzhghLeMzv8qrRrK76wABwrf3LrL6mP1", + "NodeID-nJm8Ltnf7MDCiuP3PzU4hv3RqXXKmeqd", + "NodeID-oZyu1tEJrBeFkquoqZ5rYpvsEAkfFiwD", + "NodeID-rKCpkJKNAZeE8sKEHduq8Co7GwrAdTJb", + "NodeID-rS4TWt8iuAbQTsg6ez6u5tXvUzicRzuq", + "NodeID-rU9hLEWJCxRksiPuEYm2qqof6uwWEDeo", + "NodeID-rroLHLixQkZMTsTnePdWhDrGpWenYX7t", + "NodeID-sAyLfHTC8ZQRn5HtfjNKxXDbnZTaJUqa", + "NodeID-tHkVEqdhWPdX2vJGbqDWebw2VPrho4Aq", + "NodeID-uhGb1JoQ5sv9oJaECWYN7H5PabwxehN2", + "NodeID-vV5S1LUtAxCWq9ASiDSjZpX88y2WcFGM", + "NodeID-vrzTEabKUgCBXYg3oHFwJFkR1Np6Avh5", + "NodeID-w6kJAMpdT4hB9jE4NnEfBm47PzD1UXfW", + "NodeID-xHLKdNkbh94JMSFp2vU7fbwEA712vub7", + "NodeID-xQU1Ntg4uYkkSgXivV2ELwr8s8FovRCS", + "NodeID-xVVbmFL3eww4dmBkgQ2akBxcnEy4VyLh", + "NodeID-z3Z8s8xoYQhN8A1fmNZcQx9CyXN6zxJz", + "NodeID-z3rX3CnWLi5KBXQ8nVB4W8NnLNdUBcPD", + "NodeID-zbFM8qH7MnQ8uo6rm4tZaq6vhbF4cpgt" + ] } \ No newline at end of file From 1348b6672766e8b5bae0ee7e38a78c4e6c18764b Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 16:13:01 -0400 Subject: [PATCH 80/85] nit --- vms/platformvm/vm_test.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index c431667fdf0f..67418b8f6cf2 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -1440,13 +1440,8 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { externalSender, chainRouter, timeoutManager, -<<<<<<< HEAD p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, - subnets.New(consensusCtx.NodeID, subnets.Config{GossipConfig: gossipConfig}), -======= - p2p.EngineType_ENGINE_TYPE_SNOWMAN, subnets.New(consensusCtx.NodeID, subnets.Config{}), ->>>>>>> add-checkpoints ) require.NoError(err) @@ -1510,6 +1505,15 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { ) require.NoError(err) + p2pTracker, err := p2p.NewPeerTracker( + ctx.Log, + "peer_tracker", + consensusCtx.Registerer, + set.Of(ctx.NodeID), + nil, + ) + require.NoError(err) + h, err := handler.New( bootstrapConfig.Ctx, beacons, @@ -1520,6 +1524,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { vm, subnets.New(ctx.NodeID, subnets.Config{}), tracker.NewPeers(), + p2pTracker, ) require.NoError(err) From 71513e724fa73c5ee8a5ff9964a1dde316e78c32 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 16:49:17 -0400 Subject: [PATCH 81/85] nit --- snow/engine/snowman/bootstrap/bootstrapper.go | 5 ++++- snow/networking/sender/sender.go | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 5a6fa92b7259..a4c40c855102 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -411,7 +411,10 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { nodeID, ok := b.PeerTracker.SelectPeer() if !ok { - // TODO: FIXME + // If we aren't connected to any peers, we send a request to ourself + // which is guaranteed to fail. We send this message to use the message + // timeout as a retry mechanism. Once we are connected to another node + // again we will select them to sample from. nodeID = b.Ctx.NodeID } diff --git a/snow/networking/sender/sender.go b/snow/networking/sender/sender.go index 6bbf22a4ccfb..81fd01702bd0 100644 --- a/snow/networking/sender/sender.go +++ b/snow/networking/sender/sender.go @@ -665,9 +665,10 @@ func (s *sender) SendGetAncestors(ctx context.Context, nodeID ids.NodeID, reques s.engineType, ) - // Sending a GetAncestors to myself always fails. + // Sending a GetAncestors to myself will fail. To avoid constantly sending + // myself requests when not connected to any peers, we rely on the timeout + // firing to deliver the GetAncestorsFailed message. if nodeID == s.ctx.NodeID { - go s.router.HandleInbound(ctx, inMsg) return } From 918acdf1ecf797c4c4335c8858f6af3edf5029ac Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 16:51:03 -0400 Subject: [PATCH 82/85] nit --- snow/engine/snowman/bootstrap/bootstrapper.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index a4c40c855102..bc055e29be17 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -512,6 +512,8 @@ func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request blockSet[block.ID()] = block } + // TODO: Calculate bandwidth based on the blocks that were persisted to + // disk. var ( requestLatency = time.Since(requestTime).Seconds() + epsilon bandwidth = float64(numBytes) / requestLatency From 713a06f7b1ac089b6291e2f11f7e1ba45e6ea0b2 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 17:09:03 -0400 Subject: [PATCH 83/85] this test sucks --- snow/networking/sender/sender_test.go | 33 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/snow/networking/sender/sender_test.go b/snow/networking/sender/sender_test.go index 44b4a316fec2..2005c25da2a1 100644 --- a/snow/networking/sender/sender_test.go +++ b/snow/networking/sender/sender_test.go @@ -1113,7 +1113,8 @@ func TestSender_Single_Request(t *testing.T) { type test struct { name string failedMsgF func(nodeID ids.NodeID) message.InboundMessage - assertMsgToMyself func(require *require.Assertions, msg message.InboundMessage) + shouldFailMessageToSelf bool + assertMsg func(require *require.Assertions, msg message.InboundMessage) expectedResponseOp message.Op setMsgCreatorExpect func(msgCreator *message.MockOutboundMsgBuilder) setExternalSenderExpect func(externalSender *MockExternalSender, sentTo set.Set[ids.NodeID]) @@ -1132,7 +1133,8 @@ func TestSender_Single_Request(t *testing.T) { engineType, ) }, - assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { + shouldFailMessageToSelf: false, + assertMsg: func(require *require.Assertions, msg message.InboundMessage) { require.IsType(&message.GetAncestorsFailed{}, msg.Message()) innerMsg := msg.Message().(*message.GetAncestorsFailed) require.Equal(ctx.ChainID, innerMsg.ChainID) @@ -1173,7 +1175,8 @@ func TestSender_Single_Request(t *testing.T) { requestID, ) }, - assertMsgToMyself: func(require *require.Assertions, msg message.InboundMessage) { + shouldFailMessageToSelf: true, + assertMsg: func(require *require.Assertions, msg message.InboundMessage) { require.IsType(&message.GetFailed{}, msg.Message()) innerMsg := msg.Message().(*message.GetFailed) require.Equal(ctx.ChainID, innerMsg.ChainID) @@ -1252,14 +1255,18 @@ func TestSender_Single_Request(t *testing.T) { // Note that HandleInbound is called in a separate goroutine // so we need to use a channel to synchronize the test. calledHandleInbound := make(chan struct{}) - router.EXPECT().HandleInbound(gomock.Any(), gomock.Any()).Do( - func(_ context.Context, msg message.InboundMessage) { - // Make sure we're sending ourselves - // the expected message. - tt.assertMsgToMyself(require, msg) - close(calledHandleInbound) - }, - ) + if tt.shouldFailMessageToSelf { + router.EXPECT().HandleInbound(gomock.Any(), gomock.Any()).Do( + func(_ context.Context, msg message.InboundMessage) { + // Make sure we're sending ourselves + // the expected message. + tt.assertMsg(require, msg) + close(calledHandleInbound) + }, + ) + } else { + close(calledHandleInbound) + } tt.sendF(require, sender, ctx.NodeID) @@ -1292,7 +1299,7 @@ func TestSender_Single_Request(t *testing.T) { func(_ context.Context, msg message.InboundMessage) { // Make sure we're sending ourselves // the expected message. - tt.assertMsgToMyself(require, msg) + tt.assertMsg(require, msg) close(calledHandleInbound) }, ) @@ -1328,7 +1335,7 @@ func TestSender_Single_Request(t *testing.T) { func(_ context.Context, msg message.InboundMessage) { // Make sure we're sending ourselves // the expected message. - tt.assertMsgToMyself(require, msg) + tt.assertMsg(require, msg) close(calledHandleInbound) }, ) From bdeb1b80b227f874cb4e595ce1c4ac96e78d5d3b Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 16 Apr 2024 20:32:11 -0400 Subject: [PATCH 84/85] Cleanup avalanche bootstrapping fetching --- chains/manager.go | 2 +- .../avalanche/bootstrap/bootstrapper.go | 169 +++++++++--------- .../avalanche/bootstrap/bootstrapper_test.go | 136 +++----------- snow/engine/avalanche/bootstrap/config.go | 8 +- snow/engine/snowman/bootstrap/bootstrapper.go | 1 - 5 files changed, 117 insertions(+), 199 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index b8b051c0a058..47183a819a7a 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -885,9 +885,9 @@ func (m *manager) createAvalancheChain( avalancheBootstrapperConfig := avbootstrap.Config{ AllGetsServer: avaGetHandler, Ctx: ctx, - Beacons: vdrs, StartupTracker: startupTracker, Sender: avalancheMessageSender, + PeerTracker: peerTracker, AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, VtxBlocked: vtxBlocker, TxBlocked: txBlocker, diff --git a/snow/engine/avalanche/bootstrap/bootstrapper.go b/snow/engine/avalanche/bootstrap/bootstrapper.go index d3028bc3bfce..b79c9c8cb5ff 100644 --- a/snow/engine/avalanche/bootstrap/bootstrapper.go +++ b/snow/engine/avalanche/bootstrap/bootstrapper.go @@ -6,6 +6,7 @@ package bootstrap import ( "context" "fmt" + "time" "go.uber.org/zap" @@ -18,7 +19,6 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/heap" - "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/version" ) @@ -38,6 +38,8 @@ const ( // maxOutstandingGetAncestorsRequests is the maximum number of GetAncestors // sent but not yet responded to/failed maxOutstandingGetAncestorsRequests = 10 + + epsilon = 1e-6 // small amount to add to time to avoid division by 0 ) var _ common.BootstrapableEngine = (*bootstrapper)(nil) @@ -58,7 +60,8 @@ func New( ChitsHandler: common.NewNoOpChitsHandler(config.Ctx.Log), AppHandler: config.VM, - outstandingRequests: bimap.New[common.Request, ids.ID](), + outstandingRequests: bimap.New[common.Request, ids.ID](), + outstandingRequestTimes: make(map[common.Request]time.Time), processedCache: &cache.LRU[ids.ID, struct{}]{Size: cacheSize}, onFinished: onFinished, @@ -85,7 +88,8 @@ type bootstrapper struct { metrics // tracks which validators were asked for which containers in which requests - outstandingRequests *bimap.BiMap[common.Request, ids.ID] + outstandingRequests *bimap.BiMap[common.Request, ids.ID] + outstandingRequestTimes map[common.Request]time.Time // IDs of vertices that we will send a GetAncestors request for once we are // not at the max number of outstanding requests @@ -125,84 +129,76 @@ func (b *bootstrapper) Clear(context.Context) error { // response to a GetAncestors message to [nodeID] with request ID [requestID]. // Expects vtxs[0] to be the vertex requested in the corresponding GetAncestors. func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, vtxs [][]byte) error { + request := common.Request{ + NodeID: nodeID, + RequestID: requestID, + } + requestedVtxID, ok := b.outstandingRequests.DeleteKey(request) + if !ok { // this message isn't in response to a request we made + b.Ctx.Log.Debug("received unexpected Ancestors", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return nil + } + requestTime := b.outstandingRequestTimes[request] + delete(b.outstandingRequestTimes, request) + lenVtxs := len(vtxs) if lenVtxs == 0 { b.Ctx.Log.Debug("Ancestors contains no vertices", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), ) - return b.GetAncestorsFailed(ctx, nodeID, requestID) + + b.PeerTracker.RegisterFailure(nodeID) + return b.fetch(ctx, requestedVtxID) } + if lenVtxs > b.Config.AncestorsMaxContainersReceived { + vtxs = vtxs[:b.Config.AncestorsMaxContainersReceived] + b.Ctx.Log.Debug("ignoring containers in Ancestors", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), zap.Int("numIgnored", lenVtxs-b.Config.AncestorsMaxContainersReceived), ) - - vtxs = vtxs[:b.Config.AncestorsMaxContainersReceived] } - requestedVtxID, requested := b.outstandingRequests.DeleteKey(common.Request{ - NodeID: nodeID, - RequestID: requestID, - }) - vtx, err := b.Manager.ParseVtx(ctx, vtxs[0]) // first vertex should be the one we requested in GetAncestors request + vtx, err := b.Manager.ParseVtx(ctx, vtxs[0]) if err != nil { - if !requested { - b.Ctx.Log.Debug("failed to parse unrequested vertex", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - zap.Error(err), - ) - return nil - } - if b.Ctx.Log.Enabled(logging.Verbo) { - b.Ctx.Log.Verbo("failed to parse requested vertex", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - zap.Stringer("vtxID", requestedVtxID), - zap.Binary("vtxBytes", vtxs[0]), - zap.Error(err), - ) - } else { - b.Ctx.Log.Debug("failed to parse requested vertex", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - zap.Stringer("vtxID", requestedVtxID), - zap.Error(err), - ) - } - return b.fetch(ctx, requestedVtxID) - } - - vtxID := vtx.ID() - // If the vertex is neither the requested vertex nor a needed vertex, return early and re-fetch if necessary - if requested && requestedVtxID != vtxID { - b.Ctx.Log.Debug("received incorrect vertex", + b.Ctx.Log.Debug("failed to parse requested vertex", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), - zap.Stringer("vtxID", vtxID), + zap.Stringer("vtxID", requestedVtxID), + zap.Error(err), ) + + b.PeerTracker.RegisterFailure(nodeID) return b.fetch(ctx, requestedVtxID) } - if !requested && !b.outstandingRequests.HasValue(vtxID) && !b.needToFetch.Contains(vtxID) { - b.Ctx.Log.Debug("received un-needed vertex", + + if actualID := vtx.ID(); actualID != requestedVtxID { + b.Ctx.Log.Debug("received incorrect vertex", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), - zap.Stringer("vtxID", vtxID), + zap.Stringer("vtxID", actualID), ) - return nil + + b.PeerTracker.RegisterFailure(nodeID) + return b.fetch(ctx, requestedVtxID) } - // Do not remove from outstanding requests if this did not answer a specific outstanding request - // to ensure that real responses are not dropped in favor of potentially byzantine Ancestors messages that - // could force the node to bootstrap 1 vertex at a time. - b.needToFetch.Remove(vtxID) + b.needToFetch.Remove(requestedVtxID) + + // All vertices added to [verticesToProcess] have received transitive votes + // from the accepted frontier. + var ( + numBytes = len(vtxs[0]) + verticesToProcess = make([]avalanche.Vertex, 1, len(vtxs)) + ) + verticesToProcess[0] = vtx - // All vertices added to [processVertices] have received transitive votes from the accepted frontier - processVertices := make([]avalanche.Vertex, 1, len(vtxs)) // Process all of the valid vertices in this message - processVertices[0] = vtx parents, err := vtx.Parents() if err != nil { return err @@ -212,7 +208,7 @@ func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request eligibleVertices.Add(parent.ID()) } - for _, vtxBytes := range vtxs[1:] { // Parse/persist all the vertices + for _, vtxBytes := range vtxs[1:] { vtx, err := b.Manager.ParseVtx(ctx, vtxBytes) // Persists the vtx if err != nil { b.Ctx.Log.Debug("failed to parse vertex", @@ -220,12 +216,6 @@ func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request zap.Uint32("requestID", requestID), zap.Error(err), ) - b.Ctx.Log.Debug("failed to parse vertex", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - zap.Binary("vtxBytes", vtxBytes), - zap.Error(err), - ) break } vtxID := vtx.ID() @@ -245,26 +235,41 @@ func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request for _, parent := range parents { eligibleVertices.Add(parent.ID()) } - processVertices = append(processVertices, vtx) + + numBytes += len(vtxBytes) + verticesToProcess = append(verticesToProcess, vtx) b.needToFetch.Remove(vtxID) // No need to fetch this vertex since we have it now } - return b.process(ctx, processVertices...) + // TODO: Calculate bandwidth based on the vertices that were persisted to + // disk. + var ( + requestLatency = time.Since(requestTime).Seconds() + epsilon + bandwidth = float64(numBytes) / requestLatency + ) + b.PeerTracker.RegisterResponse(nodeID, bandwidth) + + return b.process(ctx, verticesToProcess...) } func (b *bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - vtxID, ok := b.outstandingRequests.DeleteKey(common.Request{ + request := common.Request{ NodeID: nodeID, RequestID: requestID, - }) + } + vtxID, ok := b.outstandingRequests.DeleteKey(request) if !ok { - b.Ctx.Log.Debug("skipping GetAncestorsFailed call", - zap.String("reason", "no matching outstanding request"), + b.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), ) return nil } + delete(b.outstandingRequestTimes, request) + + // This node timed out their request. + b.PeerTracker.RegisterFailure(nodeID) + // Send another request for the vertex return b.fetch(ctx, vtxID) } @@ -411,21 +416,25 @@ func (b *bootstrapper) fetch(ctx context.Context, vtxIDs ...ids.ID) error { continue } - validatorIDs, err := b.Config.Beacons.Sample(b.Ctx.SubnetID, 1) // validator to send request to - if err != nil { - return fmt.Errorf("dropping request for %s as there are no validators", vtxID) + nodeID, ok := b.PeerTracker.SelectPeer() + if !ok { + // If we aren't connected to any peers, we send a request to ourself + // which is guaranteed to fail. We send this message to use the + // message timeout as a retry mechanism. Once we are connected to + // another node again we will select them to sample from. + nodeID = b.Ctx.NodeID } - validatorID := validatorIDs[0] - b.requestID++ - b.outstandingRequests.Put( - common.Request{ - NodeID: validatorID, - RequestID: b.requestID, - }, - vtxID, - ) - b.Config.Sender.SendGetAncestors(ctx, validatorID, b.requestID, vtxID) // request vertex and ancestors + b.PeerTracker.RegisterRequest(nodeID) + + b.requestID++ + request := common.Request{ + NodeID: nodeID, + RequestID: b.requestID, + } + b.outstandingRequests.Put(request, vtxID) + b.outstandingRequestTimes[request] = time.Now() + b.Config.Sender.SendGetAncestors(ctx, nodeID, b.requestID, vtxID) // request vertex and ancestors } return b.checkFinish(ctx) } diff --git a/snow/engine/avalanche/bootstrap/bootstrapper_test.go b/snow/engine/avalanche/bootstrap/bootstrapper_test.go index 8d8c107383e9..d17bbd4743ec 100644 --- a/snow/engine/avalanche/bootstrap/bootstrapper_test.go +++ b/snow/engine/avalanche/bootstrap/bootstrapper_test.go @@ -10,12 +10,13 @@ import ( "testing" "time" + "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/avalanche" @@ -28,7 +29,11 @@ import ( "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/version" + + p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p" ) var ( @@ -86,12 +91,23 @@ func newConfig(t *testing.T) (Config, ids.NodeID, *common.SenderTest, *vertex.Te avaGetHandler, err := getter.New(manager, sender, ctx.Log, time.Second, 2000, ctx.AvalancheRegisterer) require.NoError(err) + p2pTracker, err := p2p.NewPeerTracker( + logging.NoLog{}, + "", + prometheus.NewRegistry(), + nil, + version.CurrentApp, + ) + require.NoError(err) + + p2pTracker.Connected(peer, version.CurrentApp) + return Config{ AllGetsServer: avaGetHandler, Ctx: ctx, - Beacons: vdrs, StartupTracker: startupTracker, Sender: sender, + PeerTracker: p2pTracker, AncestorsMaxContainersReceived: 2000, VtxBlocked: vtxBlocker, TxBlocked: txBlocker, @@ -151,7 +167,7 @@ func TestBootstrapperSingleFrontier(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + Type: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, State: snow.NormalOp, }) return nil @@ -257,7 +273,7 @@ func TestBootstrapperByzantineResponses(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + Type: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, State: snow.NormalOp, }) return nil @@ -423,7 +439,7 @@ func TestBootstrapperTxDependencies(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + Type: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, State: snow.NormalOp, }) return nil @@ -546,7 +562,7 @@ func TestBootstrapperIncompleteAncestors(t *testing.T) { config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + Type: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE, State: snow.NormalOp, }) return nil @@ -620,111 +636,3 @@ func TestBootstrapperIncompleteAncestors(t *testing.T) { require.Equal(choices.Accepted, vtx1.Status()) require.Equal(choices.Accepted, vtx2.Status()) } - -func TestBootstrapperUnexpectedVertex(t *testing.T) { - require := require.New(t) - - config, peerID, sender, manager, vm := newConfig(t) - - vtxID0 := ids.Empty.Prefix(0) - vtxID1 := ids.Empty.Prefix(1) - - vtxBytes0 := []byte{0} - vtxBytes1 := []byte{1} - - vtx0 := &avalanche.TestVertex{ - TestDecidable: choices.TestDecidable{ - IDV: vtxID0, - StatusV: choices.Unknown, - }, - HeightV: 0, - BytesV: vtxBytes0, - } - vtx1 := &avalanche.TestVertex{ // vtx1 is the stop vertex - TestDecidable: choices.TestDecidable{ - IDV: vtxID1, - StatusV: choices.Unknown, - }, - ParentsV: []avalanche.Vertex{vtx0}, - HeightV: 1, - BytesV: vtxBytes1, - } - - config.StopVertexID = vtxID1 - bs, err := New( - config, - func(context.Context, uint32) error { - config.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_AVALANCHE, - State: snow.NormalOp, - }) - return nil - }, - ) - require.NoError(err) - - parsedVtx0 := false - parsedVtx1 := false - manager.GetVtxF = func(_ context.Context, vtxID ids.ID) (avalanche.Vertex, error) { - switch vtxID { - case vtxID0: - if parsedVtx0 { - return vtx0, nil - } - return nil, errUnknownVertex - case vtxID1: - if parsedVtx1 { - return vtx1, nil - } - return nil, errUnknownVertex - default: - require.FailNow(errUnknownVertex.Error()) - return nil, errUnknownVertex - } - } - manager.ParseVtxF = func(_ context.Context, vtxBytes []byte) (avalanche.Vertex, error) { - switch { - case bytes.Equal(vtxBytes, vtxBytes0): - vtx0.StatusV = choices.Processing - parsedVtx0 = true - return vtx0, nil - case bytes.Equal(vtxBytes, vtxBytes1): - vtx1.StatusV = choices.Processing - parsedVtx1 = true - return vtx1, nil - default: - require.FailNow(errUnknownVertex.Error()) - return nil, errUnknownVertex - } - } - - requestIDs := map[ids.ID]uint32{} - sender.SendGetAncestorsF = func(_ context.Context, vdr ids.NodeID, reqID uint32, vtxID ids.ID) { - require.Equal(peerID, vdr) - requestIDs[vtxID] = reqID - } - - vm.CantSetState = false - require.NoError(bs.Start(context.Background(), 0)) // should request vtx1 - require.Contains(requestIDs, vtxID1) - - reqID := requestIDs[vtxID1] - clear(requestIDs) - require.NoError(bs.Ancestors(context.Background(), peerID, reqID, [][]byte{vtxBytes0})) - require.Contains(requestIDs, vtxID1) - - manager.EdgeF = func(context.Context) []ids.ID { - require.Equal(choices.Accepted, vtx1.Status()) - return []ids.ID{vtxID1} - } - - vm.LinearizeF = func(_ context.Context, stopVertexID ids.ID) error { - require.Equal(vtxID1, stopVertexID) - return nil - } - - require.NoError(bs.Ancestors(context.Background(), peerID, reqID, [][]byte{vtxBytes1, vtxBytes0})) - require.Equal(choices.Accepted, vtx0.Status()) - require.Equal(choices.Accepted, vtx1.Status()) - require.Equal(snow.NormalOp, config.Ctx.State.Get().State) -} diff --git a/snow/engine/avalanche/bootstrap/config.go b/snow/engine/avalanche/bootstrap/config.go index 8151967abe9d..ec1baccc390b 100644 --- a/snow/engine/avalanche/bootstrap/config.go +++ b/snow/engine/avalanche/bootstrap/config.go @@ -5,23 +5,25 @@ package bootstrap import ( "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/avalanche/bootstrap/queue" "github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/common/tracker" - "github.com/ava-labs/avalanchego/snow/validators" ) type Config struct { common.AllGetsServer - Ctx *snow.ConsensusContext - Beacons validators.Manager + Ctx *snow.ConsensusContext StartupTracker tracker.Startup Sender common.Sender + // PeerTracker manages the set of nodes that we fetch the next block from. + PeerTracker *p2p.PeerTracker + // This node will only consider the first [AncestorsMaxContainersReceived] // containers in an ancestors message it receives. AncestorsMaxContainersReceived int diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index bc055e29be17..5be999ff9eff 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -421,7 +421,6 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { b.PeerTracker.RegisterRequest(nodeID) b.requestID++ - request := common.Request{ NodeID: nodeID, RequestID: b.requestID, From 6d2043a97641c842d19d98d092cd4b57f5ec4ade Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Thu, 18 Apr 2024 14:17:16 -0400 Subject: [PATCH 85/85] merged --- snow/engine/snowman/bootstrap/bootstrapper.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 8c4282bb68e3..2988ece9ba0e 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -421,10 +421,6 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { b.PeerTracker.RegisterRequest(nodeID) b.requestID++ -<<<<<<< HEAD -======= - ->>>>>>> master request := common.Request{ NodeID: nodeID, RequestID: b.requestID,