diff --git a/Makefile b/Makefile index b78e88a68..75a0bfbc5 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ go_clean_deps: ## Runs `go mod tidy` && `go mod vendor` .PHONY: go_lint go_lint: ## Run all linters that are triggered by the CI pipeline - docker run -t --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.51.1 golangci-lint run -v + docker run -t --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.51.1 golangci-lint run -v --timeout 2m .PHONY: gofmt gofmt: ## Format all the .go files in the project in place. @@ -304,6 +304,11 @@ generate_cli_commands_docs: ## (Re)generates the CLI commands docs (this is mean cd app/client/cli/docgen && go run . echo "CLI commands docs generated in ${cli_docs_dir}" +.PHONY: generate_node_state_machine_diagram +generate_node_state_machine_diagram: ## (Re)generates the Node State Machine diagram + go run ./state_machine/visualizer/main.go + echo "Node State Machine diagram generated in state_machine/docs/state-machine.diagram.md" + .PHONY: test_all test_all: ## Run all go unit tests go test -p 1 -count=1 ./... @@ -458,11 +463,11 @@ localnet_up: ## Starts up a k8s LocalNet with all necessary dependencies (tl;dr .PHONY: localnet_client_debug localnet_client_debug: ## Opens a `client debug` cli to interact with blockchain (e.g. change pacemaker mode, reset to genesis, etc). Though the node binary updates automatiacally on every code change (i.e. hot reloads), if client is already open you need to re-run this command to execute freshly compiled binary. - kubectl exec -it deploy/pocket-v1-cli-client -- client debug + kubectl exec -it deploy/pocket-v1-cli-client --container pocket -- client debug .PHONY: localnet_shell localnet_shell: ## Opens a shell in the pod that has the `client` cli available. The binary updates automatically whenever the code changes (i.e. hot reloads). - kubectl exec -it deploy/pocket-v1-cli-client -- /bin/bash + kubectl exec -it deploy/pocket-v1-cli-client --container pocket -- /bin/bash .PHONY: localnet_logs_validators localnet_logs_validators: ## Outputs logs from all validators @@ -477,6 +482,11 @@ localnet_down: ## Stops LocalNet and cleans up dependencies (tl;dr `tilt down` + tilt down --file=build/localnet/Tiltfile kubectl delete pvc --ignore-not-found=true data-dependencies-postgresql-0 +.PHONY: localnet_db_cli +localnet_db_cli: ## Open a CLI to the local containerized postgres instancedb_cli: + echo "View schema by running 'SELECT schema_name FROM information_schema.schemata;'" + kubectl exec -it services/dependencies-postgresql -- bash -c "psql postgresql://postgres:LocalNetPassword@localhost" + .PHONY: check_cross_module_imports check_cross_module_imports: ## Lists cross-module imports $(eval exclude_common=--exclude=Makefile --exclude-dir=shared --exclude-dir=app --exclude-dir=runtime) diff --git a/app/client/cli/actor.go b/app/client/cli/actor.go index 9239d1d7b..a1fb04340 100644 --- a/app/client/cli/actor.go +++ b/app/client/cli/actor.go @@ -107,7 +107,9 @@ If no changes are desired for the parameter, just enter the current param value return err } - pwd = readPassphrase(pwd) + if !nonInteractive { + pwd = readPassphrase(pwd) + } pk, err := kb.GetPrivKey(fromAddrHex, pwd) if err != nil { @@ -248,8 +250,9 @@ func newUnstakeCmd(cmdDef actorCmdDef) *cobra.Command { return err } - pwd = readPassphrase(pwd) - + if !nonInteractive { + pwd = readPassphrase(pwd) + } pk, err := kb.GetPrivKey(fromAddrHex, pwd) if err != nil { return err diff --git a/app/client/cli/cmd.go b/app/client/cli/cmd.go index c712ee513..88f7cef71 100644 --- a/app/client/cli/cmd.go +++ b/app/client/cli/cmd.go @@ -17,8 +17,9 @@ const ( ) var ( - remoteCLIURL string - dataDir string + remoteCLIURL string + dataDir string + nonInteractive bool ) func init() { @@ -27,6 +28,7 @@ func init() { log.Fatalf("[ERROR] Cannot find user home directory: %s", err.Error()) } rootCmd.PersistentFlags().StringVar(&remoteCLIURL, "remote_cli_url", defaults.DefaultRemoteCLIURL, "takes a remote endpoint in the form of :// (uses RPC Port)") + rootCmd.PersistentFlags().BoolVar(&nonInteractive, "non_interactive", false, "if true skips the interactive prompts wherever possible (useful for scripting & automation)") rootCmd.PersistentFlags().StringVar(&dataDir, "data_dir", homeDir+"/.pocket", "Path to store pocket related data (keybase etc.)") } diff --git a/app/client/cli/debug.go b/app/client/cli/debug.go index 3f9c9d9f6..96609be5a 100644 --- a/app/client/cli/debug.go +++ b/app/client/cli/debug.go @@ -1,16 +1,18 @@ package cli import ( + "context" "os" "github.com/manifoldco/promptui" "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/p2p" - debugABP "github.com/pokt-network/pocket/p2p/providers/addrbook_provider/debug" - debugCHP "github.com/pokt-network/pocket/p2p/providers/current_height_provider/debug" + "github.com/pokt-network/pocket/p2p/providers/addrbook_provider" + rpcABP "github.com/pokt-network/pocket/p2p/providers/addrbook_provider/rpc" + "github.com/pokt-network/pocket/p2p/providers/current_height_provider" + rpcCHP "github.com/pokt-network/pocket/p2p/providers/current_height_provider/rpc" + "github.com/pokt-network/pocket/p2p/types" "github.com/pokt-network/pocket/runtime" - coreTypes "github.com/pokt-network/pocket/shared/core/types" - pocketCrypto "github.com/pokt-network/pocket/shared/crypto" "github.com/pokt-network/pocket/shared/messaging" "github.com/pokt-network/pocket/shared/modules" "github.com/spf13/cobra" @@ -44,15 +46,17 @@ var ( PromptSendBlockRequest, } - // validators holds the list of the validators at genesis time so that we can use it to create a debug address book provider. - // Its purpose is to allow the CLI to "discover" the nodes in the network. Since currently we don't have churn and we run nodes only in LocalNet, we can rely on the genesis state. - // HACK(#416): This is a temporary solution that guarantees backward compatibility while we implement peer discovery - validators []*coreTypes.Actor - configPath string = runtime.GetEnv("CONFIG_PATH", "build/config/config1.json") genesisPath string = runtime.GetEnv("GENESIS_PATH", "build/config/genesis.json") ) +type ctxKey int + +const ( + addrBookProviderCtxKey ctxKey = iota + currentHeightProviderCtxKey +) + func init() { debugCmd := NewDebugCommand() rootCmd.AddCommand(debugCmd) @@ -64,24 +68,26 @@ func NewDebugCommand() *cobra.Command { Short: "Debug utility for rapid development", Args: cobra.ExactArgs(0), PersistentPreRun: func(cmd *cobra.Command, args []string) { - runtimeMgr := runtime.NewManagerFromFiles(configPath, genesisPath, runtime.WithClientDebugMode(), runtime.WithRandomPK()) - - // HACK(#416): this is a temporary solution that guarantees backward compatibility while we implement peer discovery. - validators = runtimeMgr.GetGenesis().Validators + runtimeMgr := runtime.NewManagerFromFiles( + configPath, genesisPath, + runtime.WithClientDebugMode(), + runtime.WithRandomPK(), + ) - debugAddressBookProvider := debugABP.NewDebugAddrBookProvider( - runtimeMgr.GetConfig().P2P, - debugABP.WithActorsByHeight( - map[int64][]*coreTypes.Actor{ - debugABP.ANY_HEIGHT: validators, - }, + modulesRegistry := runtimeMgr.GetBus().GetModulesRegistry() + addressBookProvider := rpcABP.NewRPCAddrBookProvider( + rpcABP.WithP2PConfig( + runtimeMgr.GetConfig().P2P, ), ) + modulesRegistry.RegisterModule(addressBookProvider) + cmd.SetContext(context.WithValue(cmd.Context(), addrBookProviderCtxKey, addressBookProvider)) - debugCurrentHeightProvider := debugCHP.NewDebugCurrentHeightProvider(0) + currentHeightProvider := rpcCHP.NewRPCCurrentHeightProvider() + modulesRegistry.RegisterModule(currentHeightProvider) + cmd.SetContext(context.WithValue(cmd.Context(), currentHeightProviderCtxKey, currentHeightProvider)) - // TODO(#429): refactor injecting the dependencies into the bus so that they can be consumed in an updated `P2PModule.Create()` implementation - p2pM, err := p2p.CreateWithProviders(runtimeMgr.GetBus(), debugAddressBookProvider, debugCurrentHeightProvider) + p2pM, err := p2p.Create(runtimeMgr.GetBus()) if err != nil { logger.Global.Fatal().Err(err).Msg("Failed to create p2p module") } @@ -98,7 +104,7 @@ func NewDebugCommand() *cobra.Command { func runDebug(cmd *cobra.Command, args []string) (err error) { for { if selection, err := promptGetInput(); err == nil { - handleSelect(selection) + handleSelect(cmd, selection) } else { return err } @@ -126,57 +132,57 @@ func promptGetInput() (string, error) { return result, nil } -func handleSelect(selection string) { +func handleSelect(cmd *cobra.Command, selection string) { switch selection { case PromptResetToGenesis: m := &messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_RESET_TO_GENESIS, Message: nil, } - broadcastDebugMessage(m) + broadcastDebugMessage(cmd, m) case PromptPrintNodeState: m := &messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_PRINT_NODE_STATE, Message: nil, } - broadcastDebugMessage(m) + broadcastDebugMessage(cmd, m) case PromptTriggerNextView: m := &messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_TRIGGER_NEXT_VIEW, Message: nil, } - broadcastDebugMessage(m) + broadcastDebugMessage(cmd, m) case PromptTogglePacemakerMode: m := &messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_TOGGLE_PACE_MAKER_MODE, Message: nil, } - broadcastDebugMessage(m) + broadcastDebugMessage(cmd, m) case PromptShowLatestBlockInStore: m := &messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_SHOW_LATEST_BLOCK_IN_STORE, Message: nil, } - sendDebugMessage(m) + sendDebugMessage(cmd, m) case PromptSendMetadataRequest: m := &messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_SEND_METADATA_REQ, Message: nil, } - broadcastDebugMessage(m) + broadcastDebugMessage(cmd, m) case PromptSendBlockRequest: m := &messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_SEND_BLOCK_REQ, Message: nil, } - broadcastDebugMessage(m) + broadcastDebugMessage(cmd, m) default: logger.Global.Error().Msg("Selection not yet implemented...") } } // Broadcast to the entire validator set -func broadcastDebugMessage(debugMsg *messaging.DebugMessage) { +func broadcastDebugMessage(cmd *cobra.Command, debugMsg *messaging.DebugMessage) { anyProto, err := anypb.New(debugMsg) if err != nil { logger.Global.Fatal().Err(err).Msg("Failed to create Any proto") @@ -185,10 +191,11 @@ func broadcastDebugMessage(debugMsg *messaging.DebugMessage) { // TODO(olshansky): Once we implement the cleanup layer in RainTree, we'll be able to use // broadcast. The reason it cannot be done right now is because this client is not in the // address book of the actual validator nodes, so `node1.consensus` never receives the message. - // p2pMod.Broadcast(anyProto, messaging.PocketTopic_DEBUG_TOPIC) + // p2pMod.Broadcast(anyProto) - for _, valAddr := range validators { - addr, err := pocketCrypto.NewAddress(valAddr.GetAddress()) + addrBook, err := fetchAddressBook(cmd) + for _, val := range addrBook { + addr := val.Address if err != nil { logger.Global.Fatal().Err(err).Msg("Failed to convert validator address into pocketCrypto.Address") } @@ -196,22 +203,28 @@ func broadcastDebugMessage(debugMsg *messaging.DebugMessage) { logger.Global.Fatal().Err(err).Msg("Failed to send debug message") } } + } // Send to just a single (i.e. first) validator in the set -func sendDebugMessage(debugMsg *messaging.DebugMessage) { +func sendDebugMessage(cmd *cobra.Command, debugMsg *messaging.DebugMessage) { anyProto, err := anypb.New(debugMsg) if err != nil { logger.Global.Error().Err(err).Msg("Failed to create Any proto") } + addrBook, err := fetchAddressBook(cmd) + if err != nil { + logger.Global.Fatal().Msg("Unable to retrieve the addrBook") + } + var validatorAddress []byte - if len(validators) == 0 { + if len(addrBook) == 0 { logger.Global.Fatal().Msg("No validators found") } // if the message needs to be broadcast, it'll be handled by the business logic of the message handler - validatorAddress, err = pocketCrypto.NewAddress(validators[0].GetAddress()) + validatorAddress = addrBook[0].Address if err != nil { logger.Global.Fatal().Err(err).Msg("Failed to convert validator address into pocketCrypto.Address") } @@ -220,3 +233,16 @@ func sendDebugMessage(debugMsg *messaging.DebugMessage) { logger.Global.Fatal().Err(err).Msg("Failed to send debug message") } } + +// fetchAddressBook retrieves the providers from the CLI context and uses them to retrieve the address book for the current height +func fetchAddressBook(cmd *cobra.Command) (types.AddrBook, error) { + addrBookProvider := cmd.Context().Value(addrBookProviderCtxKey) + currentHeightProvider := cmd.Context().Value(currentHeightProviderCtxKey) + + height := currentHeightProvider.(current_height_provider.CurrentHeightProvider).CurrentHeight() + addrBook, err := addrBookProvider.(addrbook_provider.AddrBookProvider).GetStakedAddrBookAtHeight(height) + if err != nil { + logger.Global.Fatal().Msg("Unable to retrieve the addrBook") + } + return addrBook, err +} diff --git a/app/client/doc/CHANGELOG.md b/app/client/doc/CHANGELOG.md index 983f0e91b..378253e12 100644 --- a/app/client/doc/CHANGELOG.md +++ b/app/client/doc/CHANGELOG.md @@ -7,7 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.0.0.14] - 2023-02-16 +## [0.0.0.15] - 2023-02-16 + +- Added `non_interactive` flag to allow for non-interactive `Stake` and `Unstake` transactions (dogfooding in `cluster-manager`) +- Updated CLI to use to source the address book and the current height from the RPC server leveraging the `rpcAddressBookProvider` and `rpcCurrentHeightProvider` respectively and the `bus` for dependency injection + +## [0.0.0.14] - 2023-02-15 - Introduced logical switch to handle parsing of the debug private keys from a local file OR from Kubernetes secret (PR #517) - Bugfix for `Stake` command. Address erroneously sent instead of the PublicKey. (PR #518) diff --git a/app/pocket/doc/CHANGELOG.md b/app/pocket/doc/CHANGELOG.md index 34820c0c6..554bd5710 100644 --- a/app/pocket/doc/CHANGELOG.md +++ b/app/pocket/doc/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.5] - 2023-02-10 + +- Updated to handle `bootstrap-nodes` flag that can be used to override the default bootstrap nodes + ## [0.0.0.4] - 2023-02-07 - Added GITHUB_WIKI tags where it was missing diff --git a/app/pocket/main.go b/app/pocket/main.go index 2ae49d495..d8be50c7f 100644 --- a/app/pocket/main.go +++ b/app/pocket/main.go @@ -12,6 +12,7 @@ import ( func main() { configFilename := flag.String("config", "", "Relative or absolute path to the config file.") genesisFilename := flag.String("genesis", "", "Relative or absolute path to the genesis file.") + bootstrapNodes := flag.String("bootstrap-nodes", "", "Comma separated list of bootstrap nodes.") v := flag.Bool("version", false, "") flag.Parse() @@ -21,7 +22,12 @@ func main() { return } - runtimeMgr := runtime.NewManagerFromFiles(*configFilename, *genesisFilename) + options := []func(*runtime.Manager){} + if bootstrapNodes != nil && *bootstrapNodes != "" { + options = append(options, runtime.WithBootstrapNodes(*bootstrapNodes)) + } + + runtimeMgr := runtime.NewManagerFromFiles(*configFilename, *genesisFilename, options...) bus, err := runtime.CreateBus(runtimeMgr) if err != nil { logger.Global.Fatal().Err(err).Msg("Failed to create bus") diff --git a/build/config/genesis.json b/build/config/genesis.json index 035d3ac47..69df85f6f 100755 --- a/build/config/genesis.json +++ b/build/config/genesis.json @@ -27,6 +27,3986 @@ { "address": "88a792b7aca673620132ef01f50e62caa58eca83", "amount": "100000000000000" + }, + { + "address": "00504987d4b181c1e97b1da9af42f3db733b1ff4", + "amount": "100000000000000" + }, + { + "address": "00604d18001a2012830b93efcc23100450e5a512", + "amount": "100000000000000" + }, + { + "address": "007046b27ad5c49969d585dd3f4f7d1e4b94a42f", + "amount": "100000000000000" + }, + { + "address": "00804475b3c75e0fb86c88d937c7753f8cab8ba8", + "amount": "100000000000000" + }, + { + "address": "0090433ae78b5539c564134809502f699c90b009", + "amount": "100000000000000" + }, + { + "address": "0100471d6796652244885d1943ea7c13e3fce90b", + "amount": "100000000000000" + }, + { + "address": "011044141a86efafeae5ecc2c6290f0894072ab7", + "amount": "100000000000000" + }, + { + "address": "01204ed35af2bbef5d4db0aeedf3a9a8958c3296", + "amount": "100000000000000" + }, + { + "address": "0130404d6a39bf7cdc14ef4be4a0910f170edd1e", + "amount": "100000000000000" + }, + { + "address": "0140481810379d6e970f5b7de3220b70a784efd5", + "amount": "100000000000000" + }, + { + "address": "01504aedb93b489402d5aa654a5c6bda01880a5f", + "amount": "100000000000000" + }, + { + "address": "0160401ddec40b7a2dbc8505e4a9e998c22604b0", + "amount": "100000000000000" + }, + { + "address": "0170495866953b63cc9ba01c141dd8be029773bb", + "amount": "100000000000000" + }, + { + "address": "01804d0db5be444aeb1a114469a4ff7eb09c91db", + "amount": "100000000000000" + }, + { + "address": "01904e5651efaafb1a557d8f61034a4edfe0fa05", + "amount": "100000000000000" + }, + { + "address": "02004e81a4ee21929a399504fd0d946c545e7a2c", + "amount": "100000000000000" + }, + { + "address": "0210494fbd4b214dd6209d33b3fc960660c9f82b", + "amount": "100000000000000" + }, + { + "address": "0220406b71d941b5b9fc73a53d08ecb09c866b10", + "amount": "100000000000000" + }, + { + "address": "023041ae1ee33ad8db492951c13393b9bb59d59b", + "amount": "100000000000000" + }, + { + "address": "024041957fc3ac22552239b75d384f141f48430b", + "amount": "100000000000000" + }, + { + "address": "025045f51c4c956e2d822e6fd3f706957a5649fe", + "amount": "100000000000000" + }, + { + "address": "02604fcd21020ff140f6da784012e68d7f72ff36", + "amount": "100000000000000" + }, + { + "address": "0270460c5775e8951e5d43b3b37dc310209afda6", + "amount": "100000000000000" + }, + { + "address": "02804033a62cf08a2074cbffe941bd019576d5ed", + "amount": "100000000000000" + }, + { + "address": "0290479bfdf5210b7541b37b551716662a2ff397", + "amount": "100000000000000" + }, + { + "address": "03004511b4ca2d30b7e8bc008a4dc53588115fb0", + "amount": "100000000000000" + }, + { + "address": "031048ce3cef36af346cffc464dc5611028cc46f", + "amount": "100000000000000" + }, + { + "address": "03204ac71039cd18d1a23b76042c5c43c4dc1053", + "amount": "100000000000000" + }, + { + "address": "03304961130710e8984124354aa55eef028ad7d9", + "amount": "100000000000000" + }, + { + "address": "03404334ac8195996d072c916805dd26d82d9b0a", + "amount": "100000000000000" + }, + { + "address": "03504f415b35148ef268a37a7bdd5cbe41c46b62", + "amount": "100000000000000" + }, + { + "address": "0360444233608b747b82c9a651526171e0cecb09", + "amount": "100000000000000" + }, + { + "address": "037041d2ebb680f8e617c1d8bd4397114ed91d7a", + "amount": "100000000000000" + }, + { + "address": "03804e19cca9f5d8d074d3f0a60f1096723dad31", + "amount": "100000000000000" + }, + { + "address": "039044952cacd6fe9eed091c8b5b85c6e758d9ff", + "amount": "100000000000000" + }, + { + "address": "04004e7265815d837bac198381b1b3e70275319e", + "amount": "100000000000000" + }, + { + "address": "04104e28743787af30fdc85123b2ec763aca309c", + "amount": "100000000000000" + }, + { + "address": "042047946bbe90534f6940b3fa2aef34fa8f68c4", + "amount": "100000000000000" + }, + { + "address": "04304a7f8c6f59737bf2f6955745677351ad65bd", + "amount": "100000000000000" + }, + { + "address": "04404de47d3b8b90f533da541a6b9cd4b162cbdb", + "amount": "100000000000000" + }, + { + "address": "04504f18acbfe31c7f671a9986a499e74cd83b87", + "amount": "100000000000000" + }, + { + "address": "046047e21a2b35c94b8e25b39a8e11e088bdcc20", + "amount": "100000000000000" + }, + { + "address": "04704eff8a68e2d520bc9d4781a1328beb4a07fd", + "amount": "100000000000000" + }, + { + "address": "04804319d93a5aae6d6932e6255afa52ff9b81ad", + "amount": "100000000000000" + }, + { + "address": "0490494bc3baea23832c354eae4472d5ca97302f", + "amount": "100000000000000" + }, + { + "address": "05004facba0b2a253bab657f428338918d081158", + "amount": "100000000000000" + }, + { + "address": "0510462d8d3fbc0a5690e68507a49809f70afac4", + "amount": "100000000000000" + }, + { + "address": "05204497fa5d1cd636ec08c1e557aad11356ffdb", + "amount": "100000000000000" + }, + { + "address": "05304bebf8de8dd3333067868402df0a855cfc26", + "amount": "100000000000000" + }, + { + "address": "054041a4f8f82ae6cdc43ae50c621cbc73a74cba", + "amount": "100000000000000" + }, + { + "address": "055047122515c7448c7eb18b249e0bd390fe017b", + "amount": "100000000000000" + }, + { + "address": "056047aa21bce308658b7ff6ed0d87356de06220", + "amount": "100000000000000" + }, + { + "address": "05704c960137bbb6c9421a77e03671a334211ec5", + "amount": "100000000000000" + }, + { + "address": "058045f9c98e9fd506e5025797b34302fbaf85e3", + "amount": "100000000000000" + }, + { + "address": "05904f94b885d875f0fe6af3185a5936518b40f5", + "amount": "100000000000000" + }, + { + "address": "06004ef2c3c4979e68257b4bff94471e570b1cab", + "amount": "100000000000000" + }, + { + "address": "0610473810cd99f9ef4e72613cf5e93fcf942b12", + "amount": "100000000000000" + }, + { + "address": "0620415cc31eef8492058687df20c86b6e228bb2", + "amount": "100000000000000" + }, + { + "address": "06304edd5eb38af2ddc8555e94678ac6ab7a0a5c", + "amount": "100000000000000" + }, + { + "address": "06404246818eada50a3335e9c7e7eb142ee6709b", + "amount": "100000000000000" + }, + { + "address": "06504c11e6b449679278529efebf00ed4c1098b2", + "amount": "100000000000000" + }, + { + "address": "06604cea653df828010889eaa56f4ff867a17881", + "amount": "100000000000000" + }, + { + "address": "067044f84aa72577dc88b9813ee081dd6235905c", + "amount": "100000000000000" + }, + { + "address": "06804ac8b703a6500ba70f36a725bc55ecbe4bbc", + "amount": "100000000000000" + }, + { + "address": "06904f896ddabf920e559954efcb468e85e351d5", + "amount": "100000000000000" + }, + { + "address": "070043cc01e70228d252b4df847c4724813f6176", + "amount": "100000000000000" + }, + { + "address": "07104b360ef5589bb8b49a7e2c3e2fa03363a059", + "amount": "100000000000000" + }, + { + "address": "072048359ff76f59da57342b93dd4cfdd42662c2", + "amount": "100000000000000" + }, + { + "address": "07304f2af4afd31973cfbd0cae5a74722ba4fd14", + "amount": "100000000000000" + }, + { + "address": "07404ac156eb80fe3092c9e39b2169c6a087194f", + "amount": "100000000000000" + }, + { + "address": "07504a01ea1839c1aef06641eb46379218dbcba9", + "amount": "100000000000000" + }, + { + "address": "0760494df0c9bf14a5a5b50f491adfcc3df6b7e6", + "amount": "100000000000000" + }, + { + "address": "07704a472cabf1433eba2d80a73204d5726a88fc", + "amount": "100000000000000" + }, + { + "address": "0780445f4375d422c87a155b6949625b227bfba2", + "amount": "100000000000000" + }, + { + "address": "07904050bb8647901a3e9b93a2296ca4334d728e", + "amount": "100000000000000" + }, + { + "address": "08004bdfd6dca205244f5a15f9d1741bcc511b54", + "amount": "100000000000000" + }, + { + "address": "081046c92e38c4202ff659168d45d742a57ffee2", + "amount": "100000000000000" + }, + { + "address": "082045bad7d45189d4c9fb379de5ae3aa7dff762", + "amount": "100000000000000" + }, + { + "address": "08304f805360247bed9730d07e755384cb0070e5", + "amount": "100000000000000" + }, + { + "address": "08404debeec7ee380d24cd384d96ff98912a450b", + "amount": "100000000000000" + }, + { + "address": "085047967a6d86f2369345e1243af970f7e4c5e2", + "amount": "100000000000000" + }, + { + "address": "086044b59a0f9b0ceee5ee9f298d17c9f1445beb", + "amount": "100000000000000" + }, + { + "address": "08704f20c81ebf51988fb1b6bef5d29c702216c9", + "amount": "100000000000000" + }, + { + "address": "08804f6d3823b4839685744cd807f5ff7f4d9712", + "amount": "100000000000000" + }, + { + "address": "089049f0d03a767dd1a2b9479cb70d2c836a0077", + "amount": "100000000000000" + }, + { + "address": "09004e53f819778cd2c0738ff055416f44baf529", + "amount": "100000000000000" + }, + { + "address": "09104c7006a42917b1d6c824dc48a4e1f87f835f", + "amount": "100000000000000" + }, + { + "address": "09204a46380169c1c9b5cbff225e771e17e32cda", + "amount": "100000000000000" + }, + { + "address": "093041155ee61c12ea790594b7b305b00ed179e6", + "amount": "100000000000000" + }, + { + "address": "09404741ec9ee6c40d009174474db97aee4db4b4", + "amount": "100000000000000" + }, + { + "address": "095049ee9b15b848f432b1fef028641e391de082", + "amount": "100000000000000" + }, + { + "address": "096046a684f4677dde3a3db075d3b3f99359d3aa", + "amount": "100000000000000" + }, + { + "address": "097048eba43973cc73cd10f1b18085424318d145", + "amount": "100000000000000" + }, + { + "address": "0980419ea31998de5d84b43f5042e4e492a5d738", + "amount": "100000000000000" + }, + { + "address": "099044a5282c4089976c6b13ab13e5423dae55ce", + "amount": "100000000000000" + }, + { + "address": "10004d40a6b66742e3fa57b3410bf4302ce68394", + "amount": "100000000000000" + }, + { + "address": "1010478e08ad97244e773bbd844c71bc0352c3e7", + "amount": "100000000000000" + }, + { + "address": "102048ed9422a043ad4129923f94f3c24bdf215a", + "amount": "100000000000000" + }, + { + "address": "103049dbf55f9d9a3f3d0accd6f9056e478913e2", + "amount": "100000000000000" + }, + { + "address": "104043f348d715650ad409135be7c070d9d95068", + "amount": "100000000000000" + }, + { + "address": "10504f7e334d7a516849b04c5aae4881070feec8", + "amount": "100000000000000" + }, + { + "address": "10604e693a25f81bfbb9fb75f88941ccc45a18bc", + "amount": "100000000000000" + }, + { + "address": "107044e187a52f8bc9caa4874d7f44796a08a929", + "amount": "100000000000000" + }, + { + "address": "10804bcb2dbf1a218a6329ecc2be8745626fcf83", + "amount": "100000000000000" + }, + { + "address": "10904ad08c08a77d484038a07b87be4186792a46", + "amount": "100000000000000" + }, + { + "address": "1100450fd02ac84b4af733541372552a91eefbc4", + "amount": "100000000000000" + }, + { + "address": "1110489c4120dc1bdf90b10c52bb7c09f0845729", + "amount": "100000000000000" + }, + { + "address": "11204b578d9a37c2b5f57096c5421d8422e2dc98", + "amount": "100000000000000" + }, + { + "address": "113043ed1a7e58689fecfbdf930ec4ee5ce5062d", + "amount": "100000000000000" + }, + { + "address": "11404c2a4d6045227e32d9f1365db6f6771076cc", + "amount": "100000000000000" + }, + { + "address": "11504b01b37eb3c132b47eb96bb004c73544b614", + "amount": "100000000000000" + }, + { + "address": "116048b88dea15cedcd35268b8ac6377dcc3d0c1", + "amount": "100000000000000" + }, + { + "address": "11704e5c9b13bb150e597e5433a0662f4a181b6f", + "amount": "100000000000000" + }, + { + "address": "11804b9efdfedf7f1adf66e07a7f0d8f808577da", + "amount": "100000000000000" + }, + { + "address": "1190497f2cc37e940a9fe00ab204a95e0c9bb680", + "amount": "100000000000000" + }, + { + "address": "120041b8df9d90f1f2552dcbaa56f5373b6c6276", + "amount": "100000000000000" + }, + { + "address": "1210432f21bce9b96de278336453b24f4393b83c", + "amount": "100000000000000" + }, + { + "address": "12204cb0d0b5c63229794302bf48a09194c9a16a", + "amount": "100000000000000" + }, + { + "address": "12304722e56d2a02d85843df27699fccaec50d65", + "amount": "100000000000000" + }, + { + "address": "1240481e5002400cb25b142fc050846f929cc48d", + "amount": "100000000000000" + }, + { + "address": "125048c33a3e3e64d000c09ea30acebc284381e1", + "amount": "100000000000000" + }, + { + "address": "126041d6d720e542f71b7f918d436d0e58ae39df", + "amount": "100000000000000" + }, + { + "address": "12704ae3578cd0b3a5173c7a787f6be855de68d9", + "amount": "100000000000000" + }, + { + "address": "12804b8317600ea5a50c022d68db259a48246d11", + "amount": "100000000000000" + }, + { + "address": "12904f277d69867eb875b9ca05631e5af8f6f3a5", + "amount": "100000000000000" + }, + { + "address": "1300421eeb1b9cef3a6de604d2170ec93b0e4339", + "amount": "100000000000000" + }, + { + "address": "13104ac49ac0178e2f2141d84fa608cd75a0b99f", + "amount": "100000000000000" + }, + { + "address": "13204c53460812c5f036d93eb1351b777293bad3", + "amount": "100000000000000" + }, + { + "address": "133046096add47f91c7390867c134ad118db1c78", + "amount": "100000000000000" + }, + { + "address": "13404cd5b310e67182d10562b603c074fe04a89e", + "amount": "100000000000000" + }, + { + "address": "13504f0cade7c2ca08f31db13dcfa7b96df30c9e", + "amount": "100000000000000" + }, + { + "address": "1360405dc963cc088d905661312288f72b8e145d", + "amount": "100000000000000" + }, + { + "address": "13704a54589c4850a0b2e541de4fd74324e6c650", + "amount": "100000000000000" + }, + { + "address": "1380420feb410699ea7969995e80705cdfdc85ca", + "amount": "100000000000000" + }, + { + "address": "13904d5175f99a8c7380356d8c62c1155167e6d9", + "amount": "100000000000000" + }, + { + "address": "140040be8bc55c39dd93872db9f69a2962773414", + "amount": "100000000000000" + }, + { + "address": "14104175cc9b1c210e6e8297c790d13590a69552", + "amount": "100000000000000" + }, + { + "address": "14204fe8d30ec07a74a1ef1c94f46089bc55e221", + "amount": "100000000000000" + }, + { + "address": "1430494a69f153da3746ffe08f78ecb49b57fc0e", + "amount": "100000000000000" + }, + { + "address": "1440427e32ed0038ec856c755a5197fadf957a2f", + "amount": "100000000000000" + }, + { + "address": "14504c4cbec1b1efe9a43158377e8adf781b6103", + "amount": "100000000000000" + }, + { + "address": "1460491d014244244ef559ea9ae513bea1dcddd2", + "amount": "100000000000000" + }, + { + "address": "14704b3f86ac92acf440b2a7e6668f93b3079e4b", + "amount": "100000000000000" + }, + { + "address": "148041a8c233054f555cb9b403f7b923cada20eb", + "amount": "100000000000000" + }, + { + "address": "14904727d2ab89e6c709207ab1c2ca3a5c272a76", + "amount": "100000000000000" + }, + { + "address": "15004c142f4e20b9335895330b5b13d057adf339", + "amount": "100000000000000" + }, + { + "address": "151048b719ee920b3e7817e638b54cccf4c1ad2b", + "amount": "100000000000000" + }, + { + "address": "1520405297a7105030cc7b9644cac18d56789c6c", + "amount": "100000000000000" + }, + { + "address": "1530493894ee67be4601d7e8319e25ec6a4a196c", + "amount": "100000000000000" + }, + { + "address": "154046cce6ed50084402f23d39f47938d8813168", + "amount": "100000000000000" + }, + { + "address": "1550401f10dd6ba3237915480caec9cc25c22e7a", + "amount": "100000000000000" + }, + { + "address": "1560428bcae398f7a6ccefcc11f8f81a3377c0bc", + "amount": "100000000000000" + }, + { + "address": "157048c978d44449301262faa959dca274a5aa4b", + "amount": "100000000000000" + }, + { + "address": "158041081d17bc38c46b8a98e790754db8df070a", + "amount": "100000000000000" + }, + { + "address": "15904f004b76f28c9711fee41dc149653d916928", + "amount": "100000000000000" + }, + { + "address": "160046a9a808312cc2b184576cb7a732ab65b54e", + "amount": "100000000000000" + }, + { + "address": "1610442c7b7596b008014c9d6513aa075e231ef2", + "amount": "100000000000000" + }, + { + "address": "162042923ff01a08e4138e8b238792a42132e1cb", + "amount": "100000000000000" + }, + { + "address": "163047124bf542385d7eadb14cc3f0bac13fdfd0", + "amount": "100000000000000" + }, + { + "address": "16404fe2f744e454f5905fef8f11624c17ea7276", + "amount": "100000000000000" + }, + { + "address": "16504776e6fa4964c1186698b9d937777c895852", + "amount": "100000000000000" + }, + { + "address": "1660429323d21e475d82412cebaa47c3239c8c7f", + "amount": "100000000000000" + }, + { + "address": "16704bb2cf4ac07c32a573f78503c348d1ad8e33", + "amount": "100000000000000" + }, + { + "address": "168042d2ebe07c3ec4d97a27f132252c6f75b2c3", + "amount": "100000000000000" + }, + { + "address": "16904d309459875b673824fb3d4892c255c438a8", + "amount": "100000000000000" + }, + { + "address": "1700459ef6255d3af804047d6e9c8543e4fb651c", + "amount": "100000000000000" + }, + { + "address": "17104093498fce764f72ff62a3cff004ff9036e2", + "amount": "100000000000000" + }, + { + "address": "17204c5f07a3ed21aa701936fc3ac7cee56f6fd9", + "amount": "100000000000000" + }, + { + "address": "173047b98d5737c2ff6cd42a05c7be49cbae4730", + "amount": "100000000000000" + }, + { + "address": "174043c704b4ca5e2386607ca0ea9aa079d060a7", + "amount": "100000000000000" + }, + { + "address": "1750407bdb0f719bc7d589b676e01a353c3a477e", + "amount": "100000000000000" + }, + { + "address": "1760481f33bdeb9a00942ff0b5495d4352905a7c", + "amount": "100000000000000" + }, + { + "address": "17704ced43739119c029327380e45977bf7cad3e", + "amount": "100000000000000" + }, + { + "address": "17804d8420f8c162e2df0e67993cb252a188b5f8", + "amount": "100000000000000" + }, + { + "address": "17904d73ab82f9143cebff44fe04792aab8655e4", + "amount": "100000000000000" + }, + { + "address": "18004a25e97b7715de5a1a81b53c9632144dc420", + "amount": "100000000000000" + }, + { + "address": "181041f149252a89292e9972914c58bd829b8c7d", + "amount": "100000000000000" + }, + { + "address": "18204561a63cd6858352fa755235fc20da17b505", + "amount": "100000000000000" + }, + { + "address": "18304635cca3b26f47928baca81db0f228812f5c", + "amount": "100000000000000" + }, + { + "address": "18404ca5c5c4b058fa69f4e447f337d688fae192", + "amount": "100000000000000" + }, + { + "address": "18504562e4766557eaac160609694f70cd994869", + "amount": "100000000000000" + }, + { + "address": "18604797ec3169f3cc49528c658a2021f9cb65aa", + "amount": "100000000000000" + }, + { + "address": "1870490db984d9ee83069932178d14b0abcaa855", + "amount": "100000000000000" + }, + { + "address": "1880411b2ea73a2c55ae9a44090a91407a1338b2", + "amount": "100000000000000" + }, + { + "address": "1890483fd47d69c9c56ebdc44b53f863636ec76b", + "amount": "100000000000000" + }, + { + "address": "190047b3262c58543426e2aca31153d1ee9a6cb4", + "amount": "100000000000000" + }, + { + "address": "19104a9dcb8c74fd201dd725760a1b6bb46132d0", + "amount": "100000000000000" + }, + { + "address": "1920414bedbca466c0cc21605f310e1e592fd883", + "amount": "100000000000000" + }, + { + "address": "19304b87b24277c3125b6b459754a661f0bf05d2", + "amount": "100000000000000" + }, + { + "address": "194046b0304151f562984df1092f9c1f7d79fa62", + "amount": "100000000000000" + }, + { + "address": "195045f4ad18d51ad82118d941853a515c6477e1", + "amount": "100000000000000" + }, + { + "address": "19604371ecba002941a630d592190da6a7b92204", + "amount": "100000000000000" + }, + { + "address": "19704ce5e62681c054346e859e481d4cead58fca", + "amount": "100000000000000" + }, + { + "address": "1980404abe063de7cb649ed7007c2acff22dc6d6", + "amount": "100000000000000" + }, + { + "address": "199041b40c048301fd79257bac2f24755e4220b5", + "amount": "100000000000000" + }, + { + "address": "200042c84cdc16db2aa5bcf29f578f19f88d828f", + "amount": "100000000000000" + }, + { + "address": "2010436f32021ed70ea837c7bb28e3e4f0eb08b4", + "amount": "100000000000000" + }, + { + "address": "202041a563d5c632cc8a16f1c47a144e9861ffc8", + "amount": "100000000000000" + }, + { + "address": "20304a95f96c1ecd467d220afe61dc00191a590d", + "amount": "100000000000000" + }, + { + "address": "204041fdfe17c0f23783b5f1bb5b957bcc2808d4", + "amount": "100000000000000" + }, + { + "address": "205047833c7643945ff04936615f36f4d6afa927", + "amount": "100000000000000" + }, + { + "address": "20604e648b33f0d377c19dda00c69fd7dbab1a35", + "amount": "100000000000000" + }, + { + "address": "20704e9cdcb655809f917a2383c5bc962d65a676", + "amount": "100000000000000" + }, + { + "address": "20804d277be9dac11fddaf7a303de7825d04fe86", + "amount": "100000000000000" + }, + { + "address": "209045028021014830c19dd005c1f15734c0279d", + "amount": "100000000000000" + }, + { + "address": "210041c9fcf43b85b482d5225e59dfd53343d4c0", + "amount": "100000000000000" + }, + { + "address": "211041068d32913cd60af834ea4046f663f5ced3", + "amount": "100000000000000" + }, + { + "address": "212045166e6cc662e8810cd340cfc2c03f5ed76b", + "amount": "100000000000000" + }, + { + "address": "213042d24128fc2d6a012d7505b0a16ae7f2c71f", + "amount": "100000000000000" + }, + { + "address": "21404dc18a0af5991775e21beef464a2abbe2465", + "amount": "100000000000000" + }, + { + "address": "21504bc8aa46ae21814ebab4a7e1b1a242d5accf", + "amount": "100000000000000" + }, + { + "address": "216043b23b77f8ba73f8fd27960292f39dbd4295", + "amount": "100000000000000" + }, + { + "address": "217044892b8c7caebfd3bd1ce03c993dc5ff86dc", + "amount": "100000000000000" + }, + { + "address": "21804f424ae6e5ea63f52935924f7f0195626b82", + "amount": "100000000000000" + }, + { + "address": "21904412d935bdf5f5e1c09240943f5ee08f096e", + "amount": "100000000000000" + }, + { + "address": "22004a7749a322d34096b8d05bf619b9149fb4b3", + "amount": "100000000000000" + }, + { + "address": "2210474930588c35eca210c11955091a0f5f884b", + "amount": "100000000000000" + }, + { + "address": "22204bc6f9ad7e4e518199856e0179a42b33a79b", + "amount": "100000000000000" + }, + { + "address": "22304a1c7c397f31624307c685f5f7a00c12f39e", + "amount": "100000000000000" + }, + { + "address": "22404a0c21626c59ebc9ff7d634016d0c7c7211f", + "amount": "100000000000000" + }, + { + "address": "2250468cad33051ab3dba059c69076dab24f7fde", + "amount": "100000000000000" + }, + { + "address": "22604387182910cc90bbc1c2263c726a16a8272a", + "amount": "100000000000000" + }, + { + "address": "22704fde9834f549d90386e8091f84260dcfa948", + "amount": "100000000000000" + }, + { + "address": "2280473c939601953bff8fa82a1f402109ef940c", + "amount": "100000000000000" + }, + { + "address": "22904d330d2bb0dc4b7107774f01e7d5c3490eb6", + "amount": "100000000000000" + }, + { + "address": "23004d5c724c1e8ec7fef279228a0c97f17e2181", + "amount": "100000000000000" + }, + { + "address": "231044e6feafd5ae2936053ec52d2313d6c8074e", + "amount": "100000000000000" + }, + { + "address": "232040240f94d8516431e17bddf998236fbb4b1f", + "amount": "100000000000000" + }, + { + "address": "23304f25914a69624d63b73f906277f3b44146da", + "amount": "100000000000000" + }, + { + "address": "2340459c2aeedd718eb6888f03ecba40f667512d", + "amount": "100000000000000" + }, + { + "address": "2350412da46f9d6df2ba9de0d5edab0e7ab04f8a", + "amount": "100000000000000" + }, + { + "address": "23604d9dda5729453dbbf6dac079d4265cf2d572", + "amount": "100000000000000" + }, + { + "address": "237046cfc5cb28de4513aeaa070cf059a4dd0b3c", + "amount": "100000000000000" + }, + { + "address": "2380476cd240c9a3ef532c44da208fec403daf43", + "amount": "100000000000000" + }, + { + "address": "239043b65e631bfba903c7be4bd9bbeccc8c77d3", + "amount": "100000000000000" + }, + { + "address": "24004e034045de6aeed0120b55ff7eff23b734fc", + "amount": "100000000000000" + }, + { + "address": "2410496835f7d8b8f66bd3e7724941d46ed0b5b8", + "amount": "100000000000000" + }, + { + "address": "242040f054acb1fd7e03be92d5a95267e6bbf40d", + "amount": "100000000000000" + }, + { + "address": "24304d490c84c40a4b2700d36f692045cb292240", + "amount": "100000000000000" + }, + { + "address": "2440427c70b5b9338d5d4d9ed1c5631168d09481", + "amount": "100000000000000" + }, + { + "address": "24504aa139ba31e9fadf8aece9319578c461be09", + "amount": "100000000000000" + }, + { + "address": "246043ee459e114da19d9733237f8ff18d1c975c", + "amount": "100000000000000" + }, + { + "address": "24704a003e960e2e3184d12bc81481c7b6d3b571", + "amount": "100000000000000" + }, + { + "address": "24804468e55eb683e108433f64f004d8e578e586", + "amount": "100000000000000" + }, + { + "address": "24904b241defa1190e86824dfb5ea06b4cba4be6", + "amount": "100000000000000" + }, + { + "address": "25004dc5f51b2acefedf7d6879a9d75c073a8fa7", + "amount": "100000000000000" + }, + { + "address": "25104987c20c2f2c7b9ad6d3a54644ab6f2a85af", + "amount": "100000000000000" + }, + { + "address": "25204b567acdac5d4a3ce796a4cc59493b11bf31", + "amount": "100000000000000" + }, + { + "address": "25304db3a407cf45ee8ea443ca0084e5b60c79b7", + "amount": "100000000000000" + }, + { + "address": "25404bd5df303cd129ad600d140d3bbcc2590a73", + "amount": "100000000000000" + }, + { + "address": "255043858b88fa0a7358e2ffcd69e7c83e402290", + "amount": "100000000000000" + }, + { + "address": "25604bc9c36ed092e5d092c67dba2622cd4e5d84", + "amount": "100000000000000" + }, + { + "address": "2570409af48f9f53d4fb971997e9551a6f278c34", + "amount": "100000000000000" + }, + { + "address": "25804bc4082281b7de23001ffd237da62c66a839", + "amount": "100000000000000" + }, + { + "address": "25904c87cad76ff937dae4f1c32a78701e16597c", + "amount": "100000000000000" + }, + { + "address": "260048cd2563d833b62eba3e96db8bf11f33b4d7", + "amount": "100000000000000" + }, + { + "address": "26104a73f4e062b78ca20f62d668a76060bbc52b", + "amount": "100000000000000" + }, + { + "address": "26204fd56b23d52c028afcff7d507f52e1540ebd", + "amount": "100000000000000" + }, + { + "address": "263046b3910eb41b62ecab8e2727c7ccf3383821", + "amount": "100000000000000" + }, + { + "address": "264040a705d84df7ced13aa8ae978fa882bdd62a", + "amount": "100000000000000" + }, + { + "address": "26504edc6b5e0ce4c2e8d7fb6ef348378ab9abba", + "amount": "100000000000000" + }, + { + "address": "2660414a17171ad23ae33e5013427ec377b4c988", + "amount": "100000000000000" + }, + { + "address": "2670497b55fc9278e4be4f1bcfe52bf9bd0443f8", + "amount": "100000000000000" + }, + { + "address": "268044a5aab702befe268a12ddca939baf687e8b", + "amount": "100000000000000" + }, + { + "address": "26904228cd6cb82cd55d4af2737166589ff50fed", + "amount": "100000000000000" + }, + { + "address": "2700435fc578db0405190e80dc52c804244f0c1a", + "amount": "100000000000000" + }, + { + "address": "271045c982bdf708abe108829b57fec34a15d164", + "amount": "100000000000000" + }, + { + "address": "2720402be517c6d4d5304d9d2afef856b4c19a66", + "amount": "100000000000000" + }, + { + "address": "273043e7bc0d2eaec59553feda2e1fb2f68cc6ab", + "amount": "100000000000000" + }, + { + "address": "27404283d4b279ba4f3eb205d7ce07556f569333", + "amount": "100000000000000" + }, + { + "address": "27504a9c3e3671f59efe6d98bfefa78a56cab907", + "amount": "100000000000000" + }, + { + "address": "2760456e71cecc99cb8c1abaa4e27755d266aea1", + "amount": "100000000000000" + }, + { + "address": "277043a71759fe5abc5292cf6329c6ed2423d8bb", + "amount": "100000000000000" + }, + { + "address": "278048f93ae0a37f2208390762bdafb1af55e14e", + "amount": "100000000000000" + }, + { + "address": "2790490db88a1189fc72bb5fd6e0f3a8bfa73db1", + "amount": "100000000000000" + }, + { + "address": "28004daf634dca5d149954fe6d4b5c4eb0028793", + "amount": "100000000000000" + }, + { + "address": "28104f10721a56e1a4a4b94e6358738665ac5dfa", + "amount": "100000000000000" + }, + { + "address": "28204f215c20cef00567debf6cb53e30661d0fab", + "amount": "100000000000000" + }, + { + "address": "283041381e612d928f5f555bf8263c8ba88d936c", + "amount": "100000000000000" + }, + { + "address": "2840417b17149dbd88c673dcf48257ac408c71fe", + "amount": "100000000000000" + }, + { + "address": "28504cc3677748731043d89db8f5daa698b81ac8", + "amount": "100000000000000" + }, + { + "address": "286047e41e279be46bad32fcdb3160883765cd03", + "amount": "100000000000000" + }, + { + "address": "28704d946c75244e893567fcdb6c942f1f9c4010", + "amount": "100000000000000" + }, + { + "address": "28804cc3a57272725f1f6576a9f191dc5ff6dfc2", + "amount": "100000000000000" + }, + { + "address": "2890417d98352e3fd93bc9428c3eafdf8a2c70df", + "amount": "100000000000000" + }, + { + "address": "29004d6f7786f10ec5eeb3d979b0cef900c1d48f", + "amount": "100000000000000" + }, + { + "address": "291040ed2dafb7f0a459bcb102fa06b51c1ea60a", + "amount": "100000000000000" + }, + { + "address": "292041e75709c5301b529946184c3f34079542e1", + "amount": "100000000000000" + }, + { + "address": "293042f94bf55835b0402f4749c527d1341d33e1", + "amount": "100000000000000" + }, + { + "address": "29404d31d48e1a6e8809dee2aa22fe1864847708", + "amount": "100000000000000" + }, + { + "address": "29504895b3565b05f833175a7e9dc7db7b4eb70b", + "amount": "100000000000000" + }, + { + "address": "29604a2caf83a8713ce0d98fe186e4bc06dd2080", + "amount": "100000000000000" + }, + { + "address": "297043b50a64aded60e47ade8736ea0abbcfc296", + "amount": "100000000000000" + }, + { + "address": "29804016798e7205be0b06dda8c467effd2b9270", + "amount": "100000000000000" + }, + { + "address": "2990404886581ad56da93b3586973995255c46a5", + "amount": "100000000000000" + }, + { + "address": "300041bf170fea639f3fa2ae44c35c286614c6e1", + "amount": "100000000000000" + }, + { + "address": "301044886121f610783dbfe7eaf5b8b18a08f98a", + "amount": "100000000000000" + }, + { + "address": "3020483107289ce0e1aa22c4b391792dcf422039", + "amount": "100000000000000" + }, + { + "address": "303043b4d44b0fd2836f794d13dfeca89eede44c", + "amount": "100000000000000" + }, + { + "address": "30404c7fde0c53e7bcd5b16f4bae7fb67cd11c7e", + "amount": "100000000000000" + }, + { + "address": "305048be380a6497e74cc9336f6f848355869e41", + "amount": "100000000000000" + }, + { + "address": "30604835f99a142c0834a2a85b64cb29123c98ce", + "amount": "100000000000000" + }, + { + "address": "30704f7df470a5cf2888feadd4465059e52d793e", + "amount": "100000000000000" + }, + { + "address": "30804079993f175db5d3709b0493629f676c835d", + "amount": "100000000000000" + }, + { + "address": "30904c5834aca2092bece28240c82b27e2284540", + "amount": "100000000000000" + }, + { + "address": "3100403f6bbac8575099e11a89a328b9a55e1532", + "amount": "100000000000000" + }, + { + "address": "31104cfb42d421636c088ef06a7a72de5518b70f", + "amount": "100000000000000" + }, + { + "address": "31204158e79b460f11fde2e511551a1a2dccf170", + "amount": "100000000000000" + }, + { + "address": "31304a71a751f080eb358f7b26db28802e944410", + "amount": "100000000000000" + }, + { + "address": "31404816c32212afd80529bf64bd4713f5f50ba5", + "amount": "100000000000000" + }, + { + "address": "3150481f573e37f4de34d89e7aa5444063241a74", + "amount": "100000000000000" + }, + { + "address": "3160464d8039476a8d689c25a0572fb72ab7429d", + "amount": "100000000000000" + }, + { + "address": "31704b6dbc7d7450f8b3845ecdc8d08537a5df93", + "amount": "100000000000000" + }, + { + "address": "3180441bdf305aa132ed094a5b69c84d79f73565", + "amount": "100000000000000" + }, + { + "address": "3190440d7937a90337ad19634ab4669bebb28883", + "amount": "100000000000000" + }, + { + "address": "3200443602a176452ee90950a5351295a5167071", + "amount": "100000000000000" + }, + { + "address": "3210418fd5fc7b7dfd7d75028018163fb59d40a8", + "amount": "100000000000000" + }, + { + "address": "32204f1160e69002d6d86e2194117f6249a5f8bf", + "amount": "100000000000000" + }, + { + "address": "32304dfb40a70da4efbcccc335595bdb146afc25", + "amount": "100000000000000" + }, + { + "address": "32404941024157ffd22cb6e63a05c4a9f3267c18", + "amount": "100000000000000" + }, + { + "address": "32504951d7b1baa55fdc210e189b0fd1b6cd26bf", + "amount": "100000000000000" + }, + { + "address": "326040355d00febef3a516080a1c0a210e44df62", + "amount": "100000000000000" + }, + { + "address": "32704184a2ced2a3c64f3ed2275b95548fef0df3", + "amount": "100000000000000" + }, + { + "address": "32804e88e2b0a67f442c4031f0b91b9c136cf9a1", + "amount": "100000000000000" + }, + { + "address": "32904335f0cc4007dfd7beaa1e0d530b0850423c", + "amount": "100000000000000" + }, + { + "address": "33004a29540a208ea27581f8c58d3a7b68cf806e", + "amount": "100000000000000" + }, + { + "address": "33104aa9a8db1d203b971470253c2947d212d101", + "amount": "100000000000000" + }, + { + "address": "332041c5bb31084f5081a12eec7e84973b9050c4", + "amount": "100000000000000" + }, + { + "address": "33304a384d2bc374d9b49fc43f1ff71266f2f72a", + "amount": "100000000000000" + }, + { + "address": "33404dad454c7792ee9ebe7debde21f3165b55d3", + "amount": "100000000000000" + }, + { + "address": "3350428dc24111ce92e5e5b3e652290969249b82", + "amount": "100000000000000" + }, + { + "address": "33604fffca2d917ac12a8c445719fce04ba347fe", + "amount": "100000000000000" + }, + { + "address": "33704b4672b8b6abc242c30e6f9093c292cdd867", + "amount": "100000000000000" + }, + { + "address": "33804d7251e69234783730671ea0e5593cd1e685", + "amount": "100000000000000" + }, + { + "address": "339048f1e8d3615618aefc20c3674333034c0a8b", + "amount": "100000000000000" + }, + { + "address": "34004bd3a6601ebcb3e9f807f4364c44b7b43864", + "amount": "100000000000000" + }, + { + "address": "341041a2048ca305a4a07850e800832e033129ab", + "amount": "100000000000000" + }, + { + "address": "3420489202fb38a72364915d27b62010f96f8e61", + "amount": "100000000000000" + }, + { + "address": "34304d8d5f4dcb922f934d4ef0a98b38ce5a0e13", + "amount": "100000000000000" + }, + { + "address": "344046b1cd587b1f8d1f3bed184c8ac5281a06b0", + "amount": "100000000000000" + }, + { + "address": "345048b73c7139ffad2e0a2b0ddd11798028c552", + "amount": "100000000000000" + }, + { + "address": "346049ff5b7d886980411f9df009654d29e63e75", + "amount": "100000000000000" + }, + { + "address": "3470401b6b883fe18a6b267ce3755038d0b69d6a", + "amount": "100000000000000" + }, + { + "address": "34804b52b3bd167852eeca5de11a16d8085c8317", + "amount": "100000000000000" + }, + { + "address": "34904565b0d34e0955d54e5ee4e0409188a9981f", + "amount": "100000000000000" + }, + { + "address": "35004add80596903433b36ff6f13f84c703dc0bf", + "amount": "100000000000000" + }, + { + "address": "35104179212912972cd195d0d99cde5872b1e49c", + "amount": "100000000000000" + }, + { + "address": "3520445de027b8aee95d67563680021bb315b503", + "amount": "100000000000000" + }, + { + "address": "353042794cdd1fbaf34e250c78f585f17d357012", + "amount": "100000000000000" + }, + { + "address": "35404987b433e937e4862e5f55664eecef795f78", + "amount": "100000000000000" + }, + { + "address": "35504f4691b2c53d2b2b9ff0efae65b716cd4cca", + "amount": "100000000000000" + }, + { + "address": "35604464f569580d399280fa87b003a1b1fd9125", + "amount": "100000000000000" + }, + { + "address": "357040ae16c5eb6dcf85e5bab749c2090524b204", + "amount": "100000000000000" + }, + { + "address": "35804153fed41c4ee1d6196544aad5613b9dcced", + "amount": "100000000000000" + }, + { + "address": "359047fdcda82972eb9253f7b774ae51bc272550", + "amount": "100000000000000" + }, + { + "address": "36004b1e194156bf223501a10a759894c232b0d1", + "amount": "100000000000000" + }, + { + "address": "361044c781ae8053f78d4fe750deda298df90036", + "amount": "100000000000000" + }, + { + "address": "36204aa085755279387564cc22318fef6fe22507", + "amount": "100000000000000" + }, + { + "address": "3630474281208e5350a097cf58438eb821df2d78", + "amount": "100000000000000" + }, + { + "address": "36404fc963beb7aaab2e6fb389cd8b5390bbce06", + "amount": "100000000000000" + }, + { + "address": "36504b124c54deecc2cc47af358a00f773f2678a", + "amount": "100000000000000" + }, + { + "address": "36604a4885997fe5a77a05011f2d386b92452e25", + "amount": "100000000000000" + }, + { + "address": "3670447ee0096cd1e3d0fd3bf90237683357290e", + "amount": "100000000000000" + }, + { + "address": "368041995c9e2c0ac7e9c85a299c2add91c408c5", + "amount": "100000000000000" + }, + { + "address": "3690419c8e772fa5828bf15addbd636ac8e1fe60", + "amount": "100000000000000" + }, + { + "address": "370049e8d9c1f35df74e5ae7319f4b4ac8c9fbef", + "amount": "100000000000000" + }, + { + "address": "371045c859507bda236654ba9be78f3f844e3c90", + "amount": "100000000000000" + }, + { + "address": "3720462ddbe4a9b926059ae3b543e112b08c22af", + "amount": "100000000000000" + }, + { + "address": "37304679217f64cfc99ee9eb50a9b4c10c787612", + "amount": "100000000000000" + }, + { + "address": "374044695975d130b6531886a84ed9c35593e6aa", + "amount": "100000000000000" + }, + { + "address": "37504427bf3ad1e9d8f319963871ace60bf9cdfa", + "amount": "100000000000000" + }, + { + "address": "37604fc15cd724a87f7e2625532ecec8a67f96c5", + "amount": "100000000000000" + }, + { + "address": "37704e0ae01d8289a58e85d076c2e53b2b439bc0", + "amount": "100000000000000" + }, + { + "address": "37804879cf71d703c18d9a1a36840e455ad5257d", + "amount": "100000000000000" + }, + { + "address": "37904a898da09c64d90b87ef12ae8eba75ab70ef", + "amount": "100000000000000" + }, + { + "address": "38004f2f4ecd24fb6e1bbb6005e395820d711c92", + "amount": "100000000000000" + }, + { + "address": "38104191f40cd1705a0b3e51565ee4efd57c37f1", + "amount": "100000000000000" + }, + { + "address": "38204d1aaec84a2ae42e8caa8c3850c89ee3152c", + "amount": "100000000000000" + }, + { + "address": "38304c41d4fbb1bf231e821459de0730d5f7125f", + "amount": "100000000000000" + }, + { + "address": "38404fc1f3333fcf83bac73dfc54b04c9254c022", + "amount": "100000000000000" + }, + { + "address": "38504eda2a7e561ceb903173e5bab2a0ce2faed1", + "amount": "100000000000000" + }, + { + "address": "38604efb24ad019fd29329afa28a3ebf9ec67459", + "amount": "100000000000000" + }, + { + "address": "38704790e2adb4e2bb9a4a1ce745b8ddd407eb7c", + "amount": "100000000000000" + }, + { + "address": "388040cd8e861404de5d6f31d7ac4066f4d029b1", + "amount": "100000000000000" + }, + { + "address": "389044cb786b0c45a99ffd18600626019faebab5", + "amount": "100000000000000" + }, + { + "address": "390048a3113b7d71429ad1fa5c7e8ea773fb17c6", + "amount": "100000000000000" + }, + { + "address": "39104907570ce9faa49e2cb481df2e8b4ed29664", + "amount": "100000000000000" + }, + { + "address": "392049205fe199c8715802f8eb2f623cca922df9", + "amount": "100000000000000" + }, + { + "address": "3930414d9c4a5d88820e9f94711c83b33adbbd3a", + "amount": "100000000000000" + }, + { + "address": "39404e0e8c539b200c10e4ea00f6ac19bd9d8fd7", + "amount": "100000000000000" + }, + { + "address": "3950409733a0c9aed0df3a771eb72ea04d65ac61", + "amount": "100000000000000" + }, + { + "address": "39604000bb0f03de6dddaae3775f0dcf5f2616d9", + "amount": "100000000000000" + }, + { + "address": "397041aa1a91734f2eb917486d585a979ac4814d", + "amount": "100000000000000" + }, + { + "address": "398044a57ac2e71e881d58eb7ccd9d9cebf6b461", + "amount": "100000000000000" + }, + { + "address": "3990423bd9c877541bd99010abce6aba593fa422", + "amount": "100000000000000" + }, + { + "address": "400048c7b8ad110fa552f5276eb18fbf133442ff", + "amount": "100000000000000" + }, + { + "address": "4010442ccf683fd62b6ca6fd7a79987226fccb1a", + "amount": "100000000000000" + }, + { + "address": "402042e8d58b8f6f8bb5cbb8f3ce6b81e94b08a5", + "amount": "100000000000000" + }, + { + "address": "403044b6a04fdec2d447e79f3b2536beafc50ccf", + "amount": "100000000000000" + }, + { + "address": "404043e086c9a544a100c6574b821496449dc4c9", + "amount": "100000000000000" + }, + { + "address": "40504d12dcb2b6c35eba82e83ea6ce1203bccfda", + "amount": "100000000000000" + }, + { + "address": "4060401de88f864e233aa7e354a39697edd5d228", + "amount": "100000000000000" + }, + { + "address": "40704173d90fa115cf632974fefb97f8ac0cdd5a", + "amount": "100000000000000" + }, + { + "address": "408040e43d125d490af0d3792fa22c8edfabf3e8", + "amount": "100000000000000" + }, + { + "address": "40904d86614f2f0fa0ffba631577fdac808d054f", + "amount": "100000000000000" + }, + { + "address": "4100406ea23a4fefbf25303fedbd8f1d057fd71f", + "amount": "100000000000000" + }, + { + "address": "41104c864e06b1cc7051845887fdad77c4e9103d", + "amount": "100000000000000" + }, + { + "address": "4120490568a1e645ade2e5eba486f5c28c202599", + "amount": "100000000000000" + }, + { + "address": "41304769c40c9be69871025782463ced1ca5f8c4", + "amount": "100000000000000" + }, + { + "address": "41404321fa09f1e26e88f8297f4ebc1c7591b8cf", + "amount": "100000000000000" + }, + { + "address": "41504cd0ecb6bb356678286b93b0db4d5a2de6ff", + "amount": "100000000000000" + }, + { + "address": "4160496316e6844b606a2a881bfeb98d7db80481", + "amount": "100000000000000" + }, + { + "address": "4170441fd1a081fa05a56f18aad4ac7a16190018", + "amount": "100000000000000" + }, + { + "address": "41804d9def2714f137af065bba450952ab45dea6", + "amount": "100000000000000" + }, + { + "address": "4190439a9b97d17674fe3ab5d897fac5a4142668", + "amount": "100000000000000" + }, + { + "address": "420043b854e78f2d5f03895bba9ef16972913320", + "amount": "100000000000000" + }, + { + "address": "42104b54a994bf1eb0f774b7e9767d0ffd3c1d5a", + "amount": "100000000000000" + }, + { + "address": "4220421e3d617e9f11ec901dfa59e39d158e8692", + "amount": "100000000000000" + }, + { + "address": "423049d1c211746cf6dda98a50eba60a2aaec6f2", + "amount": "100000000000000" + }, + { + "address": "4240491cbfd017e652fba1d170ce1154aeeb27d9", + "amount": "100000000000000" + }, + { + "address": "42504d1a343ee6649f592438307c4a5f9f63e833", + "amount": "100000000000000" + }, + { + "address": "4260455886a887a258e2c5154b8d51730b846f6d", + "amount": "100000000000000" + }, + { + "address": "42704fd9e7b7e74197f96fd308b23ceb19f52d3f", + "amount": "100000000000000" + }, + { + "address": "428043a659f56992b33f52c6f6b8c92777a39595", + "amount": "100000000000000" + }, + { + "address": "42904e252ce17c56e1269bea315365a68515da98", + "amount": "100000000000000" + }, + { + "address": "430040d176cc2342c9a788f1e2a7a4851560d163", + "amount": "100000000000000" + }, + { + "address": "43104f4c4adb2b02ee0618deb84c65a399633263", + "amount": "100000000000000" + }, + { + "address": "432041283d7e1a624097f329b52551560e470856", + "amount": "100000000000000" + }, + { + "address": "43304af2615963515f8cde685e0185ec5230c1e6", + "amount": "100000000000000" + }, + { + "address": "43404619884fc86b3652706948118802bf455f1a", + "amount": "100000000000000" + }, + { + "address": "435042aa1bad5f86965fcde5dd57b2459c7cafd0", + "amount": "100000000000000" + }, + { + "address": "436041005230bdf407da67c09a73921c8905fdb8", + "amount": "100000000000000" + }, + { + "address": "43704ee3f0f6e32519eaad5e856e9de1bac702a1", + "amount": "100000000000000" + }, + { + "address": "438040ee2dca2eaa65c4e98d46f68bc749293514", + "amount": "100000000000000" + }, + { + "address": "439047e81f6fffc2846ec87756257c7ea78a71c4", + "amount": "100000000000000" + }, + { + "address": "44004ecbb5d957fd9b7febf89841cf507d95dd34", + "amount": "100000000000000" + }, + { + "address": "44104bd54eb6c3724d9f97d5befac0b996420275", + "amount": "100000000000000" + }, + { + "address": "44204ba01215d2876f9545a1a7b57f671071d59a", + "amount": "100000000000000" + }, + { + "address": "44304b8a8220d8692f68b631a95b59265bb6a52f", + "amount": "100000000000000" + }, + { + "address": "44404ffcb1f1e1eb6a59b17731245c4becd5513f", + "amount": "100000000000000" + }, + { + "address": "44504e7cfdd173bacd0a4933ee328ed0a7946852", + "amount": "100000000000000" + }, + { + "address": "446047d1029355e34b94f47061be7b6b671bdf0e", + "amount": "100000000000000" + }, + { + "address": "44704161667f420239be206d949310d4d4b505e4", + "amount": "100000000000000" + }, + { + "address": "4480454d76128e3abf5fff4b129985a70ee449ff", + "amount": "100000000000000" + }, + { + "address": "44904aa24c16c5d4862a494c5a3a068a9a8efcce", + "amount": "100000000000000" + }, + { + "address": "450047b3d8a803358e647dca9aa2119d552ae98a", + "amount": "100000000000000" + }, + { + "address": "45104003fddc52c2a36f2ea782ef4e040d709ae5", + "amount": "100000000000000" + }, + { + "address": "45204b7689eb2cd1ab0fca85d768176803713c56", + "amount": "100000000000000" + }, + { + "address": "45304fede7bde8d0fa71a22da82ec6aeaddcdb8f", + "amount": "100000000000000" + }, + { + "address": "4540428b06b1ac971a548b844bc7cee683ac8910", + "amount": "100000000000000" + }, + { + "address": "455048c4b5b04d40803e4ea44f1f1ec7f5e2158f", + "amount": "100000000000000" + }, + { + "address": "45604c07d459d0e00e0c676191f47f54f5cc9d17", + "amount": "100000000000000" + }, + { + "address": "45704ab864f63350afe79f2c840b96205b9dc69a", + "amount": "100000000000000" + }, + { + "address": "458047e5fe56a0e4e209705fadbdb64e74dcc8da", + "amount": "100000000000000" + }, + { + "address": "459047ffc6e6f4f92c97b7a74180ccaed6e30b79", + "amount": "100000000000000" + }, + { + "address": "46004e8e048204f310b2d3ef5790c6f0fdc6ddd0", + "amount": "100000000000000" + }, + { + "address": "461045c62f269a240a2d27ba40ac33b4324b7bab", + "amount": "100000000000000" + }, + { + "address": "46204132a93bdc40c6976823dd0e6bc205f155a1", + "amount": "100000000000000" + }, + { + "address": "4630494fb9144b14d2948d5b67261345f72b691c", + "amount": "100000000000000" + }, + { + "address": "46404d167820598aed5aa93b5a057d72fc859a04", + "amount": "100000000000000" + }, + { + "address": "46504941f3f25ba5b8f7c175ddf62eaf0d06adb3", + "amount": "100000000000000" + }, + { + "address": "466045100f7e8c27325435184c01b78369480354", + "amount": "100000000000000" + }, + { + "address": "467042e5a9b3c69a66129703b8c572240c1d153c", + "amount": "100000000000000" + }, + { + "address": "46804d4141c4947fbe605d1098eafdb14b108d6f", + "amount": "100000000000000" + }, + { + "address": "4690407f05a59ab99fa62e9c931fc713ed0b2184", + "amount": "100000000000000" + }, + { + "address": "470042f846f54c551bfcf53d2cc8fc9eb50b9d77", + "amount": "100000000000000" + }, + { + "address": "4710478780ea9e0d337b24886b1b806edcbeb194", + "amount": "100000000000000" + }, + { + "address": "47204e3a7b972c67d7492b8beffd704a14a5597f", + "amount": "100000000000000" + }, + { + "address": "47304bc12fb943d98b3c1e8800e97e452b9e07b1", + "amount": "100000000000000" + }, + { + "address": "474047553b5fdd4554a8d619d04c293fad715859", + "amount": "100000000000000" + }, + { + "address": "4750444b21d48d5058a716a230d50f675d3fabd4", + "amount": "100000000000000" + }, + { + "address": "4760435ab90be6bd17d294fd923e252b414a2c04", + "amount": "100000000000000" + }, + { + "address": "477045c6548b93ad997cf88265dc4064c2a55404", + "amount": "100000000000000" + }, + { + "address": "478043234bfbdde3497569af02e9052cb5877bfc", + "amount": "100000000000000" + }, + { + "address": "479046da314d05c021dac35448b1eecc89db0481", + "amount": "100000000000000" + }, + { + "address": "48004cb51eed7e063da47540db789cb415d1b3d7", + "amount": "100000000000000" + }, + { + "address": "481041dd8949041bd011954a00d2f52fae0566c4", + "amount": "100000000000000" + }, + { + "address": "48204a827f0f7ef5545fdc74333d8422ff702284", + "amount": "100000000000000" + }, + { + "address": "48304ebd697b2501eb5a4a8ce716151c64e4dfce", + "amount": "100000000000000" + }, + { + "address": "4840420106bebe4c1da8f3863f8fecf85531e3e8", + "amount": "100000000000000" + }, + { + "address": "485045203218d25423cd22454ad34f3473b1f948", + "amount": "100000000000000" + }, + { + "address": "48604b028a5faf55d03b2259e8596034dbcfce77", + "amount": "100000000000000" + }, + { + "address": "487049a35ab4ec9d9b24e7871fe3f332f2e4ba4d", + "amount": "100000000000000" + }, + { + "address": "48804331472e8fbb1145c9f17e6f3009efb8b9c3", + "amount": "100000000000000" + }, + { + "address": "48904c7f5a4f76f41e999a31f754d77b97d0d34a", + "amount": "100000000000000" + }, + { + "address": "4900408ea7abbfd68548d4066cd47de004abdab8", + "amount": "100000000000000" + }, + { + "address": "491042831baa4824f571ab903aa3a67283beb6ed", + "amount": "100000000000000" + }, + { + "address": "49204c54c110eae17618e89cc20ba6d8249b8388", + "amount": "100000000000000" + }, + { + "address": "49304ba5346e6c9681ac40b54b0b06798543121d", + "amount": "100000000000000" + }, + { + "address": "49404cde92dd5d8ecfc884c6c23e7d4fbf02d987", + "amount": "100000000000000" + }, + { + "address": "49504a406e7533631945d33ce560f51b4954c862", + "amount": "100000000000000" + }, + { + "address": "496040841bd7d102f718cc586408765fe8b890f7", + "amount": "100000000000000" + }, + { + "address": "49704630c8f0c30ad5562fca357ad9e433327c86", + "amount": "100000000000000" + }, + { + "address": "49804b1066d6e1f2e2eb444319101bf1d410bc0f", + "amount": "100000000000000" + }, + { + "address": "499049ee379ae9666f10a57cadac6dab770bf4b8", + "amount": "100000000000000" + }, + { + "address": "50004655607ec95dc65ec29bbb415db821f07653", + "amount": "100000000000000" + }, + { + "address": "5010452968dd443161fc551d953961bf63065bf0", + "amount": "100000000000000" + }, + { + "address": "50204abd8507b4151f8a5d11f8a5c42581adf99e", + "amount": "100000000000000" + }, + { + "address": "503048aefad5aedeebe1ea87229c3c6b8f1fe42b", + "amount": "100000000000000" + }, + { + "address": "504048ca595ad0f9b68759d00c16fa58316745c6", + "amount": "100000000000000" + }, + { + "address": "50504eaf9796e76437666e40f94af993faee5c36", + "amount": "100000000000000" + }, + { + "address": "50604210365e98bf07ce91a990826a9539edc2dc", + "amount": "100000000000000" + }, + { + "address": "50704701122e4cb8ce668272e88486dfe5efe64d", + "amount": "100000000000000" + }, + { + "address": "50804a42b45c1e6f2b0b7efb62081e1352aea22f", + "amount": "100000000000000" + }, + { + "address": "5090450269b417fbaca6afb81325baeee7817a73", + "amount": "100000000000000" + }, + { + "address": "5100438648be0f3168375454a4cdb3c9e42ecb0d", + "amount": "100000000000000" + }, + { + "address": "5110453215f3d3afe3a002bf8e926b38013e7173", + "amount": "100000000000000" + }, + { + "address": "51204817b59f7a35de4503dcbfdae37d5c256bad", + "amount": "100000000000000" + }, + { + "address": "513047730b1635dd5723fda5153a055ba17744d2", + "amount": "100000000000000" + }, + { + "address": "51404aeac599ca65caa4d65039e868764352d341", + "amount": "100000000000000" + }, + { + "address": "5150443a4e437dd13f2aaf543b78c59d186771ea", + "amount": "100000000000000" + }, + { + "address": "5160499de0e7643925875defc447b38fe8724704", + "amount": "100000000000000" + }, + { + "address": "51704fd6050f0e11179f4e1f403bc5b84c83156a", + "amount": "100000000000000" + }, + { + "address": "5180446d9777a6ecc8ea5a1864392f3f053992e3", + "amount": "100000000000000" + }, + { + "address": "51904629b79abd0f0a63d29a8ef19939bb4c9b68", + "amount": "100000000000000" + }, + { + "address": "52004033b3431796cd2b6c7183b0f4b20674f013", + "amount": "100000000000000" + }, + { + "address": "521044e558ddc905ab36398e83f425b49572f802", + "amount": "100000000000000" + }, + { + "address": "522042bf74ba442b2e4b5e5c3c2eac92990809e4", + "amount": "100000000000000" + }, + { + "address": "52304b8321c4df0bd068386bcc67c38eda4e78c6", + "amount": "100000000000000" + }, + { + "address": "524043fcf064677787b4009674157e5ab106724b", + "amount": "100000000000000" + }, + { + "address": "525045a59b44173f08543f6db2dfd82da1180386", + "amount": "100000000000000" + }, + { + "address": "52604131ad343cd2d4e196bb823402aa089046c2", + "amount": "100000000000000" + }, + { + "address": "5270483dfb1a2f45363360ec692c2b07f8ba4e62", + "amount": "100000000000000" + }, + { + "address": "52804b2f75230f1d2813065a70f0a3d1bb4abc0b", + "amount": "100000000000000" + }, + { + "address": "52904d9cdc5e0a89d0efff246ef317dad054571e", + "amount": "100000000000000" + }, + { + "address": "53004082199e53af8651a8bcd495cdf0b9bda026", + "amount": "100000000000000" + }, + { + "address": "531048a70444edac7580b084639b953c483edb1c", + "amount": "100000000000000" + }, + { + "address": "532040437d02ebc3037d1c7753fd4f25dc1ef83a", + "amount": "100000000000000" + }, + { + "address": "53304f2156659c6ecc5cb4a3ab8afbe6ce298727", + "amount": "100000000000000" + }, + { + "address": "53404bccf31a949b64345f2bceb2de4e0e192552", + "amount": "100000000000000" + }, + { + "address": "53504f3c72ad9444d0d6e747cbfdac9a58180e9f", + "amount": "100000000000000" + }, + { + "address": "53604394038790e32dcbbff77dbb99f6a3ce0c1e", + "amount": "100000000000000" + }, + { + "address": "53704913ab93114aa38132ad58df09853c480171", + "amount": "100000000000000" + }, + { + "address": "53804c76af324412728608ae0e8426d96abc99c9", + "amount": "100000000000000" + }, + { + "address": "53904a4b7c3faea59d5d9b496e21ba2faf9379f2", + "amount": "100000000000000" + }, + { + "address": "54004020a779da577648aa43d0ff18b4fb26d324", + "amount": "100000000000000" + }, + { + "address": "54104186203eb30aa18f4e39ba5892c6c7161222", + "amount": "100000000000000" + }, + { + "address": "54204df4f5682d7a23f9d1c52c7afb9274962957", + "amount": "100000000000000" + }, + { + "address": "543047f632bc64ed249da3382134283074068708", + "amount": "100000000000000" + }, + { + "address": "54404c797a871873ca95884d8c30ae983dd57de9", + "amount": "100000000000000" + }, + { + "address": "545041d1f64a7d0a251ceea5cfbb843959415dfd", + "amount": "100000000000000" + }, + { + "address": "54604942a3f7615c118e3b6f27b683b3fb01903c", + "amount": "100000000000000" + }, + { + "address": "54704ac394b1d1b740d4661c17fffcb415af13e3", + "amount": "100000000000000" + }, + { + "address": "5480478c9f0787732218da068f82651023d36863", + "amount": "100000000000000" + }, + { + "address": "5490441ea32aee4b5d12cdecdd7a96b606502b1c", + "amount": "100000000000000" + }, + { + "address": "550046092b784c4710e2cd4f72c0784723f28f99", + "amount": "100000000000000" + }, + { + "address": "55104676e53c56dbf0723979519125308ffb7760", + "amount": "100000000000000" + }, + { + "address": "55204cfc23ff67ebd33b993db7a1fc8ae11ed6a9", + "amount": "100000000000000" + }, + { + "address": "553049d21748456f4d400a0e0c05b04bc4a17d42", + "amount": "100000000000000" + }, + { + "address": "55404f23ef78c2750bc800240a7c58089eec4ee5", + "amount": "100000000000000" + }, + { + "address": "555045a7188c95f9a7c2bebd91d70baf4446ef6f", + "amount": "100000000000000" + }, + { + "address": "55604b44996331b3e1bc734a5309a921a9ed68b2", + "amount": "100000000000000" + }, + { + "address": "55704c62bb4eb9f7d44463a9d23b4fc4ca967e8d", + "amount": "100000000000000" + }, + { + "address": "558041c40bda7eb7793f4974d937efbdbfe849ad", + "amount": "100000000000000" + }, + { + "address": "55904dad216482a42deafd26f46227f821c4318c", + "amount": "100000000000000" + }, + { + "address": "56004ef6b2bc5c6b261cc57df071c4d6b0d58942", + "amount": "100000000000000" + }, + { + "address": "56104b6933b27ebb07b76c9fbea00efae4b455f8", + "amount": "100000000000000" + }, + { + "address": "56204c3808a0aba40e0b892ec5ecc7ee748d656b", + "amount": "100000000000000" + }, + { + "address": "563045b3c9e24aa577bd71c73e65456725e6a43d", + "amount": "100000000000000" + }, + { + "address": "564040919f2c792a37b8169dd75787a150280910", + "amount": "100000000000000" + }, + { + "address": "565046147c04866c2804381096f4fbe231be5e27", + "amount": "100000000000000" + }, + { + "address": "56604b970a318d46fa25e919ecf52e47644d8e54", + "amount": "100000000000000" + }, + { + "address": "5670477c21534eedfda67b3ba2dedd4d1fd7a48a", + "amount": "100000000000000" + }, + { + "address": "56804868458d08fbf48b5fe3c989e528932c4bdd", + "amount": "100000000000000" + }, + { + "address": "56904945ed11c64451561a5da223dfef07a63d6c", + "amount": "100000000000000" + }, + { + "address": "570042453bea68860af0d5e1fae70f954ef92fbd", + "amount": "100000000000000" + }, + { + "address": "571048a293b79bb13e6a70d000fe0d112e4db1ec", + "amount": "100000000000000" + }, + { + "address": "57204b9e693914803c62940322f5432d213f0303", + "amount": "100000000000000" + }, + { + "address": "573041273c82a37e145392a75914fc028cb06e73", + "amount": "100000000000000" + }, + { + "address": "5740421e8340de6f8f11a052ba4c1dd0125b4a89", + "amount": "100000000000000" + }, + { + "address": "575043a39731f509415b44775c0819d1ed028f6e", + "amount": "100000000000000" + }, + { + "address": "57604dae805055c246a6fd0b455c62b1a964dcea", + "amount": "100000000000000" + }, + { + "address": "577047fd2cd22d149d9fd5cc0d2b764c10401f47", + "amount": "100000000000000" + }, + { + "address": "578045b49772c9c100287ef46ba7573d29f0787c", + "amount": "100000000000000" + }, + { + "address": "5790443ed1d326e9d7dcd5a0b08efd895aecfc9a", + "amount": "100000000000000" + }, + { + "address": "580042c8282aa038ab321e84eba447532ada0e9f", + "amount": "100000000000000" + }, + { + "address": "58104e0e46910bed78a45754b5406547c3c50fe9", + "amount": "100000000000000" + }, + { + "address": "5820411917585b430f3dcd1bf0d4ec9909077a4e", + "amount": "100000000000000" + }, + { + "address": "58304206194e2acd780efcbcd467784e84455a2d", + "amount": "100000000000000" + }, + { + "address": "584041e10f3f4e450ffff9e5843a6aaf0bd9e138", + "amount": "100000000000000" + }, + { + "address": "58504295adbe4b5825b8c647a886a8a4cd09796c", + "amount": "100000000000000" + }, + { + "address": "586047183d4b321949867cf34f33a2b89dc4cbda", + "amount": "100000000000000" + }, + { + "address": "587046ecb0f3ff0fbb597b0d129c86992ec5a610", + "amount": "100000000000000" + }, + { + "address": "58804dc8466d215f2eb4e0cce44cfc2be56a0a9e", + "amount": "100000000000000" + }, + { + "address": "589043b85f4a9eff43e7c28325bb8b4143fb3b41", + "amount": "100000000000000" + }, + { + "address": "590043d97155d5cc610fbaac50957bf5726adf38", + "amount": "100000000000000" + }, + { + "address": "591048978de1d5b41fe3295776e774cba204f182", + "amount": "100000000000000" + }, + { + "address": "5920456ab371c27ce7ea26013b948314751cb60b", + "amount": "100000000000000" + }, + { + "address": "59304b5ebd78c9b142c6c892be51e0e598cd052c", + "amount": "100000000000000" + }, + { + "address": "59404237be852ee16fd9ad5ea5cfee2c1e33e466", + "amount": "100000000000000" + }, + { + "address": "595047325b6fd4d83eb09dcdd41efe666650f407", + "amount": "100000000000000" + }, + { + "address": "59604e48e8378d4d55facfe4ebb8030b4ac15b77", + "amount": "100000000000000" + }, + { + "address": "597046a2893077b014e727ea04168cb56c0178a3", + "amount": "100000000000000" + }, + { + "address": "598042250dd6291126f9d6eaff6d2465f0f60f12", + "amount": "100000000000000" + }, + { + "address": "599042ed94c7838178f5d85634f9aa7ab8226a99", + "amount": "100000000000000" + }, + { + "address": "60004433bfc5145e5805d433007914fbd179e443", + "amount": "100000000000000" + }, + { + "address": "6010455003515da6f534e5f0350db7073839563f", + "amount": "100000000000000" + }, + { + "address": "602049f52ea2c0ebe5efe0a92e72e9e822ea4f97", + "amount": "100000000000000" + }, + { + "address": "603040fd618c8a153c2a74f73c4627ee565ff483", + "amount": "100000000000000" + }, + { + "address": "6040464732f9ff9878e360e2c16912e237a69862", + "amount": "100000000000000" + }, + { + "address": "60504b8e2db94604422624dc62c9e3126f8b7e76", + "amount": "100000000000000" + }, + { + "address": "606041d95feb88cf90feb74ddb61442bba982655", + "amount": "100000000000000" + }, + { + "address": "6070425ff0899d82336bb1038acb94aa9ba00c21", + "amount": "100000000000000" + }, + { + "address": "60804154da5db875b177aa5f89285a15129ba147", + "amount": "100000000000000" + }, + { + "address": "60904987c7f9cc9daae1355326def9b74ad5f53d", + "amount": "100000000000000" + }, + { + "address": "61004e257b9b5dd1d92ace4d326bfc6984d3eb74", + "amount": "100000000000000" + }, + { + "address": "6110407764cac536b59af8c85d3799cfd177dc71", + "amount": "100000000000000" + }, + { + "address": "61204c4cac74ff2faf6b8f5c32ff289a408bbb1d", + "amount": "100000000000000" + }, + { + "address": "6130482f2f773fd2ccdcead78253f503df74df5d", + "amount": "100000000000000" + }, + { + "address": "61404858cb7054b8cb842a186dbe60a7e300db19", + "amount": "100000000000000" + }, + { + "address": "61504179f6955dd6657724dd4146b146e4d54c09", + "amount": "100000000000000" + }, + { + "address": "61604b023003dac28306cd9220b2147390a07f49", + "amount": "100000000000000" + }, + { + "address": "61704f8eab2279a3c84e0568fb846dd66c959932", + "amount": "100000000000000" + }, + { + "address": "6180499d362b6d9765b0998a3abd7294c685f284", + "amount": "100000000000000" + }, + { + "address": "61904dbe91f98c168f4772897356e891565205d3", + "amount": "100000000000000" + }, + { + "address": "620040b3439cb928a9879b273010a99e5055e92b", + "amount": "100000000000000" + }, + { + "address": "6210405df49c7a7ee68fe3d72c9d55cc14ca0e8d", + "amount": "100000000000000" + }, + { + "address": "622040b5c622cf2fa9f9dfe29832dfe7d8944ae3", + "amount": "100000000000000" + }, + { + "address": "6230485e89c4581bbd18207c2dfa318d0e1c5c83", + "amount": "100000000000000" + }, + { + "address": "62404456d0a321660f444f9579b4f8fcb616de54", + "amount": "100000000000000" + }, + { + "address": "625045eb1422c6a258141c7420174e4f353228ca", + "amount": "100000000000000" + }, + { + "address": "62604278bc2457c61b1fb7bd62ab419160ea33bc", + "amount": "100000000000000" + }, + { + "address": "62704f0b74cd7705d048aba826b4bbdba837ee80", + "amount": "100000000000000" + }, + { + "address": "628040d02555d7e209b85123343f6c2431a5c7fb", + "amount": "100000000000000" + }, + { + "address": "62904e1ddae768ad6e9e5c9884ed3256996140c1", + "amount": "100000000000000" + }, + { + "address": "63004122cc25622025f0157cc56ea60f1551723d", + "amount": "100000000000000" + }, + { + "address": "63104ebb93a1c385fa95e48c77f1d3a1d5f99295", + "amount": "100000000000000" + }, + { + "address": "632044e7a8d184c949eb09a2869487aba0f73406", + "amount": "100000000000000" + }, + { + "address": "63304cb4079acb5dec9fab674720e23b668a30d9", + "amount": "100000000000000" + }, + { + "address": "63404b02237cdc0708fd3d0a34f46b6756844c48", + "amount": "100000000000000" + }, + { + "address": "635045f735ce51744a688f6d5075770464133b72", + "amount": "100000000000000" + }, + { + "address": "6360418f0d9fea319405d324ad5bfb4b7908260c", + "amount": "100000000000000" + }, + { + "address": "637047816ef8e3fbf907553627764c687ec67441", + "amount": "100000000000000" + }, + { + "address": "63804872395fc43ee4d6bac267c931ada198506d", + "amount": "100000000000000" + }, + { + "address": "639049314c67316267cb7b10df2a8167f9ae9b48", + "amount": "100000000000000" + }, + { + "address": "64004497fe1c37da0fafb12f633b6080929b41dc", + "amount": "100000000000000" + }, + { + "address": "6410453060cde98da46b8eeae93f4a213a51aaca", + "amount": "100000000000000" + }, + { + "address": "64204b02f42cf5b2606ee7069ba5e5b643acd036", + "amount": "100000000000000" + }, + { + "address": "64304c4006cc42bc15ad4ce569b388981fbff631", + "amount": "100000000000000" + }, + { + "address": "6440410b6010b8cda6a38d2ccc6785c5c56a70a2", + "amount": "100000000000000" + }, + { + "address": "645043e482206acec00090d8a3fdf4b96602dda3", + "amount": "100000000000000" + }, + { + "address": "6460443f08d3abef11110045198b1257a9ec76f8", + "amount": "100000000000000" + }, + { + "address": "64704a5d9ee1ee1d8e197e781319e4953ac8bb73", + "amount": "100000000000000" + }, + { + "address": "648046c02fe3c86598115b9de7ef6c1ea7ecc5f4", + "amount": "100000000000000" + }, + { + "address": "64904d6a4328e16e5a52962aa46fba9a7d35b4c9", + "amount": "100000000000000" + }, + { + "address": "65004bb380bc0c86de13d4a3547b662690da9bd9", + "amount": "100000000000000" + }, + { + "address": "65104222b9b770a93e7b6e4319b34c6c52cc9155", + "amount": "100000000000000" + }, + { + "address": "65204cb2035c55ea5df48463769e9744ad6f0393", + "amount": "100000000000000" + }, + { + "address": "653047e2d1a8fb3d9e1805dccac1cc6f2c28c556", + "amount": "100000000000000" + }, + { + "address": "654043b4e33de08eff8894cb7ca7a71a411db7d9", + "amount": "100000000000000" + }, + { + "address": "655046ec7d2eb9c66d4af6f73d2e8206566e4692", + "amount": "100000000000000" + }, + { + "address": "656047fd8c02ab8e3771d3cd053734f56a926389", + "amount": "100000000000000" + }, + { + "address": "65704439f9a3e216347069f62b7fb13e4b1f9b64", + "amount": "100000000000000" + }, + { + "address": "65804f628f171dff16be813578f80f4e3b7e0e3c", + "amount": "100000000000000" + }, + { + "address": "659049f81d3b432aedf5eec093af2f7144346c73", + "amount": "100000000000000" + }, + { + "address": "66004766c29d526595b8b005cbdce375ff5fdcec", + "amount": "100000000000000" + }, + { + "address": "66104dce510f16a8217c3844db10e5f137bc441a", + "amount": "100000000000000" + }, + { + "address": "66204361fe6b4729f27732acc739dd3764e7b07c", + "amount": "100000000000000" + }, + { + "address": "6630440e5e933646e978d8f937fd643563d99230", + "amount": "100000000000000" + }, + { + "address": "66404f5457eb934bfc6e975f9f6b04c01cc602dc", + "amount": "100000000000000" + }, + { + "address": "6650441b6f8afa3b01cd713d723be5a40c6ce247", + "amount": "100000000000000" + }, + { + "address": "666041989961aea5a1873df788e7e5a2b535334b", + "amount": "100000000000000" + }, + { + "address": "667044c105e7a685a522b53f64c4ab7de28063e6", + "amount": "100000000000000" + }, + { + "address": "668040d53879731c4a014ce64216c4c36ae2e7ac", + "amount": "100000000000000" + }, + { + "address": "6690401e4271d59a632ca3e4b06f38b445929ece", + "amount": "100000000000000" + }, + { + "address": "670046842562abde6d3d466644b9ca0f8fa8f7f2", + "amount": "100000000000000" + }, + { + "address": "671041b264453e02458397b587c4d0d550d2150d", + "amount": "100000000000000" + }, + { + "address": "672043e97db17eefaca6d9c82bd787f4c5e97128", + "amount": "100000000000000" + }, + { + "address": "6730458aec07fc2b32f4068c57314a82c6a4ae42", + "amount": "100000000000000" + }, + { + "address": "674042dca7e3832040eb9d80275364d45478017c", + "amount": "100000000000000" + }, + { + "address": "6750430cb460f6571cd65a92d9bccecbc2b89dd0", + "amount": "100000000000000" + }, + { + "address": "6760451d38daecf19bf46a6fc5fb2d280d39270e", + "amount": "100000000000000" + }, + { + "address": "67704441d1d0855396d871f4e726e929660bf8ff", + "amount": "100000000000000" + }, + { + "address": "67804ccfc22ed924ba1d5022ed11db444e0ad33f", + "amount": "100000000000000" + }, + { + "address": "679045eca99bd5ee98e2bdfe0a067b6d7eaaa477", + "amount": "100000000000000" + }, + { + "address": "68004cbe8b20f79043bd60e6d407a892725c0218", + "amount": "100000000000000" + }, + { + "address": "681040fd5fbf65ee66ccfad1fc530d0f60d675af", + "amount": "100000000000000" + }, + { + "address": "68204296b18ed685fab791e7f7371f86fa3dbf15", + "amount": "100000000000000" + }, + { + "address": "683049213af4a3ed07b8dc4a078aa8bc485fb762", + "amount": "100000000000000" + }, + { + "address": "68404ac8c50e40e149ff2a292e350b8002361c9f", + "amount": "100000000000000" + }, + { + "address": "68504af73aa4ae030a8579cd54da6a8e71b2c121", + "amount": "100000000000000" + }, + { + "address": "68604c15e95f52d3039f453eac003c8d6b85abbd", + "amount": "100000000000000" + }, + { + "address": "68704e3bc93591d552942fe92f91889fbce4832a", + "amount": "100000000000000" + }, + { + "address": "68804b25a7116144f61e73e74e21adbe825b205f", + "amount": "100000000000000" + }, + { + "address": "68904c03e391f951339c9958eb5bc72c43ad63e3", + "amount": "100000000000000" + }, + { + "address": "6900418575027f2a1c247bbaa0609ae9cf80ab75", + "amount": "100000000000000" + }, + { + "address": "691041eab10813cc60e8fed6536903cd21635b13", + "amount": "100000000000000" + }, + { + "address": "69204a4b90e76b575773b257644c33f044455e73", + "amount": "100000000000000" + }, + { + "address": "693045b878d184546a55e1f2d2ed3fee47e08a69", + "amount": "100000000000000" + }, + { + "address": "69404b70bf4a3c1854d289bf48aff4ffcc54462d", + "amount": "100000000000000" + }, + { + "address": "695047251a6b4dc26af3dafeb2ad9e8bd11899f7", + "amount": "100000000000000" + }, + { + "address": "696042291abaeefbfe88cf4c6640cb8334fb5387", + "amount": "100000000000000" + }, + { + "address": "69704c4391043c0103e88d84b976b77eb8f58511", + "amount": "100000000000000" + }, + { + "address": "698045d16859ea22f965199057d94ef729316962", + "amount": "100000000000000" + }, + { + "address": "6990471405d1359a4951ff69f05f3a6ba5e322d3", + "amount": "100000000000000" + }, + { + "address": "700045ae96df298ad66c9407341aa1c9c4b7e3df", + "amount": "100000000000000" + }, + { + "address": "70104bbe466157ff39778c0efa245e729b33a00f", + "amount": "100000000000000" + }, + { + "address": "70204fc5a25b35b2ae011c05a06debe3c138cc6c", + "amount": "100000000000000" + }, + { + "address": "70304e51707696936993f6865f3f1be774f22c05", + "amount": "100000000000000" + }, + { + "address": "704041ae13c7807d1007bce82206adc28dec9bbf", + "amount": "100000000000000" + }, + { + "address": "70504f23e2a3f569a63533ac1b116a4680596abb", + "amount": "100000000000000" + }, + { + "address": "70604bbeaf187b5b24ac8f11df5f9a404432a899", + "amount": "100000000000000" + }, + { + "address": "707043290fd9d435c104db4a9a192023f432054a", + "amount": "100000000000000" + }, + { + "address": "708049eadf139b3036e1eddded3bf44fe803da63", + "amount": "100000000000000" + }, + { + "address": "70904ac80bef69aff0800bb6554f5f01443113e9", + "amount": "100000000000000" + }, + { + "address": "710041d7fff4b20bd4460b108e314d2fc832b2d2", + "amount": "100000000000000" + }, + { + "address": "7110486af5e1932f8b0ed8e82224012d4bb4a6e6", + "amount": "100000000000000" + }, + { + "address": "7120458a83f65b14f570912acd93701cc3689098", + "amount": "100000000000000" + }, + { + "address": "71304ce8abec1dc3eb97a538274a97f65bed3a3e", + "amount": "100000000000000" + }, + { + "address": "714045b6adbfbcb7b04f6763ff9f5f7f36b0b653", + "amount": "100000000000000" + }, + { + "address": "715040b8b724a8eb1f9f31eba45e384725408d0e", + "amount": "100000000000000" + }, + { + "address": "7160455702053e3a8a3ef39971eb848d9d6fa93c", + "amount": "100000000000000" + }, + { + "address": "7170477eaccf217f57b35c55cab9e2dbc62433db", + "amount": "100000000000000" + }, + { + "address": "71804ead1df28012d17172a0775cbac6cd999306", + "amount": "100000000000000" + }, + { + "address": "71904efa4dca8d0ce5608b4689f8bf9cc51f9df8", + "amount": "100000000000000" + }, + { + "address": "720049fd5ac173f954454258e7673d1d39d2dce4", + "amount": "100000000000000" + }, + { + "address": "72104a97065ed6db665ec6d59852f1a5497f3beb", + "amount": "100000000000000" + }, + { + "address": "72204c482f30096b5a80c9411eb724979b6df892", + "amount": "100000000000000" + }, + { + "address": "72304639b82708bbdb5ab2e20dfcb5148084de30", + "amount": "100000000000000" + }, + { + "address": "72404e838cd0e07e6a01e23ca678ee364721cf92", + "amount": "100000000000000" + }, + { + "address": "72504fe21ab8f1ce70ad1f29122222a742150ff0", + "amount": "100000000000000" + }, + { + "address": "72604117cf813be0dffaefbf4806e5699344e5c3", + "amount": "100000000000000" + }, + { + "address": "72704dfacba8503a46b1e5e7e6aa8280880e6e65", + "amount": "100000000000000" + }, + { + "address": "72804ca70d543e1e4369abd90b9d6022f3a1d97c", + "amount": "100000000000000" + }, + { + "address": "729043b384b8354d7a54c2428b22222f7898f9c6", + "amount": "100000000000000" + }, + { + "address": "73004fa9859d249efb0a91fc915af55ec49cd444", + "amount": "100000000000000" + }, + { + "address": "731040db933ad7d8e99b88440a76e3cee5eb6e69", + "amount": "100000000000000" + }, + { + "address": "73204343469ac1f556f0377d90b69f3dbf5a982c", + "amount": "100000000000000" + }, + { + "address": "733049362478534ff6410823044e071eb2f83e4f", + "amount": "100000000000000" + }, + { + "address": "73404f1945447051bf690a173519ba74645e994a", + "amount": "100000000000000" + }, + { + "address": "735042862d5212cfefc9b5f324ce13fa9b325705", + "amount": "100000000000000" + }, + { + "address": "73604c4ab9e12a56a90e738b6a231cfbd5a49e66", + "amount": "100000000000000" + }, + { + "address": "73704b14cd41d45fab3fe2b4b7757d57249db53b", + "amount": "100000000000000" + }, + { + "address": "7380460d3ff8820e5b3cfb10a80d408caaa66dae", + "amount": "100000000000000" + }, + { + "address": "739048ca6dda2acaa91f555fb45dd6ba2ca17958", + "amount": "100000000000000" + }, + { + "address": "74004606ce8137e61a116e85357ab666f1aab529", + "amount": "100000000000000" + }, + { + "address": "74104e0fa50aac8cda9809d603430ea7ea65d122", + "amount": "100000000000000" + }, + { + "address": "742040c7efac6132191fa24d16fca79a600ed23e", + "amount": "100000000000000" + }, + { + "address": "7430460fa50f3a7e2d7765c6b5f30724720f6fc9", + "amount": "100000000000000" + }, + { + "address": "74404c120f2909457a3ddad0abffae055890eee9", + "amount": "100000000000000" + }, + { + "address": "74504191374ac2d4fbdbc976b63e007d8b5e7e72", + "amount": "100000000000000" + }, + { + "address": "74604ac62f17d849b24cb9a1e2bd680f107a3977", + "amount": "100000000000000" + }, + { + "address": "747047f7087dd2aeb62a5eb6e3f15c1e6e1721b5", + "amount": "100000000000000" + }, + { + "address": "74804357c658d6575aa6746be8f25c04c4e9adcb", + "amount": "100000000000000" + }, + { + "address": "7490485def5367ca659bab67b979ffd181be6852", + "amount": "100000000000000" + }, + { + "address": "7500405f2ec0db786c0d56dec170ccb668f781ae", + "amount": "100000000000000" + }, + { + "address": "7510441d0cd71400a2ddd1516c4e08d9cfc0f5af", + "amount": "100000000000000" + }, + { + "address": "75204971b2ae461e5e989ad3733bf7c83be3580c", + "amount": "100000000000000" + }, + { + "address": "75304cb27016bd796a512070a5ddad6c22cbfa34", + "amount": "100000000000000" + }, + { + "address": "75404d484447585d4699de2133301894f7f0a0b9", + "amount": "100000000000000" + }, + { + "address": "75504f5535dd8986c8688946fc5f5580b7a8dd38", + "amount": "100000000000000" + }, + { + "address": "75604cd760a93f2f5286d8a7c24bcb17a6cbc4c2", + "amount": "100000000000000" + }, + { + "address": "757040f861c5d33d40d5cd88dbf9d494c344b2c3", + "amount": "100000000000000" + }, + { + "address": "758047bbc4e2ea7a59a65b82d83577abb225991d", + "amount": "100000000000000" + }, + { + "address": "7590432ee6c2f2e6c259b3d77337501615a5bf50", + "amount": "100000000000000" + }, + { + "address": "76004b9870bfe097f21d85c768a338502c3efd29", + "amount": "100000000000000" + }, + { + "address": "7610492a5a430b406f4f95c2c204d1a400b84ad8", + "amount": "100000000000000" + }, + { + "address": "76204cea7ee3fc87e957dd7dda7a70c949f26ccd", + "amount": "100000000000000" + }, + { + "address": "76304fc25e32600ba08528d168ca05e7d2010913", + "amount": "100000000000000" + }, + { + "address": "76404f703f4798300860345bf1ff81f0de6ffe8d", + "amount": "100000000000000" + }, + { + "address": "765045358ae8a44e3b1d7caa7f46c9b78ef724ef", + "amount": "100000000000000" + }, + { + "address": "7660435988f9ee112cbea0abf18e2e7ca419949c", + "amount": "100000000000000" + }, + { + "address": "76704fb154d0c3ab08652990fe69a940ed882c93", + "amount": "100000000000000" + }, + { + "address": "7680467f75f10cd807b0a27f7628269578a1c006", + "amount": "100000000000000" + }, + { + "address": "76904da84cd85eb2ec2ff690aeb4a7a1d648f413", + "amount": "100000000000000" + }, + { + "address": "7700458dc09f5383173182fde54f7b17935882c7", + "amount": "100000000000000" + }, + { + "address": "77104d3b0c4c656adba6d327c7b79f9ce8d94800", + "amount": "100000000000000" + }, + { + "address": "7720490fd89c46309eb4dc414e4b4fabf2a7fc57", + "amount": "100000000000000" + }, + { + "address": "77304d60249375837d59fe84b04ccc716ec30e68", + "amount": "100000000000000" + }, + { + "address": "774044dc674f47ff6d1b0dcd008aa4d86d53d245", + "amount": "100000000000000" + }, + { + "address": "77504d1b358a2fcbe5970628dde6e8ec705f76d8", + "amount": "100000000000000" + }, + { + "address": "7760402fe920bf6f4df37e081b3dfdc00954ff0f", + "amount": "100000000000000" + }, + { + "address": "777044ba8b3cc26d90da9f5a5f7863ef6c9d8c53", + "amount": "100000000000000" + }, + { + "address": "77804f8edbd62aa1d1e77d7834fbd817494d7e38", + "amount": "100000000000000" + }, + { + "address": "7790428083b35b7b088c2ac0e8113d3ccdc92eeb", + "amount": "100000000000000" + }, + { + "address": "78004e3cc37af45c0e372a37b2b08460b55bd775", + "amount": "100000000000000" + }, + { + "address": "7810493ae5c20904e6e8f2426e4d195ce0f1f3e5", + "amount": "100000000000000" + }, + { + "address": "78204a6682e722ba0a892960262eb1c9fda42ffb", + "amount": "100000000000000" + }, + { + "address": "78304b58974edd0eae39ef9c965f51eb16f2be03", + "amount": "100000000000000" + }, + { + "address": "78404c610ff998f92d9cc87b4ea1573cbd8f9339", + "amount": "100000000000000" + }, + { + "address": "78504ad330e8e41e81bf50082715f817d1a0a38d", + "amount": "100000000000000" + }, + { + "address": "78604f683cad2be47167a8b646128e1e84b277fa", + "amount": "100000000000000" + }, + { + "address": "78704013460b7c14c49d5d741326012cbe122bee", + "amount": "100000000000000" + }, + { + "address": "78804e1e31a15b13f264f7722db855f5677df70c", + "amount": "100000000000000" + }, + { + "address": "789046646c7fb2a2eb633c2e5e570af634b0238a", + "amount": "100000000000000" + }, + { + "address": "79004e3e7e74b663437a69c867216f047ad606dd", + "amount": "100000000000000" + }, + { + "address": "7910492ffe5550fb16f895bb7e8250a3d715771b", + "amount": "100000000000000" + }, + { + "address": "79204718fe2312b236ec58494a3e9b7f90c89e73", + "amount": "100000000000000" + }, + { + "address": "793048a8b77b03ecc7a3bc39d744f7d413559025", + "amount": "100000000000000" + }, + { + "address": "794041ee030eb5d43c58833fddf6f205f9a8c014", + "amount": "100000000000000" + }, + { + "address": "795049298725fffe87c4593dfbccb595e8791a3b", + "amount": "100000000000000" + }, + { + "address": "796048b394f862a92e5c8d9122c9ad5d485534eb", + "amount": "100000000000000" + }, + { + "address": "79704cbe24d2a5470953109554dc4ce56a2c84d7", + "amount": "100000000000000" + }, + { + "address": "79804beaba60ecb5eb2b77d4cdfdd1942b805f49", + "amount": "100000000000000" + }, + { + "address": "799045cfacb0e38a8d911fb39ff6397adc1f15eb", + "amount": "100000000000000" + }, + { + "address": "800040c36ade282fda9785c5e62213fe0d5d0312", + "amount": "100000000000000" + }, + { + "address": "801045faaed561eef624c2aca9076a2e66ed54e6", + "amount": "100000000000000" + }, + { + "address": "80204aea3fb91f7c90dee4ebcccec023908213f1", + "amount": "100000000000000" + }, + { + "address": "803046df6243205308bfe7259304a93a9637fed8", + "amount": "100000000000000" + }, + { + "address": "804040e821386c7eb980b981c07da31a9259e76c", + "amount": "100000000000000" + }, + { + "address": "805046b83fccfe43723e00bf5eb1dc058843c80f", + "amount": "100000000000000" + }, + { + "address": "806041951a05cf13b69d8067896675b584830d0e", + "amount": "100000000000000" + }, + { + "address": "80704002998850477f6640306c3c79f0970c5371", + "amount": "100000000000000" + }, + { + "address": "808043b8a07f468d3025ba172a6bc52d2b7523c3", + "amount": "100000000000000" + }, + { + "address": "80904548b7d57c71b2eb3de9d8dacbca8c3e20b6", + "amount": "100000000000000" + }, + { + "address": "8100497c04b5bc57d186afb7b4a15c34d29b8188", + "amount": "100000000000000" + }, + { + "address": "8110496672fbcaf610dcf186d0a1b484b228484c", + "amount": "100000000000000" + }, + { + "address": "81204469c77571ceabc193ec1c488a65bd08dc78", + "amount": "100000000000000" + }, + { + "address": "81304a805fa1d581378b31d9a0ea87e1973c44f4", + "amount": "100000000000000" + }, + { + "address": "8140425c4d8f0a3217c9ab13623270f3b992c00a", + "amount": "100000000000000" + }, + { + "address": "81504ddb923189b0e870a3b50ad910a3b5753f21", + "amount": "100000000000000" + }, + { + "address": "816042f0724b82005bff27112ce3a316e901e0f4", + "amount": "100000000000000" + }, + { + "address": "8170452c586b93dc1d7e514798fbe7850c2789dd", + "amount": "100000000000000" + }, + { + "address": "81804732d11fcee01a02cde6216a8e3edf0884a6", + "amount": "100000000000000" + }, + { + "address": "819040aa22f80c84c0977e463e0763579f1609f2", + "amount": "100000000000000" + }, + { + "address": "82004fe0e73638a8772bed9964d5323cc1c8cce3", + "amount": "100000000000000" + }, + { + "address": "821040ccec8c6129935e6a3f9bcf970948d55287", + "amount": "100000000000000" + }, + { + "address": "8220437ddde50e58b8327039bc6f457649d63a31", + "amount": "100000000000000" + }, + { + "address": "823042082e15aa436506c6379eeebd842c6313a3", + "amount": "100000000000000" + }, + { + "address": "82404388de5c42b260394efbd3ad4ccf708b9a25", + "amount": "100000000000000" + }, + { + "address": "82504a4f983dfba8d0c878a61b5276f011899158", + "amount": "100000000000000" + }, + { + "address": "8260482c4fbb5891e2dbbcb6a5c639b715473cae", + "amount": "100000000000000" + }, + { + "address": "827048d080883ae8876f0da515feb5772f64fcfb", + "amount": "100000000000000" + }, + { + "address": "828045fc2303b1afa7652f424b2c568c4c3d8256", + "amount": "100000000000000" + }, + { + "address": "829044583424c97871c023f9b4234cb5d468457a", + "amount": "100000000000000" + }, + { + "address": "830049dbb7faf8390c1f0cf4976ef1215c90b7e4", + "amount": "100000000000000" + }, + { + "address": "83104c657ae2e8aa2d9c89d9480ae55aa321b252", + "amount": "100000000000000" + }, + { + "address": "83204812d180c66f212ebdb89cde6606dad7b242", + "amount": "100000000000000" + }, + { + "address": "83304fa5b0481d15a160bca05e899edef8b602bf", + "amount": "100000000000000" + }, + { + "address": "834045a632211a9ebfd436d83dd178f2994473d8", + "amount": "100000000000000" + }, + { + "address": "8350444055dbbd40bde22e6455381e283f5b6b11", + "amount": "100000000000000" + }, + { + "address": "83604d5f7b6a9054c3fd0ba3f95459976b2547b7", + "amount": "100000000000000" + }, + { + "address": "837041d1c1fd6a43e2f8b03211a6b225cdd44976", + "amount": "100000000000000" + }, + { + "address": "8380491ed4a12cfa13893e74819e311bf7a12d8f", + "amount": "100000000000000" + }, + { + "address": "83904bed445a6e9c4a6852af272da17f588dc410", + "amount": "100000000000000" + }, + { + "address": "8400455d79ff6780de6c49bae8c55c2c31cb63f7", + "amount": "100000000000000" + }, + { + "address": "84104a221b2bfba81e26b6a23359ae58cc979a55", + "amount": "100000000000000" + }, + { + "address": "842043630e1449760a1b25087f5f50a9e373ffdb", + "amount": "100000000000000" + }, + { + "address": "843042a6e0926fe91a51698694b4b959a2de377f", + "amount": "100000000000000" + }, + { + "address": "844046b4a8c4600bd55d177e4d4ea4e89d0b4ded", + "amount": "100000000000000" + }, + { + "address": "845047eb2f2acc3b5c60bedb64a6565b048159df", + "amount": "100000000000000" + }, + { + "address": "84604b8cbdca589f843a841957b104862cbcb5d6", + "amount": "100000000000000" + }, + { + "address": "847042033cfd9f001a06ebcc2504901561f21da1", + "amount": "100000000000000" + }, + { + "address": "84804082583aec69e4607a22e72c60cb056116c5", + "amount": "100000000000000" + }, + { + "address": "849046dc53c92d02169ab2d4309cf0cd760c8dcd", + "amount": "100000000000000" + }, + { + "address": "85004fd156e059ccaaf4749ba2df7ba24de530a1", + "amount": "100000000000000" + }, + { + "address": "8510485f42a056460eb4f0291b0a72af35646d87", + "amount": "100000000000000" + }, + { + "address": "8520480dd3e656c0331952c265a78fdf8e3f5d49", + "amount": "100000000000000" + }, + { + "address": "85304ee06bac526cdc6a53500afbf91d0858c3eb", + "amount": "100000000000000" + }, + { + "address": "85404ecad2db6d6e414ef872827ab2edf811536b", + "amount": "100000000000000" + }, + { + "address": "85504fec36d0d6688d26af1f6fc345e76ade37d4", + "amount": "100000000000000" + }, + { + "address": "8560447acb6bc46cf04ec87b6c5bbb6b357454e3", + "amount": "100000000000000" + }, + { + "address": "857040fcce4a431006f9c552d01e77dfbe292bff", + "amount": "100000000000000" + }, + { + "address": "85804f279fe013dbaf2bdc210af86fc87946ebb3", + "amount": "100000000000000" + }, + { + "address": "8590479a8887c9215b9374410762e43753fd63b6", + "amount": "100000000000000" + }, + { + "address": "860040cc1341444b4b08675dea43a1ba2346e10d", + "amount": "100000000000000" + }, + { + "address": "861048828d752c8e69dfca134eee268d13a3ef80", + "amount": "100000000000000" + }, + { + "address": "86204cb5b528864a8266dfb08004c84f7ca846ac", + "amount": "100000000000000" + }, + { + "address": "86304ffd7c44f1c66931ca9cb36f77d82efaa839", + "amount": "100000000000000" + }, + { + "address": "86404e14d4fb029910caecf02ef989761e3297a0", + "amount": "100000000000000" + }, + { + "address": "8650494118a2ef12e07deccc0aa8c1a9c9875871", + "amount": "100000000000000" + }, + { + "address": "866046aa60688a43250cc2ed13fb0fc4ea146b44", + "amount": "100000000000000" + }, + { + "address": "8670497332aa6a185622948006adcfb226bcf22b", + "amount": "100000000000000" + }, + { + "address": "86804452bfbef5a5b6224b73fd94691234c09c44", + "amount": "100000000000000" + }, + { + "address": "86904613b2ba2159755abc593ccdeb1ce12fb64f", + "amount": "100000000000000" + }, + { + "address": "870049c927a4c40479b65b70f03ebfe68dcce4ee", + "amount": "100000000000000" + }, + { + "address": "87104e2b9fec39b3cfd27e3f236407b8c5dd21e7", + "amount": "100000000000000" + }, + { + "address": "872049d58d11e6d5dcf92492706a57700a3b9c78", + "amount": "100000000000000" + }, + { + "address": "87304b9b70b119da73715ea15e77df1c47dee9de", + "amount": "100000000000000" + }, + { + "address": "87404d313145fbffe1a60080426331dfbbccde88", + "amount": "100000000000000" + }, + { + "address": "8750482f002575a5b05b23a4a2fe81e72a85903e", + "amount": "100000000000000" + }, + { + "address": "876040e63de214d3d97c41c5e2506835356febfd", + "amount": "100000000000000" + }, + { + "address": "8770403d44ac830ef4d787674be73fc60487e6b9", + "amount": "100000000000000" + }, + { + "address": "878046336c193431737bce3b3f7bb59fb560a306", + "amount": "100000000000000" + }, + { + "address": "8790470a45f434b064286df6716cf56884abe0d2", + "amount": "100000000000000" + }, + { + "address": "880040754a3c36b9c6dd10b7cb3eb6540d047a3f", + "amount": "100000000000000" + }, + { + "address": "8810480c4bcd788ad9e5b72667d82c42946815a3", + "amount": "100000000000000" + }, + { + "address": "882046a981d4f3fbe823cc786031162553a8e0dd", + "amount": "100000000000000" + }, + { + "address": "8830406539e2484ac4c47a6812ae758d79221c59", + "amount": "100000000000000" + }, + { + "address": "8840415de6febc6c8eff4f6a9ca2c980bdb37343", + "amount": "100000000000000" + }, + { + "address": "8850467d1d836e07f22fd0d11d127a868c568b3d", + "amount": "100000000000000" + }, + { + "address": "8860473aabc1e8c3d6e68eca590113fc9a6e18a8", + "amount": "100000000000000" + }, + { + "address": "88704d73662804ac9d280bbbf7c829b8bb44eed9", + "amount": "100000000000000" + }, + { + "address": "88804d3c7e71be9145c486df8c5e3f50fe3d585e", + "amount": "100000000000000" + }, + { + "address": "88904f29e996fe348e2e08e436d62bcfe2ab43d4", + "amount": "100000000000000" + }, + { + "address": "89004a83edbdb171fb10d403fc12f61712713dc3", + "amount": "100000000000000" + }, + { + "address": "89104c7c4650b47edcd89027f02b869b288a4233", + "amount": "100000000000000" + }, + { + "address": "89204680d0b82eb5d0a7cd38cc79303fb08c0a39", + "amount": "100000000000000" + }, + { + "address": "89304a88a2c22402b132a03b79207edfc1d53521", + "amount": "100000000000000" + }, + { + "address": "89404525c0cdadfbc8254978cbd47c3f730f6061", + "amount": "100000000000000" + }, + { + "address": "89504de91c02f4fc3514641bd2582d5a43450e67", + "amount": "100000000000000" + }, + { + "address": "89604969d23518afac4fc4b2b49cb827dea90cb4", + "amount": "100000000000000" + }, + { + "address": "897049b15315f7b4a8ec4ffef90d0db4b15fad05", + "amount": "100000000000000" + }, + { + "address": "89804e7a03a222cd2042f671f17fdb4e7b89c70b", + "amount": "100000000000000" + }, + { + "address": "8990454279c9296f15f4b9027b7ede5e875ff7ba", + "amount": "100000000000000" + }, + { + "address": "9000472babb942be176fa7c342ddb562bfc17993", + "amount": "100000000000000" + }, + { + "address": "90104d03cea867215a2f79d6b1b42fd286a2372c", + "amount": "100000000000000" + }, + { + "address": "90204df1a7d64dd87c3a2ab0e790f66ab7a078da", + "amount": "100000000000000" + }, + { + "address": "90304de617a78d7b8f131deafef6c56c60b1e157", + "amount": "100000000000000" + }, + { + "address": "90404100b1b6572b8f50e7eeab9f43c410b79bda", + "amount": "100000000000000" + }, + { + "address": "905040be7d14a7f3ecf1062254649069e5df7795", + "amount": "100000000000000" + }, + { + "address": "906042c145bb61505e6e03c8e8f0ead7506d9e14", + "amount": "100000000000000" + }, + { + "address": "90704b50a773c5ae28e867d9af6915d1a5f05b41", + "amount": "100000000000000" + }, + { + "address": "9080431cc7d962dc0df5bfa76c05c2988f7c7588", + "amount": "100000000000000" + }, + { + "address": "90904758c69a7bf7db7c018ab62672c854494f98", + "amount": "100000000000000" + }, + { + "address": "91004b7156b7f06c1df3d652361b0236b656f54c", + "amount": "100000000000000" + }, + { + "address": "91104d6aeccb5e420df5a2031b309d57f9c30af7", + "amount": "100000000000000" + }, + { + "address": "912042f7dbb1b21e5807ef53706b5a66321e65e9", + "amount": "100000000000000" + }, + { + "address": "91304671b71c2a3d12eb6d51a921509aa781f853", + "amount": "100000000000000" + }, + { + "address": "9140499d47cd284a1817d1a431eccb6c6f3897d6", + "amount": "100000000000000" + }, + { + "address": "91504815a6df26c9a3e142ee6b0509a30b258d64", + "amount": "100000000000000" + }, + { + "address": "91604800d1329fde56d1cab995ea32698b0ea48d", + "amount": "100000000000000" + }, + { + "address": "917043c3f9ccc184acb6bdebf3c7c8d1e6272d3b", + "amount": "100000000000000" + }, + { + "address": "91804ba18ce38f7c37d19530bcf0a2d08d601ebb", + "amount": "100000000000000" + }, + { + "address": "919042fc90de9cb87c320fd7ce0dfbde484d2915", + "amount": "100000000000000" + }, + { + "address": "920041940cd8a4e6fe691bac5cf316b5fd83dc85", + "amount": "100000000000000" + }, + { + "address": "92104bc1a3533ca7b034928f7c44ffebfb5669ae", + "amount": "100000000000000" + }, + { + "address": "92204b0945978912b9798859599b6a8879904dbf", + "amount": "100000000000000" + }, + { + "address": "923046ed4b42686dd841059917c2a82a19b4eae7", + "amount": "100000000000000" + }, + { + "address": "92404fdc369b099b3ba39551010a0ae267b8a0d3", + "amount": "100000000000000" + }, + { + "address": "92504a904a7a49ddc5c347704f5cf641538a683b", + "amount": "100000000000000" + }, + { + "address": "9260415480d030341a78cac35928b1d58ead468c", + "amount": "100000000000000" + }, + { + "address": "92704b20d56a52096c96853682d497809ac8a644", + "amount": "100000000000000" + }, + { + "address": "9280414564c13d52995b5c97a1edbbbe9398fd79", + "amount": "100000000000000" + }, + { + "address": "929048ae6f99b502d1e8d8659c06311fa023a37c", + "amount": "100000000000000" + }, + { + "address": "9300459038aca9253f485af17189d4d761ee16cf", + "amount": "100000000000000" + }, + { + "address": "93104dce3896e7013ec4b4373bc037ea34a9024d", + "amount": "100000000000000" + }, + { + "address": "932041772f90a64f76fd8d088179fa812f00d4e9", + "amount": "100000000000000" + }, + { + "address": "93304ed9b8185ce822360967447c164425f8ee85", + "amount": "100000000000000" + }, + { + "address": "9340469f9aa3259a2d941f668f33c1352177b431", + "amount": "100000000000000" + }, + { + "address": "9350424afed2719af57946f261e28bc536b2e670", + "amount": "100000000000000" + }, + { + "address": "93604fed35670e2a5b9bb9664ec5dd2a8df8622b", + "amount": "100000000000000" + }, + { + "address": "937044aca7e544f4f3bf390c72a528139d99570c", + "amount": "100000000000000" + }, + { + "address": "93804c365ad48f71d5feb09fb369bf71752d01f8", + "amount": "100000000000000" + }, + { + "address": "93904e6c56c737ad30ba95ee3c035ca50949a241", + "amount": "100000000000000" + }, + { + "address": "94004b81cc9f530a41b173cbe610855a0d6d64a6", + "amount": "100000000000000" + }, + { + "address": "94104967e8765b059887acc9163afd1c92bdc67f", + "amount": "100000000000000" + }, + { + "address": "94204f7637a290288069f8fa685ffdf25e1c869b", + "amount": "100000000000000" + }, + { + "address": "94304ac0c080d0a89071c616fb302379149c1b00", + "amount": "100000000000000" + }, + { + "address": "944040b51cc1b8aa4c279f762407603bcd881009", + "amount": "100000000000000" + }, + { + "address": "94504f83b51f1202cc792f8176206fb097df6012", + "amount": "100000000000000" + }, + { + "address": "946049033f9aee708411907b949654ff26b51a01", + "amount": "100000000000000" + }, + { + "address": "947041d06386084692a7c08c411407542a5f079f", + "amount": "100000000000000" + }, + { + "address": "94804f75beec2ab62c24a467dc8458052cf2d4e7", + "amount": "100000000000000" + }, + { + "address": "94904c195c64f1954eec679246d71220aa633e38", + "amount": "100000000000000" + }, + { + "address": "950040d8f3b3c16d8d5f3ebffe1a9d11bc7983e4", + "amount": "100000000000000" + }, + { + "address": "951041e30df6b7a32cb3e6d01ab859350082e095", + "amount": "100000000000000" + }, + { + "address": "952040329c551f70a521d7b61ca958e97303fc60", + "amount": "100000000000000" + }, + { + "address": "9530473f409d364affc33a63894c33404885e7c0", + "amount": "100000000000000" + }, + { + "address": "954041a001bd70a0484f3dfba6d53ae29537b9e5", + "amount": "100000000000000" + }, + { + "address": "95504bcf8b4777e0d8f4525064fa1b8546d851e8", + "amount": "100000000000000" + }, + { + "address": "95604254b548a7eb21d62929878bd1f42e768309", + "amount": "100000000000000" + }, + { + "address": "95704d45620fc4506f2a1448f6ea83d342c0b70f", + "amount": "100000000000000" + }, + { + "address": "9580450e47feb1931fc507b6fb946df04788a775", + "amount": "100000000000000" + }, + { + "address": "95904789595b1d1b9e580a52a61bd88ebf642bd2", + "amount": "100000000000000" + }, + { + "address": "96004a53c3c0bd200f6bdf8201e32bcbc97d6edf", + "amount": "100000000000000" + }, + { + "address": "96104842c185e35bfb61d5e3525531c4c68338d6", + "amount": "100000000000000" + }, + { + "address": "96204d23d73724fef1f217b9fa3629217aa78809", + "amount": "100000000000000" + }, + { + "address": "963048f029d166e675e52ac472c42fc460c51bee", + "amount": "100000000000000" + }, + { + "address": "96404e241e8ef28dc1642212be0473121bb69d24", + "amount": "100000000000000" + }, + { + "address": "96504a7b7433313702b495ab5be6b1c35f56bf17", + "amount": "100000000000000" + }, + { + "address": "96604e53196b5ccd5bda81a0235b2ff333345125", + "amount": "100000000000000" + }, + { + "address": "96704cb4c16eb1b841def729e92d8810157ce797", + "amount": "100000000000000" + }, + { + "address": "96804c0924ca87184e536e121e37e8533b318afe", + "amount": "100000000000000" + }, + { + "address": "96904e717839fd6445721e2cd9e9a14ef582919a", + "amount": "100000000000000" + }, + { + "address": "97004e3db06153e5e97c715eeedb466503ecaaec", + "amount": "100000000000000" + }, + { + "address": "97104aac1f2575cc78a5b70baaacdf0e05bf6f59", + "amount": "100000000000000" + }, + { + "address": "972049d3284c1db53a587a14ea24dff292257dd6", + "amount": "100000000000000" + }, + { + "address": "97304900781cec2ebcf1cde90ae1b08188cbc524", + "amount": "100000000000000" + }, + { + "address": "974041c53c33cc1e80534299bdaee9ba4595e6e4", + "amount": "100000000000000" + }, + { + "address": "97504ece3e7fc1dbf05d50ccae734b467caa84df", + "amount": "100000000000000" + }, + { + "address": "976044c4c2e66323bbb761f7aa1706096c9d16ec", + "amount": "100000000000000" + }, + { + "address": "97704be19df706440b2d080f50b6eb4a2bcc3c18", + "amount": "100000000000000" + }, + { + "address": "978049e7b1deb4d01f7bc0c471662d41f48a956b", + "amount": "100000000000000" + }, + { + "address": "979045ffe3a861016ce74427be6932047b59ecf7", + "amount": "100000000000000" + }, + { + "address": "98004645f52f575c3a48964e125522ee9042f775", + "amount": "100000000000000" + }, + { + "address": "981049acf75d47ad897a9971c8f93e01ee0c1723", + "amount": "100000000000000" + }, + { + "address": "982046598e03d4d845ebb540300fb2ce2f162edd", + "amount": "100000000000000" + }, + { + "address": "983048ad983e11741528bee423f0e848470bad88", + "amount": "100000000000000" + }, + { + "address": "98404d93b2fcc92eedb881c5ca5ca99d8c61baa0", + "amount": "100000000000000" + }, + { + "address": "98504ce8ea23a9d38d7785c4b9301b5afe50ecdd", + "amount": "100000000000000" + }, + { + "address": "9860440db2910abdc6e66cb518b0b74555dd3539", + "amount": "100000000000000" + }, + { + "address": "98704f188f7c760c770eb1d70c02c3359ebea0d8", + "amount": "100000000000000" + }, + { + "address": "988044c4f6178a2b15ba22ce33ee4237b35b2d60", + "amount": "100000000000000" + }, + { + "address": "989044cff1ca7843552d2fcb8e541d5d2758f0ea", + "amount": "100000000000000" + }, + { + "address": "99004fc2c160910cb7fbd45c12ee54d986550b2a", + "amount": "100000000000000" + }, + { + "address": "991048998cc29362fb3b02f7d1a841267d025923", + "amount": "100000000000000" + }, + { + "address": "9920407f43c58aaa2458d7b091db49952103078f", + "amount": "100000000000000" + }, + { + "address": "9930413e8582369bc426882f61035e35d3ca69be", + "amount": "100000000000000" + }, + { + "address": "9940420c941d4fd60b0e3a23b52ca286dc6419e4", + "amount": "100000000000000" + }, + { + "address": "99504389bd1994b88e183d558eb7eb99b949b3d3", + "amount": "100000000000000" + }, + { + "address": "99604af6e8ab294dc5b37cc6fb271b723d14d366", + "amount": "100000000000000" + }, + { + "address": "997045e7f9933b1a86d152b772d2088ef862b877", + "amount": "100000000000000" + }, + { + "address": "998040588ade5ee3d6cd2cce7467ae10cbe39898", + "amount": "100000000000000" + }, + { + "address": "99904de562388ac3ff20f477b2efe679d2ae82d0", + "amount": "100000000000000" } ], "pools": [ diff --git a/build/deployments/docker-compose.yaml b/build/deployments/docker-compose.yaml index 750043f2a..51b9013c0 100755 --- a/build/deployments/docker-compose.yaml +++ b/build/deployments/docker-compose.yaml @@ -1,5 +1,7 @@ version: "3.8" +name: pocket-v1 + # Make sure you have the loki driver installed. If not, just run `make docker_loki_install` x-loki: &loki-logging driver: loki @@ -17,6 +19,9 @@ services: build: context: ../.. dockerfile: ./build/Dockerfile.client + environment: + # Any host that is visible and connected to the cluster can be arbitrarily selected as the RPC host + - RPC_HOST=node1.consensus volumes: - ${PWD}:/go/src/github.com/pocket-network stdin_open: true diff --git a/build/docs/CHANGELOG.md b/build/docs/CHANGELOG.md index aa13f5e16..6b68e5e34 100644 --- a/build/docs/CHANGELOG.md +++ b/build/docs/CHANGELOG.md @@ -7,7 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.0.0.15] - 2023-02-16 +## [0.0.0.16] - 2023-02-16 + +- Updated genesis to include accounts for all the validators that we can use in LocalNet based on the pre-generated keys in `build/localnet/manifests/private-keys.yaml` +- Updated `docker-compose` to name the deployment as `pocket-v1` instead of `deployments` (default is the containing folder name) +- Introduced the `cluster-manager`, which is a standalone microservice in the K8S LocalNet that takes care of (for now) automatically staking/unstaking nodes that are added/removed from the deployment +- Updated manifests and K8S resources to reflect the new `cluster-manager` addition +- In K8S LocalNet, the `cli-client` now waits for `v1-validator001` since its required for address book sourcing + +## [0.0.0.15] - 2023-02-15 - Added manifests to handle `Roles`, `RoleBindings` and `ServiceAccounts` and referenced them in the `Tiltfile` - Updated `cli-client.yaml` to bind the `debug-client-account` `ServiceAccount` that has permissions to read the private keys from the `Secret` diff --git a/build/localnet/Tiltfile b/build/localnet/Tiltfile index 71fece984..e682fa4d2 100644 --- a/build/localnet/Tiltfile +++ b/build/localnet/Tiltfile @@ -27,6 +27,7 @@ if (localnet_config_file != localnet_config) or ( # CONSIDERATION: This can potentially can be replaced with a list of excluded directories. deps = [ "app", + "build/localnet", "consensus", "p2p", "persistance", @@ -46,14 +47,19 @@ helm_repo( "grafana", "https://grafana.github.io/helm-charts", resource_name="helm-repo-grafana", + labels=["helm"] ) helm_repo( "prometheus-community", "https://prometheus-community.github.io/helm-charts", resource_name="helm-repo-prometheus", + labels=["helm"] ) helm_repo( - "bitnami", "https://charts.bitnami.com/bitnami", resource_name="helm-repo-bitnami" + "bitnami", + "https://charts.bitnami.com/bitnami", + resource_name="helm-repo-bitnami", + labels=["helm"] ) # Avoid downloading dependencies if no missing/outdated charts @@ -65,6 +71,16 @@ if helm_dependencies_not_ok_count > 1: local("helm dependency update dependencies") k8s_yaml(helm("dependencies", name="dependencies", namespace="default")) +k8s_resource("dependencies-prometheus-pushgateway", labels=["monitoring"]) +k8s_resource("dependencies-loki", labels=["monitoring"]) +k8s_resource("dependencies-prometheus-node-exporter", labels=["monitoring"]) +k8s_resource("dependencies-prometheus-alertmanager", labels=["monitoring"]) +k8s_resource("dependencies-postgresql", labels=["database"]) +k8s_resource("dependencies-grafana", labels=["monitoring"]) +k8s_resource("dependencies-kube-state-metrics", labels=["monitoring"]) +k8s_resource("dependencies-promtail", labels=["monitoring"]) +k8s_resource("dependencies-prometheus-server", labels=["monitoring"]) + # Builds the pocket binary. Note target OS is linux, because no matter what your OS is, container runs linux natively or in VM. local_resource( @@ -73,6 +89,7 @@ local_resource( root_dir=root_dir ), deps=deps_full_path, + labels=['watchers'] ) local_resource( "debug client: Watch & Compile", @@ -80,6 +97,16 @@ local_resource( root_dir=root_dir ), deps=deps_full_path, + labels=['watchers'] +) +# Builds the cluster manager binary +local_resource( + 'cluster manager: Watch & Compile', + 'GOOS=linux go build -o {root_dir}/bin/cluster-manager {root_dir}/build/localnet/cluster-manager/*.go'.format( + root_dir=root_dir + ), + deps=deps_full_path, + labels=['watchers'] ) # Builds and maintains the validator container image after the binary is built on local machine, restarts a process on code change @@ -112,17 +139,42 @@ COPY bin/client-linux /usr/local/bin/client live_update=[sync("bin/client-linux", "/usr/local/bin/client")], ) +# Builds and maintains the cluster-manager container image after the binary is built on local machine +docker_build_with_restart( + "cluster-manager-image", + root_dir, + dockerfile_contents="""FROM debian:bullseye +WORKDIR / +COPY bin/cluster-manager /usr/local/bin/cluster-manager +COPY bin/client-linux /usr/local/bin/client +""", + only=['bin/cluster-manager', 'bin/client-linux'], + entrypoint=["/usr/local/bin/cluster-manager"], + live_update=[ + sync("bin/cluster-manager", "/usr/local/bin/cluster-manager"), + sync("bin/client-linux", "/usr/local/bin/client"), + ] +) + # TODO: https://github.com/tilt-dev/tilt/issues/3048 # Pushes localnet manifests to the cluster. k8s_yaml( [ "manifests/private-keys.yaml", "manifests/configs.yaml", - "manifests/cli-client.yaml", "manifests/network.yaml", "manifests/roles.yaml", "manifests/service-accounts.yaml", "manifests/role-bindings.yaml", + ] +) + +k8s_yaml(["manifests/cli-client.yaml"]) +k8s_resource('pocket-v1-cli-client', labels=['client']) +k8s_yaml(['manifests/cluster-manager.yaml']) +k8s_resource('pocket-v1-cluster-manager', labels=['cluster-manager']) +k8s_yaml( + [ local( "templates/v1-validator-template.sh %s" % localnet_config["validators"]["count"], @@ -131,6 +183,7 @@ k8s_yaml( ] ) + # Uncomment in order to expose postgres port to 5432 on the host machine in case the developer wants to connect to postgres directly # First port is the port on the host machine, second is the port on the container, so if you already have postgres running on the host machine, you can change the first port to something else # k8s_resource(new_name='postgres', @@ -143,4 +196,5 @@ k8s_resource( workload="dependencies-grafana", extra_pod_selectors=[{"app.kubernetes.io/name": "grafana"}], port_forwards=["42000:3000"], + labels=["monitoring"] ) diff --git a/build/localnet/cluster-manager/main.go b/build/localnet/cluster-manager/main.go new file mode 100644 index 000000000..9784fa252 --- /dev/null +++ b/build/localnet/cluster-manager/main.go @@ -0,0 +1,130 @@ +package main + +import ( + "context" + "fmt" + "os" + "os/exec" + "strings" + + "github.com/pokt-network/pocket/logger" + "github.com/pokt-network/pocket/runtime" + "github.com/pokt-network/pocket/runtime/defaults" + "github.com/pokt-network/pocket/shared/crypto" + "github.com/pokt-network/pocket/shared/k8s" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +const cliPath = "/usr/local/bin/client" + +var ( + rpcUrl string + log = logger.Global.CreateLoggerForModule("cluster-manager") +) + +func init() { + rpcUrl = fmt.Sprintf("http://%s:%s", runtime.GetEnv("RPC_HOST", "v1-validator001"), defaults.DefaultRPCPort) +} + +func main() { + config, err := rest.InClusterConfig() + if err != nil { + panic(err.Error()) + } + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + panic(err.Error()) + } + + validatorKeysMap, err := k8s.FetchValidatorPrivateKeys(clientset) + if err != nil { + panic(err) + } + + watcher, err := clientset.CoreV1().Services("default").Watch(context.TODO(), metav1.ListOptions{}) + if err != nil { + panic(err) + } + + for event := range watcher.ResultChan() { + service, ok := event.Object.(*v1.Service) + if !ok { + continue + } + + if !isValidator(service) { + continue + } + + validatorId := extractValidatorId(service.Name) + privateKey := getPrivateKey(validatorKeysMap, validatorId) + + switch event.Type { + case watch.Added: + log.Info().Str("validator", service.Name).Msg("Validator added to the cluster") + if err := stakeValidator(privateKey, "150000000001", []string{"0001"}, fmt.Sprintf("v1-validator%s:8080", validatorId)); err != nil { + log.Err(err).Msg("Error staking validator") + } + case watch.Deleted: + log.Info().Str("validator", service.Name).Msg("Validator deleted from the cluster") + if err := unstakeValidator(privateKey); err != nil { + log.Err(err).Msg("Error unstaking validator") + } + } + } +} + +func stakeValidator(pk crypto.PrivateKey, amount string, chains []string, serviceURL string) error { + log.Info().Str("address", pk.Address().String()).Msg("Staking Validator") + if err := os.WriteFile("./pk.json", []byte("\""+pk.String()+"\""), 0o600); err != nil { + return err + } + + args := []string{ + "--non_interactive=true", + "--remote_cli_url=" + rpcUrl, + "Validator", + "Stake", + pk.Address().String(), + amount, + strings.Join(chains, ","), + serviceURL, + } + log.Debug().Str("command", cliPath+" "+strings.Join(args, " ")).Msg("Invoking CLI") + + //nolint:gosec // G204 Dogfooding CLI + out, err := exec.Command(cliPath, args...).CombinedOutput() + log.Info().Str("output", string(out)).Msg("CLI command") + if err != nil { + return err + } + return nil +} + +func unstakeValidator(pk crypto.PrivateKey) error { + log.Info().Str("address", pk.Address().String()).Msg("Unstaking Validator") + if err := os.WriteFile("./pk.json", []byte("\""+pk.String()+"\""), 0o600); err != nil { + return err + } + + args := []string{ + "--non_interactive=true", + "--remote_cli_url=" + rpcUrl, + "Validator", + "Unstake", + pk.Address().String(), + } + log.Debug().Str("command", cliPath+" "+strings.Join(args, " ")).Msg("Invoking CLI") + + //nolint:gosec // G204 Dogfooding CLI + out, err := exec.Command(cliPath, args...).CombinedOutput() + log.Info().Str("output", string(out)).Msg("CLI command") + if err != nil { + return err + } + return nil +} diff --git a/build/localnet/cluster-manager/utils.go b/build/localnet/cluster-manager/utils.go new file mode 100644 index 000000000..b1643840e --- /dev/null +++ b/build/localnet/cluster-manager/utils.go @@ -0,0 +1,31 @@ +package main + +import ( + cryptoPocket "github.com/pokt-network/pocket/shared/crypto" + v1 "k8s.io/api/core/v1" +) + +func isValidator(service *v1.Service) bool { + return service.Labels["v1-purpose"] == "validator" +} + +func extractValidatorId(validatorName string) string { + if len(validatorName) >= 3 { + return validatorName[len(validatorName)-3:] + } + return validatorName +} + +func getPrivateKey(validatorKeysMap map[string]string, validatorId string) cryptoPocket.PrivateKey { + privHexString := validatorKeysMap[validatorId] + keyPair, err := cryptoPocket.CreateNewKeyFromString(privHexString, "", "") + if err != nil { + panic(err) + } + + privateKey, err := keyPair.Unarmour("") + if err != nil { + log.Err(err).Msg("Error unarmouring private key") + } + return privateKey +} diff --git a/build/localnet/manifests/cli-client.yaml b/build/localnet/manifests/cli-client.yaml index 730c34d59..f848b4a5b 100644 --- a/build/localnet/manifests/cli-client.yaml +++ b/build/localnet/manifests/cli-client.yaml @@ -16,6 +16,15 @@ spec: app: v1-cli-client spec: serviceAccountName: debug-client-account + initContainers: + - name: wait-for-v1-validator001 + image: busybox + command: + [ + "sh", + "-c", + "until nc -z v1-validator001 8080; do echo waiting for v1-validator001...; sleep 2; done;", + ] containers: - name: pocket image: client-image @@ -57,6 +66,9 @@ spec: value: "postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@$(POSTGRES_HOST):$(POSTGRES_PORT)/$(POSTGRES_DB)" - name: POCKET_PERSISTENCE_NODE_SCHEMA value: validator1 + # Any host that is visible and connected to the cluster can be arbitrarily selected as the RPC host + - name: RPC_HOST + value: v1-validator001 volumeMounts: - mountPath: /var/pocket/config name: config-volume diff --git a/build/localnet/manifests/cluster-manager.yaml b/build/localnet/manifests/cluster-manager.yaml new file mode 100644 index 000000000..31845897e --- /dev/null +++ b/build/localnet/manifests/cluster-manager.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: pocket-v1-cluster-manager +spec: + initContainers: + - name: wait-for-v1-validator001 + image: busybox + command: + [ + "sh", + "-c", + "until nc -z v1-validator001 8080; do echo waiting for v1-validator001...; sleep 2; done;", + ] + containers: + - name: cluster-manager + image: cluster-manager-image + imagePullPolicy: IfNotPresent + args: + - cluster-manager + serviceAccountName: cluster-manager-account diff --git a/build/localnet/manifests/configs.yaml b/build/localnet/manifests/configs.yaml index 747c205df..2b555be35 100644 --- a/build/localnet/manifests/configs.yaml +++ b/build/localnet/manifests/configs.yaml @@ -89,6 +89,3986 @@ data: { "address": "88a792b7aca673620132ef01f50e62caa58eca83", "amount": "100000000000000" + }, + { + "address": "00504987d4b181c1e97b1da9af42f3db733b1ff4", + "amount": "100000000000000" + }, + { + "address": "00604d18001a2012830b93efcc23100450e5a512", + "amount": "100000000000000" + }, + { + "address": "007046b27ad5c49969d585dd3f4f7d1e4b94a42f", + "amount": "100000000000000" + }, + { + "address": "00804475b3c75e0fb86c88d937c7753f8cab8ba8", + "amount": "100000000000000" + }, + { + "address": "0090433ae78b5539c564134809502f699c90b009", + "amount": "100000000000000" + }, + { + "address": "0100471d6796652244885d1943ea7c13e3fce90b", + "amount": "100000000000000" + }, + { + "address": "011044141a86efafeae5ecc2c6290f0894072ab7", + "amount": "100000000000000" + }, + { + "address": "01204ed35af2bbef5d4db0aeedf3a9a8958c3296", + "amount": "100000000000000" + }, + { + "address": "0130404d6a39bf7cdc14ef4be4a0910f170edd1e", + "amount": "100000000000000" + }, + { + "address": "0140481810379d6e970f5b7de3220b70a784efd5", + "amount": "100000000000000" + }, + { + "address": "01504aedb93b489402d5aa654a5c6bda01880a5f", + "amount": "100000000000000" + }, + { + "address": "0160401ddec40b7a2dbc8505e4a9e998c22604b0", + "amount": "100000000000000" + }, + { + "address": "0170495866953b63cc9ba01c141dd8be029773bb", + "amount": "100000000000000" + }, + { + "address": "01804d0db5be444aeb1a114469a4ff7eb09c91db", + "amount": "100000000000000" + }, + { + "address": "01904e5651efaafb1a557d8f61034a4edfe0fa05", + "amount": "100000000000000" + }, + { + "address": "02004e81a4ee21929a399504fd0d946c545e7a2c", + "amount": "100000000000000" + }, + { + "address": "0210494fbd4b214dd6209d33b3fc960660c9f82b", + "amount": "100000000000000" + }, + { + "address": "0220406b71d941b5b9fc73a53d08ecb09c866b10", + "amount": "100000000000000" + }, + { + "address": "023041ae1ee33ad8db492951c13393b9bb59d59b", + "amount": "100000000000000" + }, + { + "address": "024041957fc3ac22552239b75d384f141f48430b", + "amount": "100000000000000" + }, + { + "address": "025045f51c4c956e2d822e6fd3f706957a5649fe", + "amount": "100000000000000" + }, + { + "address": "02604fcd21020ff140f6da784012e68d7f72ff36", + "amount": "100000000000000" + }, + { + "address": "0270460c5775e8951e5d43b3b37dc310209afda6", + "amount": "100000000000000" + }, + { + "address": "02804033a62cf08a2074cbffe941bd019576d5ed", + "amount": "100000000000000" + }, + { + "address": "0290479bfdf5210b7541b37b551716662a2ff397", + "amount": "100000000000000" + }, + { + "address": "03004511b4ca2d30b7e8bc008a4dc53588115fb0", + "amount": "100000000000000" + }, + { + "address": "031048ce3cef36af346cffc464dc5611028cc46f", + "amount": "100000000000000" + }, + { + "address": "03204ac71039cd18d1a23b76042c5c43c4dc1053", + "amount": "100000000000000" + }, + { + "address": "03304961130710e8984124354aa55eef028ad7d9", + "amount": "100000000000000" + }, + { + "address": "03404334ac8195996d072c916805dd26d82d9b0a", + "amount": "100000000000000" + }, + { + "address": "03504f415b35148ef268a37a7bdd5cbe41c46b62", + "amount": "100000000000000" + }, + { + "address": "0360444233608b747b82c9a651526171e0cecb09", + "amount": "100000000000000" + }, + { + "address": "037041d2ebb680f8e617c1d8bd4397114ed91d7a", + "amount": "100000000000000" + }, + { + "address": "03804e19cca9f5d8d074d3f0a60f1096723dad31", + "amount": "100000000000000" + }, + { + "address": "039044952cacd6fe9eed091c8b5b85c6e758d9ff", + "amount": "100000000000000" + }, + { + "address": "04004e7265815d837bac198381b1b3e70275319e", + "amount": "100000000000000" + }, + { + "address": "04104e28743787af30fdc85123b2ec763aca309c", + "amount": "100000000000000" + }, + { + "address": "042047946bbe90534f6940b3fa2aef34fa8f68c4", + "amount": "100000000000000" + }, + { + "address": "04304a7f8c6f59737bf2f6955745677351ad65bd", + "amount": "100000000000000" + }, + { + "address": "04404de47d3b8b90f533da541a6b9cd4b162cbdb", + "amount": "100000000000000" + }, + { + "address": "04504f18acbfe31c7f671a9986a499e74cd83b87", + "amount": "100000000000000" + }, + { + "address": "046047e21a2b35c94b8e25b39a8e11e088bdcc20", + "amount": "100000000000000" + }, + { + "address": "04704eff8a68e2d520bc9d4781a1328beb4a07fd", + "amount": "100000000000000" + }, + { + "address": "04804319d93a5aae6d6932e6255afa52ff9b81ad", + "amount": "100000000000000" + }, + { + "address": "0490494bc3baea23832c354eae4472d5ca97302f", + "amount": "100000000000000" + }, + { + "address": "05004facba0b2a253bab657f428338918d081158", + "amount": "100000000000000" + }, + { + "address": "0510462d8d3fbc0a5690e68507a49809f70afac4", + "amount": "100000000000000" + }, + { + "address": "05204497fa5d1cd636ec08c1e557aad11356ffdb", + "amount": "100000000000000" + }, + { + "address": "05304bebf8de8dd3333067868402df0a855cfc26", + "amount": "100000000000000" + }, + { + "address": "054041a4f8f82ae6cdc43ae50c621cbc73a74cba", + "amount": "100000000000000" + }, + { + "address": "055047122515c7448c7eb18b249e0bd390fe017b", + "amount": "100000000000000" + }, + { + "address": "056047aa21bce308658b7ff6ed0d87356de06220", + "amount": "100000000000000" + }, + { + "address": "05704c960137bbb6c9421a77e03671a334211ec5", + "amount": "100000000000000" + }, + { + "address": "058045f9c98e9fd506e5025797b34302fbaf85e3", + "amount": "100000000000000" + }, + { + "address": "05904f94b885d875f0fe6af3185a5936518b40f5", + "amount": "100000000000000" + }, + { + "address": "06004ef2c3c4979e68257b4bff94471e570b1cab", + "amount": "100000000000000" + }, + { + "address": "0610473810cd99f9ef4e72613cf5e93fcf942b12", + "amount": "100000000000000" + }, + { + "address": "0620415cc31eef8492058687df20c86b6e228bb2", + "amount": "100000000000000" + }, + { + "address": "06304edd5eb38af2ddc8555e94678ac6ab7a0a5c", + "amount": "100000000000000" + }, + { + "address": "06404246818eada50a3335e9c7e7eb142ee6709b", + "amount": "100000000000000" + }, + { + "address": "06504c11e6b449679278529efebf00ed4c1098b2", + "amount": "100000000000000" + }, + { + "address": "06604cea653df828010889eaa56f4ff867a17881", + "amount": "100000000000000" + }, + { + "address": "067044f84aa72577dc88b9813ee081dd6235905c", + "amount": "100000000000000" + }, + { + "address": "06804ac8b703a6500ba70f36a725bc55ecbe4bbc", + "amount": "100000000000000" + }, + { + "address": "06904f896ddabf920e559954efcb468e85e351d5", + "amount": "100000000000000" + }, + { + "address": "070043cc01e70228d252b4df847c4724813f6176", + "amount": "100000000000000" + }, + { + "address": "07104b360ef5589bb8b49a7e2c3e2fa03363a059", + "amount": "100000000000000" + }, + { + "address": "072048359ff76f59da57342b93dd4cfdd42662c2", + "amount": "100000000000000" + }, + { + "address": "07304f2af4afd31973cfbd0cae5a74722ba4fd14", + "amount": "100000000000000" + }, + { + "address": "07404ac156eb80fe3092c9e39b2169c6a087194f", + "amount": "100000000000000" + }, + { + "address": "07504a01ea1839c1aef06641eb46379218dbcba9", + "amount": "100000000000000" + }, + { + "address": "0760494df0c9bf14a5a5b50f491adfcc3df6b7e6", + "amount": "100000000000000" + }, + { + "address": "07704a472cabf1433eba2d80a73204d5726a88fc", + "amount": "100000000000000" + }, + { + "address": "0780445f4375d422c87a155b6949625b227bfba2", + "amount": "100000000000000" + }, + { + "address": "07904050bb8647901a3e9b93a2296ca4334d728e", + "amount": "100000000000000" + }, + { + "address": "08004bdfd6dca205244f5a15f9d1741bcc511b54", + "amount": "100000000000000" + }, + { + "address": "081046c92e38c4202ff659168d45d742a57ffee2", + "amount": "100000000000000" + }, + { + "address": "082045bad7d45189d4c9fb379de5ae3aa7dff762", + "amount": "100000000000000" + }, + { + "address": "08304f805360247bed9730d07e755384cb0070e5", + "amount": "100000000000000" + }, + { + "address": "08404debeec7ee380d24cd384d96ff98912a450b", + "amount": "100000000000000" + }, + { + "address": "085047967a6d86f2369345e1243af970f7e4c5e2", + "amount": "100000000000000" + }, + { + "address": "086044b59a0f9b0ceee5ee9f298d17c9f1445beb", + "amount": "100000000000000" + }, + { + "address": "08704f20c81ebf51988fb1b6bef5d29c702216c9", + "amount": "100000000000000" + }, + { + "address": "08804f6d3823b4839685744cd807f5ff7f4d9712", + "amount": "100000000000000" + }, + { + "address": "089049f0d03a767dd1a2b9479cb70d2c836a0077", + "amount": "100000000000000" + }, + { + "address": "09004e53f819778cd2c0738ff055416f44baf529", + "amount": "100000000000000" + }, + { + "address": "09104c7006a42917b1d6c824dc48a4e1f87f835f", + "amount": "100000000000000" + }, + { + "address": "09204a46380169c1c9b5cbff225e771e17e32cda", + "amount": "100000000000000" + }, + { + "address": "093041155ee61c12ea790594b7b305b00ed179e6", + "amount": "100000000000000" + }, + { + "address": "09404741ec9ee6c40d009174474db97aee4db4b4", + "amount": "100000000000000" + }, + { + "address": "095049ee9b15b848f432b1fef028641e391de082", + "amount": "100000000000000" + }, + { + "address": "096046a684f4677dde3a3db075d3b3f99359d3aa", + "amount": "100000000000000" + }, + { + "address": "097048eba43973cc73cd10f1b18085424318d145", + "amount": "100000000000000" + }, + { + "address": "0980419ea31998de5d84b43f5042e4e492a5d738", + "amount": "100000000000000" + }, + { + "address": "099044a5282c4089976c6b13ab13e5423dae55ce", + "amount": "100000000000000" + }, + { + "address": "10004d40a6b66742e3fa57b3410bf4302ce68394", + "amount": "100000000000000" + }, + { + "address": "1010478e08ad97244e773bbd844c71bc0352c3e7", + "amount": "100000000000000" + }, + { + "address": "102048ed9422a043ad4129923f94f3c24bdf215a", + "amount": "100000000000000" + }, + { + "address": "103049dbf55f9d9a3f3d0accd6f9056e478913e2", + "amount": "100000000000000" + }, + { + "address": "104043f348d715650ad409135be7c070d9d95068", + "amount": "100000000000000" + }, + { + "address": "10504f7e334d7a516849b04c5aae4881070feec8", + "amount": "100000000000000" + }, + { + "address": "10604e693a25f81bfbb9fb75f88941ccc45a18bc", + "amount": "100000000000000" + }, + { + "address": "107044e187a52f8bc9caa4874d7f44796a08a929", + "amount": "100000000000000" + }, + { + "address": "10804bcb2dbf1a218a6329ecc2be8745626fcf83", + "amount": "100000000000000" + }, + { + "address": "10904ad08c08a77d484038a07b87be4186792a46", + "amount": "100000000000000" + }, + { + "address": "1100450fd02ac84b4af733541372552a91eefbc4", + "amount": "100000000000000" + }, + { + "address": "1110489c4120dc1bdf90b10c52bb7c09f0845729", + "amount": "100000000000000" + }, + { + "address": "11204b578d9a37c2b5f57096c5421d8422e2dc98", + "amount": "100000000000000" + }, + { + "address": "113043ed1a7e58689fecfbdf930ec4ee5ce5062d", + "amount": "100000000000000" + }, + { + "address": "11404c2a4d6045227e32d9f1365db6f6771076cc", + "amount": "100000000000000" + }, + { + "address": "11504b01b37eb3c132b47eb96bb004c73544b614", + "amount": "100000000000000" + }, + { + "address": "116048b88dea15cedcd35268b8ac6377dcc3d0c1", + "amount": "100000000000000" + }, + { + "address": "11704e5c9b13bb150e597e5433a0662f4a181b6f", + "amount": "100000000000000" + }, + { + "address": "11804b9efdfedf7f1adf66e07a7f0d8f808577da", + "amount": "100000000000000" + }, + { + "address": "1190497f2cc37e940a9fe00ab204a95e0c9bb680", + "amount": "100000000000000" + }, + { + "address": "120041b8df9d90f1f2552dcbaa56f5373b6c6276", + "amount": "100000000000000" + }, + { + "address": "1210432f21bce9b96de278336453b24f4393b83c", + "amount": "100000000000000" + }, + { + "address": "12204cb0d0b5c63229794302bf48a09194c9a16a", + "amount": "100000000000000" + }, + { + "address": "12304722e56d2a02d85843df27699fccaec50d65", + "amount": "100000000000000" + }, + { + "address": "1240481e5002400cb25b142fc050846f929cc48d", + "amount": "100000000000000" + }, + { + "address": "125048c33a3e3e64d000c09ea30acebc284381e1", + "amount": "100000000000000" + }, + { + "address": "126041d6d720e542f71b7f918d436d0e58ae39df", + "amount": "100000000000000" + }, + { + "address": "12704ae3578cd0b3a5173c7a787f6be855de68d9", + "amount": "100000000000000" + }, + { + "address": "12804b8317600ea5a50c022d68db259a48246d11", + "amount": "100000000000000" + }, + { + "address": "12904f277d69867eb875b9ca05631e5af8f6f3a5", + "amount": "100000000000000" + }, + { + "address": "1300421eeb1b9cef3a6de604d2170ec93b0e4339", + "amount": "100000000000000" + }, + { + "address": "13104ac49ac0178e2f2141d84fa608cd75a0b99f", + "amount": "100000000000000" + }, + { + "address": "13204c53460812c5f036d93eb1351b777293bad3", + "amount": "100000000000000" + }, + { + "address": "133046096add47f91c7390867c134ad118db1c78", + "amount": "100000000000000" + }, + { + "address": "13404cd5b310e67182d10562b603c074fe04a89e", + "amount": "100000000000000" + }, + { + "address": "13504f0cade7c2ca08f31db13dcfa7b96df30c9e", + "amount": "100000000000000" + }, + { + "address": "1360405dc963cc088d905661312288f72b8e145d", + "amount": "100000000000000" + }, + { + "address": "13704a54589c4850a0b2e541de4fd74324e6c650", + "amount": "100000000000000" + }, + { + "address": "1380420feb410699ea7969995e80705cdfdc85ca", + "amount": "100000000000000" + }, + { + "address": "13904d5175f99a8c7380356d8c62c1155167e6d9", + "amount": "100000000000000" + }, + { + "address": "140040be8bc55c39dd93872db9f69a2962773414", + "amount": "100000000000000" + }, + { + "address": "14104175cc9b1c210e6e8297c790d13590a69552", + "amount": "100000000000000" + }, + { + "address": "14204fe8d30ec07a74a1ef1c94f46089bc55e221", + "amount": "100000000000000" + }, + { + "address": "1430494a69f153da3746ffe08f78ecb49b57fc0e", + "amount": "100000000000000" + }, + { + "address": "1440427e32ed0038ec856c755a5197fadf957a2f", + "amount": "100000000000000" + }, + { + "address": "14504c4cbec1b1efe9a43158377e8adf781b6103", + "amount": "100000000000000" + }, + { + "address": "1460491d014244244ef559ea9ae513bea1dcddd2", + "amount": "100000000000000" + }, + { + "address": "14704b3f86ac92acf440b2a7e6668f93b3079e4b", + "amount": "100000000000000" + }, + { + "address": "148041a8c233054f555cb9b403f7b923cada20eb", + "amount": "100000000000000" + }, + { + "address": "14904727d2ab89e6c709207ab1c2ca3a5c272a76", + "amount": "100000000000000" + }, + { + "address": "15004c142f4e20b9335895330b5b13d057adf339", + "amount": "100000000000000" + }, + { + "address": "151048b719ee920b3e7817e638b54cccf4c1ad2b", + "amount": "100000000000000" + }, + { + "address": "1520405297a7105030cc7b9644cac18d56789c6c", + "amount": "100000000000000" + }, + { + "address": "1530493894ee67be4601d7e8319e25ec6a4a196c", + "amount": "100000000000000" + }, + { + "address": "154046cce6ed50084402f23d39f47938d8813168", + "amount": "100000000000000" + }, + { + "address": "1550401f10dd6ba3237915480caec9cc25c22e7a", + "amount": "100000000000000" + }, + { + "address": "1560428bcae398f7a6ccefcc11f8f81a3377c0bc", + "amount": "100000000000000" + }, + { + "address": "157048c978d44449301262faa959dca274a5aa4b", + "amount": "100000000000000" + }, + { + "address": "158041081d17bc38c46b8a98e790754db8df070a", + "amount": "100000000000000" + }, + { + "address": "15904f004b76f28c9711fee41dc149653d916928", + "amount": "100000000000000" + }, + { + "address": "160046a9a808312cc2b184576cb7a732ab65b54e", + "amount": "100000000000000" + }, + { + "address": "1610442c7b7596b008014c9d6513aa075e231ef2", + "amount": "100000000000000" + }, + { + "address": "162042923ff01a08e4138e8b238792a42132e1cb", + "amount": "100000000000000" + }, + { + "address": "163047124bf542385d7eadb14cc3f0bac13fdfd0", + "amount": "100000000000000" + }, + { + "address": "16404fe2f744e454f5905fef8f11624c17ea7276", + "amount": "100000000000000" + }, + { + "address": "16504776e6fa4964c1186698b9d937777c895852", + "amount": "100000000000000" + }, + { + "address": "1660429323d21e475d82412cebaa47c3239c8c7f", + "amount": "100000000000000" + }, + { + "address": "16704bb2cf4ac07c32a573f78503c348d1ad8e33", + "amount": "100000000000000" + }, + { + "address": "168042d2ebe07c3ec4d97a27f132252c6f75b2c3", + "amount": "100000000000000" + }, + { + "address": "16904d309459875b673824fb3d4892c255c438a8", + "amount": "100000000000000" + }, + { + "address": "1700459ef6255d3af804047d6e9c8543e4fb651c", + "amount": "100000000000000" + }, + { + "address": "17104093498fce764f72ff62a3cff004ff9036e2", + "amount": "100000000000000" + }, + { + "address": "17204c5f07a3ed21aa701936fc3ac7cee56f6fd9", + "amount": "100000000000000" + }, + { + "address": "173047b98d5737c2ff6cd42a05c7be49cbae4730", + "amount": "100000000000000" + }, + { + "address": "174043c704b4ca5e2386607ca0ea9aa079d060a7", + "amount": "100000000000000" + }, + { + "address": "1750407bdb0f719bc7d589b676e01a353c3a477e", + "amount": "100000000000000" + }, + { + "address": "1760481f33bdeb9a00942ff0b5495d4352905a7c", + "amount": "100000000000000" + }, + { + "address": "17704ced43739119c029327380e45977bf7cad3e", + "amount": "100000000000000" + }, + { + "address": "17804d8420f8c162e2df0e67993cb252a188b5f8", + "amount": "100000000000000" + }, + { + "address": "17904d73ab82f9143cebff44fe04792aab8655e4", + "amount": "100000000000000" + }, + { + "address": "18004a25e97b7715de5a1a81b53c9632144dc420", + "amount": "100000000000000" + }, + { + "address": "181041f149252a89292e9972914c58bd829b8c7d", + "amount": "100000000000000" + }, + { + "address": "18204561a63cd6858352fa755235fc20da17b505", + "amount": "100000000000000" + }, + { + "address": "18304635cca3b26f47928baca81db0f228812f5c", + "amount": "100000000000000" + }, + { + "address": "18404ca5c5c4b058fa69f4e447f337d688fae192", + "amount": "100000000000000" + }, + { + "address": "18504562e4766557eaac160609694f70cd994869", + "amount": "100000000000000" + }, + { + "address": "18604797ec3169f3cc49528c658a2021f9cb65aa", + "amount": "100000000000000" + }, + { + "address": "1870490db984d9ee83069932178d14b0abcaa855", + "amount": "100000000000000" + }, + { + "address": "1880411b2ea73a2c55ae9a44090a91407a1338b2", + "amount": "100000000000000" + }, + { + "address": "1890483fd47d69c9c56ebdc44b53f863636ec76b", + "amount": "100000000000000" + }, + { + "address": "190047b3262c58543426e2aca31153d1ee9a6cb4", + "amount": "100000000000000" + }, + { + "address": "19104a9dcb8c74fd201dd725760a1b6bb46132d0", + "amount": "100000000000000" + }, + { + "address": "1920414bedbca466c0cc21605f310e1e592fd883", + "amount": "100000000000000" + }, + { + "address": "19304b87b24277c3125b6b459754a661f0bf05d2", + "amount": "100000000000000" + }, + { + "address": "194046b0304151f562984df1092f9c1f7d79fa62", + "amount": "100000000000000" + }, + { + "address": "195045f4ad18d51ad82118d941853a515c6477e1", + "amount": "100000000000000" + }, + { + "address": "19604371ecba002941a630d592190da6a7b92204", + "amount": "100000000000000" + }, + { + "address": "19704ce5e62681c054346e859e481d4cead58fca", + "amount": "100000000000000" + }, + { + "address": "1980404abe063de7cb649ed7007c2acff22dc6d6", + "amount": "100000000000000" + }, + { + "address": "199041b40c048301fd79257bac2f24755e4220b5", + "amount": "100000000000000" + }, + { + "address": "200042c84cdc16db2aa5bcf29f578f19f88d828f", + "amount": "100000000000000" + }, + { + "address": "2010436f32021ed70ea837c7bb28e3e4f0eb08b4", + "amount": "100000000000000" + }, + { + "address": "202041a563d5c632cc8a16f1c47a144e9861ffc8", + "amount": "100000000000000" + }, + { + "address": "20304a95f96c1ecd467d220afe61dc00191a590d", + "amount": "100000000000000" + }, + { + "address": "204041fdfe17c0f23783b5f1bb5b957bcc2808d4", + "amount": "100000000000000" + }, + { + "address": "205047833c7643945ff04936615f36f4d6afa927", + "amount": "100000000000000" + }, + { + "address": "20604e648b33f0d377c19dda00c69fd7dbab1a35", + "amount": "100000000000000" + }, + { + "address": "20704e9cdcb655809f917a2383c5bc962d65a676", + "amount": "100000000000000" + }, + { + "address": "20804d277be9dac11fddaf7a303de7825d04fe86", + "amount": "100000000000000" + }, + { + "address": "209045028021014830c19dd005c1f15734c0279d", + "amount": "100000000000000" + }, + { + "address": "210041c9fcf43b85b482d5225e59dfd53343d4c0", + "amount": "100000000000000" + }, + { + "address": "211041068d32913cd60af834ea4046f663f5ced3", + "amount": "100000000000000" + }, + { + "address": "212045166e6cc662e8810cd340cfc2c03f5ed76b", + "amount": "100000000000000" + }, + { + "address": "213042d24128fc2d6a012d7505b0a16ae7f2c71f", + "amount": "100000000000000" + }, + { + "address": "21404dc18a0af5991775e21beef464a2abbe2465", + "amount": "100000000000000" + }, + { + "address": "21504bc8aa46ae21814ebab4a7e1b1a242d5accf", + "amount": "100000000000000" + }, + { + "address": "216043b23b77f8ba73f8fd27960292f39dbd4295", + "amount": "100000000000000" + }, + { + "address": "217044892b8c7caebfd3bd1ce03c993dc5ff86dc", + "amount": "100000000000000" + }, + { + "address": "21804f424ae6e5ea63f52935924f7f0195626b82", + "amount": "100000000000000" + }, + { + "address": "21904412d935bdf5f5e1c09240943f5ee08f096e", + "amount": "100000000000000" + }, + { + "address": "22004a7749a322d34096b8d05bf619b9149fb4b3", + "amount": "100000000000000" + }, + { + "address": "2210474930588c35eca210c11955091a0f5f884b", + "amount": "100000000000000" + }, + { + "address": "22204bc6f9ad7e4e518199856e0179a42b33a79b", + "amount": "100000000000000" + }, + { + "address": "22304a1c7c397f31624307c685f5f7a00c12f39e", + "amount": "100000000000000" + }, + { + "address": "22404a0c21626c59ebc9ff7d634016d0c7c7211f", + "amount": "100000000000000" + }, + { + "address": "2250468cad33051ab3dba059c69076dab24f7fde", + "amount": "100000000000000" + }, + { + "address": "22604387182910cc90bbc1c2263c726a16a8272a", + "amount": "100000000000000" + }, + { + "address": "22704fde9834f549d90386e8091f84260dcfa948", + "amount": "100000000000000" + }, + { + "address": "2280473c939601953bff8fa82a1f402109ef940c", + "amount": "100000000000000" + }, + { + "address": "22904d330d2bb0dc4b7107774f01e7d5c3490eb6", + "amount": "100000000000000" + }, + { + "address": "23004d5c724c1e8ec7fef279228a0c97f17e2181", + "amount": "100000000000000" + }, + { + "address": "231044e6feafd5ae2936053ec52d2313d6c8074e", + "amount": "100000000000000" + }, + { + "address": "232040240f94d8516431e17bddf998236fbb4b1f", + "amount": "100000000000000" + }, + { + "address": "23304f25914a69624d63b73f906277f3b44146da", + "amount": "100000000000000" + }, + { + "address": "2340459c2aeedd718eb6888f03ecba40f667512d", + "amount": "100000000000000" + }, + { + "address": "2350412da46f9d6df2ba9de0d5edab0e7ab04f8a", + "amount": "100000000000000" + }, + { + "address": "23604d9dda5729453dbbf6dac079d4265cf2d572", + "amount": "100000000000000" + }, + { + "address": "237046cfc5cb28de4513aeaa070cf059a4dd0b3c", + "amount": "100000000000000" + }, + { + "address": "2380476cd240c9a3ef532c44da208fec403daf43", + "amount": "100000000000000" + }, + { + "address": "239043b65e631bfba903c7be4bd9bbeccc8c77d3", + "amount": "100000000000000" + }, + { + "address": "24004e034045de6aeed0120b55ff7eff23b734fc", + "amount": "100000000000000" + }, + { + "address": "2410496835f7d8b8f66bd3e7724941d46ed0b5b8", + "amount": "100000000000000" + }, + { + "address": "242040f054acb1fd7e03be92d5a95267e6bbf40d", + "amount": "100000000000000" + }, + { + "address": "24304d490c84c40a4b2700d36f692045cb292240", + "amount": "100000000000000" + }, + { + "address": "2440427c70b5b9338d5d4d9ed1c5631168d09481", + "amount": "100000000000000" + }, + { + "address": "24504aa139ba31e9fadf8aece9319578c461be09", + "amount": "100000000000000" + }, + { + "address": "246043ee459e114da19d9733237f8ff18d1c975c", + "amount": "100000000000000" + }, + { + "address": "24704a003e960e2e3184d12bc81481c7b6d3b571", + "amount": "100000000000000" + }, + { + "address": "24804468e55eb683e108433f64f004d8e578e586", + "amount": "100000000000000" + }, + { + "address": "24904b241defa1190e86824dfb5ea06b4cba4be6", + "amount": "100000000000000" + }, + { + "address": "25004dc5f51b2acefedf7d6879a9d75c073a8fa7", + "amount": "100000000000000" + }, + { + "address": "25104987c20c2f2c7b9ad6d3a54644ab6f2a85af", + "amount": "100000000000000" + }, + { + "address": "25204b567acdac5d4a3ce796a4cc59493b11bf31", + "amount": "100000000000000" + }, + { + "address": "25304db3a407cf45ee8ea443ca0084e5b60c79b7", + "amount": "100000000000000" + }, + { + "address": "25404bd5df303cd129ad600d140d3bbcc2590a73", + "amount": "100000000000000" + }, + { + "address": "255043858b88fa0a7358e2ffcd69e7c83e402290", + "amount": "100000000000000" + }, + { + "address": "25604bc9c36ed092e5d092c67dba2622cd4e5d84", + "amount": "100000000000000" + }, + { + "address": "2570409af48f9f53d4fb971997e9551a6f278c34", + "amount": "100000000000000" + }, + { + "address": "25804bc4082281b7de23001ffd237da62c66a839", + "amount": "100000000000000" + }, + { + "address": "25904c87cad76ff937dae4f1c32a78701e16597c", + "amount": "100000000000000" + }, + { + "address": "260048cd2563d833b62eba3e96db8bf11f33b4d7", + "amount": "100000000000000" + }, + { + "address": "26104a73f4e062b78ca20f62d668a76060bbc52b", + "amount": "100000000000000" + }, + { + "address": "26204fd56b23d52c028afcff7d507f52e1540ebd", + "amount": "100000000000000" + }, + { + "address": "263046b3910eb41b62ecab8e2727c7ccf3383821", + "amount": "100000000000000" + }, + { + "address": "264040a705d84df7ced13aa8ae978fa882bdd62a", + "amount": "100000000000000" + }, + { + "address": "26504edc6b5e0ce4c2e8d7fb6ef348378ab9abba", + "amount": "100000000000000" + }, + { + "address": "2660414a17171ad23ae33e5013427ec377b4c988", + "amount": "100000000000000" + }, + { + "address": "2670497b55fc9278e4be4f1bcfe52bf9bd0443f8", + "amount": "100000000000000" + }, + { + "address": "268044a5aab702befe268a12ddca939baf687e8b", + "amount": "100000000000000" + }, + { + "address": "26904228cd6cb82cd55d4af2737166589ff50fed", + "amount": "100000000000000" + }, + { + "address": "2700435fc578db0405190e80dc52c804244f0c1a", + "amount": "100000000000000" + }, + { + "address": "271045c982bdf708abe108829b57fec34a15d164", + "amount": "100000000000000" + }, + { + "address": "2720402be517c6d4d5304d9d2afef856b4c19a66", + "amount": "100000000000000" + }, + { + "address": "273043e7bc0d2eaec59553feda2e1fb2f68cc6ab", + "amount": "100000000000000" + }, + { + "address": "27404283d4b279ba4f3eb205d7ce07556f569333", + "amount": "100000000000000" + }, + { + "address": "27504a9c3e3671f59efe6d98bfefa78a56cab907", + "amount": "100000000000000" + }, + { + "address": "2760456e71cecc99cb8c1abaa4e27755d266aea1", + "amount": "100000000000000" + }, + { + "address": "277043a71759fe5abc5292cf6329c6ed2423d8bb", + "amount": "100000000000000" + }, + { + "address": "278048f93ae0a37f2208390762bdafb1af55e14e", + "amount": "100000000000000" + }, + { + "address": "2790490db88a1189fc72bb5fd6e0f3a8bfa73db1", + "amount": "100000000000000" + }, + { + "address": "28004daf634dca5d149954fe6d4b5c4eb0028793", + "amount": "100000000000000" + }, + { + "address": "28104f10721a56e1a4a4b94e6358738665ac5dfa", + "amount": "100000000000000" + }, + { + "address": "28204f215c20cef00567debf6cb53e30661d0fab", + "amount": "100000000000000" + }, + { + "address": "283041381e612d928f5f555bf8263c8ba88d936c", + "amount": "100000000000000" + }, + { + "address": "2840417b17149dbd88c673dcf48257ac408c71fe", + "amount": "100000000000000" + }, + { + "address": "28504cc3677748731043d89db8f5daa698b81ac8", + "amount": "100000000000000" + }, + { + "address": "286047e41e279be46bad32fcdb3160883765cd03", + "amount": "100000000000000" + }, + { + "address": "28704d946c75244e893567fcdb6c942f1f9c4010", + "amount": "100000000000000" + }, + { + "address": "28804cc3a57272725f1f6576a9f191dc5ff6dfc2", + "amount": "100000000000000" + }, + { + "address": "2890417d98352e3fd93bc9428c3eafdf8a2c70df", + "amount": "100000000000000" + }, + { + "address": "29004d6f7786f10ec5eeb3d979b0cef900c1d48f", + "amount": "100000000000000" + }, + { + "address": "291040ed2dafb7f0a459bcb102fa06b51c1ea60a", + "amount": "100000000000000" + }, + { + "address": "292041e75709c5301b529946184c3f34079542e1", + "amount": "100000000000000" + }, + { + "address": "293042f94bf55835b0402f4749c527d1341d33e1", + "amount": "100000000000000" + }, + { + "address": "29404d31d48e1a6e8809dee2aa22fe1864847708", + "amount": "100000000000000" + }, + { + "address": "29504895b3565b05f833175a7e9dc7db7b4eb70b", + "amount": "100000000000000" + }, + { + "address": "29604a2caf83a8713ce0d98fe186e4bc06dd2080", + "amount": "100000000000000" + }, + { + "address": "297043b50a64aded60e47ade8736ea0abbcfc296", + "amount": "100000000000000" + }, + { + "address": "29804016798e7205be0b06dda8c467effd2b9270", + "amount": "100000000000000" + }, + { + "address": "2990404886581ad56da93b3586973995255c46a5", + "amount": "100000000000000" + }, + { + "address": "300041bf170fea639f3fa2ae44c35c286614c6e1", + "amount": "100000000000000" + }, + { + "address": "301044886121f610783dbfe7eaf5b8b18a08f98a", + "amount": "100000000000000" + }, + { + "address": "3020483107289ce0e1aa22c4b391792dcf422039", + "amount": "100000000000000" + }, + { + "address": "303043b4d44b0fd2836f794d13dfeca89eede44c", + "amount": "100000000000000" + }, + { + "address": "30404c7fde0c53e7bcd5b16f4bae7fb67cd11c7e", + "amount": "100000000000000" + }, + { + "address": "305048be380a6497e74cc9336f6f848355869e41", + "amount": "100000000000000" + }, + { + "address": "30604835f99a142c0834a2a85b64cb29123c98ce", + "amount": "100000000000000" + }, + { + "address": "30704f7df470a5cf2888feadd4465059e52d793e", + "amount": "100000000000000" + }, + { + "address": "30804079993f175db5d3709b0493629f676c835d", + "amount": "100000000000000" + }, + { + "address": "30904c5834aca2092bece28240c82b27e2284540", + "amount": "100000000000000" + }, + { + "address": "3100403f6bbac8575099e11a89a328b9a55e1532", + "amount": "100000000000000" + }, + { + "address": "31104cfb42d421636c088ef06a7a72de5518b70f", + "amount": "100000000000000" + }, + { + "address": "31204158e79b460f11fde2e511551a1a2dccf170", + "amount": "100000000000000" + }, + { + "address": "31304a71a751f080eb358f7b26db28802e944410", + "amount": "100000000000000" + }, + { + "address": "31404816c32212afd80529bf64bd4713f5f50ba5", + "amount": "100000000000000" + }, + { + "address": "3150481f573e37f4de34d89e7aa5444063241a74", + "amount": "100000000000000" + }, + { + "address": "3160464d8039476a8d689c25a0572fb72ab7429d", + "amount": "100000000000000" + }, + { + "address": "31704b6dbc7d7450f8b3845ecdc8d08537a5df93", + "amount": "100000000000000" + }, + { + "address": "3180441bdf305aa132ed094a5b69c84d79f73565", + "amount": "100000000000000" + }, + { + "address": "3190440d7937a90337ad19634ab4669bebb28883", + "amount": "100000000000000" + }, + { + "address": "3200443602a176452ee90950a5351295a5167071", + "amount": "100000000000000" + }, + { + "address": "3210418fd5fc7b7dfd7d75028018163fb59d40a8", + "amount": "100000000000000" + }, + { + "address": "32204f1160e69002d6d86e2194117f6249a5f8bf", + "amount": "100000000000000" + }, + { + "address": "32304dfb40a70da4efbcccc335595bdb146afc25", + "amount": "100000000000000" + }, + { + "address": "32404941024157ffd22cb6e63a05c4a9f3267c18", + "amount": "100000000000000" + }, + { + "address": "32504951d7b1baa55fdc210e189b0fd1b6cd26bf", + "amount": "100000000000000" + }, + { + "address": "326040355d00febef3a516080a1c0a210e44df62", + "amount": "100000000000000" + }, + { + "address": "32704184a2ced2a3c64f3ed2275b95548fef0df3", + "amount": "100000000000000" + }, + { + "address": "32804e88e2b0a67f442c4031f0b91b9c136cf9a1", + "amount": "100000000000000" + }, + { + "address": "32904335f0cc4007dfd7beaa1e0d530b0850423c", + "amount": "100000000000000" + }, + { + "address": "33004a29540a208ea27581f8c58d3a7b68cf806e", + "amount": "100000000000000" + }, + { + "address": "33104aa9a8db1d203b971470253c2947d212d101", + "amount": "100000000000000" + }, + { + "address": "332041c5bb31084f5081a12eec7e84973b9050c4", + "amount": "100000000000000" + }, + { + "address": "33304a384d2bc374d9b49fc43f1ff71266f2f72a", + "amount": "100000000000000" + }, + { + "address": "33404dad454c7792ee9ebe7debde21f3165b55d3", + "amount": "100000000000000" + }, + { + "address": "3350428dc24111ce92e5e5b3e652290969249b82", + "amount": "100000000000000" + }, + { + "address": "33604fffca2d917ac12a8c445719fce04ba347fe", + "amount": "100000000000000" + }, + { + "address": "33704b4672b8b6abc242c30e6f9093c292cdd867", + "amount": "100000000000000" + }, + { + "address": "33804d7251e69234783730671ea0e5593cd1e685", + "amount": "100000000000000" + }, + { + "address": "339048f1e8d3615618aefc20c3674333034c0a8b", + "amount": "100000000000000" + }, + { + "address": "34004bd3a6601ebcb3e9f807f4364c44b7b43864", + "amount": "100000000000000" + }, + { + "address": "341041a2048ca305a4a07850e800832e033129ab", + "amount": "100000000000000" + }, + { + "address": "3420489202fb38a72364915d27b62010f96f8e61", + "amount": "100000000000000" + }, + { + "address": "34304d8d5f4dcb922f934d4ef0a98b38ce5a0e13", + "amount": "100000000000000" + }, + { + "address": "344046b1cd587b1f8d1f3bed184c8ac5281a06b0", + "amount": "100000000000000" + }, + { + "address": "345048b73c7139ffad2e0a2b0ddd11798028c552", + "amount": "100000000000000" + }, + { + "address": "346049ff5b7d886980411f9df009654d29e63e75", + "amount": "100000000000000" + }, + { + "address": "3470401b6b883fe18a6b267ce3755038d0b69d6a", + "amount": "100000000000000" + }, + { + "address": "34804b52b3bd167852eeca5de11a16d8085c8317", + "amount": "100000000000000" + }, + { + "address": "34904565b0d34e0955d54e5ee4e0409188a9981f", + "amount": "100000000000000" + }, + { + "address": "35004add80596903433b36ff6f13f84c703dc0bf", + "amount": "100000000000000" + }, + { + "address": "35104179212912972cd195d0d99cde5872b1e49c", + "amount": "100000000000000" + }, + { + "address": "3520445de027b8aee95d67563680021bb315b503", + "amount": "100000000000000" + }, + { + "address": "353042794cdd1fbaf34e250c78f585f17d357012", + "amount": "100000000000000" + }, + { + "address": "35404987b433e937e4862e5f55664eecef795f78", + "amount": "100000000000000" + }, + { + "address": "35504f4691b2c53d2b2b9ff0efae65b716cd4cca", + "amount": "100000000000000" + }, + { + "address": "35604464f569580d399280fa87b003a1b1fd9125", + "amount": "100000000000000" + }, + { + "address": "357040ae16c5eb6dcf85e5bab749c2090524b204", + "amount": "100000000000000" + }, + { + "address": "35804153fed41c4ee1d6196544aad5613b9dcced", + "amount": "100000000000000" + }, + { + "address": "359047fdcda82972eb9253f7b774ae51bc272550", + "amount": "100000000000000" + }, + { + "address": "36004b1e194156bf223501a10a759894c232b0d1", + "amount": "100000000000000" + }, + { + "address": "361044c781ae8053f78d4fe750deda298df90036", + "amount": "100000000000000" + }, + { + "address": "36204aa085755279387564cc22318fef6fe22507", + "amount": "100000000000000" + }, + { + "address": "3630474281208e5350a097cf58438eb821df2d78", + "amount": "100000000000000" + }, + { + "address": "36404fc963beb7aaab2e6fb389cd8b5390bbce06", + "amount": "100000000000000" + }, + { + "address": "36504b124c54deecc2cc47af358a00f773f2678a", + "amount": "100000000000000" + }, + { + "address": "36604a4885997fe5a77a05011f2d386b92452e25", + "amount": "100000000000000" + }, + { + "address": "3670447ee0096cd1e3d0fd3bf90237683357290e", + "amount": "100000000000000" + }, + { + "address": "368041995c9e2c0ac7e9c85a299c2add91c408c5", + "amount": "100000000000000" + }, + { + "address": "3690419c8e772fa5828bf15addbd636ac8e1fe60", + "amount": "100000000000000" + }, + { + "address": "370049e8d9c1f35df74e5ae7319f4b4ac8c9fbef", + "amount": "100000000000000" + }, + { + "address": "371045c859507bda236654ba9be78f3f844e3c90", + "amount": "100000000000000" + }, + { + "address": "3720462ddbe4a9b926059ae3b543e112b08c22af", + "amount": "100000000000000" + }, + { + "address": "37304679217f64cfc99ee9eb50a9b4c10c787612", + "amount": "100000000000000" + }, + { + "address": "374044695975d130b6531886a84ed9c35593e6aa", + "amount": "100000000000000" + }, + { + "address": "37504427bf3ad1e9d8f319963871ace60bf9cdfa", + "amount": "100000000000000" + }, + { + "address": "37604fc15cd724a87f7e2625532ecec8a67f96c5", + "amount": "100000000000000" + }, + { + "address": "37704e0ae01d8289a58e85d076c2e53b2b439bc0", + "amount": "100000000000000" + }, + { + "address": "37804879cf71d703c18d9a1a36840e455ad5257d", + "amount": "100000000000000" + }, + { + "address": "37904a898da09c64d90b87ef12ae8eba75ab70ef", + "amount": "100000000000000" + }, + { + "address": "38004f2f4ecd24fb6e1bbb6005e395820d711c92", + "amount": "100000000000000" + }, + { + "address": "38104191f40cd1705a0b3e51565ee4efd57c37f1", + "amount": "100000000000000" + }, + { + "address": "38204d1aaec84a2ae42e8caa8c3850c89ee3152c", + "amount": "100000000000000" + }, + { + "address": "38304c41d4fbb1bf231e821459de0730d5f7125f", + "amount": "100000000000000" + }, + { + "address": "38404fc1f3333fcf83bac73dfc54b04c9254c022", + "amount": "100000000000000" + }, + { + "address": "38504eda2a7e561ceb903173e5bab2a0ce2faed1", + "amount": "100000000000000" + }, + { + "address": "38604efb24ad019fd29329afa28a3ebf9ec67459", + "amount": "100000000000000" + }, + { + "address": "38704790e2adb4e2bb9a4a1ce745b8ddd407eb7c", + "amount": "100000000000000" + }, + { + "address": "388040cd8e861404de5d6f31d7ac4066f4d029b1", + "amount": "100000000000000" + }, + { + "address": "389044cb786b0c45a99ffd18600626019faebab5", + "amount": "100000000000000" + }, + { + "address": "390048a3113b7d71429ad1fa5c7e8ea773fb17c6", + "amount": "100000000000000" + }, + { + "address": "39104907570ce9faa49e2cb481df2e8b4ed29664", + "amount": "100000000000000" + }, + { + "address": "392049205fe199c8715802f8eb2f623cca922df9", + "amount": "100000000000000" + }, + { + "address": "3930414d9c4a5d88820e9f94711c83b33adbbd3a", + "amount": "100000000000000" + }, + { + "address": "39404e0e8c539b200c10e4ea00f6ac19bd9d8fd7", + "amount": "100000000000000" + }, + { + "address": "3950409733a0c9aed0df3a771eb72ea04d65ac61", + "amount": "100000000000000" + }, + { + "address": "39604000bb0f03de6dddaae3775f0dcf5f2616d9", + "amount": "100000000000000" + }, + { + "address": "397041aa1a91734f2eb917486d585a979ac4814d", + "amount": "100000000000000" + }, + { + "address": "398044a57ac2e71e881d58eb7ccd9d9cebf6b461", + "amount": "100000000000000" + }, + { + "address": "3990423bd9c877541bd99010abce6aba593fa422", + "amount": "100000000000000" + }, + { + "address": "400048c7b8ad110fa552f5276eb18fbf133442ff", + "amount": "100000000000000" + }, + { + "address": "4010442ccf683fd62b6ca6fd7a79987226fccb1a", + "amount": "100000000000000" + }, + { + "address": "402042e8d58b8f6f8bb5cbb8f3ce6b81e94b08a5", + "amount": "100000000000000" + }, + { + "address": "403044b6a04fdec2d447e79f3b2536beafc50ccf", + "amount": "100000000000000" + }, + { + "address": "404043e086c9a544a100c6574b821496449dc4c9", + "amount": "100000000000000" + }, + { + "address": "40504d12dcb2b6c35eba82e83ea6ce1203bccfda", + "amount": "100000000000000" + }, + { + "address": "4060401de88f864e233aa7e354a39697edd5d228", + "amount": "100000000000000" + }, + { + "address": "40704173d90fa115cf632974fefb97f8ac0cdd5a", + "amount": "100000000000000" + }, + { + "address": "408040e43d125d490af0d3792fa22c8edfabf3e8", + "amount": "100000000000000" + }, + { + "address": "40904d86614f2f0fa0ffba631577fdac808d054f", + "amount": "100000000000000" + }, + { + "address": "4100406ea23a4fefbf25303fedbd8f1d057fd71f", + "amount": "100000000000000" + }, + { + "address": "41104c864e06b1cc7051845887fdad77c4e9103d", + "amount": "100000000000000" + }, + { + "address": "4120490568a1e645ade2e5eba486f5c28c202599", + "amount": "100000000000000" + }, + { + "address": "41304769c40c9be69871025782463ced1ca5f8c4", + "amount": "100000000000000" + }, + { + "address": "41404321fa09f1e26e88f8297f4ebc1c7591b8cf", + "amount": "100000000000000" + }, + { + "address": "41504cd0ecb6bb356678286b93b0db4d5a2de6ff", + "amount": "100000000000000" + }, + { + "address": "4160496316e6844b606a2a881bfeb98d7db80481", + "amount": "100000000000000" + }, + { + "address": "4170441fd1a081fa05a56f18aad4ac7a16190018", + "amount": "100000000000000" + }, + { + "address": "41804d9def2714f137af065bba450952ab45dea6", + "amount": "100000000000000" + }, + { + "address": "4190439a9b97d17674fe3ab5d897fac5a4142668", + "amount": "100000000000000" + }, + { + "address": "420043b854e78f2d5f03895bba9ef16972913320", + "amount": "100000000000000" + }, + { + "address": "42104b54a994bf1eb0f774b7e9767d0ffd3c1d5a", + "amount": "100000000000000" + }, + { + "address": "4220421e3d617e9f11ec901dfa59e39d158e8692", + "amount": "100000000000000" + }, + { + "address": "423049d1c211746cf6dda98a50eba60a2aaec6f2", + "amount": "100000000000000" + }, + { + "address": "4240491cbfd017e652fba1d170ce1154aeeb27d9", + "amount": "100000000000000" + }, + { + "address": "42504d1a343ee6649f592438307c4a5f9f63e833", + "amount": "100000000000000" + }, + { + "address": "4260455886a887a258e2c5154b8d51730b846f6d", + "amount": "100000000000000" + }, + { + "address": "42704fd9e7b7e74197f96fd308b23ceb19f52d3f", + "amount": "100000000000000" + }, + { + "address": "428043a659f56992b33f52c6f6b8c92777a39595", + "amount": "100000000000000" + }, + { + "address": "42904e252ce17c56e1269bea315365a68515da98", + "amount": "100000000000000" + }, + { + "address": "430040d176cc2342c9a788f1e2a7a4851560d163", + "amount": "100000000000000" + }, + { + "address": "43104f4c4adb2b02ee0618deb84c65a399633263", + "amount": "100000000000000" + }, + { + "address": "432041283d7e1a624097f329b52551560e470856", + "amount": "100000000000000" + }, + { + "address": "43304af2615963515f8cde685e0185ec5230c1e6", + "amount": "100000000000000" + }, + { + "address": "43404619884fc86b3652706948118802bf455f1a", + "amount": "100000000000000" + }, + { + "address": "435042aa1bad5f86965fcde5dd57b2459c7cafd0", + "amount": "100000000000000" + }, + { + "address": "436041005230bdf407da67c09a73921c8905fdb8", + "amount": "100000000000000" + }, + { + "address": "43704ee3f0f6e32519eaad5e856e9de1bac702a1", + "amount": "100000000000000" + }, + { + "address": "438040ee2dca2eaa65c4e98d46f68bc749293514", + "amount": "100000000000000" + }, + { + "address": "439047e81f6fffc2846ec87756257c7ea78a71c4", + "amount": "100000000000000" + }, + { + "address": "44004ecbb5d957fd9b7febf89841cf507d95dd34", + "amount": "100000000000000" + }, + { + "address": "44104bd54eb6c3724d9f97d5befac0b996420275", + "amount": "100000000000000" + }, + { + "address": "44204ba01215d2876f9545a1a7b57f671071d59a", + "amount": "100000000000000" + }, + { + "address": "44304b8a8220d8692f68b631a95b59265bb6a52f", + "amount": "100000000000000" + }, + { + "address": "44404ffcb1f1e1eb6a59b17731245c4becd5513f", + "amount": "100000000000000" + }, + { + "address": "44504e7cfdd173bacd0a4933ee328ed0a7946852", + "amount": "100000000000000" + }, + { + "address": "446047d1029355e34b94f47061be7b6b671bdf0e", + "amount": "100000000000000" + }, + { + "address": "44704161667f420239be206d949310d4d4b505e4", + "amount": "100000000000000" + }, + { + "address": "4480454d76128e3abf5fff4b129985a70ee449ff", + "amount": "100000000000000" + }, + { + "address": "44904aa24c16c5d4862a494c5a3a068a9a8efcce", + "amount": "100000000000000" + }, + { + "address": "450047b3d8a803358e647dca9aa2119d552ae98a", + "amount": "100000000000000" + }, + { + "address": "45104003fddc52c2a36f2ea782ef4e040d709ae5", + "amount": "100000000000000" + }, + { + "address": "45204b7689eb2cd1ab0fca85d768176803713c56", + "amount": "100000000000000" + }, + { + "address": "45304fede7bde8d0fa71a22da82ec6aeaddcdb8f", + "amount": "100000000000000" + }, + { + "address": "4540428b06b1ac971a548b844bc7cee683ac8910", + "amount": "100000000000000" + }, + { + "address": "455048c4b5b04d40803e4ea44f1f1ec7f5e2158f", + "amount": "100000000000000" + }, + { + "address": "45604c07d459d0e00e0c676191f47f54f5cc9d17", + "amount": "100000000000000" + }, + { + "address": "45704ab864f63350afe79f2c840b96205b9dc69a", + "amount": "100000000000000" + }, + { + "address": "458047e5fe56a0e4e209705fadbdb64e74dcc8da", + "amount": "100000000000000" + }, + { + "address": "459047ffc6e6f4f92c97b7a74180ccaed6e30b79", + "amount": "100000000000000" + }, + { + "address": "46004e8e048204f310b2d3ef5790c6f0fdc6ddd0", + "amount": "100000000000000" + }, + { + "address": "461045c62f269a240a2d27ba40ac33b4324b7bab", + "amount": "100000000000000" + }, + { + "address": "46204132a93bdc40c6976823dd0e6bc205f155a1", + "amount": "100000000000000" + }, + { + "address": "4630494fb9144b14d2948d5b67261345f72b691c", + "amount": "100000000000000" + }, + { + "address": "46404d167820598aed5aa93b5a057d72fc859a04", + "amount": "100000000000000" + }, + { + "address": "46504941f3f25ba5b8f7c175ddf62eaf0d06adb3", + "amount": "100000000000000" + }, + { + "address": "466045100f7e8c27325435184c01b78369480354", + "amount": "100000000000000" + }, + { + "address": "467042e5a9b3c69a66129703b8c572240c1d153c", + "amount": "100000000000000" + }, + { + "address": "46804d4141c4947fbe605d1098eafdb14b108d6f", + "amount": "100000000000000" + }, + { + "address": "4690407f05a59ab99fa62e9c931fc713ed0b2184", + "amount": "100000000000000" + }, + { + "address": "470042f846f54c551bfcf53d2cc8fc9eb50b9d77", + "amount": "100000000000000" + }, + { + "address": "4710478780ea9e0d337b24886b1b806edcbeb194", + "amount": "100000000000000" + }, + { + "address": "47204e3a7b972c67d7492b8beffd704a14a5597f", + "amount": "100000000000000" + }, + { + "address": "47304bc12fb943d98b3c1e8800e97e452b9e07b1", + "amount": "100000000000000" + }, + { + "address": "474047553b5fdd4554a8d619d04c293fad715859", + "amount": "100000000000000" + }, + { + "address": "4750444b21d48d5058a716a230d50f675d3fabd4", + "amount": "100000000000000" + }, + { + "address": "4760435ab90be6bd17d294fd923e252b414a2c04", + "amount": "100000000000000" + }, + { + "address": "477045c6548b93ad997cf88265dc4064c2a55404", + "amount": "100000000000000" + }, + { + "address": "478043234bfbdde3497569af02e9052cb5877bfc", + "amount": "100000000000000" + }, + { + "address": "479046da314d05c021dac35448b1eecc89db0481", + "amount": "100000000000000" + }, + { + "address": "48004cb51eed7e063da47540db789cb415d1b3d7", + "amount": "100000000000000" + }, + { + "address": "481041dd8949041bd011954a00d2f52fae0566c4", + "amount": "100000000000000" + }, + { + "address": "48204a827f0f7ef5545fdc74333d8422ff702284", + "amount": "100000000000000" + }, + { + "address": "48304ebd697b2501eb5a4a8ce716151c64e4dfce", + "amount": "100000000000000" + }, + { + "address": "4840420106bebe4c1da8f3863f8fecf85531e3e8", + "amount": "100000000000000" + }, + { + "address": "485045203218d25423cd22454ad34f3473b1f948", + "amount": "100000000000000" + }, + { + "address": "48604b028a5faf55d03b2259e8596034dbcfce77", + "amount": "100000000000000" + }, + { + "address": "487049a35ab4ec9d9b24e7871fe3f332f2e4ba4d", + "amount": "100000000000000" + }, + { + "address": "48804331472e8fbb1145c9f17e6f3009efb8b9c3", + "amount": "100000000000000" + }, + { + "address": "48904c7f5a4f76f41e999a31f754d77b97d0d34a", + "amount": "100000000000000" + }, + { + "address": "4900408ea7abbfd68548d4066cd47de004abdab8", + "amount": "100000000000000" + }, + { + "address": "491042831baa4824f571ab903aa3a67283beb6ed", + "amount": "100000000000000" + }, + { + "address": "49204c54c110eae17618e89cc20ba6d8249b8388", + "amount": "100000000000000" + }, + { + "address": "49304ba5346e6c9681ac40b54b0b06798543121d", + "amount": "100000000000000" + }, + { + "address": "49404cde92dd5d8ecfc884c6c23e7d4fbf02d987", + "amount": "100000000000000" + }, + { + "address": "49504a406e7533631945d33ce560f51b4954c862", + "amount": "100000000000000" + }, + { + "address": "496040841bd7d102f718cc586408765fe8b890f7", + "amount": "100000000000000" + }, + { + "address": "49704630c8f0c30ad5562fca357ad9e433327c86", + "amount": "100000000000000" + }, + { + "address": "49804b1066d6e1f2e2eb444319101bf1d410bc0f", + "amount": "100000000000000" + }, + { + "address": "499049ee379ae9666f10a57cadac6dab770bf4b8", + "amount": "100000000000000" + }, + { + "address": "50004655607ec95dc65ec29bbb415db821f07653", + "amount": "100000000000000" + }, + { + "address": "5010452968dd443161fc551d953961bf63065bf0", + "amount": "100000000000000" + }, + { + "address": "50204abd8507b4151f8a5d11f8a5c42581adf99e", + "amount": "100000000000000" + }, + { + "address": "503048aefad5aedeebe1ea87229c3c6b8f1fe42b", + "amount": "100000000000000" + }, + { + "address": "504048ca595ad0f9b68759d00c16fa58316745c6", + "amount": "100000000000000" + }, + { + "address": "50504eaf9796e76437666e40f94af993faee5c36", + "amount": "100000000000000" + }, + { + "address": "50604210365e98bf07ce91a990826a9539edc2dc", + "amount": "100000000000000" + }, + { + "address": "50704701122e4cb8ce668272e88486dfe5efe64d", + "amount": "100000000000000" + }, + { + "address": "50804a42b45c1e6f2b0b7efb62081e1352aea22f", + "amount": "100000000000000" + }, + { + "address": "5090450269b417fbaca6afb81325baeee7817a73", + "amount": "100000000000000" + }, + { + "address": "5100438648be0f3168375454a4cdb3c9e42ecb0d", + "amount": "100000000000000" + }, + { + "address": "5110453215f3d3afe3a002bf8e926b38013e7173", + "amount": "100000000000000" + }, + { + "address": "51204817b59f7a35de4503dcbfdae37d5c256bad", + "amount": "100000000000000" + }, + { + "address": "513047730b1635dd5723fda5153a055ba17744d2", + "amount": "100000000000000" + }, + { + "address": "51404aeac599ca65caa4d65039e868764352d341", + "amount": "100000000000000" + }, + { + "address": "5150443a4e437dd13f2aaf543b78c59d186771ea", + "amount": "100000000000000" + }, + { + "address": "5160499de0e7643925875defc447b38fe8724704", + "amount": "100000000000000" + }, + { + "address": "51704fd6050f0e11179f4e1f403bc5b84c83156a", + "amount": "100000000000000" + }, + { + "address": "5180446d9777a6ecc8ea5a1864392f3f053992e3", + "amount": "100000000000000" + }, + { + "address": "51904629b79abd0f0a63d29a8ef19939bb4c9b68", + "amount": "100000000000000" + }, + { + "address": "52004033b3431796cd2b6c7183b0f4b20674f013", + "amount": "100000000000000" + }, + { + "address": "521044e558ddc905ab36398e83f425b49572f802", + "amount": "100000000000000" + }, + { + "address": "522042bf74ba442b2e4b5e5c3c2eac92990809e4", + "amount": "100000000000000" + }, + { + "address": "52304b8321c4df0bd068386bcc67c38eda4e78c6", + "amount": "100000000000000" + }, + { + "address": "524043fcf064677787b4009674157e5ab106724b", + "amount": "100000000000000" + }, + { + "address": "525045a59b44173f08543f6db2dfd82da1180386", + "amount": "100000000000000" + }, + { + "address": "52604131ad343cd2d4e196bb823402aa089046c2", + "amount": "100000000000000" + }, + { + "address": "5270483dfb1a2f45363360ec692c2b07f8ba4e62", + "amount": "100000000000000" + }, + { + "address": "52804b2f75230f1d2813065a70f0a3d1bb4abc0b", + "amount": "100000000000000" + }, + { + "address": "52904d9cdc5e0a89d0efff246ef317dad054571e", + "amount": "100000000000000" + }, + { + "address": "53004082199e53af8651a8bcd495cdf0b9bda026", + "amount": "100000000000000" + }, + { + "address": "531048a70444edac7580b084639b953c483edb1c", + "amount": "100000000000000" + }, + { + "address": "532040437d02ebc3037d1c7753fd4f25dc1ef83a", + "amount": "100000000000000" + }, + { + "address": "53304f2156659c6ecc5cb4a3ab8afbe6ce298727", + "amount": "100000000000000" + }, + { + "address": "53404bccf31a949b64345f2bceb2de4e0e192552", + "amount": "100000000000000" + }, + { + "address": "53504f3c72ad9444d0d6e747cbfdac9a58180e9f", + "amount": "100000000000000" + }, + { + "address": "53604394038790e32dcbbff77dbb99f6a3ce0c1e", + "amount": "100000000000000" + }, + { + "address": "53704913ab93114aa38132ad58df09853c480171", + "amount": "100000000000000" + }, + { + "address": "53804c76af324412728608ae0e8426d96abc99c9", + "amount": "100000000000000" + }, + { + "address": "53904a4b7c3faea59d5d9b496e21ba2faf9379f2", + "amount": "100000000000000" + }, + { + "address": "54004020a779da577648aa43d0ff18b4fb26d324", + "amount": "100000000000000" + }, + { + "address": "54104186203eb30aa18f4e39ba5892c6c7161222", + "amount": "100000000000000" + }, + { + "address": "54204df4f5682d7a23f9d1c52c7afb9274962957", + "amount": "100000000000000" + }, + { + "address": "543047f632bc64ed249da3382134283074068708", + "amount": "100000000000000" + }, + { + "address": "54404c797a871873ca95884d8c30ae983dd57de9", + "amount": "100000000000000" + }, + { + "address": "545041d1f64a7d0a251ceea5cfbb843959415dfd", + "amount": "100000000000000" + }, + { + "address": "54604942a3f7615c118e3b6f27b683b3fb01903c", + "amount": "100000000000000" + }, + { + "address": "54704ac394b1d1b740d4661c17fffcb415af13e3", + "amount": "100000000000000" + }, + { + "address": "5480478c9f0787732218da068f82651023d36863", + "amount": "100000000000000" + }, + { + "address": "5490441ea32aee4b5d12cdecdd7a96b606502b1c", + "amount": "100000000000000" + }, + { + "address": "550046092b784c4710e2cd4f72c0784723f28f99", + "amount": "100000000000000" + }, + { + "address": "55104676e53c56dbf0723979519125308ffb7760", + "amount": "100000000000000" + }, + { + "address": "55204cfc23ff67ebd33b993db7a1fc8ae11ed6a9", + "amount": "100000000000000" + }, + { + "address": "553049d21748456f4d400a0e0c05b04bc4a17d42", + "amount": "100000000000000" + }, + { + "address": "55404f23ef78c2750bc800240a7c58089eec4ee5", + "amount": "100000000000000" + }, + { + "address": "555045a7188c95f9a7c2bebd91d70baf4446ef6f", + "amount": "100000000000000" + }, + { + "address": "55604b44996331b3e1bc734a5309a921a9ed68b2", + "amount": "100000000000000" + }, + { + "address": "55704c62bb4eb9f7d44463a9d23b4fc4ca967e8d", + "amount": "100000000000000" + }, + { + "address": "558041c40bda7eb7793f4974d937efbdbfe849ad", + "amount": "100000000000000" + }, + { + "address": "55904dad216482a42deafd26f46227f821c4318c", + "amount": "100000000000000" + }, + { + "address": "56004ef6b2bc5c6b261cc57df071c4d6b0d58942", + "amount": "100000000000000" + }, + { + "address": "56104b6933b27ebb07b76c9fbea00efae4b455f8", + "amount": "100000000000000" + }, + { + "address": "56204c3808a0aba40e0b892ec5ecc7ee748d656b", + "amount": "100000000000000" + }, + { + "address": "563045b3c9e24aa577bd71c73e65456725e6a43d", + "amount": "100000000000000" + }, + { + "address": "564040919f2c792a37b8169dd75787a150280910", + "amount": "100000000000000" + }, + { + "address": "565046147c04866c2804381096f4fbe231be5e27", + "amount": "100000000000000" + }, + { + "address": "56604b970a318d46fa25e919ecf52e47644d8e54", + "amount": "100000000000000" + }, + { + "address": "5670477c21534eedfda67b3ba2dedd4d1fd7a48a", + "amount": "100000000000000" + }, + { + "address": "56804868458d08fbf48b5fe3c989e528932c4bdd", + "amount": "100000000000000" + }, + { + "address": "56904945ed11c64451561a5da223dfef07a63d6c", + "amount": "100000000000000" + }, + { + "address": "570042453bea68860af0d5e1fae70f954ef92fbd", + "amount": "100000000000000" + }, + { + "address": "571048a293b79bb13e6a70d000fe0d112e4db1ec", + "amount": "100000000000000" + }, + { + "address": "57204b9e693914803c62940322f5432d213f0303", + "amount": "100000000000000" + }, + { + "address": "573041273c82a37e145392a75914fc028cb06e73", + "amount": "100000000000000" + }, + { + "address": "5740421e8340de6f8f11a052ba4c1dd0125b4a89", + "amount": "100000000000000" + }, + { + "address": "575043a39731f509415b44775c0819d1ed028f6e", + "amount": "100000000000000" + }, + { + "address": "57604dae805055c246a6fd0b455c62b1a964dcea", + "amount": "100000000000000" + }, + { + "address": "577047fd2cd22d149d9fd5cc0d2b764c10401f47", + "amount": "100000000000000" + }, + { + "address": "578045b49772c9c100287ef46ba7573d29f0787c", + "amount": "100000000000000" + }, + { + "address": "5790443ed1d326e9d7dcd5a0b08efd895aecfc9a", + "amount": "100000000000000" + }, + { + "address": "580042c8282aa038ab321e84eba447532ada0e9f", + "amount": "100000000000000" + }, + { + "address": "58104e0e46910bed78a45754b5406547c3c50fe9", + "amount": "100000000000000" + }, + { + "address": "5820411917585b430f3dcd1bf0d4ec9909077a4e", + "amount": "100000000000000" + }, + { + "address": "58304206194e2acd780efcbcd467784e84455a2d", + "amount": "100000000000000" + }, + { + "address": "584041e10f3f4e450ffff9e5843a6aaf0bd9e138", + "amount": "100000000000000" + }, + { + "address": "58504295adbe4b5825b8c647a886a8a4cd09796c", + "amount": "100000000000000" + }, + { + "address": "586047183d4b321949867cf34f33a2b89dc4cbda", + "amount": "100000000000000" + }, + { + "address": "587046ecb0f3ff0fbb597b0d129c86992ec5a610", + "amount": "100000000000000" + }, + { + "address": "58804dc8466d215f2eb4e0cce44cfc2be56a0a9e", + "amount": "100000000000000" + }, + { + "address": "589043b85f4a9eff43e7c28325bb8b4143fb3b41", + "amount": "100000000000000" + }, + { + "address": "590043d97155d5cc610fbaac50957bf5726adf38", + "amount": "100000000000000" + }, + { + "address": "591048978de1d5b41fe3295776e774cba204f182", + "amount": "100000000000000" + }, + { + "address": "5920456ab371c27ce7ea26013b948314751cb60b", + "amount": "100000000000000" + }, + { + "address": "59304b5ebd78c9b142c6c892be51e0e598cd052c", + "amount": "100000000000000" + }, + { + "address": "59404237be852ee16fd9ad5ea5cfee2c1e33e466", + "amount": "100000000000000" + }, + { + "address": "595047325b6fd4d83eb09dcdd41efe666650f407", + "amount": "100000000000000" + }, + { + "address": "59604e48e8378d4d55facfe4ebb8030b4ac15b77", + "amount": "100000000000000" + }, + { + "address": "597046a2893077b014e727ea04168cb56c0178a3", + "amount": "100000000000000" + }, + { + "address": "598042250dd6291126f9d6eaff6d2465f0f60f12", + "amount": "100000000000000" + }, + { + "address": "599042ed94c7838178f5d85634f9aa7ab8226a99", + "amount": "100000000000000" + }, + { + "address": "60004433bfc5145e5805d433007914fbd179e443", + "amount": "100000000000000" + }, + { + "address": "6010455003515da6f534e5f0350db7073839563f", + "amount": "100000000000000" + }, + { + "address": "602049f52ea2c0ebe5efe0a92e72e9e822ea4f97", + "amount": "100000000000000" + }, + { + "address": "603040fd618c8a153c2a74f73c4627ee565ff483", + "amount": "100000000000000" + }, + { + "address": "6040464732f9ff9878e360e2c16912e237a69862", + "amount": "100000000000000" + }, + { + "address": "60504b8e2db94604422624dc62c9e3126f8b7e76", + "amount": "100000000000000" + }, + { + "address": "606041d95feb88cf90feb74ddb61442bba982655", + "amount": "100000000000000" + }, + { + "address": "6070425ff0899d82336bb1038acb94aa9ba00c21", + "amount": "100000000000000" + }, + { + "address": "60804154da5db875b177aa5f89285a15129ba147", + "amount": "100000000000000" + }, + { + "address": "60904987c7f9cc9daae1355326def9b74ad5f53d", + "amount": "100000000000000" + }, + { + "address": "61004e257b9b5dd1d92ace4d326bfc6984d3eb74", + "amount": "100000000000000" + }, + { + "address": "6110407764cac536b59af8c85d3799cfd177dc71", + "amount": "100000000000000" + }, + { + "address": "61204c4cac74ff2faf6b8f5c32ff289a408bbb1d", + "amount": "100000000000000" + }, + { + "address": "6130482f2f773fd2ccdcead78253f503df74df5d", + "amount": "100000000000000" + }, + { + "address": "61404858cb7054b8cb842a186dbe60a7e300db19", + "amount": "100000000000000" + }, + { + "address": "61504179f6955dd6657724dd4146b146e4d54c09", + "amount": "100000000000000" + }, + { + "address": "61604b023003dac28306cd9220b2147390a07f49", + "amount": "100000000000000" + }, + { + "address": "61704f8eab2279a3c84e0568fb846dd66c959932", + "amount": "100000000000000" + }, + { + "address": "6180499d362b6d9765b0998a3abd7294c685f284", + "amount": "100000000000000" + }, + { + "address": "61904dbe91f98c168f4772897356e891565205d3", + "amount": "100000000000000" + }, + { + "address": "620040b3439cb928a9879b273010a99e5055e92b", + "amount": "100000000000000" + }, + { + "address": "6210405df49c7a7ee68fe3d72c9d55cc14ca0e8d", + "amount": "100000000000000" + }, + { + "address": "622040b5c622cf2fa9f9dfe29832dfe7d8944ae3", + "amount": "100000000000000" + }, + { + "address": "6230485e89c4581bbd18207c2dfa318d0e1c5c83", + "amount": "100000000000000" + }, + { + "address": "62404456d0a321660f444f9579b4f8fcb616de54", + "amount": "100000000000000" + }, + { + "address": "625045eb1422c6a258141c7420174e4f353228ca", + "amount": "100000000000000" + }, + { + "address": "62604278bc2457c61b1fb7bd62ab419160ea33bc", + "amount": "100000000000000" + }, + { + "address": "62704f0b74cd7705d048aba826b4bbdba837ee80", + "amount": "100000000000000" + }, + { + "address": "628040d02555d7e209b85123343f6c2431a5c7fb", + "amount": "100000000000000" + }, + { + "address": "62904e1ddae768ad6e9e5c9884ed3256996140c1", + "amount": "100000000000000" + }, + { + "address": "63004122cc25622025f0157cc56ea60f1551723d", + "amount": "100000000000000" + }, + { + "address": "63104ebb93a1c385fa95e48c77f1d3a1d5f99295", + "amount": "100000000000000" + }, + { + "address": "632044e7a8d184c949eb09a2869487aba0f73406", + "amount": "100000000000000" + }, + { + "address": "63304cb4079acb5dec9fab674720e23b668a30d9", + "amount": "100000000000000" + }, + { + "address": "63404b02237cdc0708fd3d0a34f46b6756844c48", + "amount": "100000000000000" + }, + { + "address": "635045f735ce51744a688f6d5075770464133b72", + "amount": "100000000000000" + }, + { + "address": "6360418f0d9fea319405d324ad5bfb4b7908260c", + "amount": "100000000000000" + }, + { + "address": "637047816ef8e3fbf907553627764c687ec67441", + "amount": "100000000000000" + }, + { + "address": "63804872395fc43ee4d6bac267c931ada198506d", + "amount": "100000000000000" + }, + { + "address": "639049314c67316267cb7b10df2a8167f9ae9b48", + "amount": "100000000000000" + }, + { + "address": "64004497fe1c37da0fafb12f633b6080929b41dc", + "amount": "100000000000000" + }, + { + "address": "6410453060cde98da46b8eeae93f4a213a51aaca", + "amount": "100000000000000" + }, + { + "address": "64204b02f42cf5b2606ee7069ba5e5b643acd036", + "amount": "100000000000000" + }, + { + "address": "64304c4006cc42bc15ad4ce569b388981fbff631", + "amount": "100000000000000" + }, + { + "address": "6440410b6010b8cda6a38d2ccc6785c5c56a70a2", + "amount": "100000000000000" + }, + { + "address": "645043e482206acec00090d8a3fdf4b96602dda3", + "amount": "100000000000000" + }, + { + "address": "6460443f08d3abef11110045198b1257a9ec76f8", + "amount": "100000000000000" + }, + { + "address": "64704a5d9ee1ee1d8e197e781319e4953ac8bb73", + "amount": "100000000000000" + }, + { + "address": "648046c02fe3c86598115b9de7ef6c1ea7ecc5f4", + "amount": "100000000000000" + }, + { + "address": "64904d6a4328e16e5a52962aa46fba9a7d35b4c9", + "amount": "100000000000000" + }, + { + "address": "65004bb380bc0c86de13d4a3547b662690da9bd9", + "amount": "100000000000000" + }, + { + "address": "65104222b9b770a93e7b6e4319b34c6c52cc9155", + "amount": "100000000000000" + }, + { + "address": "65204cb2035c55ea5df48463769e9744ad6f0393", + "amount": "100000000000000" + }, + { + "address": "653047e2d1a8fb3d9e1805dccac1cc6f2c28c556", + "amount": "100000000000000" + }, + { + "address": "654043b4e33de08eff8894cb7ca7a71a411db7d9", + "amount": "100000000000000" + }, + { + "address": "655046ec7d2eb9c66d4af6f73d2e8206566e4692", + "amount": "100000000000000" + }, + { + "address": "656047fd8c02ab8e3771d3cd053734f56a926389", + "amount": "100000000000000" + }, + { + "address": "65704439f9a3e216347069f62b7fb13e4b1f9b64", + "amount": "100000000000000" + }, + { + "address": "65804f628f171dff16be813578f80f4e3b7e0e3c", + "amount": "100000000000000" + }, + { + "address": "659049f81d3b432aedf5eec093af2f7144346c73", + "amount": "100000000000000" + }, + { + "address": "66004766c29d526595b8b005cbdce375ff5fdcec", + "amount": "100000000000000" + }, + { + "address": "66104dce510f16a8217c3844db10e5f137bc441a", + "amount": "100000000000000" + }, + { + "address": "66204361fe6b4729f27732acc739dd3764e7b07c", + "amount": "100000000000000" + }, + { + "address": "6630440e5e933646e978d8f937fd643563d99230", + "amount": "100000000000000" + }, + { + "address": "66404f5457eb934bfc6e975f9f6b04c01cc602dc", + "amount": "100000000000000" + }, + { + "address": "6650441b6f8afa3b01cd713d723be5a40c6ce247", + "amount": "100000000000000" + }, + { + "address": "666041989961aea5a1873df788e7e5a2b535334b", + "amount": "100000000000000" + }, + { + "address": "667044c105e7a685a522b53f64c4ab7de28063e6", + "amount": "100000000000000" + }, + { + "address": "668040d53879731c4a014ce64216c4c36ae2e7ac", + "amount": "100000000000000" + }, + { + "address": "6690401e4271d59a632ca3e4b06f38b445929ece", + "amount": "100000000000000" + }, + { + "address": "670046842562abde6d3d466644b9ca0f8fa8f7f2", + "amount": "100000000000000" + }, + { + "address": "671041b264453e02458397b587c4d0d550d2150d", + "amount": "100000000000000" + }, + { + "address": "672043e97db17eefaca6d9c82bd787f4c5e97128", + "amount": "100000000000000" + }, + { + "address": "6730458aec07fc2b32f4068c57314a82c6a4ae42", + "amount": "100000000000000" + }, + { + "address": "674042dca7e3832040eb9d80275364d45478017c", + "amount": "100000000000000" + }, + { + "address": "6750430cb460f6571cd65a92d9bccecbc2b89dd0", + "amount": "100000000000000" + }, + { + "address": "6760451d38daecf19bf46a6fc5fb2d280d39270e", + "amount": "100000000000000" + }, + { + "address": "67704441d1d0855396d871f4e726e929660bf8ff", + "amount": "100000000000000" + }, + { + "address": "67804ccfc22ed924ba1d5022ed11db444e0ad33f", + "amount": "100000000000000" + }, + { + "address": "679045eca99bd5ee98e2bdfe0a067b6d7eaaa477", + "amount": "100000000000000" + }, + { + "address": "68004cbe8b20f79043bd60e6d407a892725c0218", + "amount": "100000000000000" + }, + { + "address": "681040fd5fbf65ee66ccfad1fc530d0f60d675af", + "amount": "100000000000000" + }, + { + "address": "68204296b18ed685fab791e7f7371f86fa3dbf15", + "amount": "100000000000000" + }, + { + "address": "683049213af4a3ed07b8dc4a078aa8bc485fb762", + "amount": "100000000000000" + }, + { + "address": "68404ac8c50e40e149ff2a292e350b8002361c9f", + "amount": "100000000000000" + }, + { + "address": "68504af73aa4ae030a8579cd54da6a8e71b2c121", + "amount": "100000000000000" + }, + { + "address": "68604c15e95f52d3039f453eac003c8d6b85abbd", + "amount": "100000000000000" + }, + { + "address": "68704e3bc93591d552942fe92f91889fbce4832a", + "amount": "100000000000000" + }, + { + "address": "68804b25a7116144f61e73e74e21adbe825b205f", + "amount": "100000000000000" + }, + { + "address": "68904c03e391f951339c9958eb5bc72c43ad63e3", + "amount": "100000000000000" + }, + { + "address": "6900418575027f2a1c247bbaa0609ae9cf80ab75", + "amount": "100000000000000" + }, + { + "address": "691041eab10813cc60e8fed6536903cd21635b13", + "amount": "100000000000000" + }, + { + "address": "69204a4b90e76b575773b257644c33f044455e73", + "amount": "100000000000000" + }, + { + "address": "693045b878d184546a55e1f2d2ed3fee47e08a69", + "amount": "100000000000000" + }, + { + "address": "69404b70bf4a3c1854d289bf48aff4ffcc54462d", + "amount": "100000000000000" + }, + { + "address": "695047251a6b4dc26af3dafeb2ad9e8bd11899f7", + "amount": "100000000000000" + }, + { + "address": "696042291abaeefbfe88cf4c6640cb8334fb5387", + "amount": "100000000000000" + }, + { + "address": "69704c4391043c0103e88d84b976b77eb8f58511", + "amount": "100000000000000" + }, + { + "address": "698045d16859ea22f965199057d94ef729316962", + "amount": "100000000000000" + }, + { + "address": "6990471405d1359a4951ff69f05f3a6ba5e322d3", + "amount": "100000000000000" + }, + { + "address": "700045ae96df298ad66c9407341aa1c9c4b7e3df", + "amount": "100000000000000" + }, + { + "address": "70104bbe466157ff39778c0efa245e729b33a00f", + "amount": "100000000000000" + }, + { + "address": "70204fc5a25b35b2ae011c05a06debe3c138cc6c", + "amount": "100000000000000" + }, + { + "address": "70304e51707696936993f6865f3f1be774f22c05", + "amount": "100000000000000" + }, + { + "address": "704041ae13c7807d1007bce82206adc28dec9bbf", + "amount": "100000000000000" + }, + { + "address": "70504f23e2a3f569a63533ac1b116a4680596abb", + "amount": "100000000000000" + }, + { + "address": "70604bbeaf187b5b24ac8f11df5f9a404432a899", + "amount": "100000000000000" + }, + { + "address": "707043290fd9d435c104db4a9a192023f432054a", + "amount": "100000000000000" + }, + { + "address": "708049eadf139b3036e1eddded3bf44fe803da63", + "amount": "100000000000000" + }, + { + "address": "70904ac80bef69aff0800bb6554f5f01443113e9", + "amount": "100000000000000" + }, + { + "address": "710041d7fff4b20bd4460b108e314d2fc832b2d2", + "amount": "100000000000000" + }, + { + "address": "7110486af5e1932f8b0ed8e82224012d4bb4a6e6", + "amount": "100000000000000" + }, + { + "address": "7120458a83f65b14f570912acd93701cc3689098", + "amount": "100000000000000" + }, + { + "address": "71304ce8abec1dc3eb97a538274a97f65bed3a3e", + "amount": "100000000000000" + }, + { + "address": "714045b6adbfbcb7b04f6763ff9f5f7f36b0b653", + "amount": "100000000000000" + }, + { + "address": "715040b8b724a8eb1f9f31eba45e384725408d0e", + "amount": "100000000000000" + }, + { + "address": "7160455702053e3a8a3ef39971eb848d9d6fa93c", + "amount": "100000000000000" + }, + { + "address": "7170477eaccf217f57b35c55cab9e2dbc62433db", + "amount": "100000000000000" + }, + { + "address": "71804ead1df28012d17172a0775cbac6cd999306", + "amount": "100000000000000" + }, + { + "address": "71904efa4dca8d0ce5608b4689f8bf9cc51f9df8", + "amount": "100000000000000" + }, + { + "address": "720049fd5ac173f954454258e7673d1d39d2dce4", + "amount": "100000000000000" + }, + { + "address": "72104a97065ed6db665ec6d59852f1a5497f3beb", + "amount": "100000000000000" + }, + { + "address": "72204c482f30096b5a80c9411eb724979b6df892", + "amount": "100000000000000" + }, + { + "address": "72304639b82708bbdb5ab2e20dfcb5148084de30", + "amount": "100000000000000" + }, + { + "address": "72404e838cd0e07e6a01e23ca678ee364721cf92", + "amount": "100000000000000" + }, + { + "address": "72504fe21ab8f1ce70ad1f29122222a742150ff0", + "amount": "100000000000000" + }, + { + "address": "72604117cf813be0dffaefbf4806e5699344e5c3", + "amount": "100000000000000" + }, + { + "address": "72704dfacba8503a46b1e5e7e6aa8280880e6e65", + "amount": "100000000000000" + }, + { + "address": "72804ca70d543e1e4369abd90b9d6022f3a1d97c", + "amount": "100000000000000" + }, + { + "address": "729043b384b8354d7a54c2428b22222f7898f9c6", + "amount": "100000000000000" + }, + { + "address": "73004fa9859d249efb0a91fc915af55ec49cd444", + "amount": "100000000000000" + }, + { + "address": "731040db933ad7d8e99b88440a76e3cee5eb6e69", + "amount": "100000000000000" + }, + { + "address": "73204343469ac1f556f0377d90b69f3dbf5a982c", + "amount": "100000000000000" + }, + { + "address": "733049362478534ff6410823044e071eb2f83e4f", + "amount": "100000000000000" + }, + { + "address": "73404f1945447051bf690a173519ba74645e994a", + "amount": "100000000000000" + }, + { + "address": "735042862d5212cfefc9b5f324ce13fa9b325705", + "amount": "100000000000000" + }, + { + "address": "73604c4ab9e12a56a90e738b6a231cfbd5a49e66", + "amount": "100000000000000" + }, + { + "address": "73704b14cd41d45fab3fe2b4b7757d57249db53b", + "amount": "100000000000000" + }, + { + "address": "7380460d3ff8820e5b3cfb10a80d408caaa66dae", + "amount": "100000000000000" + }, + { + "address": "739048ca6dda2acaa91f555fb45dd6ba2ca17958", + "amount": "100000000000000" + }, + { + "address": "74004606ce8137e61a116e85357ab666f1aab529", + "amount": "100000000000000" + }, + { + "address": "74104e0fa50aac8cda9809d603430ea7ea65d122", + "amount": "100000000000000" + }, + { + "address": "742040c7efac6132191fa24d16fca79a600ed23e", + "amount": "100000000000000" + }, + { + "address": "7430460fa50f3a7e2d7765c6b5f30724720f6fc9", + "amount": "100000000000000" + }, + { + "address": "74404c120f2909457a3ddad0abffae055890eee9", + "amount": "100000000000000" + }, + { + "address": "74504191374ac2d4fbdbc976b63e007d8b5e7e72", + "amount": "100000000000000" + }, + { + "address": "74604ac62f17d849b24cb9a1e2bd680f107a3977", + "amount": "100000000000000" + }, + { + "address": "747047f7087dd2aeb62a5eb6e3f15c1e6e1721b5", + "amount": "100000000000000" + }, + { + "address": "74804357c658d6575aa6746be8f25c04c4e9adcb", + "amount": "100000000000000" + }, + { + "address": "7490485def5367ca659bab67b979ffd181be6852", + "amount": "100000000000000" + }, + { + "address": "7500405f2ec0db786c0d56dec170ccb668f781ae", + "amount": "100000000000000" + }, + { + "address": "7510441d0cd71400a2ddd1516c4e08d9cfc0f5af", + "amount": "100000000000000" + }, + { + "address": "75204971b2ae461e5e989ad3733bf7c83be3580c", + "amount": "100000000000000" + }, + { + "address": "75304cb27016bd796a512070a5ddad6c22cbfa34", + "amount": "100000000000000" + }, + { + "address": "75404d484447585d4699de2133301894f7f0a0b9", + "amount": "100000000000000" + }, + { + "address": "75504f5535dd8986c8688946fc5f5580b7a8dd38", + "amount": "100000000000000" + }, + { + "address": "75604cd760a93f2f5286d8a7c24bcb17a6cbc4c2", + "amount": "100000000000000" + }, + { + "address": "757040f861c5d33d40d5cd88dbf9d494c344b2c3", + "amount": "100000000000000" + }, + { + "address": "758047bbc4e2ea7a59a65b82d83577abb225991d", + "amount": "100000000000000" + }, + { + "address": "7590432ee6c2f2e6c259b3d77337501615a5bf50", + "amount": "100000000000000" + }, + { + "address": "76004b9870bfe097f21d85c768a338502c3efd29", + "amount": "100000000000000" + }, + { + "address": "7610492a5a430b406f4f95c2c204d1a400b84ad8", + "amount": "100000000000000" + }, + { + "address": "76204cea7ee3fc87e957dd7dda7a70c949f26ccd", + "amount": "100000000000000" + }, + { + "address": "76304fc25e32600ba08528d168ca05e7d2010913", + "amount": "100000000000000" + }, + { + "address": "76404f703f4798300860345bf1ff81f0de6ffe8d", + "amount": "100000000000000" + }, + { + "address": "765045358ae8a44e3b1d7caa7f46c9b78ef724ef", + "amount": "100000000000000" + }, + { + "address": "7660435988f9ee112cbea0abf18e2e7ca419949c", + "amount": "100000000000000" + }, + { + "address": "76704fb154d0c3ab08652990fe69a940ed882c93", + "amount": "100000000000000" + }, + { + "address": "7680467f75f10cd807b0a27f7628269578a1c006", + "amount": "100000000000000" + }, + { + "address": "76904da84cd85eb2ec2ff690aeb4a7a1d648f413", + "amount": "100000000000000" + }, + { + "address": "7700458dc09f5383173182fde54f7b17935882c7", + "amount": "100000000000000" + }, + { + "address": "77104d3b0c4c656adba6d327c7b79f9ce8d94800", + "amount": "100000000000000" + }, + { + "address": "7720490fd89c46309eb4dc414e4b4fabf2a7fc57", + "amount": "100000000000000" + }, + { + "address": "77304d60249375837d59fe84b04ccc716ec30e68", + "amount": "100000000000000" + }, + { + "address": "774044dc674f47ff6d1b0dcd008aa4d86d53d245", + "amount": "100000000000000" + }, + { + "address": "77504d1b358a2fcbe5970628dde6e8ec705f76d8", + "amount": "100000000000000" + }, + { + "address": "7760402fe920bf6f4df37e081b3dfdc00954ff0f", + "amount": "100000000000000" + }, + { + "address": "777044ba8b3cc26d90da9f5a5f7863ef6c9d8c53", + "amount": "100000000000000" + }, + { + "address": "77804f8edbd62aa1d1e77d7834fbd817494d7e38", + "amount": "100000000000000" + }, + { + "address": "7790428083b35b7b088c2ac0e8113d3ccdc92eeb", + "amount": "100000000000000" + }, + { + "address": "78004e3cc37af45c0e372a37b2b08460b55bd775", + "amount": "100000000000000" + }, + { + "address": "7810493ae5c20904e6e8f2426e4d195ce0f1f3e5", + "amount": "100000000000000" + }, + { + "address": "78204a6682e722ba0a892960262eb1c9fda42ffb", + "amount": "100000000000000" + }, + { + "address": "78304b58974edd0eae39ef9c965f51eb16f2be03", + "amount": "100000000000000" + }, + { + "address": "78404c610ff998f92d9cc87b4ea1573cbd8f9339", + "amount": "100000000000000" + }, + { + "address": "78504ad330e8e41e81bf50082715f817d1a0a38d", + "amount": "100000000000000" + }, + { + "address": "78604f683cad2be47167a8b646128e1e84b277fa", + "amount": "100000000000000" + }, + { + "address": "78704013460b7c14c49d5d741326012cbe122bee", + "amount": "100000000000000" + }, + { + "address": "78804e1e31a15b13f264f7722db855f5677df70c", + "amount": "100000000000000" + }, + { + "address": "789046646c7fb2a2eb633c2e5e570af634b0238a", + "amount": "100000000000000" + }, + { + "address": "79004e3e7e74b663437a69c867216f047ad606dd", + "amount": "100000000000000" + }, + { + "address": "7910492ffe5550fb16f895bb7e8250a3d715771b", + "amount": "100000000000000" + }, + { + "address": "79204718fe2312b236ec58494a3e9b7f90c89e73", + "amount": "100000000000000" + }, + { + "address": "793048a8b77b03ecc7a3bc39d744f7d413559025", + "amount": "100000000000000" + }, + { + "address": "794041ee030eb5d43c58833fddf6f205f9a8c014", + "amount": "100000000000000" + }, + { + "address": "795049298725fffe87c4593dfbccb595e8791a3b", + "amount": "100000000000000" + }, + { + "address": "796048b394f862a92e5c8d9122c9ad5d485534eb", + "amount": "100000000000000" + }, + { + "address": "79704cbe24d2a5470953109554dc4ce56a2c84d7", + "amount": "100000000000000" + }, + { + "address": "79804beaba60ecb5eb2b77d4cdfdd1942b805f49", + "amount": "100000000000000" + }, + { + "address": "799045cfacb0e38a8d911fb39ff6397adc1f15eb", + "amount": "100000000000000" + }, + { + "address": "800040c36ade282fda9785c5e62213fe0d5d0312", + "amount": "100000000000000" + }, + { + "address": "801045faaed561eef624c2aca9076a2e66ed54e6", + "amount": "100000000000000" + }, + { + "address": "80204aea3fb91f7c90dee4ebcccec023908213f1", + "amount": "100000000000000" + }, + { + "address": "803046df6243205308bfe7259304a93a9637fed8", + "amount": "100000000000000" + }, + { + "address": "804040e821386c7eb980b981c07da31a9259e76c", + "amount": "100000000000000" + }, + { + "address": "805046b83fccfe43723e00bf5eb1dc058843c80f", + "amount": "100000000000000" + }, + { + "address": "806041951a05cf13b69d8067896675b584830d0e", + "amount": "100000000000000" + }, + { + "address": "80704002998850477f6640306c3c79f0970c5371", + "amount": "100000000000000" + }, + { + "address": "808043b8a07f468d3025ba172a6bc52d2b7523c3", + "amount": "100000000000000" + }, + { + "address": "80904548b7d57c71b2eb3de9d8dacbca8c3e20b6", + "amount": "100000000000000" + }, + { + "address": "8100497c04b5bc57d186afb7b4a15c34d29b8188", + "amount": "100000000000000" + }, + { + "address": "8110496672fbcaf610dcf186d0a1b484b228484c", + "amount": "100000000000000" + }, + { + "address": "81204469c77571ceabc193ec1c488a65bd08dc78", + "amount": "100000000000000" + }, + { + "address": "81304a805fa1d581378b31d9a0ea87e1973c44f4", + "amount": "100000000000000" + }, + { + "address": "8140425c4d8f0a3217c9ab13623270f3b992c00a", + "amount": "100000000000000" + }, + { + "address": "81504ddb923189b0e870a3b50ad910a3b5753f21", + "amount": "100000000000000" + }, + { + "address": "816042f0724b82005bff27112ce3a316e901e0f4", + "amount": "100000000000000" + }, + { + "address": "8170452c586b93dc1d7e514798fbe7850c2789dd", + "amount": "100000000000000" + }, + { + "address": "81804732d11fcee01a02cde6216a8e3edf0884a6", + "amount": "100000000000000" + }, + { + "address": "819040aa22f80c84c0977e463e0763579f1609f2", + "amount": "100000000000000" + }, + { + "address": "82004fe0e73638a8772bed9964d5323cc1c8cce3", + "amount": "100000000000000" + }, + { + "address": "821040ccec8c6129935e6a3f9bcf970948d55287", + "amount": "100000000000000" + }, + { + "address": "8220437ddde50e58b8327039bc6f457649d63a31", + "amount": "100000000000000" + }, + { + "address": "823042082e15aa436506c6379eeebd842c6313a3", + "amount": "100000000000000" + }, + { + "address": "82404388de5c42b260394efbd3ad4ccf708b9a25", + "amount": "100000000000000" + }, + { + "address": "82504a4f983dfba8d0c878a61b5276f011899158", + "amount": "100000000000000" + }, + { + "address": "8260482c4fbb5891e2dbbcb6a5c639b715473cae", + "amount": "100000000000000" + }, + { + "address": "827048d080883ae8876f0da515feb5772f64fcfb", + "amount": "100000000000000" + }, + { + "address": "828045fc2303b1afa7652f424b2c568c4c3d8256", + "amount": "100000000000000" + }, + { + "address": "829044583424c97871c023f9b4234cb5d468457a", + "amount": "100000000000000" + }, + { + "address": "830049dbb7faf8390c1f0cf4976ef1215c90b7e4", + "amount": "100000000000000" + }, + { + "address": "83104c657ae2e8aa2d9c89d9480ae55aa321b252", + "amount": "100000000000000" + }, + { + "address": "83204812d180c66f212ebdb89cde6606dad7b242", + "amount": "100000000000000" + }, + { + "address": "83304fa5b0481d15a160bca05e899edef8b602bf", + "amount": "100000000000000" + }, + { + "address": "834045a632211a9ebfd436d83dd178f2994473d8", + "amount": "100000000000000" + }, + { + "address": "8350444055dbbd40bde22e6455381e283f5b6b11", + "amount": "100000000000000" + }, + { + "address": "83604d5f7b6a9054c3fd0ba3f95459976b2547b7", + "amount": "100000000000000" + }, + { + "address": "837041d1c1fd6a43e2f8b03211a6b225cdd44976", + "amount": "100000000000000" + }, + { + "address": "8380491ed4a12cfa13893e74819e311bf7a12d8f", + "amount": "100000000000000" + }, + { + "address": "83904bed445a6e9c4a6852af272da17f588dc410", + "amount": "100000000000000" + }, + { + "address": "8400455d79ff6780de6c49bae8c55c2c31cb63f7", + "amount": "100000000000000" + }, + { + "address": "84104a221b2bfba81e26b6a23359ae58cc979a55", + "amount": "100000000000000" + }, + { + "address": "842043630e1449760a1b25087f5f50a9e373ffdb", + "amount": "100000000000000" + }, + { + "address": "843042a6e0926fe91a51698694b4b959a2de377f", + "amount": "100000000000000" + }, + { + "address": "844046b4a8c4600bd55d177e4d4ea4e89d0b4ded", + "amount": "100000000000000" + }, + { + "address": "845047eb2f2acc3b5c60bedb64a6565b048159df", + "amount": "100000000000000" + }, + { + "address": "84604b8cbdca589f843a841957b104862cbcb5d6", + "amount": "100000000000000" + }, + { + "address": "847042033cfd9f001a06ebcc2504901561f21da1", + "amount": "100000000000000" + }, + { + "address": "84804082583aec69e4607a22e72c60cb056116c5", + "amount": "100000000000000" + }, + { + "address": "849046dc53c92d02169ab2d4309cf0cd760c8dcd", + "amount": "100000000000000" + }, + { + "address": "85004fd156e059ccaaf4749ba2df7ba24de530a1", + "amount": "100000000000000" + }, + { + "address": "8510485f42a056460eb4f0291b0a72af35646d87", + "amount": "100000000000000" + }, + { + "address": "8520480dd3e656c0331952c265a78fdf8e3f5d49", + "amount": "100000000000000" + }, + { + "address": "85304ee06bac526cdc6a53500afbf91d0858c3eb", + "amount": "100000000000000" + }, + { + "address": "85404ecad2db6d6e414ef872827ab2edf811536b", + "amount": "100000000000000" + }, + { + "address": "85504fec36d0d6688d26af1f6fc345e76ade37d4", + "amount": "100000000000000" + }, + { + "address": "8560447acb6bc46cf04ec87b6c5bbb6b357454e3", + "amount": "100000000000000" + }, + { + "address": "857040fcce4a431006f9c552d01e77dfbe292bff", + "amount": "100000000000000" + }, + { + "address": "85804f279fe013dbaf2bdc210af86fc87946ebb3", + "amount": "100000000000000" + }, + { + "address": "8590479a8887c9215b9374410762e43753fd63b6", + "amount": "100000000000000" + }, + { + "address": "860040cc1341444b4b08675dea43a1ba2346e10d", + "amount": "100000000000000" + }, + { + "address": "861048828d752c8e69dfca134eee268d13a3ef80", + "amount": "100000000000000" + }, + { + "address": "86204cb5b528864a8266dfb08004c84f7ca846ac", + "amount": "100000000000000" + }, + { + "address": "86304ffd7c44f1c66931ca9cb36f77d82efaa839", + "amount": "100000000000000" + }, + { + "address": "86404e14d4fb029910caecf02ef989761e3297a0", + "amount": "100000000000000" + }, + { + "address": "8650494118a2ef12e07deccc0aa8c1a9c9875871", + "amount": "100000000000000" + }, + { + "address": "866046aa60688a43250cc2ed13fb0fc4ea146b44", + "amount": "100000000000000" + }, + { + "address": "8670497332aa6a185622948006adcfb226bcf22b", + "amount": "100000000000000" + }, + { + "address": "86804452bfbef5a5b6224b73fd94691234c09c44", + "amount": "100000000000000" + }, + { + "address": "86904613b2ba2159755abc593ccdeb1ce12fb64f", + "amount": "100000000000000" + }, + { + "address": "870049c927a4c40479b65b70f03ebfe68dcce4ee", + "amount": "100000000000000" + }, + { + "address": "87104e2b9fec39b3cfd27e3f236407b8c5dd21e7", + "amount": "100000000000000" + }, + { + "address": "872049d58d11e6d5dcf92492706a57700a3b9c78", + "amount": "100000000000000" + }, + { + "address": "87304b9b70b119da73715ea15e77df1c47dee9de", + "amount": "100000000000000" + }, + { + "address": "87404d313145fbffe1a60080426331dfbbccde88", + "amount": "100000000000000" + }, + { + "address": "8750482f002575a5b05b23a4a2fe81e72a85903e", + "amount": "100000000000000" + }, + { + "address": "876040e63de214d3d97c41c5e2506835356febfd", + "amount": "100000000000000" + }, + { + "address": "8770403d44ac830ef4d787674be73fc60487e6b9", + "amount": "100000000000000" + }, + { + "address": "878046336c193431737bce3b3f7bb59fb560a306", + "amount": "100000000000000" + }, + { + "address": "8790470a45f434b064286df6716cf56884abe0d2", + "amount": "100000000000000" + }, + { + "address": "880040754a3c36b9c6dd10b7cb3eb6540d047a3f", + "amount": "100000000000000" + }, + { + "address": "8810480c4bcd788ad9e5b72667d82c42946815a3", + "amount": "100000000000000" + }, + { + "address": "882046a981d4f3fbe823cc786031162553a8e0dd", + "amount": "100000000000000" + }, + { + "address": "8830406539e2484ac4c47a6812ae758d79221c59", + "amount": "100000000000000" + }, + { + "address": "8840415de6febc6c8eff4f6a9ca2c980bdb37343", + "amount": "100000000000000" + }, + { + "address": "8850467d1d836e07f22fd0d11d127a868c568b3d", + "amount": "100000000000000" + }, + { + "address": "8860473aabc1e8c3d6e68eca590113fc9a6e18a8", + "amount": "100000000000000" + }, + { + "address": "88704d73662804ac9d280bbbf7c829b8bb44eed9", + "amount": "100000000000000" + }, + { + "address": "88804d3c7e71be9145c486df8c5e3f50fe3d585e", + "amount": "100000000000000" + }, + { + "address": "88904f29e996fe348e2e08e436d62bcfe2ab43d4", + "amount": "100000000000000" + }, + { + "address": "89004a83edbdb171fb10d403fc12f61712713dc3", + "amount": "100000000000000" + }, + { + "address": "89104c7c4650b47edcd89027f02b869b288a4233", + "amount": "100000000000000" + }, + { + "address": "89204680d0b82eb5d0a7cd38cc79303fb08c0a39", + "amount": "100000000000000" + }, + { + "address": "89304a88a2c22402b132a03b79207edfc1d53521", + "amount": "100000000000000" + }, + { + "address": "89404525c0cdadfbc8254978cbd47c3f730f6061", + "amount": "100000000000000" + }, + { + "address": "89504de91c02f4fc3514641bd2582d5a43450e67", + "amount": "100000000000000" + }, + { + "address": "89604969d23518afac4fc4b2b49cb827dea90cb4", + "amount": "100000000000000" + }, + { + "address": "897049b15315f7b4a8ec4ffef90d0db4b15fad05", + "amount": "100000000000000" + }, + { + "address": "89804e7a03a222cd2042f671f17fdb4e7b89c70b", + "amount": "100000000000000" + }, + { + "address": "8990454279c9296f15f4b9027b7ede5e875ff7ba", + "amount": "100000000000000" + }, + { + "address": "9000472babb942be176fa7c342ddb562bfc17993", + "amount": "100000000000000" + }, + { + "address": "90104d03cea867215a2f79d6b1b42fd286a2372c", + "amount": "100000000000000" + }, + { + "address": "90204df1a7d64dd87c3a2ab0e790f66ab7a078da", + "amount": "100000000000000" + }, + { + "address": "90304de617a78d7b8f131deafef6c56c60b1e157", + "amount": "100000000000000" + }, + { + "address": "90404100b1b6572b8f50e7eeab9f43c410b79bda", + "amount": "100000000000000" + }, + { + "address": "905040be7d14a7f3ecf1062254649069e5df7795", + "amount": "100000000000000" + }, + { + "address": "906042c145bb61505e6e03c8e8f0ead7506d9e14", + "amount": "100000000000000" + }, + { + "address": "90704b50a773c5ae28e867d9af6915d1a5f05b41", + "amount": "100000000000000" + }, + { + "address": "9080431cc7d962dc0df5bfa76c05c2988f7c7588", + "amount": "100000000000000" + }, + { + "address": "90904758c69a7bf7db7c018ab62672c854494f98", + "amount": "100000000000000" + }, + { + "address": "91004b7156b7f06c1df3d652361b0236b656f54c", + "amount": "100000000000000" + }, + { + "address": "91104d6aeccb5e420df5a2031b309d57f9c30af7", + "amount": "100000000000000" + }, + { + "address": "912042f7dbb1b21e5807ef53706b5a66321e65e9", + "amount": "100000000000000" + }, + { + "address": "91304671b71c2a3d12eb6d51a921509aa781f853", + "amount": "100000000000000" + }, + { + "address": "9140499d47cd284a1817d1a431eccb6c6f3897d6", + "amount": "100000000000000" + }, + { + "address": "91504815a6df26c9a3e142ee6b0509a30b258d64", + "amount": "100000000000000" + }, + { + "address": "91604800d1329fde56d1cab995ea32698b0ea48d", + "amount": "100000000000000" + }, + { + "address": "917043c3f9ccc184acb6bdebf3c7c8d1e6272d3b", + "amount": "100000000000000" + }, + { + "address": "91804ba18ce38f7c37d19530bcf0a2d08d601ebb", + "amount": "100000000000000" + }, + { + "address": "919042fc90de9cb87c320fd7ce0dfbde484d2915", + "amount": "100000000000000" + }, + { + "address": "920041940cd8a4e6fe691bac5cf316b5fd83dc85", + "amount": "100000000000000" + }, + { + "address": "92104bc1a3533ca7b034928f7c44ffebfb5669ae", + "amount": "100000000000000" + }, + { + "address": "92204b0945978912b9798859599b6a8879904dbf", + "amount": "100000000000000" + }, + { + "address": "923046ed4b42686dd841059917c2a82a19b4eae7", + "amount": "100000000000000" + }, + { + "address": "92404fdc369b099b3ba39551010a0ae267b8a0d3", + "amount": "100000000000000" + }, + { + "address": "92504a904a7a49ddc5c347704f5cf641538a683b", + "amount": "100000000000000" + }, + { + "address": "9260415480d030341a78cac35928b1d58ead468c", + "amount": "100000000000000" + }, + { + "address": "92704b20d56a52096c96853682d497809ac8a644", + "amount": "100000000000000" + }, + { + "address": "9280414564c13d52995b5c97a1edbbbe9398fd79", + "amount": "100000000000000" + }, + { + "address": "929048ae6f99b502d1e8d8659c06311fa023a37c", + "amount": "100000000000000" + }, + { + "address": "9300459038aca9253f485af17189d4d761ee16cf", + "amount": "100000000000000" + }, + { + "address": "93104dce3896e7013ec4b4373bc037ea34a9024d", + "amount": "100000000000000" + }, + { + "address": "932041772f90a64f76fd8d088179fa812f00d4e9", + "amount": "100000000000000" + }, + { + "address": "93304ed9b8185ce822360967447c164425f8ee85", + "amount": "100000000000000" + }, + { + "address": "9340469f9aa3259a2d941f668f33c1352177b431", + "amount": "100000000000000" + }, + { + "address": "9350424afed2719af57946f261e28bc536b2e670", + "amount": "100000000000000" + }, + { + "address": "93604fed35670e2a5b9bb9664ec5dd2a8df8622b", + "amount": "100000000000000" + }, + { + "address": "937044aca7e544f4f3bf390c72a528139d99570c", + "amount": "100000000000000" + }, + { + "address": "93804c365ad48f71d5feb09fb369bf71752d01f8", + "amount": "100000000000000" + }, + { + "address": "93904e6c56c737ad30ba95ee3c035ca50949a241", + "amount": "100000000000000" + }, + { + "address": "94004b81cc9f530a41b173cbe610855a0d6d64a6", + "amount": "100000000000000" + }, + { + "address": "94104967e8765b059887acc9163afd1c92bdc67f", + "amount": "100000000000000" + }, + { + "address": "94204f7637a290288069f8fa685ffdf25e1c869b", + "amount": "100000000000000" + }, + { + "address": "94304ac0c080d0a89071c616fb302379149c1b00", + "amount": "100000000000000" + }, + { + "address": "944040b51cc1b8aa4c279f762407603bcd881009", + "amount": "100000000000000" + }, + { + "address": "94504f83b51f1202cc792f8176206fb097df6012", + "amount": "100000000000000" + }, + { + "address": "946049033f9aee708411907b949654ff26b51a01", + "amount": "100000000000000" + }, + { + "address": "947041d06386084692a7c08c411407542a5f079f", + "amount": "100000000000000" + }, + { + "address": "94804f75beec2ab62c24a467dc8458052cf2d4e7", + "amount": "100000000000000" + }, + { + "address": "94904c195c64f1954eec679246d71220aa633e38", + "amount": "100000000000000" + }, + { + "address": "950040d8f3b3c16d8d5f3ebffe1a9d11bc7983e4", + "amount": "100000000000000" + }, + { + "address": "951041e30df6b7a32cb3e6d01ab859350082e095", + "amount": "100000000000000" + }, + { + "address": "952040329c551f70a521d7b61ca958e97303fc60", + "amount": "100000000000000" + }, + { + "address": "9530473f409d364affc33a63894c33404885e7c0", + "amount": "100000000000000" + }, + { + "address": "954041a001bd70a0484f3dfba6d53ae29537b9e5", + "amount": "100000000000000" + }, + { + "address": "95504bcf8b4777e0d8f4525064fa1b8546d851e8", + "amount": "100000000000000" + }, + { + "address": "95604254b548a7eb21d62929878bd1f42e768309", + "amount": "100000000000000" + }, + { + "address": "95704d45620fc4506f2a1448f6ea83d342c0b70f", + "amount": "100000000000000" + }, + { + "address": "9580450e47feb1931fc507b6fb946df04788a775", + "amount": "100000000000000" + }, + { + "address": "95904789595b1d1b9e580a52a61bd88ebf642bd2", + "amount": "100000000000000" + }, + { + "address": "96004a53c3c0bd200f6bdf8201e32bcbc97d6edf", + "amount": "100000000000000" + }, + { + "address": "96104842c185e35bfb61d5e3525531c4c68338d6", + "amount": "100000000000000" + }, + { + "address": "96204d23d73724fef1f217b9fa3629217aa78809", + "amount": "100000000000000" + }, + { + "address": "963048f029d166e675e52ac472c42fc460c51bee", + "amount": "100000000000000" + }, + { + "address": "96404e241e8ef28dc1642212be0473121bb69d24", + "amount": "100000000000000" + }, + { + "address": "96504a7b7433313702b495ab5be6b1c35f56bf17", + "amount": "100000000000000" + }, + { + "address": "96604e53196b5ccd5bda81a0235b2ff333345125", + "amount": "100000000000000" + }, + { + "address": "96704cb4c16eb1b841def729e92d8810157ce797", + "amount": "100000000000000" + }, + { + "address": "96804c0924ca87184e536e121e37e8533b318afe", + "amount": "100000000000000" + }, + { + "address": "96904e717839fd6445721e2cd9e9a14ef582919a", + "amount": "100000000000000" + }, + { + "address": "97004e3db06153e5e97c715eeedb466503ecaaec", + "amount": "100000000000000" + }, + { + "address": "97104aac1f2575cc78a5b70baaacdf0e05bf6f59", + "amount": "100000000000000" + }, + { + "address": "972049d3284c1db53a587a14ea24dff292257dd6", + "amount": "100000000000000" + }, + { + "address": "97304900781cec2ebcf1cde90ae1b08188cbc524", + "amount": "100000000000000" + }, + { + "address": "974041c53c33cc1e80534299bdaee9ba4595e6e4", + "amount": "100000000000000" + }, + { + "address": "97504ece3e7fc1dbf05d50ccae734b467caa84df", + "amount": "100000000000000" + }, + { + "address": "976044c4c2e66323bbb761f7aa1706096c9d16ec", + "amount": "100000000000000" + }, + { + "address": "97704be19df706440b2d080f50b6eb4a2bcc3c18", + "amount": "100000000000000" + }, + { + "address": "978049e7b1deb4d01f7bc0c471662d41f48a956b", + "amount": "100000000000000" + }, + { + "address": "979045ffe3a861016ce74427be6932047b59ecf7", + "amount": "100000000000000" + }, + { + "address": "98004645f52f575c3a48964e125522ee9042f775", + "amount": "100000000000000" + }, + { + "address": "981049acf75d47ad897a9971c8f93e01ee0c1723", + "amount": "100000000000000" + }, + { + "address": "982046598e03d4d845ebb540300fb2ce2f162edd", + "amount": "100000000000000" + }, + { + "address": "983048ad983e11741528bee423f0e848470bad88", + "amount": "100000000000000" + }, + { + "address": "98404d93b2fcc92eedb881c5ca5ca99d8c61baa0", + "amount": "100000000000000" + }, + { + "address": "98504ce8ea23a9d38d7785c4b9301b5afe50ecdd", + "amount": "100000000000000" + }, + { + "address": "9860440db2910abdc6e66cb518b0b74555dd3539", + "amount": "100000000000000" + }, + { + "address": "98704f188f7c760c770eb1d70c02c3359ebea0d8", + "amount": "100000000000000" + }, + { + "address": "988044c4f6178a2b15ba22ce33ee4237b35b2d60", + "amount": "100000000000000" + }, + { + "address": "989044cff1ca7843552d2fcb8e541d5d2758f0ea", + "amount": "100000000000000" + }, + { + "address": "99004fc2c160910cb7fbd45c12ee54d986550b2a", + "amount": "100000000000000" + }, + { + "address": "991048998cc29362fb3b02f7d1a841267d025923", + "amount": "100000000000000" + }, + { + "address": "9920407f43c58aaa2458d7b091db49952103078f", + "amount": "100000000000000" + }, + { + "address": "9930413e8582369bc426882f61035e35d3ca69be", + "amount": "100000000000000" + }, + { + "address": "9940420c941d4fd60b0e3a23b52ca286dc6419e4", + "amount": "100000000000000" + }, + { + "address": "99504389bd1994b88e183d558eb7eb99b949b3d3", + "amount": "100000000000000" + }, + { + "address": "99604af6e8ab294dc5b37cc6fb271b723d14d366", + "amount": "100000000000000" + }, + { + "address": "997045e7f9933b1a86d152b772d2088ef862b877", + "amount": "100000000000000" + }, + { + "address": "998040588ade5ee3d6cd2cce7467ae10cbe39898", + "amount": "100000000000000" + }, + { + "address": "99904de562388ac3ff20f477b2efe679d2ae82d0", + "amount": "100000000000000" } ], "pools": [ diff --git a/build/localnet/manifests/role-bindings.yaml b/build/localnet/manifests/role-bindings.yaml index 432ac5216..26b9ab94e 100644 --- a/build/localnet/manifests/role-bindings.yaml +++ b/build/localnet/manifests/role-bindings.yaml @@ -11,3 +11,17 @@ roleRef: kind: Role name: private-keys-viewer apiGroup: "" +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: services-watcher-binding + namespace: default +subjects: + - kind: ServiceAccount + name: cluster-manager-account + apiGroup: "" +roleRef: + kind: Role + name: services-watcher + apiGroup: "" diff --git a/build/localnet/manifests/roles.yaml b/build/localnet/manifests/roles.yaml index e956f5c06..91d6e38f1 100644 --- a/build/localnet/manifests/roles.yaml +++ b/build/localnet/manifests/roles.yaml @@ -8,3 +8,13 @@ rules: resources: ["secrets"] resourceNames: ["v1-localnet-validators-private-keys"] verbs: ["get"] +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: services-watcher + namespace: default +rules: + - apiGroups: [""] + resources: ["services"] + verbs: ["watch"] diff --git a/build/localnet/manifests/service-accounts.yaml b/build/localnet/manifests/service-accounts.yaml index cec2002bf..5de7a43ab 100644 --- a/build/localnet/manifests/service-accounts.yaml +++ b/build/localnet/manifests/service-accounts.yaml @@ -3,3 +3,9 @@ kind: ServiceAccount metadata: name: debug-client-account namespace: default +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cluster-manager-account + namespace: default diff --git a/build/localnet/templates/v1-validator-template.yaml.tpl b/build/localnet/templates/v1-validator-template.yaml.tpl index 67fa6781b..7f0b38086 100644 --- a/build/localnet/templates/v1-validator-template.yaml.tpl +++ b/build/localnet/templates/v1-validator-template.yaml.tpl @@ -103,6 +103,7 @@ metadata: namespace: default labels: app: v1-validator${VALIDATOR_NUMBER} + v1-purpose: validator spec: ports: - port: 8080 diff --git a/consensus/debugging.go b/consensus/debugging.go index e6e5eec08..c921ae5ac 100644 --- a/consensus/debugging.go +++ b/consensus/debugging.go @@ -49,10 +49,12 @@ func (m *consensusModule) GetNodeState() typesCons.ConsensusNodeState { func (m *consensusModule) resetToGenesis(_ *messaging.DebugMessage) error { m.logger.Debug().Msg(typesCons.DebugResetToGenesis) - m.height = 0 + + m.SetHeight(0) m.ResetForNewHeight() m.clearLeader() m.clearMessagesPool() + m.GetBus().GetUtilityModule().GetMempool().Clear() if err := m.GetBus().GetPersistenceModule().HandleDebugMessage(&messaging.DebugMessage{ Action: messaging.DebugMessageAction_DEBUG_PERSISTENCE_RESET_TO_GENESIS, Message: nil, diff --git a/consensus/doc/CHANGELOG.md b/consensus/doc/CHANGELOG.md index 2e3e98095..e262328a0 100644 --- a/consensus/doc/CHANGELOG.md +++ b/consensus/doc/CHANGELOG.md @@ -7,12 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.29] - 2023-02-15 + +- Modules embed `base_modules.IntegratableModule` and `base_modules.InterruptableModule` for DRYness +- Updated modules `Create` to accept generic options +- `resetToGenesis` clears the utility mempool as well +- Publishing `ConsensusNewHeightEvent` on new height + ## [0.0.0.28] - 2023-02-14 - Add a few `nolint` comments to fix the code on main ## [0.0.0.27] - 2023-02-09 - - Add `state_sync` submodule, with `state_sync` struct - Implement state sync server to advertise blocks and metadata - Create new `state_sync_handler.go` source file that handles `StateSyncMessage`s sent to the `Consensus` module diff --git a/consensus/e2e_tests/utils_test.go b/consensus/e2e_tests/utils_test.go index 646689158..81c807d3c 100644 --- a/consensus/e2e_tests/utils_test.go +++ b/consensus/e2e_tests/utils_test.go @@ -100,10 +100,9 @@ func CreateTestConsensusPocketNode( ) *shared.Node { // persistence is a dependency of consensus, so we need to create it first persistenceMock := basePersistenceMock(t, eventsChannel, bus) - err := (bus).RegisterModule(persistenceMock) - require.NoError(t, err) + bus.RegisterModule(persistenceMock) - _, err = consensus.Create(bus) + _, err := consensus.Create(bus) require.NoError(t, err) runtimeMgr := (bus).GetRuntimeMgr() @@ -114,16 +113,17 @@ func CreateTestConsensusPocketNode( telemetryMock := baseTelemetryMock(t, eventsChannel) loggerMock := baseLoggerMock(t, eventsChannel) rpcMock := baseRpcMock(t, eventsChannel) + stateMachineMock := baseStateMachineMock(t, eventsChannel) for _, module := range []modules.Module{ + stateMachineMock, p2pMock, utilityMock, telemetryMock, loggerMock, rpcMock, } { - err = (bus).RegisterModule(module) - require.NoError(t, err) + bus.RegisterModule(module) } require.NoError(t, err) @@ -424,6 +424,8 @@ func baseP2PMock(t *testing.T, eventsChannel modules.EventsChannel) *mockModules AnyTimes() p2pMock.EXPECT().GetModuleName().Return(modules.P2PModuleName).AnyTimes() + p2pMock.EXPECT().HandleEvent(gomock.Any()).Return(nil).AnyTimes() + return p2pMock } @@ -494,6 +496,16 @@ func baseRpcMock(t *testing.T, _ modules.EventsChannel) *mockModules.MockRPCModu return rpcMock } +func baseStateMachineMock(t *testing.T, _ modules.EventsChannel) *mockModules.MockStateMachineModule { + ctrl := gomock.NewController(t) + stateMachineMock := mockModules.NewMockStateMachineModule(ctrl) + stateMachineMock.EXPECT().Start().Return(nil).AnyTimes() + stateMachineMock.EXPECT().SetBus(gomock.Any()).Return().AnyTimes() + stateMachineMock.EXPECT().GetModuleName().Return(modules.StateMachineModuleName).AnyTimes() + + return stateMachineMock +} + func baseTelemetryTimeSeriesAgentMock(t *testing.T) *mockModules.MockTimeSeriesAgent { ctrl := gomock.NewController(t) timeSeriesAgentMock := mockModules.NewMockTimeSeriesAgent(ctrl) diff --git a/consensus/events.go b/consensus/events.go new file mode 100644 index 000000000..0e31f8d72 --- /dev/null +++ b/consensus/events.go @@ -0,0 +1,14 @@ +package consensus + +import ( + "github.com/pokt-network/pocket/shared/messaging" +) + +// publishNewHeightEvent publishes a new height event to the bus so that other interested IntegratableModules can react to it if necessary +func (m *consensusModule) publishNewHeightEvent(height uint64) { + newHeightEvent, err := messaging.PackMessage(&messaging.ConsensusNewHeightEvent{Height: height}) + if err != nil { + m.logger.Fatal().Err(err).Msg("Failed to pack consensus new height event") + } + m.GetBus().PublishEventToBus(newHeightEvent) +} diff --git a/consensus/leader_election/module.go b/consensus/leader_election/module.go index 8d856dd24..2004bad28 100644 --- a/consensus/leader_election/module.go +++ b/consensus/leader_election/module.go @@ -2,8 +2,8 @@ package leader_election import ( typesCons "github.com/pokt-network/pocket/consensus/types" - "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" ) type LeaderElectionModule interface { @@ -14,45 +14,29 @@ type LeaderElectionModule interface { var _ LeaderElectionModule = &leaderElectionModule{} type leaderElectionModule struct { - bus modules.Bus + base_modules.IntegratableModule + base_modules.InterruptableModule } func Create(bus modules.Bus) (modules.Module, error) { return new(leaderElectionModule).Create(bus) } -func (*leaderElectionModule) Create(bus modules.Bus) (modules.Module, error) { +func (*leaderElectionModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { m := &leaderElectionModule{} - if err := bus.RegisterModule(m); err != nil { - return nil, err - } - return m, nil -} -func (m *leaderElectionModule) Start() error { - // TODO(olshansky): Use persistence to create leader election module. - return nil -} + for _, option := range options { + option(m) + } -func (m *leaderElectionModule) Stop() error { - return nil + bus.RegisterModule(m) + return m, nil } func (m *leaderElectionModule) GetModuleName() string { return modules.LeaderElectionModuleName } -func (m *leaderElectionModule) SetBus(pocketBus modules.Bus) { - m.bus = pocketBus -} - -func (m *leaderElectionModule) GetBus() modules.Bus { - if m.bus == nil { - logger.Global.Fatal().Msg("PocketBus is not initialized") - } - return m.bus -} - func (m *leaderElectionModule) ElectNextLeader(message *typesCons.HotstuffMessage) (typesCons.NodeId, error) { nodeId, err := m.electNextLeaderDeterministicRoundRobin(message) if err != nil { diff --git a/consensus/module.go b/consensus/module.go index 4201a4a7e..dcb43f581 100644 --- a/consensus/module.go +++ b/consensus/module.go @@ -17,6 +17,7 @@ import ( coreTypes "github.com/pokt-network/pocket/shared/core/types" cryptoPocket "github.com/pokt-network/pocket/shared/crypto" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" "google.golang.org/protobuf/types/known/anypb" ) @@ -30,7 +31,8 @@ var ( ) type consensusModule struct { - bus modules.Bus + base_modules.IntegratableModule + privateKey cryptoPocket.Ed25519PrivateKey consCfg *configs.ConsensusConfig @@ -90,6 +92,7 @@ type ConsensusDebugModule interface { func (m *consensusModule) SetHeight(height uint64) { m.height = height + m.publishNewHeightEvent(height) } func (m *consensusModule) SetRound(round uint64) { @@ -136,11 +139,11 @@ func (m *consensusModule) ClearLeaderMessagesPool() { m.clearMessagesPool() } -func Create(bus modules.Bus) (modules.Module, error) { - return new(consensusModule).Create(bus) +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(consensusModule).Create(bus, options...) } -func (*consensusModule) Create(bus modules.Bus) (modules.Module, error) { +func (*consensusModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { leaderElectionMod, err := leader_election.Create(bus) if err != nil { return nil, err @@ -179,10 +182,13 @@ func (*consensusModule) Create(bus modules.Bus) (modules.Module, error) { hotstuffMempool: make(map[typesCons.HotstuffStep]*hotstuffFIFOMempool), } - if err := bus.RegisterModule(m); err != nil { - return nil, err + + for _, option := range options { + option(m) } + bus.RegisterModule(m) + runtimeMgr := bus.GetRuntimeMgr() consensusCfg := runtimeMgr.GetConfig().Consensus @@ -259,15 +265,8 @@ func (m *consensusModule) GetModuleName() string { return modules.ConsensusModuleName } -func (m *consensusModule) GetBus() modules.Bus { - if m.bus == nil { - logger.Global.Fatal().Msg("PocketBus is not initialized") - } - return m.bus -} - func (m *consensusModule) SetBus(pocketBus modules.Bus) { - m.bus = pocketBus + m.IntegratableModule.SetBus(pocketBus) if m.paceMaker != nil { m.paceMaker.SetBus(pocketBus) } diff --git a/consensus/pacemaker/module.go b/consensus/pacemaker/module.go index 46d91c1bb..a7676e562 100644 --- a/consensus/pacemaker/module.go +++ b/consensus/pacemaker/module.go @@ -11,6 +11,7 @@ import ( "github.com/pokt-network/pocket/runtime/configs" "github.com/pokt-network/pocket/shared/codec" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" "google.golang.org/protobuf/types/known/anypb" ) @@ -44,7 +45,9 @@ type Pacemaker interface { } type pacemaker struct { - bus modules.Bus + base_modules.IntegratableModule + base_modules.InterruptableModule + pacemakerCfg *configs.PacemakerConfig stepCancelFunc context.CancelFunc @@ -56,20 +59,21 @@ type pacemaker struct { logPrefix string } -func CreatePacemaker(bus modules.Bus) (modules.Module, error) { - var m pacemaker - return m.Create(bus) +func CreatePacemaker(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(pacemaker).Create(bus, options...) } -func (*pacemaker) Create(bus modules.Bus) (modules.Module, error) { +func (*pacemaker) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { m := &pacemaker{ logPrefix: defaultLogPrefix, } - if err := bus.RegisterModule(m); err != nil { - return nil, err + for _, option := range options { + option(m) } + bus.RegisterModule(m) + runtimeMgr := bus.GetRuntimeMgr() cfg := runtimeMgr.GetConfig() @@ -88,25 +92,11 @@ func (m *pacemaker) Start() error { m.RestartTimer() return nil } -func (*pacemaker) Stop() error { - return nil -} func (*pacemaker) GetModuleName() string { return pacemakerModuleName } -func (m *pacemaker) SetBus(pocketBus modules.Bus) { - m.bus = pocketBus -} - -func (m *pacemaker) GetBus() modules.Bus { - if m.bus == nil { - log.Fatalf("PocketBus is not initialized") - } - return m.bus -} - func (m *pacemaker) SetLogPrefix(logPrefix string) { m.logPrefix = logPrefix } diff --git a/consensus/state_sync/module.go b/consensus/state_sync/module.go index 74bcf353b..4e45b06dd 100644 --- a/consensus/state_sync/module.go +++ b/consensus/state_sync/module.go @@ -55,20 +55,21 @@ type stateSync struct { logPrefix string } -func CreateStateSync(bus modules.Bus) (modules.Module, error) { - var m stateSync - return m.Create(bus) +func CreateStateSync(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(stateSync).Create(bus, options...) } -func (*stateSync) Create(bus modules.Bus) (modules.Module, error) { +func (*stateSync) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { m := &stateSync{ logPrefix: DefaultLogPrefix, } - if err := bus.RegisterModule(m); err != nil { - return nil, err + for _, option := range options { + option(m) } + bus.RegisterModule(m) + // when node is starting, it is in sync mode, as it might need to bootstrap to the latest state m.currentMode = Sync m.serverMode = false diff --git a/go.mod b/go.mod index a292ac7d7..727486770 100644 --- a/go.mod +++ b/go.mod @@ -20,11 +20,13 @@ require ( require ( github.com/benbjohnson/clock v1.3.0 github.com/celestiaorg/smt v0.2.1-0.20220414134126-dba215ccb884 + github.com/deepmap/oapi-codegen v1.12.4 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/getkin/kin-openapi v0.107.0 github.com/jackc/pgconn v1.13.0 github.com/jordanorelli/lexnum v0.0.0-20141216151731-460eeb125754 github.com/labstack/echo/v4 v4.9.1 + github.com/looplab/fsm v1.0.1 github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/mapstructure v1.5.0 github.com/quasilyte/go-ruleguard/dsl v0.3.21 @@ -33,6 +35,7 @@ require ( github.com/spf13/viper v1.13.0 golang.org/x/term v0.3.0 gopkg.in/yaml.v2 v2.4.0 + k8s.io/api v0.26.1 k8s.io/apimachinery v0.26.1 k8s.io/client-go v0.26.1 ) @@ -63,9 +66,11 @@ require ( github.com/sirupsen/logrus v1.9.0 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect + gotest.tools v2.2.0+incompatible // indirect ) require ( + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/go-logr/logr v1.2.3 // indirect @@ -73,12 +78,13 @@ require ( github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jackc/puddle/v2 v2.1.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/lib/pq v1.10.6 // indirect + github.com/lib/pq v1.10.2 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -93,8 +99,6 @@ require ( golang.org/x/sync v0.1.0 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gotest.tools v2.2.0+incompatible // indirect - k8s.io/api v0.26.1 // indirect k8s.io/klog/v2 v2.80.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect diff --git a/go.sum b/go.sum index ae3da1f69..3534172a2 100644 --- a/go.sum +++ b/go.sum @@ -51,11 +51,14 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-ecvrf v0.0.1 h1:wv45+kZ0mG4G9oSTMjAlbgKqa4tPbNr4WLoCWqz5/bo= github.com/ProtonMail/go-ecvrf v0.0.1/go.mod h1:fhZbiRYn62/JGnBG2NGwCx0oT+gr/+I5R/hwiyAFpAU= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -63,6 +66,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/celestiaorg/smt v0.2.1-0.20220414134126-dba215ccb884 h1:iRNKw2WmAbVgGMNYzDH5Y2yY3+jyxwEK9Hc5pwIjZAE= github.com/celestiaorg/smt v0.2.1-0.20220414134126-dba215ccb884/go.mod h1:/sdYDakowo/XaxS2Fl7CBqtuf/O2uTqF2zmAUFAtAiw= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= @@ -106,6 +110,8 @@ github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxG github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s= +github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas= github.com/dgraph-io/badger/v3 v3.2103.2 h1:dpyM5eCJAtQCBcMCZcT4UBZchuTJgCywerHHgmxfxM8= github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= @@ -240,6 +246,8 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -311,6 +319,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -339,8 +348,10 @@ github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/looplab/fsm v1.0.1 h1:OEW0ORrIx095N/6lgoGkFkotqH6s7vaFPsgjLAaF5QU= +github.com/looplab/fsm v1.0.1/go.mod h1:PmD3fFvQEIsjMEfvZdrCDZ6y8VwKTwWNjlpEr6IKPO4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -481,6 +492,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/logger/docs/CHANGELOG.md b/logger/docs/CHANGELOG.md index abba623a7..fc8acb230 100644 --- a/logger/docs/CHANGELOG.md +++ b/logger/docs/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.7] - 2023-02-10 + +- Module embeds `base_modules.IntegratableModule` and `base_modules.InterruptableModule` for DRYness + ## [0.0.0.6] - 2023-02-09 - `loggerModule` type-checking for `modules.Module` diff --git a/logger/module.go b/logger/module.go index 918b9ae75..2f7e26ebb 100644 --- a/logger/module.go +++ b/logger/module.go @@ -7,12 +7,16 @@ import ( "github.com/pokt-network/pocket/runtime/configs" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" "github.com/rs/zerolog" ) var _ modules.Module = &loggerModule{} type loggerModule struct { + base_modules.IntegratableModule + base_modules.InterruptableModule + zerolog.Logger bus modules.Bus config *configs.LoggerConfig @@ -49,24 +53,27 @@ func init() { } } -func Create(bus modules.Bus) (modules.Module, error) { - return new(loggerModule).Create(bus) +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(loggerModule).Create(bus, options...) } func (*loggerModule) CreateLoggerForModule(moduleName string) modules.Logger { return Global.Logger.With().Str("module", moduleName).Logger() } -func (*loggerModule) Create(bus modules.Bus) (modules.Module, error) { +func (*loggerModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { runtimeMgr := bus.GetRuntimeMgr() cfg := runtimeMgr.GetConfig() m := &loggerModule{ config: cfg.Logger, } - if err := bus.RegisterModule(m); err != nil { - return nil, err + + for _, option := range options { + option(m) } + bus.RegisterModule(m) + Global.config = m.config Global.CreateLoggerForModule("global") @@ -95,25 +102,10 @@ func (m *loggerModule) Start() error { return nil } -func (m *loggerModule) Stop() error { - return nil -} - func (m *loggerModule) GetModuleName() string { return modules.LoggerModuleName } -func (m *loggerModule) SetBus(bus modules.Bus) { - m.bus = bus -} - -func (m *loggerModule) GetBus() modules.Bus { - if m.bus == nil { - m.Logger.Fatal().Msg("Bus is not initialized") - } - return m.bus -} - func (m *loggerModule) GetLogger() modules.Logger { return m.Logger } diff --git a/p2p/CHANGELOG.md b/p2p/CHANGELOG.md index ac5eeeb3f..0e56d0b90 100644 --- a/p2p/CHANGELOG.md +++ b/p2p/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.26] - 2023-02-10 + +- Modules embed `base_modules.IntegratableModule` and `base_modules.InterruptableModule` for DRYness +- Deprecated `debugAddressBookProvider` +- Added `rpcAddressBookProvider` to source the address book from the RPC server +- Leveraging `bus` for dependency injection of the `addressBookProvider` and `currentHeightProvider` +- Deprecated `debugCurrentHeightProvider` +- Added `rpcCurrentHeightProvider` to source the current height from the RPC server +- Fixed raintree to use the `currentHeightProvider` instead of consensus (that was what we wanted to avoid in the first place) +- Added `getAddrBookDelta` to calculate changes to the address book between heights and update the internal state and componentry accordingly +- Added basic `bootstrap` nodes support +- Reacting to `ConsensusNewHeightEventType` and `StateMachineTransitionEventType` to update the address book and current height and determine if a bootstrap is needed +- Updated tests + ## [0.0.0.25] - 2023-02-09 - Updated logging initialization and passing to the network component instead of using the global logger @@ -130,8 +144,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `peersManager` and `target` in order to abstract away and eliminate redundant computations - Refactored debug logging in `getTarget` to print first and second target on the same line - Refactored `AddPeerToAddrBook` to use an event-driven approach in order to leverage sorted data structures -- Added `RemovePeerToAddrBook` making use of the same pattern -- Improved performance of `AddPeerToAddrBook` and `RemovePeerToAddrBook` by making the implementations O(n) +- Added `RemovePeerFromAddrBook` making use of the same pattern +- Improved performance of `AddPeerToAddrBook` and `RemovePeerFromAddrBook` by making the implementations O(n) - Updated `stdnetwork` to use a map instead of a slice ## [0.0.0.2] - 2022-08-25 diff --git a/p2p/addrbook_delta.go b/p2p/addrbook_delta.go new file mode 100644 index 000000000..5484ab277 --- /dev/null +++ b/p2p/addrbook_delta.go @@ -0,0 +1,25 @@ +package p2p + +import typesP2P "github.com/pokt-network/pocket/p2p/types" + +// getAddrBookDelta returns the difference between two AddrBook slices +func getAddrBookDelta(before, after typesP2P.AddrBook) (added, removed []*typesP2P.NetworkPeer) { + oldMap := make(map[string]*typesP2P.NetworkPeer) + for _, np := range before { + oldMap[np.Address.String()] = np + } + + for _, np := range after { + if _, ok := oldMap[np.Address.String()]; !ok { + added = append(added, np) + continue + } + delete(oldMap, np.Address.String()) + } + + for _, u := range oldMap { + removed = append(removed, u) + } + + return +} diff --git a/p2p/addrbook_delta_test.go b/p2p/addrbook_delta_test.go new file mode 100644 index 000000000..4539f1726 --- /dev/null +++ b/p2p/addrbook_delta_test.go @@ -0,0 +1,66 @@ +package p2p + +import ( + "testing" + + typesP2P "github.com/pokt-network/pocket/p2p/types" + "github.com/pokt-network/pocket/shared/crypto" + "github.com/stretchr/testify/require" +) + +func Test_getAddrBookDelta(t *testing.T) { + type args struct { + before typesP2P.AddrBook + after typesP2P.AddrBook + } + tests := []struct { + name string + args args + wantAdded []*typesP2P.NetworkPeer + wantRemoved []*typesP2P.NetworkPeer + }{ + { + name: "empty slices should return empty slices", + args: args{ + before: []*typesP2P.NetworkPeer{}, + after: []*typesP2P.NetworkPeer{}, + }, + wantAdded: []*typesP2P.NetworkPeer{}, + wantRemoved: []*typesP2P.NetworkPeer{}, + }, + { + name: "when a peer is added, it should be in the added slice", + args: args{ + before: []*typesP2P.NetworkPeer{}, + after: []*typesP2P.NetworkPeer{{Address: crypto.AddressFromString("000000000000000000000000000000000001")}}, + }, + wantAdded: []*typesP2P.NetworkPeer{{Address: crypto.AddressFromString("000000000000000000000000000000000001")}}, + wantRemoved: []*typesP2P.NetworkPeer{}, + }, + { + name: "when a peer is removed, it should be in the removed slice", + args: args{ + before: []*typesP2P.NetworkPeer{{Address: crypto.AddressFromString("000000000000000000000000000000000001")}}, + after: []*typesP2P.NetworkPeer{}, + }, + wantAdded: []*typesP2P.NetworkPeer{}, + wantRemoved: []*typesP2P.NetworkPeer{{Address: crypto.AddressFromString("000000000000000000000000000000000001")}}, + }, + { + name: "when no peers are added or removed, both slices should be empty", + args: args{ + before: []*typesP2P.NetworkPeer{{Address: crypto.AddressFromString("000000000000000000000000000000000001")}, {Address: crypto.AddressFromString("000000000000000000000000000000000002")}}, + after: []*typesP2P.NetworkPeer{{Address: crypto.AddressFromString("000000000000000000000000000000000001")}, {Address: crypto.AddressFromString("000000000000000000000000000000000002")}}, + }, + wantAdded: []*typesP2P.NetworkPeer{}, + wantRemoved: []*typesP2P.NetworkPeer{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotAdded, gotRemoved := getAddrBookDelta(tt.args.before, tt.args.after) + require.ElementsMatch(t, gotAdded, tt.wantAdded) + require.ElementsMatch(t, gotRemoved, tt.wantRemoved) + }) + } +} diff --git a/p2p/event_handler.go b/p2p/event_handler.go new file mode 100644 index 000000000..02c115b21 --- /dev/null +++ b/p2p/event_handler.go @@ -0,0 +1,74 @@ +package p2p + +import ( + "fmt" + + "github.com/pokt-network/pocket/shared/codec" + coreTypes "github.com/pokt-network/pocket/shared/core/types" + "github.com/pokt-network/pocket/shared/messaging" + "google.golang.org/protobuf/types/known/anypb" +) + +func (m *p2pModule) HandleEvent(event *anypb.Any) error { + evt, err := codec.GetCodec().FromAny(event) + if err != nil { + return err + } + + switch event.MessageName() { + case messaging.ConsensusNewHeightEventType: + consensusNewHeightEvent, ok := evt.(*messaging.ConsensusNewHeightEvent) + if !ok { + return fmt.Errorf("failed to cast event to ConsensusNewHeightEvent") + } + + addrBook := m.network.GetAddrBook() + newAddrBook, err := m.addrBookProvider.GetStakedAddrBookAtHeight(consensusNewHeightEvent.Height) + + if err != nil { + return err + } + + added, removed := getAddrBookDelta(addrBook, newAddrBook) + for _, add := range added { + if err := m.network.AddPeerToAddrBook(add); err != nil { + return err + } + } + for _, rm := range removed { + if err := m.network.RemovePeerFromAddrBook(rm); err != nil { + return err + } + } + + case messaging.StateMachineTransitionEventType: + stateMachineTransitionEvent, ok := evt.(*messaging.StateMachineTransitionEvent) + if !ok { + return fmt.Errorf("failed to cast event to StateMachineTransitionEvent") + } + + if stateMachineTransitionEvent.NewState == string(coreTypes.StateMachineState_P2P_Bootstrapping) { + addrBook := m.network.GetAddrBook() + if len(addrBook) == 0 { + m.logger.Warn().Msg("No peers in addrbook, bootstrapping") + + err := bootstrap(m) + if err != nil { + return err + } + } + if !isSelfInAddrBook(m.address, addrBook) { + m.logger.Warn().Msg("Self address not found in addresbook, advertising") + // TODO: (link libp2p issue) advertise node to network, populate internal addressbook adding self as first peer + } + if err := m.GetBus().GetStateMachineModule().SendEvent(coreTypes.StateMachineEvent_P2P_IsBootstrapped); err != nil { + return err + } + } + + default: + return fmt.Errorf("unknown event type: %s", event.MessageName()) + } + + return nil +} diff --git a/p2p/module.go b/p2p/module.go index c43a424b7..69c2d8e69 100644 --- a/p2p/module.go +++ b/p2p/module.go @@ -1,18 +1,33 @@ package p2p import ( + "context" + "encoding/csv" + "fmt" "log" + "net/http" + "regexp" + "strconv" + "strings" "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/p2p/providers" + "github.com/pokt-network/pocket/p2p/providers/addrbook_provider" persABP "github.com/pokt-network/pocket/p2p/providers/addrbook_provider/persistence" + rpcABP "github.com/pokt-network/pocket/p2p/providers/addrbook_provider/rpc" + "github.com/pokt-network/pocket/p2p/providers/current_height_provider" + rpcCHP "github.com/pokt-network/pocket/p2p/providers/current_height_provider/rpc" "github.com/pokt-network/pocket/p2p/raintree" "github.com/pokt-network/pocket/p2p/stdnetwork" "github.com/pokt-network/pocket/p2p/transport" typesP2P "github.com/pokt-network/pocket/p2p/types" + "github.com/pokt-network/pocket/rpc" + "github.com/pokt-network/pocket/runtime/configs" + "github.com/pokt-network/pocket/runtime/defaults" cryptoPocket "github.com/pokt-network/pocket/shared/crypto" "github.com/pokt-network/pocket/shared/messaging" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" "github.com/pokt-network/pocket/telemetry" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" @@ -21,7 +36,7 @@ import ( var _ modules.P2PModule = &p2pModule{} type p2pModule struct { - bus modules.Bus + base_modules.IntegratableModule listener typesP2P.Transport address cryptoPocket.Address @@ -30,55 +45,33 @@ type p2pModule struct { network typesP2P.Network - injectedAddrBookProvider providers.AddrBookProvider - injectedCurrentHeightProvider providers.CurrentHeightProvider + addrBookProvider providers.AddrBookProvider + currentHeightProvider providers.CurrentHeightProvider + + bootstrapNodes []string } -func Create(bus modules.Bus) (modules.Module, error) { - return new(p2pModule).Create(bus) +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(p2pModule).Create(bus, options...) } -// TODO(#429): need to define a better pattern for dependency injection. Currently we are probably limiting ourselves by having a common constructor `Create(bus modules.Bus) (modules.Module, error)` for all modules. -func CreateWithProviders(bus modules.Bus, addrBookProvider providers.AddrBookProvider, currentHeightProvider providers.CurrentHeightProvider) (modules.Module, error) { +func (*p2pModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { log.Println("Creating network module") m := &p2pModule{} - if err := bus.RegisterModule(m); err != nil { - return nil, err + + for _, option := range options { + option(m) } + bus.RegisterModule(m) + runtimeMgr := bus.GetRuntimeMgr() cfg := runtimeMgr.GetConfig() p2pCfg := cfg.P2P - privateKey, err := cryptoPocket.NewPrivateKey(p2pCfg.GetPrivateKey()) - if err != nil { + if err := configureBootstrapNodes(p2pCfg, m); err != nil { return nil, err } - m.address = privateKey.Address() - m.injectedAddrBookProvider = addrBookProvider - m.injectedCurrentHeightProvider = currentHeightProvider - - if !cfg.ClientDebugMode { - l, err := transport.CreateListener(p2pCfg) - if err != nil { - return nil, err - } - m.listener = l - } - - return m, nil -} - -func (*p2pModule) Create(bus modules.Bus) (modules.Module, error) { - log.Println("Creating network module") - m := &p2pModule{} - if err := bus.RegisterModule(m); err != nil { - return nil, err - } - - runtimeMgr := bus.GetRuntimeMgr() - cfg := runtimeMgr.GetConfig() - p2pCfg := cfg.P2P privateKey, err := cryptoPocket.NewPrivateKey(p2pCfg.PrivateKey) if err != nil { @@ -86,6 +79,8 @@ func (*p2pModule) Create(bus modules.Bus) (modules.Module, error) { } m.address = privateKey.Address() + m.setupDependencies() + if !cfg.ClientDebugMode { l, err := transport.CreateListener(p2pCfg) if err != nil { @@ -97,18 +92,18 @@ func (*p2pModule) Create(bus modules.Bus) (modules.Module, error) { return m, nil } -func (m *p2pModule) SetBus(bus modules.Bus) { - // INVESTIGATE: Can the code flow be modified to set the bus here? - // m.network.SetBus(m.GetBus()) - m.bus = bus -} +func (m *p2pModule) setupDependencies() { + addrBookProvider, err := m.GetBus().GetModulesRegistry().GetModule(addrbook_provider.ModuleName) + if err != nil { + addrBookProvider = persABP.NewPersistenceAddrBookProvider(m.GetBus()) + } + m.addrBookProvider = addrBookProvider.(providers.AddrBookProvider) -func (m *p2pModule) GetBus() modules.Bus { - if m.bus == nil { - m.logger.Warn().Msg("PocketBus is not initialized") - return nil + currentHeightProvider, err := m.GetBus().GetModulesRegistry().GetModule(current_height_provider.ModuleName) + if err != nil { + currentHeightProvider = m.GetBus().GetConsensusModule() } - return m.bus + m.currentHeightProvider = currentHeightProvider.(providers.CurrentHeightProvider) } func (m *p2pModule) GetModuleName() string { @@ -119,16 +114,13 @@ func (m *p2pModule) Start() error { m.logger = logger.Global.CreateLoggerForModule(m.GetModuleName()) m.logger.Info().Msg("Starting network module") - addrbookProvider := getAddrBookProvider(m) - currentHeightProvider := getCurrentHeightProvider(m) - cfg := m.GetBus().GetRuntimeMgr().GetConfig() // TODO: pass down logger if cfg.P2P.UseRainTree { - m.network = raintree.NewRainTreeNetwork(m.address, m.GetBus(), addrbookProvider, currentHeightProvider) + m.network = raintree.NewRainTreeNetwork(m.address, m.GetBus(), m.addrBookProvider, m.currentHeightProvider) } else { - m.network = stdnetwork.NewNetwork(m.GetBus(), addrbookProvider, currentHeightProvider) + m.network = stdnetwork.NewNetwork(m.GetBus(), m.addrBookProvider, m.currentHeightProvider) } if cfg.ClientDebugMode { @@ -162,28 +154,6 @@ func (m *p2pModule) Start() error { return nil } -// CLEANUP(#429): marked for removal since we'll implement a better pattern for dependency injection -func getAddrBookProvider(m *p2pModule) providers.AddrBookProvider { - var addrbookProvider providers.AddrBookProvider - if m.injectedAddrBookProvider == nil { - addrbookProvider = persABP.NewPersistenceAddrBookProvider(m.GetBus()) - } else { - addrbookProvider = m.injectedAddrBookProvider - } - return addrbookProvider -} - -// CLEANUP(#429): marked for removal since we'll implement a better pattern for dependency injection -func getCurrentHeightProvider(m *p2pModule) providers.CurrentHeightProvider { - var currentHeightProvider providers.CurrentHeightProvider - if m.injectedCurrentHeightProvider == nil { - currentHeightProvider = m.GetBus().GetConsensusModule() - } else { - currentHeightProvider = m.injectedCurrentHeightProvider - } - return currentHeightProvider -} - func (m *p2pModule) Stop() error { m.logger.Info().Msg("Stopping network module") if err := m.listener.Close(); err != nil { @@ -247,3 +217,99 @@ func (m *p2pModule) handleNetworkMessage(networkMsgData []byte) { m.GetBus().PublishEventToBus(&event) } + +func configureBootstrapNodes(p2pCfg *configs.P2PConfig, m *p2pModule) error { + var csvReader *csv.Reader + customBootstrapNodesCsv := strings.Trim(p2pCfg.BootstrapNodesCsv, " ") + if customBootstrapNodesCsv == "" { + csvReader = csv.NewReader(strings.NewReader(defaults.DefaultP2PBootstrapNodesCsv)) + } else { + csvReader = csv.NewReader(strings.NewReader(customBootstrapNodesCsv)) + } + bootStrapNodes, err := csvReader.Read() + if err != nil { + return fmt.Errorf("error parsing bootstrap nodes: %w", err) + } + for _, node := range bootStrapNodes { + if !isValidHostnamePort(node) { + return fmt.Errorf("invalid bootstrap node: %s", node) + } + } + m.bootstrapNodes = bootStrapNodes + return nil +} + +func isValidHostnamePort(str string) bool { + pattern := regexp.MustCompile(`^(https?)://([a-zA-Z0-9.-]+):(\d{1,5})$`) + matches := pattern.FindStringSubmatch(str) + if len(matches) != 4 { + return false + } + protocol := matches[1] + if protocol != "http" && protocol != "https" { + return false + } + port, err := strconv.Atoi(matches[3]) + if err != nil || port < 0 || port > 65535 { + return false + } + return true +} + +func isSelfInAddrBook(selfAddr cryptoPocket.Address, addrBook typesP2P.AddrBook) bool { + for _, peer := range addrBook { + if peer.Address.Equals(selfAddr) { + return true + } + } + return false +} + +func bootstrap(m *p2pModule) error { + var ( + addrBook typesP2P.AddrBook + ) + + for _, bootstrapNode := range m.bootstrapNodes { + m.logger.Info().Str("endpoint", bootstrapNode).Msg("Attempting to bootstrap from bootstrap node") // TODO: deblasis - fix this. For some reason it's not logging + log.Println("Attempting to bootstrap from bootstrap node: " + bootstrapNode) + + client, err := rpc.NewClientWithResponses(bootstrapNode) + if err != nil { + continue + } + healthCheck, err := client.GetV1Health(context.TODO()) + if err != nil || healthCheck == nil || healthCheck.StatusCode != http.StatusOK { + log.Println("Error getting a green health check from bootstrap node: " + bootstrapNode) + continue + } + + addressBookProvider := rpcABP.NewRPCAddrBookProvider( + rpcABP.WithP2PConfig( + m.GetBus().GetRuntimeMgr().GetConfig().P2P, + ), + rpcABP.WithCustomRPCUrl(bootstrapNode), + ) + + currentHeightProvider := rpcCHP.NewRPCCurrentHeightProvider(rpcCHP.WithCustomRPCUrl(bootstrapNode)) + + addrBook, err = addressBookProvider.GetStakedAddrBookAtHeight(currentHeightProvider.CurrentHeight()) + if err != nil { + m.logger.Warn().Err(err).Str("endpoint", bootstrapNode).Msg("Error getting address book from bootstrap node") // TODO: deblasis - fix this. For some reason it's not logging + log.Println("Error getting address book from bootstrap node: " + bootstrapNode) + continue + } + } + + if len(addrBook) == 0 { + return fmt.Errorf("bootstrap failed") + } + + for _, peer := range addrBook { + log.Println("Adding peer to addrBook: " + peer.Address.String()) + if err := m.network.AddPeerToAddrBook(peer); err != nil { + return err + } + } + return nil +} diff --git a/p2p/module_test.go b/p2p/module_test.go new file mode 100644 index 000000000..02e49c8f1 --- /dev/null +++ b/p2p/module_test.go @@ -0,0 +1,108 @@ +package p2p + +import ( + "strings" + "testing" + + "github.com/pokt-network/pocket/runtime/configs" + "github.com/pokt-network/pocket/runtime/defaults" + "github.com/stretchr/testify/require" +) + +func Test_configureBootstrapNodes(t *testing.T) { + defaultBootstrapNodes := strings.Split(defaults.DefaultP2PBootstrapNodesCsv, ",") + type args struct { + p2pCfg *configs.P2PConfig + m *p2pModule + } + tests := []struct { + name string + args args + wantBootstrapNodes []string + wantErr bool + }{ + { + name: "unset boostrap nodes should yield no error and return DefaultP2PBootstrapNodes", + args: args{ + p2pCfg: &configs.P2PConfig{}, + m: new(p2pModule), + }, + wantErr: false, + wantBootstrapNodes: defaultBootstrapNodes, + }, + { + name: "empty string boostrap nodes should yield no error and return DefaultP2PBootstrapNodes", + args: args{ + p2pCfg: &configs.P2PConfig{ + BootstrapNodesCsv: "", + }, + m: new(p2pModule), + }, + wantErr: false, + wantBootstrapNodes: defaultBootstrapNodes, + }, + { + name: "untrimmed empty string boostrap nodes should yield no error and return DefaultP2PBootstrapNodes", + args: args{ + p2pCfg: &configs.P2PConfig{ + BootstrapNodesCsv: " ", + }, + m: new(p2pModule), + }, + wantErr: false, + wantBootstrapNodes: defaultBootstrapNodes, + }, + { + name: "untrimmed string boostrap nodes should yield no error and return DefaultP2PBootstrapNodes", + args: args{ + p2pCfg: &configs.P2PConfig{ + BootstrapNodesCsv: " http://somenode:50832 ", + }, + m: new(p2pModule), + }, + wantErr: false, + wantBootstrapNodes: []string{"http://somenode:50832"}, + }, + { + name: "custom bootstrap nodes should yield no error and return the custom bootstrap node", + args: args{ + p2pCfg: &configs.P2PConfig{ + BootstrapNodesCsv: "http://somenode:50832,http://someothernode:50832", + }, + m: new(p2pModule), + }, + wantBootstrapNodes: []string{"http://somenode:50832", "http://someothernode:50832"}, + wantErr: false, + }, + { + name: "malformed bootstrap nodes string should yield an error and return nil", + args: args{ + p2pCfg: &configs.P2PConfig{ + BootstrapNodesCsv: "\n\n", + }, + m: &p2pModule{}, + }, + wantBootstrapNodes: []string(nil), + wantErr: true, + }, + { + name: "invalid hostname:port pattern for bootstrap nodes string should yield an error and return nil", + args: args{ + p2pCfg: &configs.P2PConfig{ + BootstrapNodesCsv: "http://somenode:99999", + }, + m: &p2pModule{}, + }, + wantBootstrapNodes: []string(nil), + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := configureBootstrapNodes(tt.args.p2pCfg, tt.args.m); (err != nil) != tt.wantErr { + t.Errorf("configureBootstrapNodes() error = %v, wantErr %v", err, tt.wantErr) + } + require.EqualValues(t, tt.wantBootstrapNodes, tt.args.m.bootstrapNodes) + }) + } +} diff --git a/p2p/providers/addrbook_provider/addrbook_provider.go b/p2p/providers/addrbook_provider/addrbook_provider.go index 1820259cd..b42dcb4a2 100644 --- a/p2p/providers/addrbook_provider/addrbook_provider.go +++ b/p2p/providers/addrbook_provider/addrbook_provider.go @@ -10,10 +10,16 @@ import ( "github.com/pokt-network/pocket/runtime/configs" coreTypes "github.com/pokt-network/pocket/shared/core/types" cryptoPocket "github.com/pokt-network/pocket/shared/crypto" + "github.com/pokt-network/pocket/shared/modules" ) +const ModuleName = "addrbook_provider" + // AddrBookProvider is an interface that provides AddrBook accessors type AddrBookProvider interface { + modules.IntegratableModule + modules.InterruptableModule + GetStakedAddrBookAtHeight(height uint64) (typesP2P.AddrBook, error) GetConnFactory() typesP2P.ConnectionFactory GetP2PConfig() *configs.P2PConfig diff --git a/p2p/providers/addrbook_provider/debug/provider.go b/p2p/providers/addrbook_provider/debug/provider.go deleted file mode 100644 index a5afa14f0..000000000 --- a/p2p/providers/addrbook_provider/debug/provider.go +++ /dev/null @@ -1,74 +0,0 @@ -package debug - -import ( - "log" - - "github.com/pokt-network/pocket/p2p/providers/addrbook_provider" - "github.com/pokt-network/pocket/p2p/transport" - typesP2P "github.com/pokt-network/pocket/p2p/types" - "github.com/pokt-network/pocket/runtime/configs" - coreTypes "github.com/pokt-network/pocket/shared/core/types" -) - -const ( - // ANY_HEIGHT is a special height that will be used to indicate that the actors are valid for all heights (including future heights) - ANY_HEIGHT = -1 -) - -var _ addrbook_provider.AddrBookProvider = &debugAddrBookProvider{} - -type debugAddrBookProvider struct { - p2pCfg *configs.P2PConfig - actorsByHeight map[int64][]*coreTypes.Actor - connFactory typesP2P.ConnectionFactory -} - -func NewDebugAddrBookProvider(p2pCfg *configs.P2PConfig, options ...func(*debugAddrBookProvider)) *debugAddrBookProvider { - dabp := &debugAddrBookProvider{ - p2pCfg: p2pCfg, - connFactory: transport.CreateDialer, // default connection factory, overridable with WithConnectionFactory() - } - - for _, o := range options { - o(dabp) - } - - return dabp -} - -func WithActorsByHeight(actorsByHeight map[int64][]*coreTypes.Actor) func(*debugAddrBookProvider) { - return func(pabp *debugAddrBookProvider) { - pabp.actorsByHeight = actorsByHeight - } -} - -func (dabp *debugAddrBookProvider) getActorsByHeight(height uint64) []*coreTypes.Actor { - if stakedActors, ok := dabp.actorsByHeight[ANY_HEIGHT]; ok { - log.Println("[DEBUG] Ignoring height param in debugAddrBookProvider") - return stakedActors - } - - if stakedActors, ok := dabp.actorsByHeight[int64(height)]; ok { - return stakedActors - } - - log.Fatalf("No actors found for height %d. Please make sure you configured the provider via WithActorsByHeight", height) - return nil -} - -func (dabp *debugAddrBookProvider) GetStakedAddrBookAtHeight(height uint64) (typesP2P.AddrBook, error) { - stakedActors := dabp.getActorsByHeight(height) - return addrbook_provider.ActorsToAddrBook(dabp, stakedActors) -} - -func (dabp *debugAddrBookProvider) GetConnFactory() typesP2P.ConnectionFactory { - return dabp.connFactory -} - -func (dabp *debugAddrBookProvider) GetP2PConfig() *configs.P2PConfig { - return dabp.p2pCfg -} - -func (dabp *debugAddrBookProvider) SetConnectionFactory(connFactory typesP2P.ConnectionFactory) { - dabp.connFactory = connFactory -} diff --git a/p2p/providers/addrbook_provider/persistence/provider.go b/p2p/providers/addrbook_provider/persistence/provider.go index 5ece1a2f5..234e8cf13 100644 --- a/p2p/providers/addrbook_provider/persistence/provider.go +++ b/p2p/providers/addrbook_provider/persistence/provider.go @@ -6,20 +6,22 @@ import ( typesP2P "github.com/pokt-network/pocket/p2p/types" "github.com/pokt-network/pocket/runtime/configs" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" ) -var _ modules.IntegratableModule = &persistenceAddrBookProvider{} var _ addrbook_provider.AddrBookProvider = &persistenceAddrBookProvider{} type persistenceAddrBookProvider struct { - bus modules.Bus + base_modules.IntegratableModule + base_modules.InterruptableModule + connFactory typesP2P.ConnectionFactory } func NewPersistenceAddrBookProvider(bus modules.Bus, options ...func(*persistenceAddrBookProvider)) *persistenceAddrBookProvider { pabp := &persistenceAddrBookProvider{ - bus: bus, - connFactory: transport.CreateDialer, // default connection factory, overridable with WithConnectionFactory() + IntegratableModule: *base_modules.NewIntegratableModule(bus), + connFactory: transport.CreateDialer, // default connection factory, overridable with WithConnectionFactory() } for _, o := range options { @@ -29,12 +31,16 @@ func NewPersistenceAddrBookProvider(bus modules.Bus, options ...func(*persistenc return pabp } -func (pabp *persistenceAddrBookProvider) GetBus() modules.Bus { - return pabp.bus +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(persistenceAddrBookProvider).Create(bus, options...) +} + +func (*persistenceAddrBookProvider) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return NewPersistenceAddrBookProvider(bus), nil } -func (pabp *persistenceAddrBookProvider) SetBus(bus modules.Bus) { - pabp.bus = bus +func (*persistenceAddrBookProvider) GetModuleName() string { + return addrbook_provider.ModuleName } func (pabp *persistenceAddrBookProvider) GetStakedAddrBookAtHeight(height uint64) (typesP2P.AddrBook, error) { diff --git a/p2p/providers/addrbook_provider/rpc/provider.go b/p2p/providers/addrbook_provider/rpc/provider.go new file mode 100644 index 000000000..effdf5439 --- /dev/null +++ b/p2p/providers/addrbook_provider/rpc/provider.go @@ -0,0 +1,138 @@ +package rpc + +import ( + "context" + "fmt" + "log" + "net/http" + "time" + + "github.com/pokt-network/pocket/p2p/providers/addrbook_provider" + "github.com/pokt-network/pocket/p2p/transport" + typesP2P "github.com/pokt-network/pocket/p2p/types" + "github.com/pokt-network/pocket/rpc" + "github.com/pokt-network/pocket/runtime" + "github.com/pokt-network/pocket/runtime/configs" + "github.com/pokt-network/pocket/runtime/defaults" + "github.com/pokt-network/pocket/shared/core/types" + "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" +) + +var ( + _ addrbook_provider.AddrBookProvider = &rpcAddrBookProvider{} + rpcHost string +) + +func init() { + // by default, we point at the same endpoint used by the CLI but the debug client is used either in docker-compose of K8S, therefore we cater for overriding + rpcHost = runtime.GetEnv("RPC_HOST", defaults.DefaultRPCHost) +} + +type rpcAddrBookProvider struct { + base_modules.IntegratableModule + base_modules.InterruptableModule + + rpcUrl string + p2pCfg *configs.P2PConfig + rpcClient *rpc.ClientWithResponses + + connFactory typesP2P.ConnectionFactory +} + +func NewRPCAddrBookProvider(options ...modules.ModuleOption) *rpcAddrBookProvider { + dabp := &rpcAddrBookProvider{ + rpcUrl: fmt.Sprintf("http://%s:%s", rpcHost, defaults.DefaultRPCPort), + connFactory: transport.CreateDialer, // default connection factory, overridable with WithConnectionFactory() + } + + for _, o := range options { + o(dabp) + } + + initRPCClient(dabp) + + return dabp +} + +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(rpcAddrBookProvider).Create(bus, options...) +} + +func (*rpcAddrBookProvider) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return NewRPCAddrBookProvider(options...), nil +} + +func (*rpcAddrBookProvider) GetModuleName() string { + return addrbook_provider.ModuleName +} + +func (dabp *rpcAddrBookProvider) GetStakedAddrBookAtHeight(height uint64) (typesP2P.AddrBook, error) { + ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) + defer cancel() + + var ( + h int64 = int64(height) + actorType rpc.ActorTypesEnum = "validator" + ) + response, err := dabp.rpcClient.GetV1P2pStakedActorsAddressBookWithResponse(ctx, &rpc.GetV1P2pStakedActorsAddressBookParams{Height: &h, ActorType: &actorType}) + if err != nil { + return nil, err + } + statusCode := response.StatusCode() + if statusCode != http.StatusOK { + return nil, fmt.Errorf("error retrieving addressbook via rpc. Unexpected status code: %d", statusCode) + } + + rpcActors := response.JSON200.Actors + var coreActors []*types.Actor + for _, rpcActor := range rpcActors { + coreActors = append(coreActors, &types.Actor{ + Address: rpcActor.Address, + PublicKey: rpcActor.PublicKey, + GenericParam: rpcActor.ServiceUrl, + ActorType: types.ActorType_ACTOR_TYPE_VAL, + }) + } + + return addrbook_provider.ActorsToAddrBook(dabp, coreActors) +} + +func (dabp *rpcAddrBookProvider) GetConnFactory() typesP2P.ConnectionFactory { + return dabp.connFactory +} + +func (dabp *rpcAddrBookProvider) GetP2PConfig() *configs.P2PConfig { + if dabp.p2pCfg == nil { + return dabp.GetBus().GetRuntimeMgr().GetConfig().P2P + } + return dabp.p2pCfg +} + +func (dabp *rpcAddrBookProvider) SetConnectionFactory(connFactory typesP2P.ConnectionFactory) { + dabp.connFactory = connFactory +} + +func initRPCClient(dabp *rpcAddrBookProvider) { + rpcClient, err := rpc.NewClientWithResponses(dabp.rpcUrl) + if err != nil { + log.Fatalf("could not create RPC client: %v", err) + } + dabp.rpcClient = rpcClient +} + +// options + +// WithP2PConfig allows to specify a custom P2P config +func WithP2PConfig(p2pCfg *configs.P2PConfig) modules.ModuleOption { + return func(rabp modules.InitializableModule) { + rabp.(*rpcAddrBookProvider).p2pCfg = p2pCfg + } +} + +// WithCustomRPCUrl allows to specify a custom RPC URL +func WithCustomRPCUrl(rpcUrl string) modules.ModuleOption { + return func(rabp modules.InitializableModule) { + rabp.(*rpcAddrBookProvider).rpcUrl = rpcUrl + } +} diff --git a/p2p/providers/current_height_provider/current_height_provider.go b/p2p/providers/current_height_provider/current_height_provider.go index feb858bc2..9d797fffd 100644 --- a/p2p/providers/current_height_provider/current_height_provider.go +++ b/p2p/providers/current_height_provider/current_height_provider.go @@ -2,6 +2,13 @@ package current_height_provider //go:generate mockgen -source=$GOFILE -destination=../../types/mocks/current_height_provider_mock.go -package=mock_types github.com/pokt-network/pocket/p2p/types CurrentHeightProvider +import "github.com/pokt-network/pocket/shared/modules" + +const ModuleName = "current_height_provider" + type CurrentHeightProvider interface { + modules.IntegratableModule + modules.InterruptableModule + CurrentHeight() uint64 } diff --git a/p2p/providers/current_height_provider/debug/provider.go b/p2p/providers/current_height_provider/debug/provider.go deleted file mode 100644 index 7575cdd9e..000000000 --- a/p2p/providers/current_height_provider/debug/provider.go +++ /dev/null @@ -1,21 +0,0 @@ -package debug - -import "github.com/pokt-network/pocket/p2p/providers/current_height_provider" - -var _ current_height_provider.CurrentHeightProvider = &debugCurrentHeightProvider{} - -type debugCurrentHeightProvider struct { - currentHeight uint64 -} - -func (dchp *debugCurrentHeightProvider) CurrentHeight() uint64 { - return dchp.currentHeight -} - -func NewDebugCurrentHeightProvider(height uint64) *debugCurrentHeightProvider { - dchp := &debugCurrentHeightProvider{ - currentHeight: height, - } - - return dchp -} diff --git a/p2p/providers/current_height_provider/rpc/provider.go b/p2p/providers/current_height_provider/rpc/provider.go new file mode 100644 index 000000000..8a4bf865c --- /dev/null +++ b/p2p/providers/current_height_provider/rpc/provider.go @@ -0,0 +1,96 @@ +package rpc + +import ( + "context" + "fmt" + "log" + "net/http" + "time" + + "github.com/pokt-network/pocket/p2p/providers/current_height_provider" + "github.com/pokt-network/pocket/rpc" + "github.com/pokt-network/pocket/runtime" + "github.com/pokt-network/pocket/runtime/defaults" + "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" +) + +var ( + _ current_height_provider.CurrentHeightProvider = &rpcCurrentHeightProvider{} + rpcHost string +) + +func init() { + // by default, we point at the same endpoint used by the CLI but the debug client is used either in docker-compose of K8S, therefore we cater for overriding + rpcHost = runtime.GetEnv("RPC_HOST", defaults.Validator1EndpointK8S) +} + +type rpcCurrentHeightProvider struct { + base_modules.IntegratableModule + base_modules.InterruptableModule + + rpcUrl string + rpcClient *rpc.ClientWithResponses +} + +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(rpcCurrentHeightProvider).Create(bus, options...) +} + +// Create implements current_height_provider.CurrentHeightProvider +func (*rpcCurrentHeightProvider) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return NewRPCCurrentHeightProvider(options...), nil +} + +// GetModuleName implements current_height_provider.CurrentHeightProvider +func (*rpcCurrentHeightProvider) GetModuleName() string { + return current_height_provider.ModuleName +} + +func (dchp *rpcCurrentHeightProvider) CurrentHeight() uint64 { + ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) + + response, err := dchp.rpcClient.GetV1ConsensusStateWithResponse(ctx) + if err != nil { + cancel() + log.Fatalf("could not get consensus state from RPC: %v", err) + } + statusCode := response.StatusCode() + if statusCode != http.StatusOK { + cancel() + log.Fatalf("error retrieving consensus state from RPC. Unexpected status code: %d", statusCode) + } + cancel() + return uint64(response.JSONDefault.Height) +} + +func NewRPCCurrentHeightProvider(options ...modules.ModuleOption) *rpcCurrentHeightProvider { + dabp := &rpcCurrentHeightProvider{ + rpcUrl: fmt.Sprintf("http://%s:%s", rpcHost, defaults.DefaultRPCPort), + } + + for _, o := range options { + o(dabp) + } + + initRPCClient(dabp) + + return dabp +} + +func initRPCClient(dabp *rpcCurrentHeightProvider) { + rpcClient, err := rpc.NewClientWithResponses(dabp.rpcUrl) + if err != nil { + log.Fatalf("could not create RPC client: %v", err) + } + dabp.rpcClient = rpcClient +} + +// options + +// WithCustomRPCUrl allows to specify a custom RPC URL +func WithCustomRPCUrl(rpcUrl string) modules.ModuleOption { + return func(rabp modules.InitializableModule) { + rabp.(*rpcCurrentHeightProvider).rpcUrl = rpcUrl + } +} diff --git a/p2p/raintree/addrbook_utils.go b/p2p/raintree/addrbook_utils.go index 55109a8ac..bfe14c439 100644 --- a/p2p/raintree/addrbook_utils.go +++ b/p2p/raintree/addrbook_utils.go @@ -17,7 +17,7 @@ func (n *rainTreeNetwork) getAddrBookLength(level uint32, height uint64) int { peersManagerStateView := n.peersManager.getNetworkView() // if we are propagating a message from a previous height, we need to instantiate an ephemeral peersManager (without add/remove) - if height < n.GetBus().GetConsensusModule().CurrentHeight() { + if height < n.currentHeightProvider.CurrentHeight() { peersManagerWithAddrBookProvider, err := newPeersManagerWithAddrBookProvider(n.selfAddr, n.addrBookProvider, height) if err != nil { n.logger.Fatal().Err(err).Msg("Error initializing rainTreeNetwork peersManagerWithAddrBookProvider") @@ -31,7 +31,7 @@ func (n *rainTreeNetwork) getAddrBookLength(level uint32, height uint64) int { // getTargetsAtLevel returns the targets for a given level func (n *rainTreeNetwork) getTargetsAtLevel(level uint32) []target { - height := n.GetBus().GetConsensusModule().CurrentHeight() + height := n.currentHeightProvider.CurrentHeight() addrBookLengthAtHeight := n.getAddrBookLength(level, height) firstTarget := n.getTarget(firstMsgTargetPercentage, addrBookLengthAtHeight, level) secondTarget := n.getTarget(secondMsgTargetPercentage, addrBookLengthAtHeight, level) diff --git a/p2p/raintree/network.go b/p2p/raintree/network.go index 3b19cd883..9630059e4 100644 --- a/p2p/raintree/network.go +++ b/p2p/raintree/network.go @@ -14,17 +14,15 @@ import ( "github.com/pokt-network/pocket/shared/mempool" "github.com/pokt-network/pocket/shared/messaging" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" telemetry "github.com/pokt-network/pocket/telemetry" "google.golang.org/protobuf/proto" ) -var ( - _ typesP2P.Network = &rainTreeNetwork{} - _ modules.IntegratableModule = &rainTreeNetwork{} -) +var _ typesP2P.Network = &rainTreeNetwork{} type rainTreeNetwork struct { - bus modules.Bus + base_modules.IntegratableModule selfAddr cryptoPocket.Address addrBookProvider addrbook_provider.AddrBookProvider @@ -32,6 +30,8 @@ type rainTreeNetwork struct { peersManager *peersManager nonceDeduper *mempool.GenericFIFOSet[uint64, uint64] + currentHeightProvider providers.CurrentHeightProvider + logger modules.Logger } @@ -52,11 +52,12 @@ func NewRainTreeNetwork(addr cryptoPocket.Address, bus modules.Bus, addrBookProv p2pCfg := bus.GetRuntimeMgr().GetConfig().P2P n := &rainTreeNetwork{ - selfAddr: addr, - peersManager: pm, - nonceDeduper: mempool.NewGenericFIFOSet[uint64, uint64](int(p2pCfg.MaxMempoolCount)), - addrBookProvider: addrBookProvider, - logger: networkLogger, + selfAddr: addr, + peersManager: pm, + nonceDeduper: mempool.NewGenericFIFOSet[uint64, uint64](int(p2pCfg.MaxMempoolCount)), + addrBookProvider: addrBookProvider, + currentHeightProvider: currentHeightProvider, + logger: networkLogger, } n.SetBus(bus) return typesP2P.Network(n) @@ -223,21 +224,13 @@ func (n *rainTreeNetwork) AddPeerToAddrBook(peer *typesP2P.NetworkPeer) error { return nil } -func (n *rainTreeNetwork) RemovePeerToAddrBook(peer *typesP2P.NetworkPeer) error { +func (n *rainTreeNetwork) RemovePeerFromAddrBook(peer *typesP2P.NetworkPeer) error { n.peersManager.wg.Add(1) n.peersManager.eventCh <- addressBookEvent{removeFromAddressBook, peer} n.peersManager.wg.Wait() return nil } -func (n *rainTreeNetwork) SetBus(bus modules.Bus) { - n.bus = bus -} - -func (n *rainTreeNetwork) GetBus() modules.Bus { - return n.bus -} - func shouldSendToTarget(target target) bool { return !target.isSelf } diff --git a/p2p/raintree/network_test.go b/p2p/raintree/network_test.go index ba082b645..311f64715 100644 --- a/p2p/raintree/network_test.go +++ b/p2p/raintree/network_test.go @@ -46,7 +46,7 @@ func TestRainTreeNetwork_AddPeerToAddrBook(t *testing.T) { require.Equal(t, peer, stateView.addrBookMap[peerAddr.String()], "addrBookMap does not contain peer") } -func TestRainTreeNetwork_RemovePeerToAddrBook(t *testing.T) { +func TestRainTreeNetwork_RemovePeerFromAddrBook(t *testing.T) { ctrl := gomock.NewController(t) // starting with an address book having only self and an arbitrary number of peers `numAddressesInAddressBook`` @@ -67,7 +67,7 @@ func TestRainTreeNetwork_RemovePeerToAddrBook(t *testing.T) { // removing a peer peer := addrBook[1] - err = network.RemovePeerToAddrBook(peer) + err = network.RemovePeerFromAddrBook(peer) require.NoError(t, err) stateView = network.peersManager.getNetworkView() diff --git a/p2p/stdnetwork/network.go b/p2p/stdnetwork/network.go index 841edeebc..712bd61ed 100644 --- a/p2p/stdnetwork/network.go +++ b/p2p/stdnetwork/network.go @@ -84,7 +84,7 @@ func (n *network) AddPeerToAddrBook(peer *typesP2P.NetworkPeer) error { return nil } -func (n *network) RemovePeerToAddrBook(peer *typesP2P.NetworkPeer) error { +func (n *network) RemovePeerFromAddrBook(peer *typesP2P.NetworkPeer) error { delete(n.addrBookMap, peer.Address.String()) return nil } diff --git a/p2p/types/network.go b/p2p/types/network.go index 90daedb91..66daaa8ae 100644 --- a/p2p/types/network.go +++ b/p2p/types/network.go @@ -18,7 +18,7 @@ type Network interface { // Address book helpers GetAddrBook() AddrBook AddPeerToAddrBook(peer *NetworkPeer) error - RemovePeerToAddrBook(peer *NetworkPeer) error + RemovePeerFromAddrBook(peer *NetworkPeer) error // This function was added to specifically support the RainTree implementation. // Handles the raw data received from the network and returns the data to be processed diff --git a/p2p/utils_test.go b/p2p/utils_test.go index 37fdc8dbb..b6cdbf560 100644 --- a/p2p/utils_test.go +++ b/p2p/utils_test.go @@ -10,12 +10,14 @@ import ( "testing" "time" - types "github.com/pokt-network/pocket/runtime/configs/types" - "github.com/golang/mock/gomock" + "github.com/pokt-network/pocket/p2p/providers/addrbook_provider" + "github.com/pokt-network/pocket/p2p/providers/current_height_provider" typesP2P "github.com/pokt-network/pocket/p2p/types" mocksP2P "github.com/pokt-network/pocket/p2p/types/mocks" + "github.com/pokt-network/pocket/runtime" "github.com/pokt-network/pocket/runtime/configs" + types "github.com/pokt-network/pocket/runtime/configs/types" "github.com/pokt-network/pocket/runtime/genesis" coreTypes "github.com/pokt-network/pocket/shared/core/types" cryptoPocket "github.com/pokt-network/pocket/shared/crypto" @@ -150,10 +152,13 @@ func createMockBus(t *testing.T, runtimeMgr modules.RuntimeMgr) *mockModules.Moc ctrl := gomock.NewController(t) mockBus := mockModules.NewMockBus(ctrl) mockBus.EXPECT().GetRuntimeMgr().Return(runtimeMgr).AnyTimes() - mockBus.EXPECT().RegisterModule(gomock.Any()).DoAndReturn(func(m modules.Module) error { + mockBus.EXPECT().RegisterModule(gomock.Any()).DoAndReturn(func(m modules.Module) { m.SetBus(mockBus) - return nil }).AnyTimes() + mockModulesRegistry := mockModules.NewMockModulesRegistry(ctrl) + mockModulesRegistry.EXPECT().GetModule(addrbook_provider.ModuleName).Return(nil, runtime.ErrModuleNotRegistered(addrbook_provider.ModuleName)).AnyTimes() + mockModulesRegistry.EXPECT().GetModule(current_height_provider.ModuleName).Return(nil, runtime.ErrModuleNotRegistered(current_height_provider.ModuleName)).AnyTimes() + mockBus.EXPECT().GetModulesRegistry().Return(mockModulesRegistry).AnyTimes() mockBus.EXPECT().PublishEventToBus(gomock.Any()).AnyTimes() return mockBus } @@ -201,8 +206,7 @@ func prepareConsensusMock(t *testing.T, busMock *mockModules.MockBus) *mockModul consensusMock.EXPECT().GetBus().Return(busMock).AnyTimes() consensusMock.EXPECT().SetBus(busMock).AnyTimes() consensusMock.EXPECT().GetModuleName().Return(modules.ConsensusModuleName).AnyTimes() - err := busMock.RegisterModule(consensusMock) - require.NoError(t, err) + busMock.RegisterModule(consensusMock) return consensusMock } @@ -221,8 +225,7 @@ func preparePersistenceMock(t *testing.T, busMock *mockModules.MockBus, genesisS persistenceMock.EXPECT().GetBus().Return(busMock).AnyTimes() persistenceMock.EXPECT().SetBus(busMock).AnyTimes() persistenceMock.EXPECT().GetModuleName().Return(modules.PersistenceModuleName).AnyTimes() - err := busMock.RegisterModule(persistenceMock) - require.NoError(t, err) + busMock.RegisterModule(persistenceMock) return persistenceMock } @@ -241,8 +244,7 @@ func prepareTelemetryMock(t *testing.T, busMock *mockModules.MockBus, valId stri telemetryMock.EXPECT().GetModuleName().Return(modules.TelemetryModuleName).AnyTimes() telemetryMock.EXPECT().GetBus().Return(busMock).AnyTimes() telemetryMock.EXPECT().SetBus(busMock).AnyTimes() - err := busMock.RegisterModule(telemetryMock) - require.NoError(t, err) + busMock.RegisterModule(telemetryMock) return telemetryMock } diff --git a/persistence/docs/CHANGELOG.md b/persistence/docs/CHANGELOG.md index 8f790c2a6..b13b7a898 100644 --- a/persistence/docs/CHANGELOG.md +++ b/persistence/docs/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.36] - 2023-02-15 + +- Module now embeds `base_modules.IntegratableModule` for DRYness + ## [0.0.0.35] - 2023-02-15 - Add a few `nolint` comments to fix the code on main @@ -32,7 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.0.0.30] - 2023-02-04 -- Changed log lines to utilize new logger module. +- Changed log lines to utilize new logger module ## [0.0.0.29] - 2023-01-31 diff --git a/persistence/module.go b/persistence/module.go index 887fa8594..3f5f5faf2 100644 --- a/persistence/module.go +++ b/persistence/module.go @@ -11,6 +11,7 @@ import ( "github.com/pokt-network/pocket/runtime/configs" "github.com/pokt-network/pocket/runtime/genesis" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" ) var ( @@ -23,7 +24,8 @@ var ( // TODO: convert address and public key to string not bytes in all account and actor functions // TODO: remove address parameter from all pool operations type persistenceModule struct { - bus modules.Bus + base_modules.IntegratableModule + config *configs.PersistenceConfig genesisState *genesis.GenesisState @@ -37,18 +39,21 @@ type persistenceModule struct { writeContext *PostgresContext // only one write context is allowed at a time } -func Create(bus modules.Bus) (modules.Module, error) { - return new(persistenceModule).Create(bus) +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(persistenceModule).Create(bus, options...) } -func (*persistenceModule) Create(bus modules.Bus) (modules.Module, error) { +func (*persistenceModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { m := &persistenceModule{ writeContext: nil, } - if err := bus.RegisterModule(m); err != nil { - return nil, err + + for _, option := range options { + option(m) } + bus.RegisterModule(m) + runtimeMgr := bus.GetRuntimeMgr() persistenceCfg := runtimeMgr.GetConfig().Persistence @@ -117,17 +122,6 @@ func (m *persistenceModule) GetModuleName() string { return modules.PersistenceModuleName } -func (m *persistenceModule) SetBus(bus modules.Bus) { - m.bus = bus -} - -func (m *persistenceModule) GetBus() modules.Bus { - if m.bus == nil { - logger.Global.Fatal().Msg("PocketBus is not initialized") - } - return m.bus -} - func (m *persistenceModule) NewRWContext(height int64) (modules.PersistenceRWContext, error) { if m.writeContext != nil && m.writeContext.conn != nil && !m.writeContext.conn.IsClosed() { return nil, fmt.Errorf("write context already exists") diff --git a/rpc/doc/CHANGELOG.md b/rpc/doc/CHANGELOG.md index 869d12656..79aff212c 100644 --- a/rpc/doc/CHANGELOG.md +++ b/rpc/doc/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.11] - 2023-02-10 + +- Updated RPC to expose the node's address book via GET `/v1/p2p/staked_actors_address_book` +- Updated modules to embed `base_modules.IntegratableModule` and `base_modules.InterruptableModule` for DRYness + ## [0.0.0.10] - 2023-02-07 - Added GITHUB_WIKI tags where it was missing diff --git a/rpc/handlers.go b/rpc/handlers.go index 10fc44834..6d45ca076 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -7,6 +7,8 @@ import ( "github.com/labstack/echo/v4" "github.com/pokt-network/pocket/app" "github.com/pokt-network/pocket/shared/codec" + typesCore "github.com/pokt-network/pocket/shared/core/types" + "github.com/pokt-network/pocket/shared/modules" typesUtil "github.com/pokt-network/pocket/utility/types" ) @@ -67,3 +69,77 @@ func (s *rpcServer) broadcastMessage(msgBz []byte) error { } return nil } + +func (s *rpcServer) GetV1P2pStakedActorsAddressBook(ctx echo.Context, params GetV1P2pStakedActorsAddressBookParams) error { + var height int64 + var actors []Actor + + if params.Height != nil { + height = *params.Height + } else { + height = int64(s.GetBus().GetConsensusModule().CurrentHeight()) + } + + persistenceContext, err := s.GetBus().GetPersistenceModule().NewReadContext(height) + if err != nil { + return ctx.String(http.StatusInternalServerError, err.Error()) + } + defer persistenceContext.Close() + + protocolActorGetter := getProtocolActorGetter(persistenceContext, params) + + protocolActors, err := protocolActorGetter(height) + if err != nil { + return ctx.String(http.StatusInternalServerError, err.Error()) + } + + for _, protocolActor := range protocolActors { + actors = append(actors, Actor{ + Address: protocolActor.Address, + Type: protocolActorToRPCActorTypeEnum(protocolActor.ActorType), + PublicKey: protocolActor.PublicKey, + ServiceUrl: protocolActor.GenericParam, + }) + } + + response := P2PStakedActorsResponse{ + Actors: actors, + Height: height, + } + + return ctx.JSON(http.StatusOK, response) +} + +// protocolActorToRPCActorTypeEnum converts a protocol actor type to the rpc actor type enum +func protocolActorToRPCActorTypeEnum(protocolActorType typesCore.ActorType) ActorTypesEnum { + switch protocolActorType { + case typesCore.ActorType_ACTOR_TYPE_APP: + return Application + case typesCore.ActorType_ACTOR_TYPE_FISH: + return Fisherman + case typesCore.ActorType_ACTOR_TYPE_SERVICENODE: + return ServiceNode + case typesCore.ActorType_ACTOR_TYPE_VAL: + return Validator + default: + panic("invalid actor type") + } +} + +// getProtocolActorGetter returns the correct protocol actor getter function based on the actor type parameter +func getProtocolActorGetter(persistenceContext modules.PersistenceReadContext, params GetV1P2pStakedActorsAddressBookParams) func(height int64) ([]*typesCore.Actor, error) { + var protocolActorGetter func(height int64) ([]*typesCore.Actor, error) = persistenceContext.GetAllStakedActors + if params.ActorType != nil { + switch *params.ActorType { + case Application: + protocolActorGetter = persistenceContext.GetAllApps + case Fisherman: + protocolActorGetter = persistenceContext.GetAllFishermen + case ServiceNode: + protocolActorGetter = persistenceContext.GetAllServiceNodes + case Validator: + protocolActorGetter = persistenceContext.GetAllValidators + } + } + return protocolActorGetter +} diff --git a/rpc/module.go b/rpc/module.go index c05b67b74..17537d70a 100644 --- a/rpc/module.go +++ b/rpc/module.go @@ -9,35 +9,41 @@ import ( "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/runtime/configs" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" ) var _ modules.RPCModule = &rpcModule{} type rpcModule struct { - bus modules.Bus + base_modules.IntegratableModule + base_modules.InterruptableModule + logger modules.Logger config *configs.RPCConfig } -func Create(bus modules.Bus) (modules.Module, error) { - return new(rpcModule).Create(bus) +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(rpcModule).Create(bus, options...) } -func (*rpcModule) Create(bus modules.Bus) (modules.Module, error) { +func (*rpcModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { runtimeMgr := bus.GetRuntimeMgr() cfg := runtimeMgr.GetConfig() rpcCfg := cfg.RPC - rpcMod := modules.RPCModule(&rpcModule{ + m := modules.RPCModule(&rpcModule{ config: rpcCfg, }) if !rpcCfg.Enabled { - rpcMod = &noopRpcModule{} + m = &noopRpcModule{} } - if err := bus.RegisterModule(rpcMod); err != nil { - return nil, err + + for _, option := range options { + option(m) } - return rpcMod, nil + bus.RegisterModule(m) + + return m, nil } func (u *rpcModule) Start() error { @@ -46,21 +52,6 @@ func (u *rpcModule) Start() error { return nil } -func (u *rpcModule) Stop() error { - return nil -} - func (u *rpcModule) GetModuleName() string { return modules.RPCModuleName } - -func (u *rpcModule) SetBus(bus modules.Bus) { - u.bus = bus -} - -func (u *rpcModule) GetBus() modules.Bus { - if u.bus == nil { - u.logger.Fatal().Msg("Bus is not initialized") - } - return u.bus -} diff --git a/rpc/noop_module.go b/rpc/noop_module.go index daad5b40c..1c7401b80 100644 --- a/rpc/noop_module.go +++ b/rpc/noop_module.go @@ -4,31 +4,25 @@ import ( "log" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" ) var _ modules.RPCModule = &noopRpcModule{} -type noopRpcModule struct{} +type noopRpcModule struct { + base_modules.IntegratableModule + base_modules.InterruptableModule +} func (m *noopRpcModule) GetModuleName() string { return "noop_rpc_module" } -func (m *noopRpcModule) Create(bus modules.Bus) (modules.Module, error) { +func (m *noopRpcModule) Create(bus modules.Bus, _ ...modules.ModuleOption) (modules.Module, error) { return &rpcModule{}, nil } -func (m *noopRpcModule) SetBus(_ modules.Bus) {} - -func (m *noopRpcModule) GetBus() modules.Bus { - return nil -} - func (m *noopRpcModule) Start() error { log.Println("[WARN] RPC server: OFFLINE") return nil } - -func (m *noopRpcModule) Stop() error { - return nil -} diff --git a/rpc/rpc.go b/rpc/rpc.go index ec9117584..76794bbdc 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -2,6 +2,7 @@ package rpc // importing because used by code-generated files that are git ignored and to allow go mod tidy and go mod vendor to function properly import ( + _ "github.com/deepmap/oapi-codegen/pkg/runtime" _ "github.com/getkin/kin-openapi/openapi3" _ "github.com/labstack/echo/v4" ) diff --git a/rpc/server.go b/rpc/server.go index 087b3ea06..696c78a58 100644 --- a/rpc/server.go +++ b/rpc/server.go @@ -7,10 +7,11 @@ import ( "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" ) type rpcServer struct { - bus modules.Bus + base_modules.IntegratableModule logger modules.Logger } @@ -66,11 +67,3 @@ func (s *rpcServer) StartRPC(port string, timeout uint64, logger *modules.Logger s.logger.Fatal().Err(err).Msg("RPC server failed to start") } } - -func (s *rpcServer) SetBus(bus modules.Bus) { - s.bus = bus -} - -func (s *rpcServer) GetBus() modules.Bus { - return s.bus -} diff --git a/rpc/v1/openapi.yaml b/rpc/v1/openapi.yaml index 3183d561b..aefe9f481 100644 --- a/rpc/v1/openapi.yaml +++ b/rpc/v1/openapi.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 servers: - - url: 'http://localhost:50832' + - url: "http://localhost:50832" info: description: >- This is the API definition Pocket Network Node RPC interface. @@ -12,12 +12,12 @@ info: Pocket verifies all relayed data and proportionally rewards the participating nodes with POKT. version: 1.0.0 title: Pocket Network - termsOfService: 'https://pokt.network/terms/' + termsOfService: "https://pokt.network/terms/" contact: email: hola@pokt.network license: name: MIT License - url: 'https://github.com/pokt-network/pocket/blob/main/LICENSE' + url: "https://github.com/pokt-network/pocket/blob/main/LICENSE" tags: - name: version description: Version of the Pocket API @@ -34,11 +34,11 @@ paths: - health summary: Get the liveness of the Pocket API node responses: - '200': + "200": description: Healthy - '404': + "404": description: Unhealthy - Unreachable - '500': + "500": description: Unhealthy - Server Error /v1/version: get: @@ -64,13 +64,8 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConsensusState' - example: - { - "height": 75016, - "round": 0, - "step": 3 - } + $ref: "#/components/schemas/ConsensusState" + example: { "height": 75016, "round": 0, "step": 3 } /v1/client/broadcast_tx_sync: post: tags: @@ -82,23 +77,64 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RawTXRequest' + $ref: "#/components/schemas/RawTXRequest" responses: - '200': + "200": description: Transaction added to the mempool without errors - '400': + "400": description: Bad request content: text/plain: example: "description of failure" - '500': + "500": description: An error occurred while adding the transaction to the mempool content: text/plain: example: "description of failure" + + /v1/p2p/staked_actors_address_book: + get: + tags: + - p2p + summary: Returns the protocol actor address book + parameters: + - in: query + name: height + required: false + schema: + type: integer + format: int64 + minimum: 0 + description: The height the query will be executed on. By default it uses the current height of the consensus module. This may be the latest height if synched or an earlier height if synching. + - in: query + name: actor_type + required: false + schema: + $ref: "#/components/schemas/ActorTypesEnum" + description: The type of actor the address book will be populated with. By default it returns an address book for all protocol actors supported by the blockchain + + responses: + "200": + description: Staked actors response + content: + application/json: + schema: + $ref: "#/components/schemas/P2PStakedActorsResponse" + + "400": + description: Bad request + content: + text/plain: + example: "description of failure" + "500": + description: An error occurred while retrieving the staked actors address book + content: + text/plain: + example: "description of failure" + externalDocs: description: Find out more about Pocket Network - url: 'https://pokt.network' + url: "https://pokt.network" components: schemas: RawTXRequest: @@ -112,23 +148,61 @@ components: raw_hex_bytes: type: string ConsensusState: - type: object - required: - - height - - round - - step - properties: - height: - type: integer - format: int64 - round: - type: integer - format: int64 - step: - type: integer - format: int64 - requestBodies: {} + type: object + required: + - height + - round + - step + properties: + height: + type: integer + format: int64 + round: + type: integer + format: int64 + step: + type: integer + format: int64 + Actor: + type: object + required: + - type + - address + - public_key + - service_url + properties: + type: + $ref: "#/components/schemas/ActorTypesEnum" + address: + type: string + public_key: + type: string + service_url: + type: string + + P2PStakedActorsResponse: + type: object + required: + - actors + - height + properties: + actors: + type: "array" + items: + $ref: "#/components/schemas/Actor" + height: + type: integer + format: int64 + + ActorTypesEnum: + type: string + enum: + - validator + - service_node + - fisherman + - application + securitySchemes: {} links: {} callbacks: {} -security: [] \ No newline at end of file +security: [] diff --git a/runtime/bus.go b/runtime/bus.go index 3289ba9f2..014dbc585 100644 --- a/runtime/bus.go +++ b/runtime/bus.go @@ -4,6 +4,7 @@ import ( "log" "sync" + "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/runtime/defaults" "github.com/pokt-network/pocket/shared/messaging" "github.com/pokt-network/pocket/shared/modules" @@ -21,7 +22,7 @@ type bus struct { // Node events channel modules.EventsChannel - modulesMap map[string]modules.Module + modulesRegistry modules.ModulesRegistry runtimeMgr modules.RuntimeMgr } @@ -34,17 +35,20 @@ func (b *bus) Create(runtimeMgr modules.RuntimeMgr) (modules.Bus, error) { bus := &bus{ channel: make(modules.EventsChannel, defaults.DefaultBusBufferSize), - runtimeMgr: runtimeMgr, - modulesMap: make(map[string]modules.Module), + runtimeMgr: runtimeMgr, + modulesRegistry: NewModulesRegistry(), } return bus, nil } -func (m *bus) RegisterModule(module modules.Module) error { +func (m *bus) GetModulesRegistry() modules.ModulesRegistry { + return m.modulesRegistry +} + +func (m *bus) RegisterModule(module modules.Module) { module.SetBus(m) - m.modulesMap[module.GetModuleName()] = module - return nil + m.modulesRegistry.RegisterModule(module) } func (m *bus) PublishEventToBus(e *messaging.PocketEnvelope) { @@ -61,41 +65,41 @@ func (m *bus) GetEventBus() modules.EventsChannel { } func (m *bus) GetPersistenceModule() modules.PersistenceModule { - if mod, ok := m.modulesMap[modules.PersistenceModuleName]; ok { - return mod.(modules.PersistenceModule) + mod, err := m.modulesRegistry.GetModule(modules.PersistenceModuleName) + if err != nil { + logger.Global.Logger.Fatal().Err(err).Msg("failed to get module from modulesRegistry") } - log.Fatalf("%s", ErrModuleNotRegistered("persistence")) - return nil + return mod.(modules.PersistenceModule) } func (m *bus) GetP2PModule() modules.P2PModule { - if mod, ok := m.modulesMap[modules.P2PModuleName]; ok { - return mod.(modules.P2PModule) + mod, err := m.modulesRegistry.GetModule(modules.P2PModuleName) + if err != nil { + logger.Global.Logger.Fatal().Err(err).Msg("failed to get module from modulesRegistry") } - log.Fatalf("%s", ErrModuleNotRegistered("P2P")) - return nil + return mod.(modules.P2PModule) } func (m *bus) GetUtilityModule() modules.UtilityModule { - if mod, ok := m.modulesMap[modules.UtilityModuleName]; ok { - return mod.(modules.UtilityModule) + mod, err := m.modulesRegistry.GetModule(modules.UtilityModuleName) + if err != nil { + logger.Global.Logger.Fatal().Err(err).Msg("failed to get module from modulesRegistry") } - log.Fatalf("%s", ErrModuleNotRegistered(modules.UtilityModuleName)) - return nil + return mod.(modules.UtilityModule) } func (m *bus) GetConsensusModule() modules.ConsensusModule { - if mod, ok := m.modulesMap[modules.ConsensusModuleName]; ok { - return mod.(modules.ConsensusModule) + mod, err := m.modulesRegistry.GetModule(modules.ConsensusModuleName) + if err != nil { + logger.Global.Logger.Fatal().Err(err).Msg("failed to get module from modulesRegistry") } - log.Fatalf("%s", ErrModuleNotRegistered(modules.ConsensusModuleName)) - return nil + return mod.(modules.ConsensusModule) } func (m *bus) GetTelemetryModule() modules.TelemetryModule { for _, moduleName := range telemetry.ImplementationNames { - telemetryMod, ok := m.modulesMap[moduleName] - if ok { + telemetryMod, err := m.modulesRegistry.GetModule(moduleName) + if err == nil { return telemetryMod.(modules.TelemetryModule) } } @@ -107,26 +111,32 @@ func (m *bus) GetTelemetryModule() modules.TelemetryModule { if err != nil { log.Fatalf("failed to create noop telemetry module: %v", err) } - if err := m.RegisterModule(noopModule); err != nil { - log.Fatalf("[ERROR] Failed to register telemetry module: %v", err.Error()) - } + m.RegisterModule(noopModule) return noopModule.(modules.TelemetryModule) } func (m *bus) GetLoggerModule() modules.LoggerModule { - if mod, ok := m.modulesMap[modules.LoggerModuleName]; ok { - return mod.(modules.LoggerModule) + mod, err := m.modulesRegistry.GetModule(modules.LoggerModuleName) + if err != nil { + logger.Global.Logger.Fatal().Err(err).Msg("failed to get module from modulesRegistry") } - log.Fatalf("%s", ErrModuleNotRegistered(modules.LoggerModuleName)) - return nil + return mod.(modules.LoggerModule) } func (m *bus) GetRPCModule() modules.RPCModule { - if mod, ok := m.modulesMap[modules.RPCModuleName]; ok { - return mod.(modules.RPCModule) + mod, err := m.modulesRegistry.GetModule(modules.RPCModuleName) + if err != nil { + logger.Global.Logger.Fatal().Err(err).Msg("failed to get module from modulesRegistry") + } + return mod.(modules.RPCModule) +} + +func (m *bus) GetStateMachineModule() modules.StateMachineModule { + mod, err := m.modulesRegistry.GetModule(modules.StateMachineModuleName) + if err != nil { + logger.Global.Logger.Fatal().Err(err).Msg("failed to get module from modulesRegistry") } - log.Fatalf("%s", ErrModuleNotRegistered(modules.RPCModuleName)) - return nil + return mod.(modules.StateMachineModule) } func (m *bus) GetRuntimeMgr() modules.RuntimeMgr { diff --git a/runtime/configs/config.go b/runtime/configs/config.go index 21e18ea5f..44af2c544 100644 --- a/runtime/configs/config.go +++ b/runtime/configs/config.go @@ -51,8 +51,8 @@ func NewDefaultConfig(options ...func(*Config)) *Config { Format: defaults.DefaultLoggerFormat, }, RPC: &RPCConfig{ - Timeout: defaults.DefaultRpcTimeout, - Port: defaults.DefaultRpcPort, + Timeout: defaults.DefaultRPCTimeout, + Port: defaults.DefaultRPCPort, }, } diff --git a/runtime/configs/proto/p2p_config.proto b/runtime/configs/proto/p2p_config.proto index d21b56028..171bc2db8 100644 --- a/runtime/configs/proto/p2p_config.proto +++ b/runtime/configs/proto/p2p_config.proto @@ -13,4 +13,5 @@ message P2PConfig { conn.ConnectionType connection_type = 4; uint64 max_mempool_count = 5; // this is used to limit the number of nonces that can be stored in the mempool, after which a FIFO mechanism is used to remove the oldest nonces and make space for the new ones bool is_client_only = 6; + string bootstrap_nodes_csv = 7; // string in the format "http://somenode:50832,http://someothernode:50832". Refer to `p2p/module_test.go` for additional details. } diff --git a/runtime/defaults/defaults.go b/runtime/defaults/defaults.go index f83bdf815..fa0030612 100644 --- a/runtime/defaults/defaults.go +++ b/runtime/defaults/defaults.go @@ -2,19 +2,23 @@ package defaults import ( "fmt" + "strings" - types "github.com/pokt-network/pocket/runtime/configs/types" + "github.com/pokt-network/pocket/runtime/configs/types" ) const ( - defaultRPCPort = "50832" - defaultRPCHost = "localhost" - defaultRPCTimeout = 30000 - DefaultBusBufferSize = 100 + DefaultRPCPort = "50832" + DefaultBusBufferSize = 100 + DefaultRPCHost = "localhost" + Validator1EndpointDockerCompose = "node1.consensus" + Validator1EndpointK8S = "v1-validator001" + + defaultRPCTimeout = 30000 ) var ( - DefaultRemoteCLIURL = fmt.Sprintf("http://%s:%s", defaultRPCHost, defaultRPCPort) + DefaultRemoteCLIURL = fmt.Sprintf("http://%s:%s", DefaultRPCHost, DefaultRPCPort) // consensus DefaultConsensusMaxMempoolBytes = uint64(500000000) @@ -33,6 +37,15 @@ var ( DefaultP2PUseRainTree = true DefaultP2PConnectionType = types.ConnectionType_TCPConnection DefaultP2PMaxMempoolCount = uint64(1e5) + // DefaultP2PBootstrapNodesCsv is a list of nodes to bootstrap the network with. By convention, for now, the first validator will provide bootstrapping facilities. + // + // In LocalNet, the developer will have only one of the two stack online, therefore this is also a poor's man way to simulate the scenario in which a boostrap node is offline. + //nolint:gocritic // stringConcatSimplify TBD in code review. + DefaultP2PBootstrapNodesCsv = strings.Join([]string{ + fmt.Sprintf("http://%s:%s", Validator1EndpointDockerCompose, DefaultRPCPort), + fmt.Sprintf("http://%s:%s", Validator1EndpointK8S, DefaultRPCPort), + }, ",") + // telemetry DefaultTelemetryEnabled = true DefaultTelemetryAddress = "0.0.0.0:9000" @@ -41,6 +54,5 @@ var ( DefaultLoggerLevel = "debug" DefaultLoggerFormat = "pretty" // rpc - DefaultRpcPort = defaultRPCPort - DefaultRpcTimeout = uint64(defaultRPCTimeout) + DefaultRPCTimeout = uint64(defaultRPCTimeout) ) diff --git a/runtime/docs/CHANGELOG.md b/runtime/docs/CHANGELOG.md index de6062661..b9062c442 100644 --- a/runtime/docs/CHANGELOG.md +++ b/runtime/docs/CHANGELOG.md @@ -7,7 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.0.0.18] - 2023-02-16 +## [0.0.0.19] - 2023-02-16 + +- Added `bootstrap_nodes_csv` in `P2PConfig` to allow for a comma separated list of bootstrap nodes +- Introduced `modules.ModulesRegistry` for better separation of concerns +- Added `StateMachineModule` accessors +- `Manager` embeds `base_modules.IntegratableModule` for DRYness + +## [0.0.0.18] - 2023-02-15 - Added `IsProcessRunningInsideKubernetes` and centralized `GetEnv` so that it can be used across the board diff --git a/runtime/errors.go b/runtime/errors.go index 7ec9e1cc8..6750fd52a 100644 --- a/runtime/errors.go +++ b/runtime/errors.go @@ -4,7 +4,7 @@ import ( "fmt" ) -const ModuleNotRegisteredError = "module %s not found, did you call bus.RegisterModule() ?" +const ModuleNotRegisteredError = "module %s not found, did you call ModulesRegistry.RegisterModule() ?" func ErrModuleNotRegistered(moduleName string) error { return fmt.Errorf(ModuleNotRegisteredError, moduleName) diff --git a/runtime/manager.go b/runtime/manager.go index f08a52212..8e7281c7f 100644 --- a/runtime/manager.go +++ b/runtime/manager.go @@ -16,17 +16,19 @@ import ( "github.com/pokt-network/pocket/runtime/genesis" cryptoPocket "github.com/pokt-network/pocket/shared/crypto" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" "github.com/spf13/viper" ) var _ modules.RuntimeMgr = &Manager{} type Manager struct { + base_modules.IntegratableModule + config *configs.Config genesisState *genesis.GenesisState clock clock.Clock - bus modules.Bus } func NewManager(config *configs.Config, gen *genesis.GenesisState, options ...func(*Manager)) *Manager { @@ -39,7 +41,7 @@ func NewManager(config *configs.Config, gen *genesis.GenesisState, options ...fu mgr.config = config mgr.genesisState = gen mgr.clock = clock.New() - mgr.bus = bus + mgr.IntegratableModule = *base_modules.NewIntegratableModule(bus) for _, o := range options { o(mgr) @@ -77,10 +79,6 @@ func (m *Manager) GetGenesis() *genesis.GenesisState { return m.genesisState } -func (b *Manager) GetBus() modules.Bus { - return b.bus -} - func (m *Manager) GetClock() clock.Clock { return m.clock } @@ -167,3 +165,9 @@ func WithClientDebugMode() func(*Manager) { b.config.ClientDebugMode = true } } + +func WithBootstrapNodes(bootstrapNodesCsv string) func(*Manager) { + return func(b *Manager) { + b.config.P2P.BootstrapNodesCsv = bootstrapNodesCsv + } +} diff --git a/runtime/manager_test.go b/runtime/manager_test.go index e57f4ca20..773a25900 100644 --- a/runtime/manager_test.go +++ b/runtime/manager_test.go @@ -79,6 +79,3986 @@ var expectedGenesis = &genesis.GenesisState{ Address: "88a792b7aca673620132ef01f50e62caa58eca83", Amount: "100000000000000", }, + { + Address: "00504987d4b181c1e97b1da9af42f3db733b1ff4", + Amount: "100000000000000", + }, + { + Address: "00604d18001a2012830b93efcc23100450e5a512", + Amount: "100000000000000", + }, + { + Address: "007046b27ad5c49969d585dd3f4f7d1e4b94a42f", + Amount: "100000000000000", + }, + { + Address: "00804475b3c75e0fb86c88d937c7753f8cab8ba8", + Amount: "100000000000000", + }, + { + Address: "0090433ae78b5539c564134809502f699c90b009", + Amount: "100000000000000", + }, + { + Address: "0100471d6796652244885d1943ea7c13e3fce90b", + Amount: "100000000000000", + }, + { + Address: "011044141a86efafeae5ecc2c6290f0894072ab7", + Amount: "100000000000000", + }, + { + Address: "01204ed35af2bbef5d4db0aeedf3a9a8958c3296", + Amount: "100000000000000", + }, + { + Address: "0130404d6a39bf7cdc14ef4be4a0910f170edd1e", + Amount: "100000000000000", + }, + { + Address: "0140481810379d6e970f5b7de3220b70a784efd5", + Amount: "100000000000000", + }, + { + Address: "01504aedb93b489402d5aa654a5c6bda01880a5f", + Amount: "100000000000000", + }, + { + Address: "0160401ddec40b7a2dbc8505e4a9e998c22604b0", + Amount: "100000000000000", + }, + { + Address: "0170495866953b63cc9ba01c141dd8be029773bb", + Amount: "100000000000000", + }, + { + Address: "01804d0db5be444aeb1a114469a4ff7eb09c91db", + Amount: "100000000000000", + }, + { + Address: "01904e5651efaafb1a557d8f61034a4edfe0fa05", + Amount: "100000000000000", + }, + { + Address: "02004e81a4ee21929a399504fd0d946c545e7a2c", + Amount: "100000000000000", + }, + { + Address: "0210494fbd4b214dd6209d33b3fc960660c9f82b", + Amount: "100000000000000", + }, + { + Address: "0220406b71d941b5b9fc73a53d08ecb09c866b10", + Amount: "100000000000000", + }, + { + Address: "023041ae1ee33ad8db492951c13393b9bb59d59b", + Amount: "100000000000000", + }, + { + Address: "024041957fc3ac22552239b75d384f141f48430b", + Amount: "100000000000000", + }, + { + Address: "025045f51c4c956e2d822e6fd3f706957a5649fe", + Amount: "100000000000000", + }, + { + Address: "02604fcd21020ff140f6da784012e68d7f72ff36", + Amount: "100000000000000", + }, + { + Address: "0270460c5775e8951e5d43b3b37dc310209afda6", + Amount: "100000000000000", + }, + { + Address: "02804033a62cf08a2074cbffe941bd019576d5ed", + Amount: "100000000000000", + }, + { + Address: "0290479bfdf5210b7541b37b551716662a2ff397", + Amount: "100000000000000", + }, + { + Address: "03004511b4ca2d30b7e8bc008a4dc53588115fb0", + Amount: "100000000000000", + }, + { + Address: "031048ce3cef36af346cffc464dc5611028cc46f", + Amount: "100000000000000", + }, + { + Address: "03204ac71039cd18d1a23b76042c5c43c4dc1053", + Amount: "100000000000000", + }, + { + Address: "03304961130710e8984124354aa55eef028ad7d9", + Amount: "100000000000000", + }, + { + Address: "03404334ac8195996d072c916805dd26d82d9b0a", + Amount: "100000000000000", + }, + { + Address: "03504f415b35148ef268a37a7bdd5cbe41c46b62", + Amount: "100000000000000", + }, + { + Address: "0360444233608b747b82c9a651526171e0cecb09", + Amount: "100000000000000", + }, + { + Address: "037041d2ebb680f8e617c1d8bd4397114ed91d7a", + Amount: "100000000000000", + }, + { + Address: "03804e19cca9f5d8d074d3f0a60f1096723dad31", + Amount: "100000000000000", + }, + { + Address: "039044952cacd6fe9eed091c8b5b85c6e758d9ff", + Amount: "100000000000000", + }, + { + Address: "04004e7265815d837bac198381b1b3e70275319e", + Amount: "100000000000000", + }, + { + Address: "04104e28743787af30fdc85123b2ec763aca309c", + Amount: "100000000000000", + }, + { + Address: "042047946bbe90534f6940b3fa2aef34fa8f68c4", + Amount: "100000000000000", + }, + { + Address: "04304a7f8c6f59737bf2f6955745677351ad65bd", + Amount: "100000000000000", + }, + { + Address: "04404de47d3b8b90f533da541a6b9cd4b162cbdb", + Amount: "100000000000000", + }, + { + Address: "04504f18acbfe31c7f671a9986a499e74cd83b87", + Amount: "100000000000000", + }, + { + Address: "046047e21a2b35c94b8e25b39a8e11e088bdcc20", + Amount: "100000000000000", + }, + { + Address: "04704eff8a68e2d520bc9d4781a1328beb4a07fd", + Amount: "100000000000000", + }, + { + Address: "04804319d93a5aae6d6932e6255afa52ff9b81ad", + Amount: "100000000000000", + }, + { + Address: "0490494bc3baea23832c354eae4472d5ca97302f", + Amount: "100000000000000", + }, + { + Address: "05004facba0b2a253bab657f428338918d081158", + Amount: "100000000000000", + }, + { + Address: "0510462d8d3fbc0a5690e68507a49809f70afac4", + Amount: "100000000000000", + }, + { + Address: "05204497fa5d1cd636ec08c1e557aad11356ffdb", + Amount: "100000000000000", + }, + { + Address: "05304bebf8de8dd3333067868402df0a855cfc26", + Amount: "100000000000000", + }, + { + Address: "054041a4f8f82ae6cdc43ae50c621cbc73a74cba", + Amount: "100000000000000", + }, + { + Address: "055047122515c7448c7eb18b249e0bd390fe017b", + Amount: "100000000000000", + }, + { + Address: "056047aa21bce308658b7ff6ed0d87356de06220", + Amount: "100000000000000", + }, + { + Address: "05704c960137bbb6c9421a77e03671a334211ec5", + Amount: "100000000000000", + }, + { + Address: "058045f9c98e9fd506e5025797b34302fbaf85e3", + Amount: "100000000000000", + }, + { + Address: "05904f94b885d875f0fe6af3185a5936518b40f5", + Amount: "100000000000000", + }, + { + Address: "06004ef2c3c4979e68257b4bff94471e570b1cab", + Amount: "100000000000000", + }, + { + Address: "0610473810cd99f9ef4e72613cf5e93fcf942b12", + Amount: "100000000000000", + }, + { + Address: "0620415cc31eef8492058687df20c86b6e228bb2", + Amount: "100000000000000", + }, + { + Address: "06304edd5eb38af2ddc8555e94678ac6ab7a0a5c", + Amount: "100000000000000", + }, + { + Address: "06404246818eada50a3335e9c7e7eb142ee6709b", + Amount: "100000000000000", + }, + { + Address: "06504c11e6b449679278529efebf00ed4c1098b2", + Amount: "100000000000000", + }, + { + Address: "06604cea653df828010889eaa56f4ff867a17881", + Amount: "100000000000000", + }, + { + Address: "067044f84aa72577dc88b9813ee081dd6235905c", + Amount: "100000000000000", + }, + { + Address: "06804ac8b703a6500ba70f36a725bc55ecbe4bbc", + Amount: "100000000000000", + }, + { + Address: "06904f896ddabf920e559954efcb468e85e351d5", + Amount: "100000000000000", + }, + { + Address: "070043cc01e70228d252b4df847c4724813f6176", + Amount: "100000000000000", + }, + { + Address: "07104b360ef5589bb8b49a7e2c3e2fa03363a059", + Amount: "100000000000000", + }, + { + Address: "072048359ff76f59da57342b93dd4cfdd42662c2", + Amount: "100000000000000", + }, + { + Address: "07304f2af4afd31973cfbd0cae5a74722ba4fd14", + Amount: "100000000000000", + }, + { + Address: "07404ac156eb80fe3092c9e39b2169c6a087194f", + Amount: "100000000000000", + }, + { + Address: "07504a01ea1839c1aef06641eb46379218dbcba9", + Amount: "100000000000000", + }, + { + Address: "0760494df0c9bf14a5a5b50f491adfcc3df6b7e6", + Amount: "100000000000000", + }, + { + Address: "07704a472cabf1433eba2d80a73204d5726a88fc", + Amount: "100000000000000", + }, + { + Address: "0780445f4375d422c87a155b6949625b227bfba2", + Amount: "100000000000000", + }, + { + Address: "07904050bb8647901a3e9b93a2296ca4334d728e", + Amount: "100000000000000", + }, + { + Address: "08004bdfd6dca205244f5a15f9d1741bcc511b54", + Amount: "100000000000000", + }, + { + Address: "081046c92e38c4202ff659168d45d742a57ffee2", + Amount: "100000000000000", + }, + { + Address: "082045bad7d45189d4c9fb379de5ae3aa7dff762", + Amount: "100000000000000", + }, + { + Address: "08304f805360247bed9730d07e755384cb0070e5", + Amount: "100000000000000", + }, + { + Address: "08404debeec7ee380d24cd384d96ff98912a450b", + Amount: "100000000000000", + }, + { + Address: "085047967a6d86f2369345e1243af970f7e4c5e2", + Amount: "100000000000000", + }, + { + Address: "086044b59a0f9b0ceee5ee9f298d17c9f1445beb", + Amount: "100000000000000", + }, + { + Address: "08704f20c81ebf51988fb1b6bef5d29c702216c9", + Amount: "100000000000000", + }, + { + Address: "08804f6d3823b4839685744cd807f5ff7f4d9712", + Amount: "100000000000000", + }, + { + Address: "089049f0d03a767dd1a2b9479cb70d2c836a0077", + Amount: "100000000000000", + }, + { + Address: "09004e53f819778cd2c0738ff055416f44baf529", + Amount: "100000000000000", + }, + { + Address: "09104c7006a42917b1d6c824dc48a4e1f87f835f", + Amount: "100000000000000", + }, + { + Address: "09204a46380169c1c9b5cbff225e771e17e32cda", + Amount: "100000000000000", + }, + { + Address: "093041155ee61c12ea790594b7b305b00ed179e6", + Amount: "100000000000000", + }, + { + Address: "09404741ec9ee6c40d009174474db97aee4db4b4", + Amount: "100000000000000", + }, + { + Address: "095049ee9b15b848f432b1fef028641e391de082", + Amount: "100000000000000", + }, + { + Address: "096046a684f4677dde3a3db075d3b3f99359d3aa", + Amount: "100000000000000", + }, + { + Address: "097048eba43973cc73cd10f1b18085424318d145", + Amount: "100000000000000", + }, + { + Address: "0980419ea31998de5d84b43f5042e4e492a5d738", + Amount: "100000000000000", + }, + { + Address: "099044a5282c4089976c6b13ab13e5423dae55ce", + Amount: "100000000000000", + }, + { + Address: "10004d40a6b66742e3fa57b3410bf4302ce68394", + Amount: "100000000000000", + }, + { + Address: "1010478e08ad97244e773bbd844c71bc0352c3e7", + Amount: "100000000000000", + }, + { + Address: "102048ed9422a043ad4129923f94f3c24bdf215a", + Amount: "100000000000000", + }, + { + Address: "103049dbf55f9d9a3f3d0accd6f9056e478913e2", + Amount: "100000000000000", + }, + { + Address: "104043f348d715650ad409135be7c070d9d95068", + Amount: "100000000000000", + }, + { + Address: "10504f7e334d7a516849b04c5aae4881070feec8", + Amount: "100000000000000", + }, + { + Address: "10604e693a25f81bfbb9fb75f88941ccc45a18bc", + Amount: "100000000000000", + }, + { + Address: "107044e187a52f8bc9caa4874d7f44796a08a929", + Amount: "100000000000000", + }, + { + Address: "10804bcb2dbf1a218a6329ecc2be8745626fcf83", + Amount: "100000000000000", + }, + { + Address: "10904ad08c08a77d484038a07b87be4186792a46", + Amount: "100000000000000", + }, + { + Address: "1100450fd02ac84b4af733541372552a91eefbc4", + Amount: "100000000000000", + }, + { + Address: "1110489c4120dc1bdf90b10c52bb7c09f0845729", + Amount: "100000000000000", + }, + { + Address: "11204b578d9a37c2b5f57096c5421d8422e2dc98", + Amount: "100000000000000", + }, + { + Address: "113043ed1a7e58689fecfbdf930ec4ee5ce5062d", + Amount: "100000000000000", + }, + { + Address: "11404c2a4d6045227e32d9f1365db6f6771076cc", + Amount: "100000000000000", + }, + { + Address: "11504b01b37eb3c132b47eb96bb004c73544b614", + Amount: "100000000000000", + }, + { + Address: "116048b88dea15cedcd35268b8ac6377dcc3d0c1", + Amount: "100000000000000", + }, + { + Address: "11704e5c9b13bb150e597e5433a0662f4a181b6f", + Amount: "100000000000000", + }, + { + Address: "11804b9efdfedf7f1adf66e07a7f0d8f808577da", + Amount: "100000000000000", + }, + { + Address: "1190497f2cc37e940a9fe00ab204a95e0c9bb680", + Amount: "100000000000000", + }, + { + Address: "120041b8df9d90f1f2552dcbaa56f5373b6c6276", + Amount: "100000000000000", + }, + { + Address: "1210432f21bce9b96de278336453b24f4393b83c", + Amount: "100000000000000", + }, + { + Address: "12204cb0d0b5c63229794302bf48a09194c9a16a", + Amount: "100000000000000", + }, + { + Address: "12304722e56d2a02d85843df27699fccaec50d65", + Amount: "100000000000000", + }, + { + Address: "1240481e5002400cb25b142fc050846f929cc48d", + Amount: "100000000000000", + }, + { + Address: "125048c33a3e3e64d000c09ea30acebc284381e1", + Amount: "100000000000000", + }, + { + Address: "126041d6d720e542f71b7f918d436d0e58ae39df", + Amount: "100000000000000", + }, + { + Address: "12704ae3578cd0b3a5173c7a787f6be855de68d9", + Amount: "100000000000000", + }, + { + Address: "12804b8317600ea5a50c022d68db259a48246d11", + Amount: "100000000000000", + }, + { + Address: "12904f277d69867eb875b9ca05631e5af8f6f3a5", + Amount: "100000000000000", + }, + { + Address: "1300421eeb1b9cef3a6de604d2170ec93b0e4339", + Amount: "100000000000000", + }, + { + Address: "13104ac49ac0178e2f2141d84fa608cd75a0b99f", + Amount: "100000000000000", + }, + { + Address: "13204c53460812c5f036d93eb1351b777293bad3", + Amount: "100000000000000", + }, + { + Address: "133046096add47f91c7390867c134ad118db1c78", + Amount: "100000000000000", + }, + { + Address: "13404cd5b310e67182d10562b603c074fe04a89e", + Amount: "100000000000000", + }, + { + Address: "13504f0cade7c2ca08f31db13dcfa7b96df30c9e", + Amount: "100000000000000", + }, + { + Address: "1360405dc963cc088d905661312288f72b8e145d", + Amount: "100000000000000", + }, + { + Address: "13704a54589c4850a0b2e541de4fd74324e6c650", + Amount: "100000000000000", + }, + { + Address: "1380420feb410699ea7969995e80705cdfdc85ca", + Amount: "100000000000000", + }, + { + Address: "13904d5175f99a8c7380356d8c62c1155167e6d9", + Amount: "100000000000000", + }, + { + Address: "140040be8bc55c39dd93872db9f69a2962773414", + Amount: "100000000000000", + }, + { + Address: "14104175cc9b1c210e6e8297c790d13590a69552", + Amount: "100000000000000", + }, + { + Address: "14204fe8d30ec07a74a1ef1c94f46089bc55e221", + Amount: "100000000000000", + }, + { + Address: "1430494a69f153da3746ffe08f78ecb49b57fc0e", + Amount: "100000000000000", + }, + { + Address: "1440427e32ed0038ec856c755a5197fadf957a2f", + Amount: "100000000000000", + }, + { + Address: "14504c4cbec1b1efe9a43158377e8adf781b6103", + Amount: "100000000000000", + }, + { + Address: "1460491d014244244ef559ea9ae513bea1dcddd2", + Amount: "100000000000000", + }, + { + Address: "14704b3f86ac92acf440b2a7e6668f93b3079e4b", + Amount: "100000000000000", + }, + { + Address: "148041a8c233054f555cb9b403f7b923cada20eb", + Amount: "100000000000000", + }, + { + Address: "14904727d2ab89e6c709207ab1c2ca3a5c272a76", + Amount: "100000000000000", + }, + { + Address: "15004c142f4e20b9335895330b5b13d057adf339", + Amount: "100000000000000", + }, + { + Address: "151048b719ee920b3e7817e638b54cccf4c1ad2b", + Amount: "100000000000000", + }, + { + Address: "1520405297a7105030cc7b9644cac18d56789c6c", + Amount: "100000000000000", + }, + { + Address: "1530493894ee67be4601d7e8319e25ec6a4a196c", + Amount: "100000000000000", + }, + { + Address: "154046cce6ed50084402f23d39f47938d8813168", + Amount: "100000000000000", + }, + { + Address: "1550401f10dd6ba3237915480caec9cc25c22e7a", + Amount: "100000000000000", + }, + { + Address: "1560428bcae398f7a6ccefcc11f8f81a3377c0bc", + Amount: "100000000000000", + }, + { + Address: "157048c978d44449301262faa959dca274a5aa4b", + Amount: "100000000000000", + }, + { + Address: "158041081d17bc38c46b8a98e790754db8df070a", + Amount: "100000000000000", + }, + { + Address: "15904f004b76f28c9711fee41dc149653d916928", + Amount: "100000000000000", + }, + { + Address: "160046a9a808312cc2b184576cb7a732ab65b54e", + Amount: "100000000000000", + }, + { + Address: "1610442c7b7596b008014c9d6513aa075e231ef2", + Amount: "100000000000000", + }, + { + Address: "162042923ff01a08e4138e8b238792a42132e1cb", + Amount: "100000000000000", + }, + { + Address: "163047124bf542385d7eadb14cc3f0bac13fdfd0", + Amount: "100000000000000", + }, + { + Address: "16404fe2f744e454f5905fef8f11624c17ea7276", + Amount: "100000000000000", + }, + { + Address: "16504776e6fa4964c1186698b9d937777c895852", + Amount: "100000000000000", + }, + { + Address: "1660429323d21e475d82412cebaa47c3239c8c7f", + Amount: "100000000000000", + }, + { + Address: "16704bb2cf4ac07c32a573f78503c348d1ad8e33", + Amount: "100000000000000", + }, + { + Address: "168042d2ebe07c3ec4d97a27f132252c6f75b2c3", + Amount: "100000000000000", + }, + { + Address: "16904d309459875b673824fb3d4892c255c438a8", + Amount: "100000000000000", + }, + { + Address: "1700459ef6255d3af804047d6e9c8543e4fb651c", + Amount: "100000000000000", + }, + { + Address: "17104093498fce764f72ff62a3cff004ff9036e2", + Amount: "100000000000000", + }, + { + Address: "17204c5f07a3ed21aa701936fc3ac7cee56f6fd9", + Amount: "100000000000000", + }, + { + Address: "173047b98d5737c2ff6cd42a05c7be49cbae4730", + Amount: "100000000000000", + }, + { + Address: "174043c704b4ca5e2386607ca0ea9aa079d060a7", + Amount: "100000000000000", + }, + { + Address: "1750407bdb0f719bc7d589b676e01a353c3a477e", + Amount: "100000000000000", + }, + { + Address: "1760481f33bdeb9a00942ff0b5495d4352905a7c", + Amount: "100000000000000", + }, + { + Address: "17704ced43739119c029327380e45977bf7cad3e", + Amount: "100000000000000", + }, + { + Address: "17804d8420f8c162e2df0e67993cb252a188b5f8", + Amount: "100000000000000", + }, + { + Address: "17904d73ab82f9143cebff44fe04792aab8655e4", + Amount: "100000000000000", + }, + { + Address: "18004a25e97b7715de5a1a81b53c9632144dc420", + Amount: "100000000000000", + }, + { + Address: "181041f149252a89292e9972914c58bd829b8c7d", + Amount: "100000000000000", + }, + { + Address: "18204561a63cd6858352fa755235fc20da17b505", + Amount: "100000000000000", + }, + { + Address: "18304635cca3b26f47928baca81db0f228812f5c", + Amount: "100000000000000", + }, + { + Address: "18404ca5c5c4b058fa69f4e447f337d688fae192", + Amount: "100000000000000", + }, + { + Address: "18504562e4766557eaac160609694f70cd994869", + Amount: "100000000000000", + }, + { + Address: "18604797ec3169f3cc49528c658a2021f9cb65aa", + Amount: "100000000000000", + }, + { + Address: "1870490db984d9ee83069932178d14b0abcaa855", + Amount: "100000000000000", + }, + { + Address: "1880411b2ea73a2c55ae9a44090a91407a1338b2", + Amount: "100000000000000", + }, + { + Address: "1890483fd47d69c9c56ebdc44b53f863636ec76b", + Amount: "100000000000000", + }, + { + Address: "190047b3262c58543426e2aca31153d1ee9a6cb4", + Amount: "100000000000000", + }, + { + Address: "19104a9dcb8c74fd201dd725760a1b6bb46132d0", + Amount: "100000000000000", + }, + { + Address: "1920414bedbca466c0cc21605f310e1e592fd883", + Amount: "100000000000000", + }, + { + Address: "19304b87b24277c3125b6b459754a661f0bf05d2", + Amount: "100000000000000", + }, + { + Address: "194046b0304151f562984df1092f9c1f7d79fa62", + Amount: "100000000000000", + }, + { + Address: "195045f4ad18d51ad82118d941853a515c6477e1", + Amount: "100000000000000", + }, + { + Address: "19604371ecba002941a630d592190da6a7b92204", + Amount: "100000000000000", + }, + { + Address: "19704ce5e62681c054346e859e481d4cead58fca", + Amount: "100000000000000", + }, + { + Address: "1980404abe063de7cb649ed7007c2acff22dc6d6", + Amount: "100000000000000", + }, + { + Address: "199041b40c048301fd79257bac2f24755e4220b5", + Amount: "100000000000000", + }, + { + Address: "200042c84cdc16db2aa5bcf29f578f19f88d828f", + Amount: "100000000000000", + }, + { + Address: "2010436f32021ed70ea837c7bb28e3e4f0eb08b4", + Amount: "100000000000000", + }, + { + Address: "202041a563d5c632cc8a16f1c47a144e9861ffc8", + Amount: "100000000000000", + }, + { + Address: "20304a95f96c1ecd467d220afe61dc00191a590d", + Amount: "100000000000000", + }, + { + Address: "204041fdfe17c0f23783b5f1bb5b957bcc2808d4", + Amount: "100000000000000", + }, + { + Address: "205047833c7643945ff04936615f36f4d6afa927", + Amount: "100000000000000", + }, + { + Address: "20604e648b33f0d377c19dda00c69fd7dbab1a35", + Amount: "100000000000000", + }, + { + Address: "20704e9cdcb655809f917a2383c5bc962d65a676", + Amount: "100000000000000", + }, + { + Address: "20804d277be9dac11fddaf7a303de7825d04fe86", + Amount: "100000000000000", + }, + { + Address: "209045028021014830c19dd005c1f15734c0279d", + Amount: "100000000000000", + }, + { + Address: "210041c9fcf43b85b482d5225e59dfd53343d4c0", + Amount: "100000000000000", + }, + { + Address: "211041068d32913cd60af834ea4046f663f5ced3", + Amount: "100000000000000", + }, + { + Address: "212045166e6cc662e8810cd340cfc2c03f5ed76b", + Amount: "100000000000000", + }, + { + Address: "213042d24128fc2d6a012d7505b0a16ae7f2c71f", + Amount: "100000000000000", + }, + { + Address: "21404dc18a0af5991775e21beef464a2abbe2465", + Amount: "100000000000000", + }, + { + Address: "21504bc8aa46ae21814ebab4a7e1b1a242d5accf", + Amount: "100000000000000", + }, + { + Address: "216043b23b77f8ba73f8fd27960292f39dbd4295", + Amount: "100000000000000", + }, + { + Address: "217044892b8c7caebfd3bd1ce03c993dc5ff86dc", + Amount: "100000000000000", + }, + { + Address: "21804f424ae6e5ea63f52935924f7f0195626b82", + Amount: "100000000000000", + }, + { + Address: "21904412d935bdf5f5e1c09240943f5ee08f096e", + Amount: "100000000000000", + }, + { + Address: "22004a7749a322d34096b8d05bf619b9149fb4b3", + Amount: "100000000000000", + }, + { + Address: "2210474930588c35eca210c11955091a0f5f884b", + Amount: "100000000000000", + }, + { + Address: "22204bc6f9ad7e4e518199856e0179a42b33a79b", + Amount: "100000000000000", + }, + { + Address: "22304a1c7c397f31624307c685f5f7a00c12f39e", + Amount: "100000000000000", + }, + { + Address: "22404a0c21626c59ebc9ff7d634016d0c7c7211f", + Amount: "100000000000000", + }, + { + Address: "2250468cad33051ab3dba059c69076dab24f7fde", + Amount: "100000000000000", + }, + { + Address: "22604387182910cc90bbc1c2263c726a16a8272a", + Amount: "100000000000000", + }, + { + Address: "22704fde9834f549d90386e8091f84260dcfa948", + Amount: "100000000000000", + }, + { + Address: "2280473c939601953bff8fa82a1f402109ef940c", + Amount: "100000000000000", + }, + { + Address: "22904d330d2bb0dc4b7107774f01e7d5c3490eb6", + Amount: "100000000000000", + }, + { + Address: "23004d5c724c1e8ec7fef279228a0c97f17e2181", + Amount: "100000000000000", + }, + { + Address: "231044e6feafd5ae2936053ec52d2313d6c8074e", + Amount: "100000000000000", + }, + { + Address: "232040240f94d8516431e17bddf998236fbb4b1f", + Amount: "100000000000000", + }, + { + Address: "23304f25914a69624d63b73f906277f3b44146da", + Amount: "100000000000000", + }, + { + Address: "2340459c2aeedd718eb6888f03ecba40f667512d", + Amount: "100000000000000", + }, + { + Address: "2350412da46f9d6df2ba9de0d5edab0e7ab04f8a", + Amount: "100000000000000", + }, + { + Address: "23604d9dda5729453dbbf6dac079d4265cf2d572", + Amount: "100000000000000", + }, + { + Address: "237046cfc5cb28de4513aeaa070cf059a4dd0b3c", + Amount: "100000000000000", + }, + { + Address: "2380476cd240c9a3ef532c44da208fec403daf43", + Amount: "100000000000000", + }, + { + Address: "239043b65e631bfba903c7be4bd9bbeccc8c77d3", + Amount: "100000000000000", + }, + { + Address: "24004e034045de6aeed0120b55ff7eff23b734fc", + Amount: "100000000000000", + }, + { + Address: "2410496835f7d8b8f66bd3e7724941d46ed0b5b8", + Amount: "100000000000000", + }, + { + Address: "242040f054acb1fd7e03be92d5a95267e6bbf40d", + Amount: "100000000000000", + }, + { + Address: "24304d490c84c40a4b2700d36f692045cb292240", + Amount: "100000000000000", + }, + { + Address: "2440427c70b5b9338d5d4d9ed1c5631168d09481", + Amount: "100000000000000", + }, + { + Address: "24504aa139ba31e9fadf8aece9319578c461be09", + Amount: "100000000000000", + }, + { + Address: "246043ee459e114da19d9733237f8ff18d1c975c", + Amount: "100000000000000", + }, + { + Address: "24704a003e960e2e3184d12bc81481c7b6d3b571", + Amount: "100000000000000", + }, + { + Address: "24804468e55eb683e108433f64f004d8e578e586", + Amount: "100000000000000", + }, + { + Address: "24904b241defa1190e86824dfb5ea06b4cba4be6", + Amount: "100000000000000", + }, + { + Address: "25004dc5f51b2acefedf7d6879a9d75c073a8fa7", + Amount: "100000000000000", + }, + { + Address: "25104987c20c2f2c7b9ad6d3a54644ab6f2a85af", + Amount: "100000000000000", + }, + { + Address: "25204b567acdac5d4a3ce796a4cc59493b11bf31", + Amount: "100000000000000", + }, + { + Address: "25304db3a407cf45ee8ea443ca0084e5b60c79b7", + Amount: "100000000000000", + }, + { + Address: "25404bd5df303cd129ad600d140d3bbcc2590a73", + Amount: "100000000000000", + }, + { + Address: "255043858b88fa0a7358e2ffcd69e7c83e402290", + Amount: "100000000000000", + }, + { + Address: "25604bc9c36ed092e5d092c67dba2622cd4e5d84", + Amount: "100000000000000", + }, + { + Address: "2570409af48f9f53d4fb971997e9551a6f278c34", + Amount: "100000000000000", + }, + { + Address: "25804bc4082281b7de23001ffd237da62c66a839", + Amount: "100000000000000", + }, + { + Address: "25904c87cad76ff937dae4f1c32a78701e16597c", + Amount: "100000000000000", + }, + { + Address: "260048cd2563d833b62eba3e96db8bf11f33b4d7", + Amount: "100000000000000", + }, + { + Address: "26104a73f4e062b78ca20f62d668a76060bbc52b", + Amount: "100000000000000", + }, + { + Address: "26204fd56b23d52c028afcff7d507f52e1540ebd", + Amount: "100000000000000", + }, + { + Address: "263046b3910eb41b62ecab8e2727c7ccf3383821", + Amount: "100000000000000", + }, + { + Address: "264040a705d84df7ced13aa8ae978fa882bdd62a", + Amount: "100000000000000", + }, + { + Address: "26504edc6b5e0ce4c2e8d7fb6ef348378ab9abba", + Amount: "100000000000000", + }, + { + Address: "2660414a17171ad23ae33e5013427ec377b4c988", + Amount: "100000000000000", + }, + { + Address: "2670497b55fc9278e4be4f1bcfe52bf9bd0443f8", + Amount: "100000000000000", + }, + { + Address: "268044a5aab702befe268a12ddca939baf687e8b", + Amount: "100000000000000", + }, + { + Address: "26904228cd6cb82cd55d4af2737166589ff50fed", + Amount: "100000000000000", + }, + { + Address: "2700435fc578db0405190e80dc52c804244f0c1a", + Amount: "100000000000000", + }, + { + Address: "271045c982bdf708abe108829b57fec34a15d164", + Amount: "100000000000000", + }, + { + Address: "2720402be517c6d4d5304d9d2afef856b4c19a66", + Amount: "100000000000000", + }, + { + Address: "273043e7bc0d2eaec59553feda2e1fb2f68cc6ab", + Amount: "100000000000000", + }, + { + Address: "27404283d4b279ba4f3eb205d7ce07556f569333", + Amount: "100000000000000", + }, + { + Address: "27504a9c3e3671f59efe6d98bfefa78a56cab907", + Amount: "100000000000000", + }, + { + Address: "2760456e71cecc99cb8c1abaa4e27755d266aea1", + Amount: "100000000000000", + }, + { + Address: "277043a71759fe5abc5292cf6329c6ed2423d8bb", + Amount: "100000000000000", + }, + { + Address: "278048f93ae0a37f2208390762bdafb1af55e14e", + Amount: "100000000000000", + }, + { + Address: "2790490db88a1189fc72bb5fd6e0f3a8bfa73db1", + Amount: "100000000000000", + }, + { + Address: "28004daf634dca5d149954fe6d4b5c4eb0028793", + Amount: "100000000000000", + }, + { + Address: "28104f10721a56e1a4a4b94e6358738665ac5dfa", + Amount: "100000000000000", + }, + { + Address: "28204f215c20cef00567debf6cb53e30661d0fab", + Amount: "100000000000000", + }, + { + Address: "283041381e612d928f5f555bf8263c8ba88d936c", + Amount: "100000000000000", + }, + { + Address: "2840417b17149dbd88c673dcf48257ac408c71fe", + Amount: "100000000000000", + }, + { + Address: "28504cc3677748731043d89db8f5daa698b81ac8", + Amount: "100000000000000", + }, + { + Address: "286047e41e279be46bad32fcdb3160883765cd03", + Amount: "100000000000000", + }, + { + Address: "28704d946c75244e893567fcdb6c942f1f9c4010", + Amount: "100000000000000", + }, + { + Address: "28804cc3a57272725f1f6576a9f191dc5ff6dfc2", + Amount: "100000000000000", + }, + { + Address: "2890417d98352e3fd93bc9428c3eafdf8a2c70df", + Amount: "100000000000000", + }, + { + Address: "29004d6f7786f10ec5eeb3d979b0cef900c1d48f", + Amount: "100000000000000", + }, + { + Address: "291040ed2dafb7f0a459bcb102fa06b51c1ea60a", + Amount: "100000000000000", + }, + { + Address: "292041e75709c5301b529946184c3f34079542e1", + Amount: "100000000000000", + }, + { + Address: "293042f94bf55835b0402f4749c527d1341d33e1", + Amount: "100000000000000", + }, + { + Address: "29404d31d48e1a6e8809dee2aa22fe1864847708", + Amount: "100000000000000", + }, + { + Address: "29504895b3565b05f833175a7e9dc7db7b4eb70b", + Amount: "100000000000000", + }, + { + Address: "29604a2caf83a8713ce0d98fe186e4bc06dd2080", + Amount: "100000000000000", + }, + { + Address: "297043b50a64aded60e47ade8736ea0abbcfc296", + Amount: "100000000000000", + }, + { + Address: "29804016798e7205be0b06dda8c467effd2b9270", + Amount: "100000000000000", + }, + { + Address: "2990404886581ad56da93b3586973995255c46a5", + Amount: "100000000000000", + }, + { + Address: "300041bf170fea639f3fa2ae44c35c286614c6e1", + Amount: "100000000000000", + }, + { + Address: "301044886121f610783dbfe7eaf5b8b18a08f98a", + Amount: "100000000000000", + }, + { + Address: "3020483107289ce0e1aa22c4b391792dcf422039", + Amount: "100000000000000", + }, + { + Address: "303043b4d44b0fd2836f794d13dfeca89eede44c", + Amount: "100000000000000", + }, + { + Address: "30404c7fde0c53e7bcd5b16f4bae7fb67cd11c7e", + Amount: "100000000000000", + }, + { + Address: "305048be380a6497e74cc9336f6f848355869e41", + Amount: "100000000000000", + }, + { + Address: "30604835f99a142c0834a2a85b64cb29123c98ce", + Amount: "100000000000000", + }, + { + Address: "30704f7df470a5cf2888feadd4465059e52d793e", + Amount: "100000000000000", + }, + { + Address: "30804079993f175db5d3709b0493629f676c835d", + Amount: "100000000000000", + }, + { + Address: "30904c5834aca2092bece28240c82b27e2284540", + Amount: "100000000000000", + }, + { + Address: "3100403f6bbac8575099e11a89a328b9a55e1532", + Amount: "100000000000000", + }, + { + Address: "31104cfb42d421636c088ef06a7a72de5518b70f", + Amount: "100000000000000", + }, + { + Address: "31204158e79b460f11fde2e511551a1a2dccf170", + Amount: "100000000000000", + }, + { + Address: "31304a71a751f080eb358f7b26db28802e944410", + Amount: "100000000000000", + }, + { + Address: "31404816c32212afd80529bf64bd4713f5f50ba5", + Amount: "100000000000000", + }, + { + Address: "3150481f573e37f4de34d89e7aa5444063241a74", + Amount: "100000000000000", + }, + { + Address: "3160464d8039476a8d689c25a0572fb72ab7429d", + Amount: "100000000000000", + }, + { + Address: "31704b6dbc7d7450f8b3845ecdc8d08537a5df93", + Amount: "100000000000000", + }, + { + Address: "3180441bdf305aa132ed094a5b69c84d79f73565", + Amount: "100000000000000", + }, + { + Address: "3190440d7937a90337ad19634ab4669bebb28883", + Amount: "100000000000000", + }, + { + Address: "3200443602a176452ee90950a5351295a5167071", + Amount: "100000000000000", + }, + { + Address: "3210418fd5fc7b7dfd7d75028018163fb59d40a8", + Amount: "100000000000000", + }, + { + Address: "32204f1160e69002d6d86e2194117f6249a5f8bf", + Amount: "100000000000000", + }, + { + Address: "32304dfb40a70da4efbcccc335595bdb146afc25", + Amount: "100000000000000", + }, + { + Address: "32404941024157ffd22cb6e63a05c4a9f3267c18", + Amount: "100000000000000", + }, + { + Address: "32504951d7b1baa55fdc210e189b0fd1b6cd26bf", + Amount: "100000000000000", + }, + { + Address: "326040355d00febef3a516080a1c0a210e44df62", + Amount: "100000000000000", + }, + { + Address: "32704184a2ced2a3c64f3ed2275b95548fef0df3", + Amount: "100000000000000", + }, + { + Address: "32804e88e2b0a67f442c4031f0b91b9c136cf9a1", + Amount: "100000000000000", + }, + { + Address: "32904335f0cc4007dfd7beaa1e0d530b0850423c", + Amount: "100000000000000", + }, + { + Address: "33004a29540a208ea27581f8c58d3a7b68cf806e", + Amount: "100000000000000", + }, + { + Address: "33104aa9a8db1d203b971470253c2947d212d101", + Amount: "100000000000000", + }, + { + Address: "332041c5bb31084f5081a12eec7e84973b9050c4", + Amount: "100000000000000", + }, + { + Address: "33304a384d2bc374d9b49fc43f1ff71266f2f72a", + Amount: "100000000000000", + }, + { + Address: "33404dad454c7792ee9ebe7debde21f3165b55d3", + Amount: "100000000000000", + }, + { + Address: "3350428dc24111ce92e5e5b3e652290969249b82", + Amount: "100000000000000", + }, + { + Address: "33604fffca2d917ac12a8c445719fce04ba347fe", + Amount: "100000000000000", + }, + { + Address: "33704b4672b8b6abc242c30e6f9093c292cdd867", + Amount: "100000000000000", + }, + { + Address: "33804d7251e69234783730671ea0e5593cd1e685", + Amount: "100000000000000", + }, + { + Address: "339048f1e8d3615618aefc20c3674333034c0a8b", + Amount: "100000000000000", + }, + { + Address: "34004bd3a6601ebcb3e9f807f4364c44b7b43864", + Amount: "100000000000000", + }, + { + Address: "341041a2048ca305a4a07850e800832e033129ab", + Amount: "100000000000000", + }, + { + Address: "3420489202fb38a72364915d27b62010f96f8e61", + Amount: "100000000000000", + }, + { + Address: "34304d8d5f4dcb922f934d4ef0a98b38ce5a0e13", + Amount: "100000000000000", + }, + { + Address: "344046b1cd587b1f8d1f3bed184c8ac5281a06b0", + Amount: "100000000000000", + }, + { + Address: "345048b73c7139ffad2e0a2b0ddd11798028c552", + Amount: "100000000000000", + }, + { + Address: "346049ff5b7d886980411f9df009654d29e63e75", + Amount: "100000000000000", + }, + { + Address: "3470401b6b883fe18a6b267ce3755038d0b69d6a", + Amount: "100000000000000", + }, + { + Address: "34804b52b3bd167852eeca5de11a16d8085c8317", + Amount: "100000000000000", + }, + { + Address: "34904565b0d34e0955d54e5ee4e0409188a9981f", + Amount: "100000000000000", + }, + { + Address: "35004add80596903433b36ff6f13f84c703dc0bf", + Amount: "100000000000000", + }, + { + Address: "35104179212912972cd195d0d99cde5872b1e49c", + Amount: "100000000000000", + }, + { + Address: "3520445de027b8aee95d67563680021bb315b503", + Amount: "100000000000000", + }, + { + Address: "353042794cdd1fbaf34e250c78f585f17d357012", + Amount: "100000000000000", + }, + { + Address: "35404987b433e937e4862e5f55664eecef795f78", + Amount: "100000000000000", + }, + { + Address: "35504f4691b2c53d2b2b9ff0efae65b716cd4cca", + Amount: "100000000000000", + }, + { + Address: "35604464f569580d399280fa87b003a1b1fd9125", + Amount: "100000000000000", + }, + { + Address: "357040ae16c5eb6dcf85e5bab749c2090524b204", + Amount: "100000000000000", + }, + { + Address: "35804153fed41c4ee1d6196544aad5613b9dcced", + Amount: "100000000000000", + }, + { + Address: "359047fdcda82972eb9253f7b774ae51bc272550", + Amount: "100000000000000", + }, + { + Address: "36004b1e194156bf223501a10a759894c232b0d1", + Amount: "100000000000000", + }, + { + Address: "361044c781ae8053f78d4fe750deda298df90036", + Amount: "100000000000000", + }, + { + Address: "36204aa085755279387564cc22318fef6fe22507", + Amount: "100000000000000", + }, + { + Address: "3630474281208e5350a097cf58438eb821df2d78", + Amount: "100000000000000", + }, + { + Address: "36404fc963beb7aaab2e6fb389cd8b5390bbce06", + Amount: "100000000000000", + }, + { + Address: "36504b124c54deecc2cc47af358a00f773f2678a", + Amount: "100000000000000", + }, + { + Address: "36604a4885997fe5a77a05011f2d386b92452e25", + Amount: "100000000000000", + }, + { + Address: "3670447ee0096cd1e3d0fd3bf90237683357290e", + Amount: "100000000000000", + }, + { + Address: "368041995c9e2c0ac7e9c85a299c2add91c408c5", + Amount: "100000000000000", + }, + { + Address: "3690419c8e772fa5828bf15addbd636ac8e1fe60", + Amount: "100000000000000", + }, + { + Address: "370049e8d9c1f35df74e5ae7319f4b4ac8c9fbef", + Amount: "100000000000000", + }, + { + Address: "371045c859507bda236654ba9be78f3f844e3c90", + Amount: "100000000000000", + }, + { + Address: "3720462ddbe4a9b926059ae3b543e112b08c22af", + Amount: "100000000000000", + }, + { + Address: "37304679217f64cfc99ee9eb50a9b4c10c787612", + Amount: "100000000000000", + }, + { + Address: "374044695975d130b6531886a84ed9c35593e6aa", + Amount: "100000000000000", + }, + { + Address: "37504427bf3ad1e9d8f319963871ace60bf9cdfa", + Amount: "100000000000000", + }, + { + Address: "37604fc15cd724a87f7e2625532ecec8a67f96c5", + Amount: "100000000000000", + }, + { + Address: "37704e0ae01d8289a58e85d076c2e53b2b439bc0", + Amount: "100000000000000", + }, + { + Address: "37804879cf71d703c18d9a1a36840e455ad5257d", + Amount: "100000000000000", + }, + { + Address: "37904a898da09c64d90b87ef12ae8eba75ab70ef", + Amount: "100000000000000", + }, + { + Address: "38004f2f4ecd24fb6e1bbb6005e395820d711c92", + Amount: "100000000000000", + }, + { + Address: "38104191f40cd1705a0b3e51565ee4efd57c37f1", + Amount: "100000000000000", + }, + { + Address: "38204d1aaec84a2ae42e8caa8c3850c89ee3152c", + Amount: "100000000000000", + }, + { + Address: "38304c41d4fbb1bf231e821459de0730d5f7125f", + Amount: "100000000000000", + }, + { + Address: "38404fc1f3333fcf83bac73dfc54b04c9254c022", + Amount: "100000000000000", + }, + { + Address: "38504eda2a7e561ceb903173e5bab2a0ce2faed1", + Amount: "100000000000000", + }, + { + Address: "38604efb24ad019fd29329afa28a3ebf9ec67459", + Amount: "100000000000000", + }, + { + Address: "38704790e2adb4e2bb9a4a1ce745b8ddd407eb7c", + Amount: "100000000000000", + }, + { + Address: "388040cd8e861404de5d6f31d7ac4066f4d029b1", + Amount: "100000000000000", + }, + { + Address: "389044cb786b0c45a99ffd18600626019faebab5", + Amount: "100000000000000", + }, + { + Address: "390048a3113b7d71429ad1fa5c7e8ea773fb17c6", + Amount: "100000000000000", + }, + { + Address: "39104907570ce9faa49e2cb481df2e8b4ed29664", + Amount: "100000000000000", + }, + { + Address: "392049205fe199c8715802f8eb2f623cca922df9", + Amount: "100000000000000", + }, + { + Address: "3930414d9c4a5d88820e9f94711c83b33adbbd3a", + Amount: "100000000000000", + }, + { + Address: "39404e0e8c539b200c10e4ea00f6ac19bd9d8fd7", + Amount: "100000000000000", + }, + { + Address: "3950409733a0c9aed0df3a771eb72ea04d65ac61", + Amount: "100000000000000", + }, + { + Address: "39604000bb0f03de6dddaae3775f0dcf5f2616d9", + Amount: "100000000000000", + }, + { + Address: "397041aa1a91734f2eb917486d585a979ac4814d", + Amount: "100000000000000", + }, + { + Address: "398044a57ac2e71e881d58eb7ccd9d9cebf6b461", + Amount: "100000000000000", + }, + { + Address: "3990423bd9c877541bd99010abce6aba593fa422", + Amount: "100000000000000", + }, + { + Address: "400048c7b8ad110fa552f5276eb18fbf133442ff", + Amount: "100000000000000", + }, + { + Address: "4010442ccf683fd62b6ca6fd7a79987226fccb1a", + Amount: "100000000000000", + }, + { + Address: "402042e8d58b8f6f8bb5cbb8f3ce6b81e94b08a5", + Amount: "100000000000000", + }, + { + Address: "403044b6a04fdec2d447e79f3b2536beafc50ccf", + Amount: "100000000000000", + }, + { + Address: "404043e086c9a544a100c6574b821496449dc4c9", + Amount: "100000000000000", + }, + { + Address: "40504d12dcb2b6c35eba82e83ea6ce1203bccfda", + Amount: "100000000000000", + }, + { + Address: "4060401de88f864e233aa7e354a39697edd5d228", + Amount: "100000000000000", + }, + { + Address: "40704173d90fa115cf632974fefb97f8ac0cdd5a", + Amount: "100000000000000", + }, + { + Address: "408040e43d125d490af0d3792fa22c8edfabf3e8", + Amount: "100000000000000", + }, + { + Address: "40904d86614f2f0fa0ffba631577fdac808d054f", + Amount: "100000000000000", + }, + { + Address: "4100406ea23a4fefbf25303fedbd8f1d057fd71f", + Amount: "100000000000000", + }, + { + Address: "41104c864e06b1cc7051845887fdad77c4e9103d", + Amount: "100000000000000", + }, + { + Address: "4120490568a1e645ade2e5eba486f5c28c202599", + Amount: "100000000000000", + }, + { + Address: "41304769c40c9be69871025782463ced1ca5f8c4", + Amount: "100000000000000", + }, + { + Address: "41404321fa09f1e26e88f8297f4ebc1c7591b8cf", + Amount: "100000000000000", + }, + { + Address: "41504cd0ecb6bb356678286b93b0db4d5a2de6ff", + Amount: "100000000000000", + }, + { + Address: "4160496316e6844b606a2a881bfeb98d7db80481", + Amount: "100000000000000", + }, + { + Address: "4170441fd1a081fa05a56f18aad4ac7a16190018", + Amount: "100000000000000", + }, + { + Address: "41804d9def2714f137af065bba450952ab45dea6", + Amount: "100000000000000", + }, + { + Address: "4190439a9b97d17674fe3ab5d897fac5a4142668", + Amount: "100000000000000", + }, + { + Address: "420043b854e78f2d5f03895bba9ef16972913320", + Amount: "100000000000000", + }, + { + Address: "42104b54a994bf1eb0f774b7e9767d0ffd3c1d5a", + Amount: "100000000000000", + }, + { + Address: "4220421e3d617e9f11ec901dfa59e39d158e8692", + Amount: "100000000000000", + }, + { + Address: "423049d1c211746cf6dda98a50eba60a2aaec6f2", + Amount: "100000000000000", + }, + { + Address: "4240491cbfd017e652fba1d170ce1154aeeb27d9", + Amount: "100000000000000", + }, + { + Address: "42504d1a343ee6649f592438307c4a5f9f63e833", + Amount: "100000000000000", + }, + { + Address: "4260455886a887a258e2c5154b8d51730b846f6d", + Amount: "100000000000000", + }, + { + Address: "42704fd9e7b7e74197f96fd308b23ceb19f52d3f", + Amount: "100000000000000", + }, + { + Address: "428043a659f56992b33f52c6f6b8c92777a39595", + Amount: "100000000000000", + }, + { + Address: "42904e252ce17c56e1269bea315365a68515da98", + Amount: "100000000000000", + }, + { + Address: "430040d176cc2342c9a788f1e2a7a4851560d163", + Amount: "100000000000000", + }, + { + Address: "43104f4c4adb2b02ee0618deb84c65a399633263", + Amount: "100000000000000", + }, + { + Address: "432041283d7e1a624097f329b52551560e470856", + Amount: "100000000000000", + }, + { + Address: "43304af2615963515f8cde685e0185ec5230c1e6", + Amount: "100000000000000", + }, + { + Address: "43404619884fc86b3652706948118802bf455f1a", + Amount: "100000000000000", + }, + { + Address: "435042aa1bad5f86965fcde5dd57b2459c7cafd0", + Amount: "100000000000000", + }, + { + Address: "436041005230bdf407da67c09a73921c8905fdb8", + Amount: "100000000000000", + }, + { + Address: "43704ee3f0f6e32519eaad5e856e9de1bac702a1", + Amount: "100000000000000", + }, + { + Address: "438040ee2dca2eaa65c4e98d46f68bc749293514", + Amount: "100000000000000", + }, + { + Address: "439047e81f6fffc2846ec87756257c7ea78a71c4", + Amount: "100000000000000", + }, + { + Address: "44004ecbb5d957fd9b7febf89841cf507d95dd34", + Amount: "100000000000000", + }, + { + Address: "44104bd54eb6c3724d9f97d5befac0b996420275", + Amount: "100000000000000", + }, + { + Address: "44204ba01215d2876f9545a1a7b57f671071d59a", + Amount: "100000000000000", + }, + { + Address: "44304b8a8220d8692f68b631a95b59265bb6a52f", + Amount: "100000000000000", + }, + { + Address: "44404ffcb1f1e1eb6a59b17731245c4becd5513f", + Amount: "100000000000000", + }, + { + Address: "44504e7cfdd173bacd0a4933ee328ed0a7946852", + Amount: "100000000000000", + }, + { + Address: "446047d1029355e34b94f47061be7b6b671bdf0e", + Amount: "100000000000000", + }, + { + Address: "44704161667f420239be206d949310d4d4b505e4", + Amount: "100000000000000", + }, + { + Address: "4480454d76128e3abf5fff4b129985a70ee449ff", + Amount: "100000000000000", + }, + { + Address: "44904aa24c16c5d4862a494c5a3a068a9a8efcce", + Amount: "100000000000000", + }, + { + Address: "450047b3d8a803358e647dca9aa2119d552ae98a", + Amount: "100000000000000", + }, + { + Address: "45104003fddc52c2a36f2ea782ef4e040d709ae5", + Amount: "100000000000000", + }, + { + Address: "45204b7689eb2cd1ab0fca85d768176803713c56", + Amount: "100000000000000", + }, + { + Address: "45304fede7bde8d0fa71a22da82ec6aeaddcdb8f", + Amount: "100000000000000", + }, + { + Address: "4540428b06b1ac971a548b844bc7cee683ac8910", + Amount: "100000000000000", + }, + { + Address: "455048c4b5b04d40803e4ea44f1f1ec7f5e2158f", + Amount: "100000000000000", + }, + { + Address: "45604c07d459d0e00e0c676191f47f54f5cc9d17", + Amount: "100000000000000", + }, + { + Address: "45704ab864f63350afe79f2c840b96205b9dc69a", + Amount: "100000000000000", + }, + { + Address: "458047e5fe56a0e4e209705fadbdb64e74dcc8da", + Amount: "100000000000000", + }, + { + Address: "459047ffc6e6f4f92c97b7a74180ccaed6e30b79", + Amount: "100000000000000", + }, + { + Address: "46004e8e048204f310b2d3ef5790c6f0fdc6ddd0", + Amount: "100000000000000", + }, + { + Address: "461045c62f269a240a2d27ba40ac33b4324b7bab", + Amount: "100000000000000", + }, + { + Address: "46204132a93bdc40c6976823dd0e6bc205f155a1", + Amount: "100000000000000", + }, + { + Address: "4630494fb9144b14d2948d5b67261345f72b691c", + Amount: "100000000000000", + }, + { + Address: "46404d167820598aed5aa93b5a057d72fc859a04", + Amount: "100000000000000", + }, + { + Address: "46504941f3f25ba5b8f7c175ddf62eaf0d06adb3", + Amount: "100000000000000", + }, + { + Address: "466045100f7e8c27325435184c01b78369480354", + Amount: "100000000000000", + }, + { + Address: "467042e5a9b3c69a66129703b8c572240c1d153c", + Amount: "100000000000000", + }, + { + Address: "46804d4141c4947fbe605d1098eafdb14b108d6f", + Amount: "100000000000000", + }, + { + Address: "4690407f05a59ab99fa62e9c931fc713ed0b2184", + Amount: "100000000000000", + }, + { + Address: "470042f846f54c551bfcf53d2cc8fc9eb50b9d77", + Amount: "100000000000000", + }, + { + Address: "4710478780ea9e0d337b24886b1b806edcbeb194", + Amount: "100000000000000", + }, + { + Address: "47204e3a7b972c67d7492b8beffd704a14a5597f", + Amount: "100000000000000", + }, + { + Address: "47304bc12fb943d98b3c1e8800e97e452b9e07b1", + Amount: "100000000000000", + }, + { + Address: "474047553b5fdd4554a8d619d04c293fad715859", + Amount: "100000000000000", + }, + { + Address: "4750444b21d48d5058a716a230d50f675d3fabd4", + Amount: "100000000000000", + }, + { + Address: "4760435ab90be6bd17d294fd923e252b414a2c04", + Amount: "100000000000000", + }, + { + Address: "477045c6548b93ad997cf88265dc4064c2a55404", + Amount: "100000000000000", + }, + { + Address: "478043234bfbdde3497569af02e9052cb5877bfc", + Amount: "100000000000000", + }, + { + Address: "479046da314d05c021dac35448b1eecc89db0481", + Amount: "100000000000000", + }, + { + Address: "48004cb51eed7e063da47540db789cb415d1b3d7", + Amount: "100000000000000", + }, + { + Address: "481041dd8949041bd011954a00d2f52fae0566c4", + Amount: "100000000000000", + }, + { + Address: "48204a827f0f7ef5545fdc74333d8422ff702284", + Amount: "100000000000000", + }, + { + Address: "48304ebd697b2501eb5a4a8ce716151c64e4dfce", + Amount: "100000000000000", + }, + { + Address: "4840420106bebe4c1da8f3863f8fecf85531e3e8", + Amount: "100000000000000", + }, + { + Address: "485045203218d25423cd22454ad34f3473b1f948", + Amount: "100000000000000", + }, + { + Address: "48604b028a5faf55d03b2259e8596034dbcfce77", + Amount: "100000000000000", + }, + { + Address: "487049a35ab4ec9d9b24e7871fe3f332f2e4ba4d", + Amount: "100000000000000", + }, + { + Address: "48804331472e8fbb1145c9f17e6f3009efb8b9c3", + Amount: "100000000000000", + }, + { + Address: "48904c7f5a4f76f41e999a31f754d77b97d0d34a", + Amount: "100000000000000", + }, + { + Address: "4900408ea7abbfd68548d4066cd47de004abdab8", + Amount: "100000000000000", + }, + { + Address: "491042831baa4824f571ab903aa3a67283beb6ed", + Amount: "100000000000000", + }, + { + Address: "49204c54c110eae17618e89cc20ba6d8249b8388", + Amount: "100000000000000", + }, + { + Address: "49304ba5346e6c9681ac40b54b0b06798543121d", + Amount: "100000000000000", + }, + { + Address: "49404cde92dd5d8ecfc884c6c23e7d4fbf02d987", + Amount: "100000000000000", + }, + { + Address: "49504a406e7533631945d33ce560f51b4954c862", + Amount: "100000000000000", + }, + { + Address: "496040841bd7d102f718cc586408765fe8b890f7", + Amount: "100000000000000", + }, + { + Address: "49704630c8f0c30ad5562fca357ad9e433327c86", + Amount: "100000000000000", + }, + { + Address: "49804b1066d6e1f2e2eb444319101bf1d410bc0f", + Amount: "100000000000000", + }, + { + Address: "499049ee379ae9666f10a57cadac6dab770bf4b8", + Amount: "100000000000000", + }, + { + Address: "50004655607ec95dc65ec29bbb415db821f07653", + Amount: "100000000000000", + }, + { + Address: "5010452968dd443161fc551d953961bf63065bf0", + Amount: "100000000000000", + }, + { + Address: "50204abd8507b4151f8a5d11f8a5c42581adf99e", + Amount: "100000000000000", + }, + { + Address: "503048aefad5aedeebe1ea87229c3c6b8f1fe42b", + Amount: "100000000000000", + }, + { + Address: "504048ca595ad0f9b68759d00c16fa58316745c6", + Amount: "100000000000000", + }, + { + Address: "50504eaf9796e76437666e40f94af993faee5c36", + Amount: "100000000000000", + }, + { + Address: "50604210365e98bf07ce91a990826a9539edc2dc", + Amount: "100000000000000", + }, + { + Address: "50704701122e4cb8ce668272e88486dfe5efe64d", + Amount: "100000000000000", + }, + { + Address: "50804a42b45c1e6f2b0b7efb62081e1352aea22f", + Amount: "100000000000000", + }, + { + Address: "5090450269b417fbaca6afb81325baeee7817a73", + Amount: "100000000000000", + }, + { + Address: "5100438648be0f3168375454a4cdb3c9e42ecb0d", + Amount: "100000000000000", + }, + { + Address: "5110453215f3d3afe3a002bf8e926b38013e7173", + Amount: "100000000000000", + }, + { + Address: "51204817b59f7a35de4503dcbfdae37d5c256bad", + Amount: "100000000000000", + }, + { + Address: "513047730b1635dd5723fda5153a055ba17744d2", + Amount: "100000000000000", + }, + { + Address: "51404aeac599ca65caa4d65039e868764352d341", + Amount: "100000000000000", + }, + { + Address: "5150443a4e437dd13f2aaf543b78c59d186771ea", + Amount: "100000000000000", + }, + { + Address: "5160499de0e7643925875defc447b38fe8724704", + Amount: "100000000000000", + }, + { + Address: "51704fd6050f0e11179f4e1f403bc5b84c83156a", + Amount: "100000000000000", + }, + { + Address: "5180446d9777a6ecc8ea5a1864392f3f053992e3", + Amount: "100000000000000", + }, + { + Address: "51904629b79abd0f0a63d29a8ef19939bb4c9b68", + Amount: "100000000000000", + }, + { + Address: "52004033b3431796cd2b6c7183b0f4b20674f013", + Amount: "100000000000000", + }, + { + Address: "521044e558ddc905ab36398e83f425b49572f802", + Amount: "100000000000000", + }, + { + Address: "522042bf74ba442b2e4b5e5c3c2eac92990809e4", + Amount: "100000000000000", + }, + { + Address: "52304b8321c4df0bd068386bcc67c38eda4e78c6", + Amount: "100000000000000", + }, + { + Address: "524043fcf064677787b4009674157e5ab106724b", + Amount: "100000000000000", + }, + { + Address: "525045a59b44173f08543f6db2dfd82da1180386", + Amount: "100000000000000", + }, + { + Address: "52604131ad343cd2d4e196bb823402aa089046c2", + Amount: "100000000000000", + }, + { + Address: "5270483dfb1a2f45363360ec692c2b07f8ba4e62", + Amount: "100000000000000", + }, + { + Address: "52804b2f75230f1d2813065a70f0a3d1bb4abc0b", + Amount: "100000000000000", + }, + { + Address: "52904d9cdc5e0a89d0efff246ef317dad054571e", + Amount: "100000000000000", + }, + { + Address: "53004082199e53af8651a8bcd495cdf0b9bda026", + Amount: "100000000000000", + }, + { + Address: "531048a70444edac7580b084639b953c483edb1c", + Amount: "100000000000000", + }, + { + Address: "532040437d02ebc3037d1c7753fd4f25dc1ef83a", + Amount: "100000000000000", + }, + { + Address: "53304f2156659c6ecc5cb4a3ab8afbe6ce298727", + Amount: "100000000000000", + }, + { + Address: "53404bccf31a949b64345f2bceb2de4e0e192552", + Amount: "100000000000000", + }, + { + Address: "53504f3c72ad9444d0d6e747cbfdac9a58180e9f", + Amount: "100000000000000", + }, + { + Address: "53604394038790e32dcbbff77dbb99f6a3ce0c1e", + Amount: "100000000000000", + }, + { + Address: "53704913ab93114aa38132ad58df09853c480171", + Amount: "100000000000000", + }, + { + Address: "53804c76af324412728608ae0e8426d96abc99c9", + Amount: "100000000000000", + }, + { + Address: "53904a4b7c3faea59d5d9b496e21ba2faf9379f2", + Amount: "100000000000000", + }, + { + Address: "54004020a779da577648aa43d0ff18b4fb26d324", + Amount: "100000000000000", + }, + { + Address: "54104186203eb30aa18f4e39ba5892c6c7161222", + Amount: "100000000000000", + }, + { + Address: "54204df4f5682d7a23f9d1c52c7afb9274962957", + Amount: "100000000000000", + }, + { + Address: "543047f632bc64ed249da3382134283074068708", + Amount: "100000000000000", + }, + { + Address: "54404c797a871873ca95884d8c30ae983dd57de9", + Amount: "100000000000000", + }, + { + Address: "545041d1f64a7d0a251ceea5cfbb843959415dfd", + Amount: "100000000000000", + }, + { + Address: "54604942a3f7615c118e3b6f27b683b3fb01903c", + Amount: "100000000000000", + }, + { + Address: "54704ac394b1d1b740d4661c17fffcb415af13e3", + Amount: "100000000000000", + }, + { + Address: "5480478c9f0787732218da068f82651023d36863", + Amount: "100000000000000", + }, + { + Address: "5490441ea32aee4b5d12cdecdd7a96b606502b1c", + Amount: "100000000000000", + }, + { + Address: "550046092b784c4710e2cd4f72c0784723f28f99", + Amount: "100000000000000", + }, + { + Address: "55104676e53c56dbf0723979519125308ffb7760", + Amount: "100000000000000", + }, + { + Address: "55204cfc23ff67ebd33b993db7a1fc8ae11ed6a9", + Amount: "100000000000000", + }, + { + Address: "553049d21748456f4d400a0e0c05b04bc4a17d42", + Amount: "100000000000000", + }, + { + Address: "55404f23ef78c2750bc800240a7c58089eec4ee5", + Amount: "100000000000000", + }, + { + Address: "555045a7188c95f9a7c2bebd91d70baf4446ef6f", + Amount: "100000000000000", + }, + { + Address: "55604b44996331b3e1bc734a5309a921a9ed68b2", + Amount: "100000000000000", + }, + { + Address: "55704c62bb4eb9f7d44463a9d23b4fc4ca967e8d", + Amount: "100000000000000", + }, + { + Address: "558041c40bda7eb7793f4974d937efbdbfe849ad", + Amount: "100000000000000", + }, + { + Address: "55904dad216482a42deafd26f46227f821c4318c", + Amount: "100000000000000", + }, + { + Address: "56004ef6b2bc5c6b261cc57df071c4d6b0d58942", + Amount: "100000000000000", + }, + { + Address: "56104b6933b27ebb07b76c9fbea00efae4b455f8", + Amount: "100000000000000", + }, + { + Address: "56204c3808a0aba40e0b892ec5ecc7ee748d656b", + Amount: "100000000000000", + }, + { + Address: "563045b3c9e24aa577bd71c73e65456725e6a43d", + Amount: "100000000000000", + }, + { + Address: "564040919f2c792a37b8169dd75787a150280910", + Amount: "100000000000000", + }, + { + Address: "565046147c04866c2804381096f4fbe231be5e27", + Amount: "100000000000000", + }, + { + Address: "56604b970a318d46fa25e919ecf52e47644d8e54", + Amount: "100000000000000", + }, + { + Address: "5670477c21534eedfda67b3ba2dedd4d1fd7a48a", + Amount: "100000000000000", + }, + { + Address: "56804868458d08fbf48b5fe3c989e528932c4bdd", + Amount: "100000000000000", + }, + { + Address: "56904945ed11c64451561a5da223dfef07a63d6c", + Amount: "100000000000000", + }, + { + Address: "570042453bea68860af0d5e1fae70f954ef92fbd", + Amount: "100000000000000", + }, + { + Address: "571048a293b79bb13e6a70d000fe0d112e4db1ec", + Amount: "100000000000000", + }, + { + Address: "57204b9e693914803c62940322f5432d213f0303", + Amount: "100000000000000", + }, + { + Address: "573041273c82a37e145392a75914fc028cb06e73", + Amount: "100000000000000", + }, + { + Address: "5740421e8340de6f8f11a052ba4c1dd0125b4a89", + Amount: "100000000000000", + }, + { + Address: "575043a39731f509415b44775c0819d1ed028f6e", + Amount: "100000000000000", + }, + { + Address: "57604dae805055c246a6fd0b455c62b1a964dcea", + Amount: "100000000000000", + }, + { + Address: "577047fd2cd22d149d9fd5cc0d2b764c10401f47", + Amount: "100000000000000", + }, + { + Address: "578045b49772c9c100287ef46ba7573d29f0787c", + Amount: "100000000000000", + }, + { + Address: "5790443ed1d326e9d7dcd5a0b08efd895aecfc9a", + Amount: "100000000000000", + }, + { + Address: "580042c8282aa038ab321e84eba447532ada0e9f", + Amount: "100000000000000", + }, + { + Address: "58104e0e46910bed78a45754b5406547c3c50fe9", + Amount: "100000000000000", + }, + { + Address: "5820411917585b430f3dcd1bf0d4ec9909077a4e", + Amount: "100000000000000", + }, + { + Address: "58304206194e2acd780efcbcd467784e84455a2d", + Amount: "100000000000000", + }, + { + Address: "584041e10f3f4e450ffff9e5843a6aaf0bd9e138", + Amount: "100000000000000", + }, + { + Address: "58504295adbe4b5825b8c647a886a8a4cd09796c", + Amount: "100000000000000", + }, + { + Address: "586047183d4b321949867cf34f33a2b89dc4cbda", + Amount: "100000000000000", + }, + { + Address: "587046ecb0f3ff0fbb597b0d129c86992ec5a610", + Amount: "100000000000000", + }, + { + Address: "58804dc8466d215f2eb4e0cce44cfc2be56a0a9e", + Amount: "100000000000000", + }, + { + Address: "589043b85f4a9eff43e7c28325bb8b4143fb3b41", + Amount: "100000000000000", + }, + { + Address: "590043d97155d5cc610fbaac50957bf5726adf38", + Amount: "100000000000000", + }, + { + Address: "591048978de1d5b41fe3295776e774cba204f182", + Amount: "100000000000000", + }, + { + Address: "5920456ab371c27ce7ea26013b948314751cb60b", + Amount: "100000000000000", + }, + { + Address: "59304b5ebd78c9b142c6c892be51e0e598cd052c", + Amount: "100000000000000", + }, + { + Address: "59404237be852ee16fd9ad5ea5cfee2c1e33e466", + Amount: "100000000000000", + }, + { + Address: "595047325b6fd4d83eb09dcdd41efe666650f407", + Amount: "100000000000000", + }, + { + Address: "59604e48e8378d4d55facfe4ebb8030b4ac15b77", + Amount: "100000000000000", + }, + { + Address: "597046a2893077b014e727ea04168cb56c0178a3", + Amount: "100000000000000", + }, + { + Address: "598042250dd6291126f9d6eaff6d2465f0f60f12", + Amount: "100000000000000", + }, + { + Address: "599042ed94c7838178f5d85634f9aa7ab8226a99", + Amount: "100000000000000", + }, + { + Address: "60004433bfc5145e5805d433007914fbd179e443", + Amount: "100000000000000", + }, + { + Address: "6010455003515da6f534e5f0350db7073839563f", + Amount: "100000000000000", + }, + { + Address: "602049f52ea2c0ebe5efe0a92e72e9e822ea4f97", + Amount: "100000000000000", + }, + { + Address: "603040fd618c8a153c2a74f73c4627ee565ff483", + Amount: "100000000000000", + }, + { + Address: "6040464732f9ff9878e360e2c16912e237a69862", + Amount: "100000000000000", + }, + { + Address: "60504b8e2db94604422624dc62c9e3126f8b7e76", + Amount: "100000000000000", + }, + { + Address: "606041d95feb88cf90feb74ddb61442bba982655", + Amount: "100000000000000", + }, + { + Address: "6070425ff0899d82336bb1038acb94aa9ba00c21", + Amount: "100000000000000", + }, + { + Address: "60804154da5db875b177aa5f89285a15129ba147", + Amount: "100000000000000", + }, + { + Address: "60904987c7f9cc9daae1355326def9b74ad5f53d", + Amount: "100000000000000", + }, + { + Address: "61004e257b9b5dd1d92ace4d326bfc6984d3eb74", + Amount: "100000000000000", + }, + { + Address: "6110407764cac536b59af8c85d3799cfd177dc71", + Amount: "100000000000000", + }, + { + Address: "61204c4cac74ff2faf6b8f5c32ff289a408bbb1d", + Amount: "100000000000000", + }, + { + Address: "6130482f2f773fd2ccdcead78253f503df74df5d", + Amount: "100000000000000", + }, + { + Address: "61404858cb7054b8cb842a186dbe60a7e300db19", + Amount: "100000000000000", + }, + { + Address: "61504179f6955dd6657724dd4146b146e4d54c09", + Amount: "100000000000000", + }, + { + Address: "61604b023003dac28306cd9220b2147390a07f49", + Amount: "100000000000000", + }, + { + Address: "61704f8eab2279a3c84e0568fb846dd66c959932", + Amount: "100000000000000", + }, + { + Address: "6180499d362b6d9765b0998a3abd7294c685f284", + Amount: "100000000000000", + }, + { + Address: "61904dbe91f98c168f4772897356e891565205d3", + Amount: "100000000000000", + }, + { + Address: "620040b3439cb928a9879b273010a99e5055e92b", + Amount: "100000000000000", + }, + { + Address: "6210405df49c7a7ee68fe3d72c9d55cc14ca0e8d", + Amount: "100000000000000", + }, + { + Address: "622040b5c622cf2fa9f9dfe29832dfe7d8944ae3", + Amount: "100000000000000", + }, + { + Address: "6230485e89c4581bbd18207c2dfa318d0e1c5c83", + Amount: "100000000000000", + }, + { + Address: "62404456d0a321660f444f9579b4f8fcb616de54", + Amount: "100000000000000", + }, + { + Address: "625045eb1422c6a258141c7420174e4f353228ca", + Amount: "100000000000000", + }, + { + Address: "62604278bc2457c61b1fb7bd62ab419160ea33bc", + Amount: "100000000000000", + }, + { + Address: "62704f0b74cd7705d048aba826b4bbdba837ee80", + Amount: "100000000000000", + }, + { + Address: "628040d02555d7e209b85123343f6c2431a5c7fb", + Amount: "100000000000000", + }, + { + Address: "62904e1ddae768ad6e9e5c9884ed3256996140c1", + Amount: "100000000000000", + }, + { + Address: "63004122cc25622025f0157cc56ea60f1551723d", + Amount: "100000000000000", + }, + { + Address: "63104ebb93a1c385fa95e48c77f1d3a1d5f99295", + Amount: "100000000000000", + }, + { + Address: "632044e7a8d184c949eb09a2869487aba0f73406", + Amount: "100000000000000", + }, + { + Address: "63304cb4079acb5dec9fab674720e23b668a30d9", + Amount: "100000000000000", + }, + { + Address: "63404b02237cdc0708fd3d0a34f46b6756844c48", + Amount: "100000000000000", + }, + { + Address: "635045f735ce51744a688f6d5075770464133b72", + Amount: "100000000000000", + }, + { + Address: "6360418f0d9fea319405d324ad5bfb4b7908260c", + Amount: "100000000000000", + }, + { + Address: "637047816ef8e3fbf907553627764c687ec67441", + Amount: "100000000000000", + }, + { + Address: "63804872395fc43ee4d6bac267c931ada198506d", + Amount: "100000000000000", + }, + { + Address: "639049314c67316267cb7b10df2a8167f9ae9b48", + Amount: "100000000000000", + }, + { + Address: "64004497fe1c37da0fafb12f633b6080929b41dc", + Amount: "100000000000000", + }, + { + Address: "6410453060cde98da46b8eeae93f4a213a51aaca", + Amount: "100000000000000", + }, + { + Address: "64204b02f42cf5b2606ee7069ba5e5b643acd036", + Amount: "100000000000000", + }, + { + Address: "64304c4006cc42bc15ad4ce569b388981fbff631", + Amount: "100000000000000", + }, + { + Address: "6440410b6010b8cda6a38d2ccc6785c5c56a70a2", + Amount: "100000000000000", + }, + { + Address: "645043e482206acec00090d8a3fdf4b96602dda3", + Amount: "100000000000000", + }, + { + Address: "6460443f08d3abef11110045198b1257a9ec76f8", + Amount: "100000000000000", + }, + { + Address: "64704a5d9ee1ee1d8e197e781319e4953ac8bb73", + Amount: "100000000000000", + }, + { + Address: "648046c02fe3c86598115b9de7ef6c1ea7ecc5f4", + Amount: "100000000000000", + }, + { + Address: "64904d6a4328e16e5a52962aa46fba9a7d35b4c9", + Amount: "100000000000000", + }, + { + Address: "65004bb380bc0c86de13d4a3547b662690da9bd9", + Amount: "100000000000000", + }, + { + Address: "65104222b9b770a93e7b6e4319b34c6c52cc9155", + Amount: "100000000000000", + }, + { + Address: "65204cb2035c55ea5df48463769e9744ad6f0393", + Amount: "100000000000000", + }, + { + Address: "653047e2d1a8fb3d9e1805dccac1cc6f2c28c556", + Amount: "100000000000000", + }, + { + Address: "654043b4e33de08eff8894cb7ca7a71a411db7d9", + Amount: "100000000000000", + }, + { + Address: "655046ec7d2eb9c66d4af6f73d2e8206566e4692", + Amount: "100000000000000", + }, + { + Address: "656047fd8c02ab8e3771d3cd053734f56a926389", + Amount: "100000000000000", + }, + { + Address: "65704439f9a3e216347069f62b7fb13e4b1f9b64", + Amount: "100000000000000", + }, + { + Address: "65804f628f171dff16be813578f80f4e3b7e0e3c", + Amount: "100000000000000", + }, + { + Address: "659049f81d3b432aedf5eec093af2f7144346c73", + Amount: "100000000000000", + }, + { + Address: "66004766c29d526595b8b005cbdce375ff5fdcec", + Amount: "100000000000000", + }, + { + Address: "66104dce510f16a8217c3844db10e5f137bc441a", + Amount: "100000000000000", + }, + { + Address: "66204361fe6b4729f27732acc739dd3764e7b07c", + Amount: "100000000000000", + }, + { + Address: "6630440e5e933646e978d8f937fd643563d99230", + Amount: "100000000000000", + }, + { + Address: "66404f5457eb934bfc6e975f9f6b04c01cc602dc", + Amount: "100000000000000", + }, + { + Address: "6650441b6f8afa3b01cd713d723be5a40c6ce247", + Amount: "100000000000000", + }, + { + Address: "666041989961aea5a1873df788e7e5a2b535334b", + Amount: "100000000000000", + }, + { + Address: "667044c105e7a685a522b53f64c4ab7de28063e6", + Amount: "100000000000000", + }, + { + Address: "668040d53879731c4a014ce64216c4c36ae2e7ac", + Amount: "100000000000000", + }, + { + Address: "6690401e4271d59a632ca3e4b06f38b445929ece", + Amount: "100000000000000", + }, + { + Address: "670046842562abde6d3d466644b9ca0f8fa8f7f2", + Amount: "100000000000000", + }, + { + Address: "671041b264453e02458397b587c4d0d550d2150d", + Amount: "100000000000000", + }, + { + Address: "672043e97db17eefaca6d9c82bd787f4c5e97128", + Amount: "100000000000000", + }, + { + Address: "6730458aec07fc2b32f4068c57314a82c6a4ae42", + Amount: "100000000000000", + }, + { + Address: "674042dca7e3832040eb9d80275364d45478017c", + Amount: "100000000000000", + }, + { + Address: "6750430cb460f6571cd65a92d9bccecbc2b89dd0", + Amount: "100000000000000", + }, + { + Address: "6760451d38daecf19bf46a6fc5fb2d280d39270e", + Amount: "100000000000000", + }, + { + Address: "67704441d1d0855396d871f4e726e929660bf8ff", + Amount: "100000000000000", + }, + { + Address: "67804ccfc22ed924ba1d5022ed11db444e0ad33f", + Amount: "100000000000000", + }, + { + Address: "679045eca99bd5ee98e2bdfe0a067b6d7eaaa477", + Amount: "100000000000000", + }, + { + Address: "68004cbe8b20f79043bd60e6d407a892725c0218", + Amount: "100000000000000", + }, + { + Address: "681040fd5fbf65ee66ccfad1fc530d0f60d675af", + Amount: "100000000000000", + }, + { + Address: "68204296b18ed685fab791e7f7371f86fa3dbf15", + Amount: "100000000000000", + }, + { + Address: "683049213af4a3ed07b8dc4a078aa8bc485fb762", + Amount: "100000000000000", + }, + { + Address: "68404ac8c50e40e149ff2a292e350b8002361c9f", + Amount: "100000000000000", + }, + { + Address: "68504af73aa4ae030a8579cd54da6a8e71b2c121", + Amount: "100000000000000", + }, + { + Address: "68604c15e95f52d3039f453eac003c8d6b85abbd", + Amount: "100000000000000", + }, + { + Address: "68704e3bc93591d552942fe92f91889fbce4832a", + Amount: "100000000000000", + }, + { + Address: "68804b25a7116144f61e73e74e21adbe825b205f", + Amount: "100000000000000", + }, + { + Address: "68904c03e391f951339c9958eb5bc72c43ad63e3", + Amount: "100000000000000", + }, + { + Address: "6900418575027f2a1c247bbaa0609ae9cf80ab75", + Amount: "100000000000000", + }, + { + Address: "691041eab10813cc60e8fed6536903cd21635b13", + Amount: "100000000000000", + }, + { + Address: "69204a4b90e76b575773b257644c33f044455e73", + Amount: "100000000000000", + }, + { + Address: "693045b878d184546a55e1f2d2ed3fee47e08a69", + Amount: "100000000000000", + }, + { + Address: "69404b70bf4a3c1854d289bf48aff4ffcc54462d", + Amount: "100000000000000", + }, + { + Address: "695047251a6b4dc26af3dafeb2ad9e8bd11899f7", + Amount: "100000000000000", + }, + { + Address: "696042291abaeefbfe88cf4c6640cb8334fb5387", + Amount: "100000000000000", + }, + { + Address: "69704c4391043c0103e88d84b976b77eb8f58511", + Amount: "100000000000000", + }, + { + Address: "698045d16859ea22f965199057d94ef729316962", + Amount: "100000000000000", + }, + { + Address: "6990471405d1359a4951ff69f05f3a6ba5e322d3", + Amount: "100000000000000", + }, + { + Address: "700045ae96df298ad66c9407341aa1c9c4b7e3df", + Amount: "100000000000000", + }, + { + Address: "70104bbe466157ff39778c0efa245e729b33a00f", + Amount: "100000000000000", + }, + { + Address: "70204fc5a25b35b2ae011c05a06debe3c138cc6c", + Amount: "100000000000000", + }, + { + Address: "70304e51707696936993f6865f3f1be774f22c05", + Amount: "100000000000000", + }, + { + Address: "704041ae13c7807d1007bce82206adc28dec9bbf", + Amount: "100000000000000", + }, + { + Address: "70504f23e2a3f569a63533ac1b116a4680596abb", + Amount: "100000000000000", + }, + { + Address: "70604bbeaf187b5b24ac8f11df5f9a404432a899", + Amount: "100000000000000", + }, + { + Address: "707043290fd9d435c104db4a9a192023f432054a", + Amount: "100000000000000", + }, + { + Address: "708049eadf139b3036e1eddded3bf44fe803da63", + Amount: "100000000000000", + }, + { + Address: "70904ac80bef69aff0800bb6554f5f01443113e9", + Amount: "100000000000000", + }, + { + Address: "710041d7fff4b20bd4460b108e314d2fc832b2d2", + Amount: "100000000000000", + }, + { + Address: "7110486af5e1932f8b0ed8e82224012d4bb4a6e6", + Amount: "100000000000000", + }, + { + Address: "7120458a83f65b14f570912acd93701cc3689098", + Amount: "100000000000000", + }, + { + Address: "71304ce8abec1dc3eb97a538274a97f65bed3a3e", + Amount: "100000000000000", + }, + { + Address: "714045b6adbfbcb7b04f6763ff9f5f7f36b0b653", + Amount: "100000000000000", + }, + { + Address: "715040b8b724a8eb1f9f31eba45e384725408d0e", + Amount: "100000000000000", + }, + { + Address: "7160455702053e3a8a3ef39971eb848d9d6fa93c", + Amount: "100000000000000", + }, + { + Address: "7170477eaccf217f57b35c55cab9e2dbc62433db", + Amount: "100000000000000", + }, + { + Address: "71804ead1df28012d17172a0775cbac6cd999306", + Amount: "100000000000000", + }, + { + Address: "71904efa4dca8d0ce5608b4689f8bf9cc51f9df8", + Amount: "100000000000000", + }, + { + Address: "720049fd5ac173f954454258e7673d1d39d2dce4", + Amount: "100000000000000", + }, + { + Address: "72104a97065ed6db665ec6d59852f1a5497f3beb", + Amount: "100000000000000", + }, + { + Address: "72204c482f30096b5a80c9411eb724979b6df892", + Amount: "100000000000000", + }, + { + Address: "72304639b82708bbdb5ab2e20dfcb5148084de30", + Amount: "100000000000000", + }, + { + Address: "72404e838cd0e07e6a01e23ca678ee364721cf92", + Amount: "100000000000000", + }, + { + Address: "72504fe21ab8f1ce70ad1f29122222a742150ff0", + Amount: "100000000000000", + }, + { + Address: "72604117cf813be0dffaefbf4806e5699344e5c3", + Amount: "100000000000000", + }, + { + Address: "72704dfacba8503a46b1e5e7e6aa8280880e6e65", + Amount: "100000000000000", + }, + { + Address: "72804ca70d543e1e4369abd90b9d6022f3a1d97c", + Amount: "100000000000000", + }, + { + Address: "729043b384b8354d7a54c2428b22222f7898f9c6", + Amount: "100000000000000", + }, + { + Address: "73004fa9859d249efb0a91fc915af55ec49cd444", + Amount: "100000000000000", + }, + { + Address: "731040db933ad7d8e99b88440a76e3cee5eb6e69", + Amount: "100000000000000", + }, + { + Address: "73204343469ac1f556f0377d90b69f3dbf5a982c", + Amount: "100000000000000", + }, + { + Address: "733049362478534ff6410823044e071eb2f83e4f", + Amount: "100000000000000", + }, + { + Address: "73404f1945447051bf690a173519ba74645e994a", + Amount: "100000000000000", + }, + { + Address: "735042862d5212cfefc9b5f324ce13fa9b325705", + Amount: "100000000000000", + }, + { + Address: "73604c4ab9e12a56a90e738b6a231cfbd5a49e66", + Amount: "100000000000000", + }, + { + Address: "73704b14cd41d45fab3fe2b4b7757d57249db53b", + Amount: "100000000000000", + }, + { + Address: "7380460d3ff8820e5b3cfb10a80d408caaa66dae", + Amount: "100000000000000", + }, + { + Address: "739048ca6dda2acaa91f555fb45dd6ba2ca17958", + Amount: "100000000000000", + }, + { + Address: "74004606ce8137e61a116e85357ab666f1aab529", + Amount: "100000000000000", + }, + { + Address: "74104e0fa50aac8cda9809d603430ea7ea65d122", + Amount: "100000000000000", + }, + { + Address: "742040c7efac6132191fa24d16fca79a600ed23e", + Amount: "100000000000000", + }, + { + Address: "7430460fa50f3a7e2d7765c6b5f30724720f6fc9", + Amount: "100000000000000", + }, + { + Address: "74404c120f2909457a3ddad0abffae055890eee9", + Amount: "100000000000000", + }, + { + Address: "74504191374ac2d4fbdbc976b63e007d8b5e7e72", + Amount: "100000000000000", + }, + { + Address: "74604ac62f17d849b24cb9a1e2bd680f107a3977", + Amount: "100000000000000", + }, + { + Address: "747047f7087dd2aeb62a5eb6e3f15c1e6e1721b5", + Amount: "100000000000000", + }, + { + Address: "74804357c658d6575aa6746be8f25c04c4e9adcb", + Amount: "100000000000000", + }, + { + Address: "7490485def5367ca659bab67b979ffd181be6852", + Amount: "100000000000000", + }, + { + Address: "7500405f2ec0db786c0d56dec170ccb668f781ae", + Amount: "100000000000000", + }, + { + Address: "7510441d0cd71400a2ddd1516c4e08d9cfc0f5af", + Amount: "100000000000000", + }, + { + Address: "75204971b2ae461e5e989ad3733bf7c83be3580c", + Amount: "100000000000000", + }, + { + Address: "75304cb27016bd796a512070a5ddad6c22cbfa34", + Amount: "100000000000000", + }, + { + Address: "75404d484447585d4699de2133301894f7f0a0b9", + Amount: "100000000000000", + }, + { + Address: "75504f5535dd8986c8688946fc5f5580b7a8dd38", + Amount: "100000000000000", + }, + { + Address: "75604cd760a93f2f5286d8a7c24bcb17a6cbc4c2", + Amount: "100000000000000", + }, + { + Address: "757040f861c5d33d40d5cd88dbf9d494c344b2c3", + Amount: "100000000000000", + }, + { + Address: "758047bbc4e2ea7a59a65b82d83577abb225991d", + Amount: "100000000000000", + }, + { + Address: "7590432ee6c2f2e6c259b3d77337501615a5bf50", + Amount: "100000000000000", + }, + { + Address: "76004b9870bfe097f21d85c768a338502c3efd29", + Amount: "100000000000000", + }, + { + Address: "7610492a5a430b406f4f95c2c204d1a400b84ad8", + Amount: "100000000000000", + }, + { + Address: "76204cea7ee3fc87e957dd7dda7a70c949f26ccd", + Amount: "100000000000000", + }, + { + Address: "76304fc25e32600ba08528d168ca05e7d2010913", + Amount: "100000000000000", + }, + { + Address: "76404f703f4798300860345bf1ff81f0de6ffe8d", + Amount: "100000000000000", + }, + { + Address: "765045358ae8a44e3b1d7caa7f46c9b78ef724ef", + Amount: "100000000000000", + }, + { + Address: "7660435988f9ee112cbea0abf18e2e7ca419949c", + Amount: "100000000000000", + }, + { + Address: "76704fb154d0c3ab08652990fe69a940ed882c93", + Amount: "100000000000000", + }, + { + Address: "7680467f75f10cd807b0a27f7628269578a1c006", + Amount: "100000000000000", + }, + { + Address: "76904da84cd85eb2ec2ff690aeb4a7a1d648f413", + Amount: "100000000000000", + }, + { + Address: "7700458dc09f5383173182fde54f7b17935882c7", + Amount: "100000000000000", + }, + { + Address: "77104d3b0c4c656adba6d327c7b79f9ce8d94800", + Amount: "100000000000000", + }, + { + Address: "7720490fd89c46309eb4dc414e4b4fabf2a7fc57", + Amount: "100000000000000", + }, + { + Address: "77304d60249375837d59fe84b04ccc716ec30e68", + Amount: "100000000000000", + }, + { + Address: "774044dc674f47ff6d1b0dcd008aa4d86d53d245", + Amount: "100000000000000", + }, + { + Address: "77504d1b358a2fcbe5970628dde6e8ec705f76d8", + Amount: "100000000000000", + }, + { + Address: "7760402fe920bf6f4df37e081b3dfdc00954ff0f", + Amount: "100000000000000", + }, + { + Address: "777044ba8b3cc26d90da9f5a5f7863ef6c9d8c53", + Amount: "100000000000000", + }, + { + Address: "77804f8edbd62aa1d1e77d7834fbd817494d7e38", + Amount: "100000000000000", + }, + { + Address: "7790428083b35b7b088c2ac0e8113d3ccdc92eeb", + Amount: "100000000000000", + }, + { + Address: "78004e3cc37af45c0e372a37b2b08460b55bd775", + Amount: "100000000000000", + }, + { + Address: "7810493ae5c20904e6e8f2426e4d195ce0f1f3e5", + Amount: "100000000000000", + }, + { + Address: "78204a6682e722ba0a892960262eb1c9fda42ffb", + Amount: "100000000000000", + }, + { + Address: "78304b58974edd0eae39ef9c965f51eb16f2be03", + Amount: "100000000000000", + }, + { + Address: "78404c610ff998f92d9cc87b4ea1573cbd8f9339", + Amount: "100000000000000", + }, + { + Address: "78504ad330e8e41e81bf50082715f817d1a0a38d", + Amount: "100000000000000", + }, + { + Address: "78604f683cad2be47167a8b646128e1e84b277fa", + Amount: "100000000000000", + }, + { + Address: "78704013460b7c14c49d5d741326012cbe122bee", + Amount: "100000000000000", + }, + { + Address: "78804e1e31a15b13f264f7722db855f5677df70c", + Amount: "100000000000000", + }, + { + Address: "789046646c7fb2a2eb633c2e5e570af634b0238a", + Amount: "100000000000000", + }, + { + Address: "79004e3e7e74b663437a69c867216f047ad606dd", + Amount: "100000000000000", + }, + { + Address: "7910492ffe5550fb16f895bb7e8250a3d715771b", + Amount: "100000000000000", + }, + { + Address: "79204718fe2312b236ec58494a3e9b7f90c89e73", + Amount: "100000000000000", + }, + { + Address: "793048a8b77b03ecc7a3bc39d744f7d413559025", + Amount: "100000000000000", + }, + { + Address: "794041ee030eb5d43c58833fddf6f205f9a8c014", + Amount: "100000000000000", + }, + { + Address: "795049298725fffe87c4593dfbccb595e8791a3b", + Amount: "100000000000000", + }, + { + Address: "796048b394f862a92e5c8d9122c9ad5d485534eb", + Amount: "100000000000000", + }, + { + Address: "79704cbe24d2a5470953109554dc4ce56a2c84d7", + Amount: "100000000000000", + }, + { + Address: "79804beaba60ecb5eb2b77d4cdfdd1942b805f49", + Amount: "100000000000000", + }, + { + Address: "799045cfacb0e38a8d911fb39ff6397adc1f15eb", + Amount: "100000000000000", + }, + { + Address: "800040c36ade282fda9785c5e62213fe0d5d0312", + Amount: "100000000000000", + }, + { + Address: "801045faaed561eef624c2aca9076a2e66ed54e6", + Amount: "100000000000000", + }, + { + Address: "80204aea3fb91f7c90dee4ebcccec023908213f1", + Amount: "100000000000000", + }, + { + Address: "803046df6243205308bfe7259304a93a9637fed8", + Amount: "100000000000000", + }, + { + Address: "804040e821386c7eb980b981c07da31a9259e76c", + Amount: "100000000000000", + }, + { + Address: "805046b83fccfe43723e00bf5eb1dc058843c80f", + Amount: "100000000000000", + }, + { + Address: "806041951a05cf13b69d8067896675b584830d0e", + Amount: "100000000000000", + }, + { + Address: "80704002998850477f6640306c3c79f0970c5371", + Amount: "100000000000000", + }, + { + Address: "808043b8a07f468d3025ba172a6bc52d2b7523c3", + Amount: "100000000000000", + }, + { + Address: "80904548b7d57c71b2eb3de9d8dacbca8c3e20b6", + Amount: "100000000000000", + }, + { + Address: "8100497c04b5bc57d186afb7b4a15c34d29b8188", + Amount: "100000000000000", + }, + { + Address: "8110496672fbcaf610dcf186d0a1b484b228484c", + Amount: "100000000000000", + }, + { + Address: "81204469c77571ceabc193ec1c488a65bd08dc78", + Amount: "100000000000000", + }, + { + Address: "81304a805fa1d581378b31d9a0ea87e1973c44f4", + Amount: "100000000000000", + }, + { + Address: "8140425c4d8f0a3217c9ab13623270f3b992c00a", + Amount: "100000000000000", + }, + { + Address: "81504ddb923189b0e870a3b50ad910a3b5753f21", + Amount: "100000000000000", + }, + { + Address: "816042f0724b82005bff27112ce3a316e901e0f4", + Amount: "100000000000000", + }, + { + Address: "8170452c586b93dc1d7e514798fbe7850c2789dd", + Amount: "100000000000000", + }, + { + Address: "81804732d11fcee01a02cde6216a8e3edf0884a6", + Amount: "100000000000000", + }, + { + Address: "819040aa22f80c84c0977e463e0763579f1609f2", + Amount: "100000000000000", + }, + { + Address: "82004fe0e73638a8772bed9964d5323cc1c8cce3", + Amount: "100000000000000", + }, + { + Address: "821040ccec8c6129935e6a3f9bcf970948d55287", + Amount: "100000000000000", + }, + { + Address: "8220437ddde50e58b8327039bc6f457649d63a31", + Amount: "100000000000000", + }, + { + Address: "823042082e15aa436506c6379eeebd842c6313a3", + Amount: "100000000000000", + }, + { + Address: "82404388de5c42b260394efbd3ad4ccf708b9a25", + Amount: "100000000000000", + }, + { + Address: "82504a4f983dfba8d0c878a61b5276f011899158", + Amount: "100000000000000", + }, + { + Address: "8260482c4fbb5891e2dbbcb6a5c639b715473cae", + Amount: "100000000000000", + }, + { + Address: "827048d080883ae8876f0da515feb5772f64fcfb", + Amount: "100000000000000", + }, + { + Address: "828045fc2303b1afa7652f424b2c568c4c3d8256", + Amount: "100000000000000", + }, + { + Address: "829044583424c97871c023f9b4234cb5d468457a", + Amount: "100000000000000", + }, + { + Address: "830049dbb7faf8390c1f0cf4976ef1215c90b7e4", + Amount: "100000000000000", + }, + { + Address: "83104c657ae2e8aa2d9c89d9480ae55aa321b252", + Amount: "100000000000000", + }, + { + Address: "83204812d180c66f212ebdb89cde6606dad7b242", + Amount: "100000000000000", + }, + { + Address: "83304fa5b0481d15a160bca05e899edef8b602bf", + Amount: "100000000000000", + }, + { + Address: "834045a632211a9ebfd436d83dd178f2994473d8", + Amount: "100000000000000", + }, + { + Address: "8350444055dbbd40bde22e6455381e283f5b6b11", + Amount: "100000000000000", + }, + { + Address: "83604d5f7b6a9054c3fd0ba3f95459976b2547b7", + Amount: "100000000000000", + }, + { + Address: "837041d1c1fd6a43e2f8b03211a6b225cdd44976", + Amount: "100000000000000", + }, + { + Address: "8380491ed4a12cfa13893e74819e311bf7a12d8f", + Amount: "100000000000000", + }, + { + Address: "83904bed445a6e9c4a6852af272da17f588dc410", + Amount: "100000000000000", + }, + { + Address: "8400455d79ff6780de6c49bae8c55c2c31cb63f7", + Amount: "100000000000000", + }, + { + Address: "84104a221b2bfba81e26b6a23359ae58cc979a55", + Amount: "100000000000000", + }, + { + Address: "842043630e1449760a1b25087f5f50a9e373ffdb", + Amount: "100000000000000", + }, + { + Address: "843042a6e0926fe91a51698694b4b959a2de377f", + Amount: "100000000000000", + }, + { + Address: "844046b4a8c4600bd55d177e4d4ea4e89d0b4ded", + Amount: "100000000000000", + }, + { + Address: "845047eb2f2acc3b5c60bedb64a6565b048159df", + Amount: "100000000000000", + }, + { + Address: "84604b8cbdca589f843a841957b104862cbcb5d6", + Amount: "100000000000000", + }, + { + Address: "847042033cfd9f001a06ebcc2504901561f21da1", + Amount: "100000000000000", + }, + { + Address: "84804082583aec69e4607a22e72c60cb056116c5", + Amount: "100000000000000", + }, + { + Address: "849046dc53c92d02169ab2d4309cf0cd760c8dcd", + Amount: "100000000000000", + }, + { + Address: "85004fd156e059ccaaf4749ba2df7ba24de530a1", + Amount: "100000000000000", + }, + { + Address: "8510485f42a056460eb4f0291b0a72af35646d87", + Amount: "100000000000000", + }, + { + Address: "8520480dd3e656c0331952c265a78fdf8e3f5d49", + Amount: "100000000000000", + }, + { + Address: "85304ee06bac526cdc6a53500afbf91d0858c3eb", + Amount: "100000000000000", + }, + { + Address: "85404ecad2db6d6e414ef872827ab2edf811536b", + Amount: "100000000000000", + }, + { + Address: "85504fec36d0d6688d26af1f6fc345e76ade37d4", + Amount: "100000000000000", + }, + { + Address: "8560447acb6bc46cf04ec87b6c5bbb6b357454e3", + Amount: "100000000000000", + }, + { + Address: "857040fcce4a431006f9c552d01e77dfbe292bff", + Amount: "100000000000000", + }, + { + Address: "85804f279fe013dbaf2bdc210af86fc87946ebb3", + Amount: "100000000000000", + }, + { + Address: "8590479a8887c9215b9374410762e43753fd63b6", + Amount: "100000000000000", + }, + { + Address: "860040cc1341444b4b08675dea43a1ba2346e10d", + Amount: "100000000000000", + }, + { + Address: "861048828d752c8e69dfca134eee268d13a3ef80", + Amount: "100000000000000", + }, + { + Address: "86204cb5b528864a8266dfb08004c84f7ca846ac", + Amount: "100000000000000", + }, + { + Address: "86304ffd7c44f1c66931ca9cb36f77d82efaa839", + Amount: "100000000000000", + }, + { + Address: "86404e14d4fb029910caecf02ef989761e3297a0", + Amount: "100000000000000", + }, + { + Address: "8650494118a2ef12e07deccc0aa8c1a9c9875871", + Amount: "100000000000000", + }, + { + Address: "866046aa60688a43250cc2ed13fb0fc4ea146b44", + Amount: "100000000000000", + }, + { + Address: "8670497332aa6a185622948006adcfb226bcf22b", + Amount: "100000000000000", + }, + { + Address: "86804452bfbef5a5b6224b73fd94691234c09c44", + Amount: "100000000000000", + }, + { + Address: "86904613b2ba2159755abc593ccdeb1ce12fb64f", + Amount: "100000000000000", + }, + { + Address: "870049c927a4c40479b65b70f03ebfe68dcce4ee", + Amount: "100000000000000", + }, + { + Address: "87104e2b9fec39b3cfd27e3f236407b8c5dd21e7", + Amount: "100000000000000", + }, + { + Address: "872049d58d11e6d5dcf92492706a57700a3b9c78", + Amount: "100000000000000", + }, + { + Address: "87304b9b70b119da73715ea15e77df1c47dee9de", + Amount: "100000000000000", + }, + { + Address: "87404d313145fbffe1a60080426331dfbbccde88", + Amount: "100000000000000", + }, + { + Address: "8750482f002575a5b05b23a4a2fe81e72a85903e", + Amount: "100000000000000", + }, + { + Address: "876040e63de214d3d97c41c5e2506835356febfd", + Amount: "100000000000000", + }, + { + Address: "8770403d44ac830ef4d787674be73fc60487e6b9", + Amount: "100000000000000", + }, + { + Address: "878046336c193431737bce3b3f7bb59fb560a306", + Amount: "100000000000000", + }, + { + Address: "8790470a45f434b064286df6716cf56884abe0d2", + Amount: "100000000000000", + }, + { + Address: "880040754a3c36b9c6dd10b7cb3eb6540d047a3f", + Amount: "100000000000000", + }, + { + Address: "8810480c4bcd788ad9e5b72667d82c42946815a3", + Amount: "100000000000000", + }, + { + Address: "882046a981d4f3fbe823cc786031162553a8e0dd", + Amount: "100000000000000", + }, + { + Address: "8830406539e2484ac4c47a6812ae758d79221c59", + Amount: "100000000000000", + }, + { + Address: "8840415de6febc6c8eff4f6a9ca2c980bdb37343", + Amount: "100000000000000", + }, + { + Address: "8850467d1d836e07f22fd0d11d127a868c568b3d", + Amount: "100000000000000", + }, + { + Address: "8860473aabc1e8c3d6e68eca590113fc9a6e18a8", + Amount: "100000000000000", + }, + { + Address: "88704d73662804ac9d280bbbf7c829b8bb44eed9", + Amount: "100000000000000", + }, + { + Address: "88804d3c7e71be9145c486df8c5e3f50fe3d585e", + Amount: "100000000000000", + }, + { + Address: "88904f29e996fe348e2e08e436d62bcfe2ab43d4", + Amount: "100000000000000", + }, + { + Address: "89004a83edbdb171fb10d403fc12f61712713dc3", + Amount: "100000000000000", + }, + { + Address: "89104c7c4650b47edcd89027f02b869b288a4233", + Amount: "100000000000000", + }, + { + Address: "89204680d0b82eb5d0a7cd38cc79303fb08c0a39", + Amount: "100000000000000", + }, + { + Address: "89304a88a2c22402b132a03b79207edfc1d53521", + Amount: "100000000000000", + }, + { + Address: "89404525c0cdadfbc8254978cbd47c3f730f6061", + Amount: "100000000000000", + }, + { + Address: "89504de91c02f4fc3514641bd2582d5a43450e67", + Amount: "100000000000000", + }, + { + Address: "89604969d23518afac4fc4b2b49cb827dea90cb4", + Amount: "100000000000000", + }, + { + Address: "897049b15315f7b4a8ec4ffef90d0db4b15fad05", + Amount: "100000000000000", + }, + { + Address: "89804e7a03a222cd2042f671f17fdb4e7b89c70b", + Amount: "100000000000000", + }, + { + Address: "8990454279c9296f15f4b9027b7ede5e875ff7ba", + Amount: "100000000000000", + }, + { + Address: "9000472babb942be176fa7c342ddb562bfc17993", + Amount: "100000000000000", + }, + { + Address: "90104d03cea867215a2f79d6b1b42fd286a2372c", + Amount: "100000000000000", + }, + { + Address: "90204df1a7d64dd87c3a2ab0e790f66ab7a078da", + Amount: "100000000000000", + }, + { + Address: "90304de617a78d7b8f131deafef6c56c60b1e157", + Amount: "100000000000000", + }, + { + Address: "90404100b1b6572b8f50e7eeab9f43c410b79bda", + Amount: "100000000000000", + }, + { + Address: "905040be7d14a7f3ecf1062254649069e5df7795", + Amount: "100000000000000", + }, + { + Address: "906042c145bb61505e6e03c8e8f0ead7506d9e14", + Amount: "100000000000000", + }, + { + Address: "90704b50a773c5ae28e867d9af6915d1a5f05b41", + Amount: "100000000000000", + }, + { + Address: "9080431cc7d962dc0df5bfa76c05c2988f7c7588", + Amount: "100000000000000", + }, + { + Address: "90904758c69a7bf7db7c018ab62672c854494f98", + Amount: "100000000000000", + }, + { + Address: "91004b7156b7f06c1df3d652361b0236b656f54c", + Amount: "100000000000000", + }, + { + Address: "91104d6aeccb5e420df5a2031b309d57f9c30af7", + Amount: "100000000000000", + }, + { + Address: "912042f7dbb1b21e5807ef53706b5a66321e65e9", + Amount: "100000000000000", + }, + { + Address: "91304671b71c2a3d12eb6d51a921509aa781f853", + Amount: "100000000000000", + }, + { + Address: "9140499d47cd284a1817d1a431eccb6c6f3897d6", + Amount: "100000000000000", + }, + { + Address: "91504815a6df26c9a3e142ee6b0509a30b258d64", + Amount: "100000000000000", + }, + { + Address: "91604800d1329fde56d1cab995ea32698b0ea48d", + Amount: "100000000000000", + }, + { + Address: "917043c3f9ccc184acb6bdebf3c7c8d1e6272d3b", + Amount: "100000000000000", + }, + { + Address: "91804ba18ce38f7c37d19530bcf0a2d08d601ebb", + Amount: "100000000000000", + }, + { + Address: "919042fc90de9cb87c320fd7ce0dfbde484d2915", + Amount: "100000000000000", + }, + { + Address: "920041940cd8a4e6fe691bac5cf316b5fd83dc85", + Amount: "100000000000000", + }, + { + Address: "92104bc1a3533ca7b034928f7c44ffebfb5669ae", + Amount: "100000000000000", + }, + { + Address: "92204b0945978912b9798859599b6a8879904dbf", + Amount: "100000000000000", + }, + { + Address: "923046ed4b42686dd841059917c2a82a19b4eae7", + Amount: "100000000000000", + }, + { + Address: "92404fdc369b099b3ba39551010a0ae267b8a0d3", + Amount: "100000000000000", + }, + { + Address: "92504a904a7a49ddc5c347704f5cf641538a683b", + Amount: "100000000000000", + }, + { + Address: "9260415480d030341a78cac35928b1d58ead468c", + Amount: "100000000000000", + }, + { + Address: "92704b20d56a52096c96853682d497809ac8a644", + Amount: "100000000000000", + }, + { + Address: "9280414564c13d52995b5c97a1edbbbe9398fd79", + Amount: "100000000000000", + }, + { + Address: "929048ae6f99b502d1e8d8659c06311fa023a37c", + Amount: "100000000000000", + }, + { + Address: "9300459038aca9253f485af17189d4d761ee16cf", + Amount: "100000000000000", + }, + { + Address: "93104dce3896e7013ec4b4373bc037ea34a9024d", + Amount: "100000000000000", + }, + { + Address: "932041772f90a64f76fd8d088179fa812f00d4e9", + Amount: "100000000000000", + }, + { + Address: "93304ed9b8185ce822360967447c164425f8ee85", + Amount: "100000000000000", + }, + { + Address: "9340469f9aa3259a2d941f668f33c1352177b431", + Amount: "100000000000000", + }, + { + Address: "9350424afed2719af57946f261e28bc536b2e670", + Amount: "100000000000000", + }, + { + Address: "93604fed35670e2a5b9bb9664ec5dd2a8df8622b", + Amount: "100000000000000", + }, + { + Address: "937044aca7e544f4f3bf390c72a528139d99570c", + Amount: "100000000000000", + }, + { + Address: "93804c365ad48f71d5feb09fb369bf71752d01f8", + Amount: "100000000000000", + }, + { + Address: "93904e6c56c737ad30ba95ee3c035ca50949a241", + Amount: "100000000000000", + }, + { + Address: "94004b81cc9f530a41b173cbe610855a0d6d64a6", + Amount: "100000000000000", + }, + { + Address: "94104967e8765b059887acc9163afd1c92bdc67f", + Amount: "100000000000000", + }, + { + Address: "94204f7637a290288069f8fa685ffdf25e1c869b", + Amount: "100000000000000", + }, + { + Address: "94304ac0c080d0a89071c616fb302379149c1b00", + Amount: "100000000000000", + }, + { + Address: "944040b51cc1b8aa4c279f762407603bcd881009", + Amount: "100000000000000", + }, + { + Address: "94504f83b51f1202cc792f8176206fb097df6012", + Amount: "100000000000000", + }, + { + Address: "946049033f9aee708411907b949654ff26b51a01", + Amount: "100000000000000", + }, + { + Address: "947041d06386084692a7c08c411407542a5f079f", + Amount: "100000000000000", + }, + { + Address: "94804f75beec2ab62c24a467dc8458052cf2d4e7", + Amount: "100000000000000", + }, + { + Address: "94904c195c64f1954eec679246d71220aa633e38", + Amount: "100000000000000", + }, + { + Address: "950040d8f3b3c16d8d5f3ebffe1a9d11bc7983e4", + Amount: "100000000000000", + }, + { + Address: "951041e30df6b7a32cb3e6d01ab859350082e095", + Amount: "100000000000000", + }, + { + Address: "952040329c551f70a521d7b61ca958e97303fc60", + Amount: "100000000000000", + }, + { + Address: "9530473f409d364affc33a63894c33404885e7c0", + Amount: "100000000000000", + }, + { + Address: "954041a001bd70a0484f3dfba6d53ae29537b9e5", + Amount: "100000000000000", + }, + { + Address: "95504bcf8b4777e0d8f4525064fa1b8546d851e8", + Amount: "100000000000000", + }, + { + Address: "95604254b548a7eb21d62929878bd1f42e768309", + Amount: "100000000000000", + }, + { + Address: "95704d45620fc4506f2a1448f6ea83d342c0b70f", + Amount: "100000000000000", + }, + { + Address: "9580450e47feb1931fc507b6fb946df04788a775", + Amount: "100000000000000", + }, + { + Address: "95904789595b1d1b9e580a52a61bd88ebf642bd2", + Amount: "100000000000000", + }, + { + Address: "96004a53c3c0bd200f6bdf8201e32bcbc97d6edf", + Amount: "100000000000000", + }, + { + Address: "96104842c185e35bfb61d5e3525531c4c68338d6", + Amount: "100000000000000", + }, + { + Address: "96204d23d73724fef1f217b9fa3629217aa78809", + Amount: "100000000000000", + }, + { + Address: "963048f029d166e675e52ac472c42fc460c51bee", + Amount: "100000000000000", + }, + { + Address: "96404e241e8ef28dc1642212be0473121bb69d24", + Amount: "100000000000000", + }, + { + Address: "96504a7b7433313702b495ab5be6b1c35f56bf17", + Amount: "100000000000000", + }, + { + Address: "96604e53196b5ccd5bda81a0235b2ff333345125", + Amount: "100000000000000", + }, + { + Address: "96704cb4c16eb1b841def729e92d8810157ce797", + Amount: "100000000000000", + }, + { + Address: "96804c0924ca87184e536e121e37e8533b318afe", + Amount: "100000000000000", + }, + { + Address: "96904e717839fd6445721e2cd9e9a14ef582919a", + Amount: "100000000000000", + }, + { + Address: "97004e3db06153e5e97c715eeedb466503ecaaec", + Amount: "100000000000000", + }, + { + Address: "97104aac1f2575cc78a5b70baaacdf0e05bf6f59", + Amount: "100000000000000", + }, + { + Address: "972049d3284c1db53a587a14ea24dff292257dd6", + Amount: "100000000000000", + }, + { + Address: "97304900781cec2ebcf1cde90ae1b08188cbc524", + Amount: "100000000000000", + }, + { + Address: "974041c53c33cc1e80534299bdaee9ba4595e6e4", + Amount: "100000000000000", + }, + { + Address: "97504ece3e7fc1dbf05d50ccae734b467caa84df", + Amount: "100000000000000", + }, + { + Address: "976044c4c2e66323bbb761f7aa1706096c9d16ec", + Amount: "100000000000000", + }, + { + Address: "97704be19df706440b2d080f50b6eb4a2bcc3c18", + Amount: "100000000000000", + }, + { + Address: "978049e7b1deb4d01f7bc0c471662d41f48a956b", + Amount: "100000000000000", + }, + { + Address: "979045ffe3a861016ce74427be6932047b59ecf7", + Amount: "100000000000000", + }, + { + Address: "98004645f52f575c3a48964e125522ee9042f775", + Amount: "100000000000000", + }, + { + Address: "981049acf75d47ad897a9971c8f93e01ee0c1723", + Amount: "100000000000000", + }, + { + Address: "982046598e03d4d845ebb540300fb2ce2f162edd", + Amount: "100000000000000", + }, + { + Address: "983048ad983e11741528bee423f0e848470bad88", + Amount: "100000000000000", + }, + { + Address: "98404d93b2fcc92eedb881c5ca5ca99d8c61baa0", + Amount: "100000000000000", + }, + { + Address: "98504ce8ea23a9d38d7785c4b9301b5afe50ecdd", + Amount: "100000000000000", + }, + { + Address: "9860440db2910abdc6e66cb518b0b74555dd3539", + Amount: "100000000000000", + }, + { + Address: "98704f188f7c760c770eb1d70c02c3359ebea0d8", + Amount: "100000000000000", + }, + { + Address: "988044c4f6178a2b15ba22ce33ee4237b35b2d60", + Amount: "100000000000000", + }, + { + Address: "989044cff1ca7843552d2fcb8e541d5d2758f0ea", + Amount: "100000000000000", + }, + { + Address: "99004fc2c160910cb7fbd45c12ee54d986550b2a", + Amount: "100000000000000", + }, + { + Address: "991048998cc29362fb3b02f7d1a841267d025923", + Amount: "100000000000000", + }, + { + Address: "9920407f43c58aaa2458d7b091db49952103078f", + Amount: "100000000000000", + }, + { + Address: "9930413e8582369bc426882f61035e35d3ca69be", + Amount: "100000000000000", + }, + { + Address: "9940420c941d4fd60b0e3a23b52ca286dc6419e4", + Amount: "100000000000000", + }, + { + Address: "99504389bd1994b88e183d558eb7eb99b949b3d3", + Amount: "100000000000000", + }, + { + Address: "99604af6e8ab294dc5b37cc6fb271b723d14d366", + Amount: "100000000000000", + }, + { + Address: "997045e7f9933b1a86d152b772d2088ef862b877", + Amount: "100000000000000", + }, + { + Address: "998040588ade5ee3d6cd2cce7467ae10cbe39898", + Amount: "100000000000000", + }, + { + Address: "99904de562388ac3ff20f477b2efe679d2ae82d0", + Amount: "100000000000000", + }, }, Applications: []*types.Actor{ { diff --git a/runtime/modules_registry.go b/runtime/modules_registry.go new file mode 100644 index 000000000..85b9c2c75 --- /dev/null +++ b/runtime/modules_registry.go @@ -0,0 +1,35 @@ +package runtime + +import ( + "sync" + + "github.com/pokt-network/pocket/shared/modules" +) + +var _ modules.ModulesRegistry = &modulesRegistry{} + +type modulesRegistry struct { + m sync.Mutex + registry map[string]modules.Module +} + +func NewModulesRegistry() *modulesRegistry { + return &modulesRegistry{ + registry: make(map[string]modules.Module), + } +} + +func (m *modulesRegistry) RegisterModule(module modules.Module) { + m.m.Lock() + defer m.m.Unlock() + m.registry[module.GetModuleName()] = module +} + +func (m *modulesRegistry) GetModule(moduleName string) (modules.Module, error) { + m.m.Lock() + defer m.m.Unlock() + if mod, ok := m.registry[moduleName]; ok { + return mod, nil + } + return nil, ErrModuleNotRegistered(moduleName) +} diff --git a/shared/CHANGELOG.md b/shared/CHANGELOG.md index 35c3b664f..ffbbd7e69 100644 --- a/shared/CHANGELOG.md +++ b/shared/CHANGELOG.md @@ -7,7 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.0.0.26] - 2023-02-16 +## [0.0.0.27] - 2023-02-16 + +- Added `UnmarshalText` to `Ed25519PrivateKey` +- Added events `ConsensusNewHeightEvent` and `StateMachineTransitionEvent` +- Introduced `BaseInterruptableModule` and `IntegratableModule` to reduce repetition and boilerpate code (DRYness) +- Added `ModulesRegistry` and `StateMachineModule` accessors and interfaces +- Introduced generic `ModuleOption` pattern to fine tune modules behaviour +- Added `StateMachine` to the `node` initialization + +## [0.0.0.26] - 2023-02-15 - Added `FetchValidatorPrivateKeys` function since it is going to be used by the `debug-client` and also by the upcoming `cluster-manager` [#490](https://github.com/pokt-network/pocket/issues/490) diff --git a/shared/README.md b/shared/README.md index 58938f471..992ed5e50 100644 --- a/shared/README.md +++ b/shared/README.md @@ -18,11 +18,12 @@ ## Code Structure ```bash -shared # [to-be-refactored] All of this is bound to change -├── codec # App wide encoding (currently protobuf) -├── config # Utilities to load and verify Node configurations -├── crypto # Shared crypto utilities specific to Pocket -├── modules # Interfaces to the core Pocket modules +shared # [to-be-refactored] All of this is bound to change +├── codec # App wide encoding (currently protobuf) +├── config # Utilities to load and verify Node configurations +├── crypto # Shared crypto utilities specific to Pocket +├── modules # Interfaces to the core Pocket modules +| ├── base_modules # Base modules that are meant to be embed into the module structs in order to reduce boilerplate code | ├── module.go | ├── bus_module.go | ├── consensus_module.go @@ -30,10 +31,10 @@ shared # [to-be-refactored] All of this is bound to change | ├── utility_module.go | ├── persistence_module.go | ├── telemetry_module.go -| ├── types.go # Shared interfaces -├── tests # Cross-module and shared testing_artifacts (to be refactored to make testing more modular) -├── node.go # The main entrypoint to the Pocket Node -├── bus.go # Implementation of the Bus module +| ├── types.go # Shared interfaces +├── tests # Cross-module and shared testing_artifacts (to be refactored to make testing more modular) +├── node.go # The main entrypoint to the Pocket Node +├── bus.go # Implementation of the Bus module ``` ## High Level Architecture diff --git a/shared/core/types/events.go b/shared/core/types/events.go new file mode 100644 index 000000000..9321f1eb8 --- /dev/null +++ b/shared/core/types/events.go @@ -0,0 +1,13 @@ +package types + +type StateMachineEvent string + +const ( + StateMachineEvent_Start StateMachineEvent = "Start" + + StateMachineEvent_P2P_IsBootstrapped StateMachineEvent = "P2P_IsBootstrapped" + + StateMachineEvent_Consensus_IsUnsynched StateMachineEvent = "Consensus_IsUnsynched" + StateMachineEvent_Consensus_IsSyncing StateMachineEvent = "Consensus_IsSyncing" + StateMachineEvent_Consensus_IsCaughtUp StateMachineEvent = "Consensus_IsCaughtUp" +) diff --git a/shared/core/types/states.go b/shared/core/types/states.go new file mode 100644 index 000000000..adc8be077 --- /dev/null +++ b/shared/core/types/states.go @@ -0,0 +1,14 @@ +package types + +type StateMachineState string + +const ( + StateMachineState_Stopped StateMachineState = "Stopped" + + StateMachineState_P2P_Bootstrapping StateMachineState = "P2P_Bootstrapping" + StateMachineState_P2P_Bootstrapped StateMachineState = "P2P_Bootstrapped" + + StateMachineState_Consensus_Unsynched StateMachineState = "Consensus_Unsynched" + StateMachineState_Consensus_SyncMode StateMachineState = "Consensus_SyncMode" + StateMachineState_Consensus_Synced StateMachineState = "Consensus_Synced" +) diff --git a/shared/crypto/ed25519.go b/shared/crypto/ed25519.go index fed0f5925..9d1cd66a0 100644 --- a/shared/crypto/ed25519.go +++ b/shared/crypto/ed25519.go @@ -119,6 +119,11 @@ func (priv *Ed25519PrivateKey) UnmarshalJSON(data []byte) error { if err != nil { return err } + return priv.UnmarshalText([]byte(privateKey)) +} + +func (priv *Ed25519PrivateKey) UnmarshalText(data []byte) error { + privateKey := string(data) keyBytes, err := hex.DecodeString(privateKey) if err != nil { return err diff --git a/shared/messaging/events.go b/shared/messaging/events.go index 1ccfdf0c0..ecaf6c0d1 100644 --- a/shared/messaging/events.go +++ b/shared/messaging/events.go @@ -1,5 +1,7 @@ package messaging const ( - NodeStartedEventType = "pocket.NodeStartedEvent" + NodeStartedEventType = "pocket.NodeStartedEvent" + ConsensusNewHeightEventType = "pocket.ConsensusNewHeightEvent" + StateMachineTransitionEventType = "pocket.StateMachineTransitionEvent" ) diff --git a/shared/messaging/proto/events.proto b/shared/messaging/proto/events.proto index 22356bcc7..13931be93 100644 --- a/shared/messaging/proto/events.proto +++ b/shared/messaging/proto/events.proto @@ -5,3 +5,13 @@ package pocket; option go_package = "github.com/pokt-network/pocket/shared/messaging"; message NodeStartedEvent {} + +message ConsensusNewHeightEvent { + uint64 height = 1; +} + +message StateMachineTransitionEvent { + string event = 1; + string previous_state = 2; + string new_state = 3; +} diff --git a/shared/modules/base_modules/integratable_module.go b/shared/modules/base_modules/integratable_module.go new file mode 100644 index 000000000..4b24254c4 --- /dev/null +++ b/shared/modules/base_modules/integratable_module.go @@ -0,0 +1,25 @@ +package base_modules + +import "github.com/pokt-network/pocket/shared/modules" + +var _ modules.IntegratableModule = &IntegratableModule{} + +// IntegratableModule is a base struct that is meant to be embedded in module structs that implement the interface `modules.IntegratableModule`. +// +// It provides the basic logic for the `SetBus` and `GetBus` methods and allows the implementer to reduce boilerplate code keeping the code +// DRY (Don't Repeat Yourself) while preserving the ability to override the methods if needed. +type IntegratableModule struct { + bus modules.Bus +} + +func NewIntegratableModule(bus modules.Bus) *IntegratableModule { + return &IntegratableModule{bus: bus} +} + +func (m *IntegratableModule) GetBus() modules.Bus { + return m.bus +} + +func (m *IntegratableModule) SetBus(bus modules.Bus) { + m.bus = bus +} diff --git a/shared/modules/base_modules/interruptable_module.go b/shared/modules/base_modules/interruptable_module.go new file mode 100644 index 000000000..9ad46f793 --- /dev/null +++ b/shared/modules/base_modules/interruptable_module.go @@ -0,0 +1,19 @@ +package base_modules + +import "github.com/pokt-network/pocket/shared/modules" + +var _ modules.InterruptableModule = &InterruptableModule{} + +// InterruptableModule is a noop implementation of the InterruptableModule interface. +// +// It is useful for modules that do not need any particular logic to be executed when started or stopped. +// In these situations, just embed this struct into the module struct. +type InterruptableModule struct{} + +func (*InterruptableModule) Start() error { + return nil +} + +func (*InterruptableModule) Stop() error { + return nil +} diff --git a/shared/modules/bus_module.go b/shared/modules/bus_module.go index d71e06e84..62f5f3b74 100644 --- a/shared/modules/bus_module.go +++ b/shared/modules/bus_module.go @@ -19,7 +19,9 @@ type Bus interface { GetBusEvent() *messaging.PocketEnvelope GetEventBus() EventsChannel - RegisterModule(module Module) error + // Dependency Injection / Service Discovery + GetModulesRegistry() ModulesRegistry + RegisterModule(module Module) // Pocket modules GetPersistenceModule() PersistenceModule @@ -29,6 +31,7 @@ type Bus interface { GetTelemetryModule() TelemetryModule GetLoggerModule() LoggerModule GetRPCModule() RPCModule + GetStateMachineModule() StateMachineModule // Runtime GetRuntimeMgr() RuntimeMgr diff --git a/shared/modules/doc/README.md b/shared/modules/doc/README.md index d7fdddea1..cec167a68 100644 --- a/shared/modules/doc/README.md +++ b/shared/modules/doc/README.md @@ -43,7 +43,10 @@ TODO(#235): Update once runtime configs are implemented #### Create the module -Module creation uses a typical constructor pattern signature `Create(bus modules.Bus) (modules.Module, error)` +Module creation uses a typical constructor pattern signature `Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error)` + +Where `options ...modules.ModuleOption` is an optional variadic argument that allows for the passing of options to the module. +This is useful to configure the module at creation time and it's usually used during prototyping and in "sub-modules" that don't have a specific configuration file and where adding it would add unnecessary complexity and overhead. If a module has a lot of `ModuleOption`s, at that point a configuration file might be advisable. Currently, module creation is not embedded or enforced in the interface to prevent the initializer from having to use clunky creation syntax -> `modPackage.new(module).Create(bus modules.Bus)` rather `modPackage.Create(bus modules.Bus)` diff --git a/shared/modules/module.go b/shared/modules/module.go index 7e9ef989e..c6cf64c0c 100644 --- a/shared/modules/module.go +++ b/shared/modules/module.go @@ -20,9 +20,10 @@ type InterruptableModule interface { Stop() error } +type ModuleOption func(InitializableModule) type InitializableModule interface { GetModuleName() string - Create(bus Bus) (Module, error) + Create(bus Bus, options ...ModuleOption) (Module, error) } type KeyholderModule interface { diff --git a/shared/modules/modules_registry_module.go b/shared/modules/modules_registry_module.go new file mode 100644 index 000000000..67f2ef340 --- /dev/null +++ b/shared/modules/modules_registry_module.go @@ -0,0 +1,10 @@ +package modules + +//go:generate mockgen -source=$GOFILE -destination=./mocks/modules_registry_mock.go -aux_files=github.com/pokt-network/pocket/shared/modules=module.go + +type ModulesRegistry interface { + // RegisterModule registers a Module with the ModuleRegistry + RegisterModule(module Module) + // GetModule returns a Module by name or nil if not found in the ModuleRegistry + GetModule(moduleName string) (Module, error) +} diff --git a/shared/modules/p2p_module.go b/shared/modules/p2p_module.go index aea86dc2d..93ea6e63c 100644 --- a/shared/modules/p2p_module.go +++ b/shared/modules/p2p_module.go @@ -21,6 +21,9 @@ type P2PModule interface { // A direct asynchronous Send(addr cryptoPocket.Address, msg *anypb.Any) error + // HandleEvent is used to react to events that occur inside the application + HandleEvent(*anypb.Any) error + // CONSIDERATION: The P2P module currently does implement a synchronous "request-response" pattern // for core business logic between nodes. Rather, all communication is done // asynchronously via a "fire-and-forget" pattern using `Send` and `Broadcast`. diff --git a/shared/modules/state_machine_module.go b/shared/modules/state_machine_module.go new file mode 100644 index 000000000..5e7de8fc6 --- /dev/null +++ b/shared/modules/state_machine_module.go @@ -0,0 +1,15 @@ +package modules + +//go:generate mockgen -source=$GOFILE -destination=./mocks/state_machine_module_mock.go -aux_files=github.com/pokt-network/pocket/shared/modules=module.go + +import ( + coreTypes "github.com/pokt-network/pocket/shared/core/types" +) + +const StateMachineModuleName = "state_machine" + +type StateMachineModule interface { + Module + + SendEvent(event coreTypes.StateMachineEvent, args ...any) error +} diff --git a/shared/node.go b/shared/node.go index 4af232ea9..971a6ecf0 100644 --- a/shared/node.go +++ b/shared/node.go @@ -6,9 +6,11 @@ import ( "github.com/pokt-network/pocket/p2p" "github.com/pokt-network/pocket/persistence" "github.com/pokt-network/pocket/rpc" + coreTypes "github.com/pokt-network/pocket/shared/core/types" cryptoPocket "github.com/pokt-network/pocket/shared/crypto" "github.com/pokt-network/pocket/shared/messaging" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/state_machine" "github.com/pokt-network/pocket/telemetry" "github.com/pokt-network/pocket/utility" ) @@ -26,12 +28,13 @@ func NewNodeWithP2PAddress(address cryptoPocket.Address) *Node { return &Node{p2pAddress: address} } -func CreateNode(bus modules.Bus) (modules.Module, error) { - return new(Node).Create(bus) +func CreateNode(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(Node).Create(bus, options...) } -func (m *Node) Create(bus modules.Bus) (modules.Module, error) { - for _, mod := range []func(modules.Bus) (modules.Module, error){ +func (m *Node) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + for _, mod := range []func(modules.Bus, ...modules.ModuleOption) (modules.Module, error){ + state_machine.Create, persistence.Create, utility.Create, consensus.Create, @@ -61,6 +64,10 @@ func (node *Node) Start() error { // IMPORTANT: Order of module startup here matters + if err := node.GetBus().GetStateMachineModule().Start(); err != nil { + return err + } + if err := node.GetBus().GetTelemetryModule().Start(); err != nil { return err } @@ -124,6 +131,9 @@ func (node *Node) handleEvent(message *messaging.PocketEnvelope) error { switch contentType { case messaging.NodeStartedEventType: logger.Global.Info().Msg("Received NodeStartedEvent") + if err := node.GetBus().GetStateMachineModule().SendEvent(coreTypes.StateMachineEvent_Start); err != nil { + return err + } case consensus.HotstuffMessageContentType: return node.GetBus().GetConsensusModule().HandleMessage(message.Content) case consensus.StateSyncMessageContentType: @@ -132,6 +142,8 @@ func (node *Node) handleEvent(message *messaging.PocketEnvelope) error { return node.GetBus().GetUtilityModule().HandleMessage(message.Content) case messaging.DebugMessageEventType: return node.handleDebugMessage(message) + case messaging.ConsensusNewHeightEventType, messaging.StateMachineTransitionEventType: + return node.GetBus().GetP2PModule().HandleEvent(message.Content) default: logger.Global.Warn().Msgf("Unsupported message content type: %s", contentType) } diff --git a/state_machine/docs/CHANGELOG.md b/state_machine/docs/CHANGELOG.md new file mode 100644 index 000000000..efab941aa --- /dev/null +++ b/state_machine/docs/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +All notable changes to this module will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.0.0.1] - 2023-02-10 + +- Introduced this `CHANGELOG.md` and `README.md` +- Added `StateMachineModule` implementation with a POC of the finite state machine that will be used to manage the node lifecycle +- Added `StateMachine` diagram generator (linked in README.md) +- Integrated the `StateMachine` with the `bus` to propagate `StateMachineTransitionEvent` events whenever they occur + + diff --git a/state_machine/docs/README.md b/state_machine/docs/README.md new file mode 100644 index 000000000..5a2239b03 --- /dev/null +++ b/state_machine/docs/README.md @@ -0,0 +1,64 @@ +# State Machine Module + +> ⚠️ Work in progress ⚠️ - At the time of writing this document, the architecture is still being defined. +> +> This is pretty much a POC at the moment. + +This document outlines the purpose of this module, its components and how they all interact with the other modules. + +## Contents +- [Overview](#overview) +- [Code Structure](#code-structure) +- [High Level Architecture](#high-level-architecture) + - [FSM primer](#fsm-primer) +- [Current State Machine Definition](#current-state-machine-definition) + +## Overview + +The `StateMachine` module implements a FSM (Finite State Machine) that is responsible for managing the node lifecycle since its internal behaviour can be different depending on certain conditions that are used to determine the current state. + +In a nutshell: The FSM guarantees that the node is always in one specific state and verifies state transition (i.e. edges) to/from valid states (i.e. vertices). + +## Code Structure + +```bash +├── docs +│ ├── CHANGELOG.md # Changelog +│ ├── README.md # You are here +│ └── state-machine.diagram.md # State machine diagram (generated by visualizer/main.go) +├── fsm.go # Finite State Machine definition (events, states, transitions) +├── module.go # Implementation of the StateMachine module +└── visualizer + └── main.go # State machine diagram generator +``` + +## High Level Architecture + +High-level implementation details: + +- The [github.com/looplab/fsm](https://github.com/looplab/fsm) library is used to implement the FSM +- Pocket builds a wrapper around `looplab/fsm` to integrate with the other modules +- The `StateMachineModule` can be accessed via the `bus` from any other `IntegratableModule` +- State machine transitions emit `StateMachineTransitionEvent` events that subscribed pocket modules can listen to +- The `node` has a central [event handler](../../shared/node.go) for events that fan-out event handling to the relevant modules during state transitions + +### FSM primer + +The FSM has a declarative definition of an initial state and a set of transitions that have an `Event`, `Source` states and a single `Destination` state. + +These are the main building blocks: + +- **Event**: An event is a string that represents an action that can trigger a transition. For example, the event `start` can be used to trigger a transition from the `stopped` state to the `starting` state. +- **State**: A state is a string that represents a state that the FSM can be in. For example, the state `stopped` can be used to represent a state where the node is not running. +- **Callback**: A callback is a function that is called when a transition occurs. For example, a callback can be used to log the transition or to perform some other action. (there are various types of callbacks that essentially drive the WHEN they are called and help building more complex behaviours like transition cancelling, etc. but we won't cover them here, please read the FSM library documentation for more details) + +## Current State Machine Definition + +A diagram of the current state machine definition can be found [here](state-machine.diagram.md) +If you make any changes to it, you can re-generate it via: + +```bash +make generate_node_state_machine_diagram +``` + + diff --git a/state_machine/docs/state-machine.diagram.md b/state_machine/docs/state-machine.diagram.md new file mode 100644 index 000000000..651f4b20b --- /dev/null +++ b/state_machine/docs/state-machine.diagram.md @@ -0,0 +1,14 @@ +# Node Finite State Machine + +The following diagram displays the various states and events that govern the functionality of the node. + +```mermaid +stateDiagram-v2 + [*] --> Stopped + Consensus_SyncMode --> Consensus_Synced: Consensus_IsCaughtUp + Consensus_Unsynched --> Consensus_SyncMode: Consensus_IsSyncing + P2P_Bootstrapped --> Consensus_Synced: Consensus_IsCaughtUp + P2P_Bootstrapped --> Consensus_Unsynched: Consensus_IsUnsynched + P2P_Bootstrapping --> P2P_Bootstrapped: P2P_IsBootstrapped + Stopped --> P2P_Bootstrapping: Start +``` \ No newline at end of file diff --git a/state_machine/fsm.go b/state_machine/fsm.go new file mode 100644 index 000000000..df6051eb4 --- /dev/null +++ b/state_machine/fsm.go @@ -0,0 +1,67 @@ +package state_machine + +import ( + "github.com/looplab/fsm" + + coreTypes "github.com/pokt-network/pocket/shared/core/types" +) + +// NewNodeFSM returns a KISS Finite State Machine that is meant to mimick the various "states" of the node. +// +// The current set of states and events captures a limited subset of state sync and P2P bootstrapping-related events. +// More states & events in any of the modules supported should be added and documented here. +func NewNodeFSM(callbacks *fsm.Callbacks, options ...func(*fsm.FSM)) *fsm.FSM { + var cb = fsm.Callbacks{} + if callbacks != nil { + cb = *callbacks + } + + stateMachine := fsm.NewFSM( + string(coreTypes.StateMachineState_Stopped), + fsm.Events{ + { + Name: string(coreTypes.StateMachineEvent_Start), + Src: []string{ + string(coreTypes.StateMachineState_Stopped), + }, + Dst: string(coreTypes.StateMachineState_P2P_Bootstrapping), + }, + { + Name: string(coreTypes.StateMachineEvent_P2P_IsBootstrapped), + Src: []string{ + string(coreTypes.StateMachineState_P2P_Bootstrapping), + }, + Dst: string(coreTypes.StateMachineState_P2P_Bootstrapped), + }, + { + Name: string(coreTypes.StateMachineEvent_Consensus_IsUnsynched), + Src: []string{ + string(coreTypes.StateMachineState_P2P_Bootstrapped), + }, + Dst: string(coreTypes.StateMachineState_Consensus_Unsynched), + }, + { + Name: string(coreTypes.StateMachineEvent_Consensus_IsSyncing), + Src: []string{ + string(coreTypes.StateMachineState_Consensus_Unsynched), + }, + Dst: string(coreTypes.StateMachineState_Consensus_SyncMode), + }, + { + Name: string(coreTypes.StateMachineEvent_Consensus_IsCaughtUp), + Src: []string{ + string(coreTypes.StateMachineState_P2P_Bootstrapped), + string(coreTypes.StateMachineState_Consensus_SyncMode), + }, + Dst: string(coreTypes.StateMachineState_Consensus_Synced), + }, + }, + cb, + ) + + for _, option := range options { + option(stateMachine) + } + + return stateMachine +} diff --git a/state_machine/module.go b/state_machine/module.go new file mode 100644 index 000000000..d8410b3f0 --- /dev/null +++ b/state_machine/module.go @@ -0,0 +1,78 @@ +package state_machine + +import ( + "context" + + "github.com/looplab/fsm" + "github.com/pokt-network/pocket/logger" + coreTypes "github.com/pokt-network/pocket/shared/core/types" + "github.com/pokt-network/pocket/shared/messaging" + "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" +) + +var _ modules.StateMachineModule = &stateMachineModule{} + +type stateMachineModule struct { + base_modules.IntegratableModule + base_modules.InterruptableModule + + *fsm.FSM + logger modules.Logger +} + +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(stateMachineModule).Create(bus, options...) +} + +func (*stateMachineModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + m := &stateMachineModule{ + logger: logger.Global.CreateLoggerForModule(modules.StateMachineModuleName), + } + + m.FSM = NewNodeFSM(&fsm.Callbacks{ + "enter_state": func(_ context.Context, e *fsm.Event) { + m.logger.Info(). + Str("event", e.Event). + Str("sourceState", e.Src). + Msgf("entering state %s", e.Dst) + + newStateMachineTransitionEvent, err := messaging.PackMessage(&messaging.StateMachineTransitionEvent{ + Event: e.Event, + PreviousState: e.Src, + NewState: e.Dst, + }) + if err != nil { + m.logger.Fatal().Err(err).Msg("failed to pack state machine transition event") + } + + bus.PublishEventToBus(newStateMachineTransitionEvent) + }, + }) + + for _, option := range options { + option(m) + } + + bus.RegisterModule(m) + + return m, nil +} + +func (m *stateMachineModule) GetModuleName() string { + return modules.StateMachineModuleName +} + +func (m *stateMachineModule) SendEvent(event coreTypes.StateMachineEvent, args ...any) error { + return m.Event(context.TODO(), string(event), args) +} + +// options + +func WithCustomStateMachine(stateMachine *fsm.FSM) modules.ModuleOption { + return func(m modules.InitializableModule) { + if m, ok := m.(*stateMachineModule); ok { + m.FSM = stateMachine + } + } +} diff --git a/state_machine/visualizer/main.go b/state_machine/visualizer/main.go new file mode 100644 index 000000000..78824db40 --- /dev/null +++ b/state_machine/visualizer/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "os" + + "github.com/looplab/fsm" + "github.com/pokt-network/pocket/state_machine" +) + +func main() { + stateMachine := state_machine.NewNodeFSM(nil) + + mermaidStateDiagram, err := fsm.VisualizeForMermaidWithGraphType(stateMachine, fsm.StateDiagram) + if err != nil { + panic(err) + } + + header := "# Node Finite State Machine\n\nThe following diagram displays the various states and events that govern the functionality of the node.\n\n```mermaid\n" + footer := "```" + if err := os.WriteFile("state_machine/docs/state-machine.diagram.md", []byte(header+mermaidStateDiagram+footer), 0o600); err != nil { + panic(err) + } +} diff --git a/telemetry/CHANGELOG.md b/telemetry/CHANGELOG.md index 6b4dfe9b2..197e07dcc 100644 --- a/telemetry/CHANGELOG.md +++ b/telemetry/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.8] - 2023-02-10 + +- Modules embed `base_modules.IntegratableModule` and `base_modules.InterruptableModule` for DRYness + ## [0.0.0.7] - 2023-02-07 - Added GITHUB_WIKI tags where it was missing diff --git a/telemetry/module.go b/telemetry/module.go index 6904ed40e..ba4f4f2aa 100644 --- a/telemetry/module.go +++ b/telemetry/module.go @@ -2,6 +2,7 @@ package telemetry import ( "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" ) var ( @@ -12,14 +13,17 @@ var ( } ) -type telemetryModule struct{} +type telemetryModule struct { + base_modules.IntegratableModule + base_modules.InterruptableModule +} -func Create(bus modules.Bus) (modules.Module, error) { - return new(telemetryModule).Create(bus) +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(telemetryModule).Create(bus, options...) } // TODO(pocket/issues/99): Add a switch statement and configuration variable when support for other telemetry modules is added. -func (*telemetryModule) Create(bus modules.Bus) (modules.Module, error) { +func (*telemetryModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { runtimeMgr := bus.GetRuntimeMgr() cfg := runtimeMgr.GetConfig() @@ -32,8 +36,4 @@ func (*telemetryModule) Create(bus modules.Bus) (modules.Module, error) { } } -func (t *telemetryModule) GetModuleName() string { return modules.TelemetryModuleName } -func (t *telemetryModule) SetBus(bus modules.Bus) {} -func (t *telemetryModule) GetBus() modules.Bus { return nil } -func (t *telemetryModule) Start() error { return nil } -func (t *telemetryModule) Stop() error { return nil } +func (t *telemetryModule) GetModuleName() string { return modules.TelemetryModuleName } diff --git a/telemetry/noop_module.go b/telemetry/noop_module.go index 6a1316935..e2fd75184 100644 --- a/telemetry/noop_module.go +++ b/telemetry/noop_module.go @@ -22,16 +22,18 @@ func NOOP(args ...any) { logger.Global.Debug().Msg("NOOP") } -func CreateNoopTelemetryModule(bus modules.Bus) (modules.Module, error) { - var m NoopTelemetryModule - return m.Create(bus) +func CreateNoopTelemetryModule(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(NoopTelemetryModule).Create(bus, options...) } -func (*NoopTelemetryModule) Create(bus modules.Bus) (modules.Module, error) { +func (*NoopTelemetryModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { m := &NoopTelemetryModule{} - if err := bus.RegisterModule(m); err != nil { - return nil, err + + for _, option := range options { + option(m) } + + bus.RegisterModule(m) return m, nil } diff --git a/telemetry/prometheus_module.go b/telemetry/prometheus_module.go index 1dd0191df..08dc017ae 100644 --- a/telemetry/prometheus_module.go +++ b/telemetry/prometheus_module.go @@ -8,6 +8,7 @@ import ( "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/runtime/configs" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -23,7 +24,9 @@ var ( // DISCUSS(team): Should the warning logs in this module be handled differently? type PrometheusTelemetryModule struct { - bus modules.Bus + base_modules.IntegratableModule + base_modules.InterruptableModule + config *configs.TelemetryConfig logger modules.Logger @@ -33,17 +36,19 @@ type PrometheusTelemetryModule struct { gaugeVectors map[string]prometheus.GaugeVec } -func CreatePrometheusTelemetryModule(bus modules.Bus) (modules.Module, error) { - var m PrometheusTelemetryModule - return m.Create(bus) +func CreatePrometheusTelemetryModule(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(PrometheusTelemetryModule).Create(bus, options...) } -func (*PrometheusTelemetryModule) Create(bus modules.Bus) (modules.Module, error) { +func (*PrometheusTelemetryModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { m := &PrometheusTelemetryModule{} - if err := bus.RegisterModule(m); err != nil { - return nil, err + + for _, option := range options { + option(m) } + bus.RegisterModule(m) + runtimeMgr := bus.GetRuntimeMgr() cfg := runtimeMgr.GetConfig() telemetryCfg := cfg.Telemetry @@ -79,25 +84,10 @@ func (m *PrometheusTelemetryModule) Start() error { return nil } -func (m *PrometheusTelemetryModule) Stop() error { - return nil -} - -func (m *PrometheusTelemetryModule) SetBus(bus modules.Bus) { - m.bus = bus -} - func (m *PrometheusTelemetryModule) GetModuleName() string { return fmt.Sprintf("%s_prometheus", modules.TelemetryModuleName) } -func (m *PrometheusTelemetryModule) GetBus() modules.Bus { - if m.bus == nil { - m.logger.Fatal().Msg("PocketBus is not initialized") - } - return m.bus -} - // EventMetricsAgent interface implementation func (m *PrometheusTelemetryModule) GetEventMetricsAgent() modules.EventMetricsAgent { return modules.EventMetricsAgent(m) diff --git a/utility/block.go b/utility/block.go index c3d94cbaf..f5ff620af 100644 --- a/utility/block.go +++ b/utility/block.go @@ -57,6 +57,7 @@ func (u *utilityContext) CreateAndApplyProposalBlock(proposer []byte, maxTransac } txResult, err := u.applyTx(txIndex, tx) if err != nil { + u.logger.Err(err).Msg("Error in ApplyTransaction") // TODO(#327): Properly implement 'unhappy path' for save points if err := u.revertLastSavePoint(); err != nil { return "", nil, err diff --git a/utility/doc/CHANGELOG.md b/utility/doc/CHANGELOG.md index 036ea583e..2269a5270 100644 --- a/utility/doc/CHANGELOG.md +++ b/utility/doc/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.0.28] - 2023-02-15 + +- Module embeds `base_modules.IntegratableModule` and `base_modules.InterruptableModule` for DRYness +- Logging error if `ApplyTransaction` fails (it was completely ignored before and it was really hard to understand what was going on) + ## [0.0.0.27] - 2023-02-14 - Added a `Validatable` type for basic validation diff --git a/utility/message_handler.go b/utility/message_handler.go index 88387c34c..93d43c870 100644 --- a/utility/message_handler.go +++ b/utility/message_handler.go @@ -3,7 +3,6 @@ package utility import ( "encoding/hex" "fmt" - "log" "math/big" "github.com/pokt-network/pocket/shared/codec" @@ -32,9 +31,7 @@ func (u *utilityModule) HandleMessage(message *anypb.Any) error { } else if err := u.CheckTransaction(txGossipMsg.Tx); err != nil { return err } - - log.Println("MEMPOOL: Successfully added a new message to the mempool!") - + u.logger.Info().Str("source", "MEMPOOL").Msg("Successfully added a new message to the mempool!") default: return types.ErrUnknownMessageType(message.MessageName()) } diff --git a/utility/module.go b/utility/module.go index 24c7d64d5..0bc28b1f5 100644 --- a/utility/module.go +++ b/utility/module.go @@ -5,6 +5,7 @@ import ( "github.com/pokt-network/pocket/runtime/configs" "github.com/pokt-network/pocket/shared/mempool" "github.com/pokt-network/pocket/shared/modules" + "github.com/pokt-network/pocket/shared/modules/base_modules" "github.com/pokt-network/pocket/utility/types" ) @@ -14,23 +15,28 @@ var ( ) type utilityModule struct { - bus modules.Bus + base_modules.IntegratableModule + base_modules.InterruptableModule + config *configs.UtilityConfig logger modules.Logger mempool mempool.TXMempool } -func Create(bus modules.Bus) (modules.Module, error) { - return new(utilityModule).Create(bus) +func Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { + return new(utilityModule).Create(bus, options...) } -func (*utilityModule) Create(bus modules.Bus) (modules.Module, error) { +func (*utilityModule) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) { m := &utilityModule{} - if err := bus.RegisterModule(m); err != nil { - return nil, err + + for _, option := range options { + option(m) } + bus.RegisterModule(m) + runtimeMgr := bus.GetRuntimeMgr() cfg := runtimeMgr.GetConfig() @@ -47,25 +53,10 @@ func (u *utilityModule) Start() error { return nil } -func (u *utilityModule) Stop() error { - return nil -} - func (u *utilityModule) GetModuleName() string { return modules.UtilityModuleName } -func (u *utilityModule) SetBus(bus modules.Bus) { - u.bus = bus -} - -func (u *utilityModule) GetBus() modules.Bus { - if u.bus == nil { - u.logger.Fatal().Msg("Bus is not initialized") - } - return u.bus -} - func (u *utilityModule) GetMempool() mempool.TXMempool { return u.mempool }