Add populate db script
This commit adds a populate db script, used by QA, but also very useful to test Login/Logout flows.
This commit is contained in:
parent
92404a5ab7
commit
188eabef0b
|
@ -0,0 +1,2 @@
|
|||
populate-db
|
||||
tmp/
|
|
@ -0,0 +1,40 @@
|
|||
### How to build
|
||||
|
||||
You must have go installed.
|
||||
Then you can run, from `cmd/populate-db`
|
||||
|
||||
```
|
||||
go build
|
||||
```
|
||||
|
||||
which should create a `populate-db` executable
|
||||
|
||||
### How to run
|
||||
```
|
||||
./populate-db --added-contacts 100 --contacts 200 --public-chats 100 --one-to-one-chats 40 --number-of-messages 2 --seed-phrase "your seed phrase"
|
||||
```
|
||||
|
||||
|
||||
The parameters are:
|
||||
|
||||
`added-contacts`: contacts you have added
|
||||
`contacts`: number of "contacts" in the database, these are not added by you
|
||||
`one-to-one-chats`: the number of one to one chats open
|
||||
`public-chats`: the number of public chats
|
||||
`number-of-messages`: the number of messages in each chat
|
||||
`seed-phrase`: the seed phrase of the account to be created
|
||||
|
||||
The db will be created in the `./tmp` directory
|
||||
|
||||
### How to import the db
|
||||
|
||||
1) Create an account in status-react
|
||||
2) Login, copy the seed phrase
|
||||
3) Create a db using this script using the seed phrase
|
||||
4) Copy the db to the import directory
|
||||
5) Import the database
|
||||
6) Login
|
||||
|
||||
|
||||
Note that the db is not complete, so the app might not be fully functioning, but it
|
||||
should be good enough to test performance and probably migrations
|
|
@ -0,0 +1,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// configFlags represents an array of JSON configuration files passed to a command line utility
|
||||
type configFlags []string
|
||||
|
||||
func (f *configFlags) String() string {
|
||||
return strings.Join(*f, ", ")
|
||||
}
|
||||
|
||||
func (f *configFlags) Set(value string) error {
|
||||
if !path.IsAbs(value) {
|
||||
// Convert to absolute path
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
value = path.Join(cwd, value)
|
||||
}
|
||||
|
||||
// Check that the file exists
|
||||
stat, err := os.Stat(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stat.IsDir() {
|
||||
return fmt.Errorf("path does not represent a file: %s", value)
|
||||
}
|
||||
*f = append(*f, value)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/status-im/status-go/params"
|
||||
)
|
||||
|
||||
// nolint: deadcode
|
||||
func TestStatusFlag(t *testing.T) {
|
||||
service := "status"
|
||||
|
||||
scenarios := []struct {
|
||||
ipcEnabled bool
|
||||
httpEnabled bool
|
||||
flag string
|
||||
err error
|
||||
enabled bool
|
||||
public bool
|
||||
}{
|
||||
// no flags
|
||||
{},
|
||||
// -status=ipc -ipc
|
||||
{
|
||||
ipcEnabled: true,
|
||||
flag: "ipc",
|
||||
enabled: true,
|
||||
},
|
||||
// -status=http -http
|
||||
{
|
||||
httpEnabled: true,
|
||||
flag: "http",
|
||||
enabled: true,
|
||||
public: true,
|
||||
},
|
||||
// -status=ipc -http -ipc
|
||||
{
|
||||
httpEnabled: true,
|
||||
ipcEnabled: true,
|
||||
flag: "ipc",
|
||||
enabled: true,
|
||||
},
|
||||
// -http -ipc
|
||||
{
|
||||
httpEnabled: true,
|
||||
ipcEnabled: true,
|
||||
flag: "",
|
||||
},
|
||||
// -status=ipc
|
||||
{
|
||||
err: errStatusServiceRequiresIPC,
|
||||
flag: "ipc",
|
||||
},
|
||||
// -status=http
|
||||
{
|
||||
err: errStatusServiceRequiresHTTP,
|
||||
flag: "http",
|
||||
},
|
||||
// -status=bad-value
|
||||
{
|
||||
err: errStatusServiceInvalidFlag,
|
||||
flag: "bad-value",
|
||||
},
|
||||
}
|
||||
|
||||
for i, s := range scenarios {
|
||||
msg := fmt.Sprintf("scenario %d", i)
|
||||
|
||||
c, err := params.NewNodeConfig("", 0)
|
||||
require.Nil(t, err, msg)
|
||||
|
||||
c.IPCEnabled = s.ipcEnabled
|
||||
c.HTTPEnabled = s.httpEnabled
|
||||
|
||||
c, err = configureStatusService(s.flag, c)
|
||||
|
||||
if s.err != nil {
|
||||
require.Equal(t, s.err, err, msg)
|
||||
require.Nil(t, c, msg)
|
||||
continue
|
||||
}
|
||||
|
||||
require.Nil(t, err, msg)
|
||||
require.Equal(t, s.enabled, c.EnableStatusService, msg)
|
||||
|
||||
modules := c.FormatAPIModules()
|
||||
if s.public {
|
||||
require.Contains(t, modules, service, msg)
|
||||
} else {
|
||||
require.NotContains(t, modules, service, msg)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,524 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
stdlog "log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"github.com/status-im/status-go/account/generator"
|
||||
"github.com/status-im/status-go/api"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/multiaccounts"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
//"github.com/status-im/status-go/appdatabase"
|
||||
//gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/logutils"
|
||||
"github.com/status-im/status-go/params"
|
||||
"github.com/status-im/status-go/protocol"
|
||||
"github.com/status-im/status-go/protocol/common"
|
||||
"github.com/status-im/status-go/protocol/identity/alias"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
wakuextn "github.com/status-im/status-go/services/wakuext"
|
||||
)
|
||||
|
||||
type testTimeSource struct{}
|
||||
|
||||
func (t *testTimeSource) GetCurrentTime() uint64 {
|
||||
return uint64(time.Now().Unix())
|
||||
}
|
||||
|
||||
const (
|
||||
serverClientName = "Statusd"
|
||||
)
|
||||
|
||||
var (
|
||||
configFiles configFlags
|
||||
logLevel = flag.String("log", "", `Log level, one of: "ERROR", "WARN", "INFO", "DEBUG", and "TRACE"`)
|
||||
logWithoutColors = flag.Bool("log-without-color", false, "Disables log colors")
|
||||
ipcEnabled = flag.Bool("ipc", false, "Enable IPC RPC endpoint")
|
||||
ipcFile = flag.String("ipcfile", "", "Set IPC file path")
|
||||
seedPhrase = flag.String("seed-phrase", "", "Seed phrase")
|
||||
pprofEnabled = flag.Bool("pprof", false, "Enable runtime profiling via pprof")
|
||||
pprofPort = flag.Int("pprof-port", 52525, "Port for runtime profiling via pprof")
|
||||
version = flag.Bool("version", false, "Print version and dump configuration")
|
||||
nAddedContacts = flag.Int("added-contacts", 100, "Number of added contacts to create")
|
||||
nContacts = flag.Int("contacts", 100, "Number of contacts to create")
|
||||
nPublicChats = flag.Int("public-chats", 5, "Number of public chats")
|
||||
nMessages = flag.Int("number-of-messages", 0, "Number of messages for each chat")
|
||||
nOneToOneChats = flag.Int("one-to-one-chats", 5, "Number of one to one chats")
|
||||
|
||||
dataDir = flag.String("dir", getDefaultDataDir(), "Directory used by node to store data")
|
||||
register = flag.Bool("register", false, "Register and make the node discoverable by other nodes")
|
||||
networkID = flag.Int(
|
||||
"network-id",
|
||||
params.RopstenNetworkID,
|
||||
fmt.Sprintf(
|
||||
"A network ID: %d (Mainnet), %d (Ropsten), %d (Rinkeby), %d (Goerli)",
|
||||
params.MainNetworkID, params.RopstenNetworkID, params.RinkebyNetworkID, params.GoerliNetworkID,
|
||||
),
|
||||
)
|
||||
listenAddr = flag.String("addr", "", "address to bind listener to")
|
||||
|
||||
syncAndExit = flag.Int("sync-and-exit", -1, "Timeout in minutes for blockchain sync and exit, zero means no timeout unless sync is finished")
|
||||
)
|
||||
|
||||
// All general log messages in this package should be routed through this logger.
|
||||
var logger = log.New("package", "status-go/cmd/statusd")
|
||||
|
||||
func init() {
|
||||
flag.Var(&configFiles, "c", "JSON configuration file(s). Multiple configuration files can be specified, and will be merged in occurrence order")
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
func main() {
|
||||
colors := terminal.IsTerminal(int(os.Stdin.Fd()))
|
||||
if err := logutils.OverrideRootLog(true, "ERROR", logutils.FileOptions{}, colors); err != nil {
|
||||
stdlog.Fatalf("Error initializing logger: %v", err)
|
||||
}
|
||||
|
||||
flag.Usage = printUsage
|
||||
flag.Parse()
|
||||
if flag.NArg() > 0 {
|
||||
printUsage()
|
||||
logger.Error("Extra args in command line: %v", flag.Args())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
opts := []params.Option{}
|
||||
|
||||
config, err := params.NewNodeConfigWithDefaultsAndFiles(
|
||||
*dataDir,
|
||||
uint64(*networkID),
|
||||
opts,
|
||||
configFiles,
|
||||
)
|
||||
if err != nil {
|
||||
printUsage()
|
||||
logger.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Use listenAddr if and only if explicitly provided in the arguments.
|
||||
// The default value is set in params.NewNodeConfigWithDefaultsAndFiles().
|
||||
if *listenAddr != "" {
|
||||
config.ListenAddr = *listenAddr
|
||||
}
|
||||
|
||||
// enable IPC RPC
|
||||
if *ipcEnabled {
|
||||
config.IPCEnabled = true
|
||||
config.IPCFile = *ipcFile
|
||||
}
|
||||
|
||||
// set up logging options
|
||||
setupLogging(config)
|
||||
|
||||
// We want statusd to be distinct from StatusIM client.
|
||||
config.Name = serverClientName
|
||||
|
||||
if *version {
|
||||
printVersion(config)
|
||||
return
|
||||
}
|
||||
|
||||
backend := api.NewGethStatusBackend()
|
||||
err = ImportAccount(*seedPhrase, backend)
|
||||
if err != nil {
|
||||
logger.Error("failed", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
wakuextservice, err := backend.WakuExtService()
|
||||
if err != nil {
|
||||
logger.Error("failed", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
wakuext := wakuextn.NewPublicAPI(wakuextservice)
|
||||
|
||||
// This will start the push notification server as well as
|
||||
// the config is set to Enabled
|
||||
_, err = wakuext.StartMessenger()
|
||||
if err != nil {
|
||||
logger.Error("failed to start messenger", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("Creating added contacts")
|
||||
|
||||
for i := 0; i < *nAddedContacts; i++ {
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
logger.Error("failed", err)
|
||||
return
|
||||
}
|
||||
|
||||
keyString := common.PubkeyToHex(&key.PublicKey)
|
||||
_, err = wakuext.AddContact(context.Background(), keyString)
|
||||
if err != nil {
|
||||
logger.Error("failed", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("Creating contacts")
|
||||
|
||||
for i := 0; i < *nContacts; i++ {
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
contact, err := protocol.BuildContactFromPublicKey(&key.PublicKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = wakuext.SaveContact(context.Background(), contact)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("Creating public chats")
|
||||
|
||||
for i := 0; i < *nPublicChats; i++ {
|
||||
chat := protocol.CreatePublicChat(randomString(10), &testTimeSource{})
|
||||
chat.SyncedTo = 0
|
||||
chat.SyncedFrom = 0
|
||||
|
||||
err = wakuext.SaveChat(context.Background(), chat)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var messages []*common.Message
|
||||
|
||||
for i := 0; i < *nMessages; i++ {
|
||||
messages = append(messages, buildMessage(chat, i))
|
||||
|
||||
}
|
||||
|
||||
if len(messages) > 0 {
|
||||
if err := wakuext.SaveMessages(context.Background(), messages); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.Info("Creating one to one chats")
|
||||
|
||||
for i := 0; i < *nOneToOneChats; i++ {
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
keyString := common.PubkeyToHex(&key.PublicKey)
|
||||
chat := protocol.CreateOneToOneChat(keyString, &key.PublicKey, &testTimeSource{})
|
||||
chat.SyncedTo = 0
|
||||
chat.SyncedFrom = 0
|
||||
err = wakuext.SaveChat(context.Background(), chat)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var messages []*common.Message
|
||||
|
||||
for i := 0; i < *nMessages; i++ {
|
||||
messages = append(messages, buildMessage(chat, i))
|
||||
|
||||
}
|
||||
|
||||
if len(messages) > 0 {
|
||||
if err := wakuext.SaveMessages(context.Background(), messages); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getDefaultDataDir() string {
|
||||
if home := os.Getenv("HOME"); home != "" {
|
||||
return filepath.Join(home, ".statusd")
|
||||
}
|
||||
return "./statusd-data"
|
||||
}
|
||||
|
||||
func setupLogging(config *params.NodeConfig) {
|
||||
if *logLevel != "" {
|
||||
config.LogLevel = *logLevel
|
||||
}
|
||||
|
||||
colors := !(*logWithoutColors) && terminal.IsTerminal(int(os.Stdin.Fd()))
|
||||
if err := logutils.OverrideRootLogWithConfig(config, colors); err != nil {
|
||||
stdlog.Fatalf("Error initializing logger: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
errStatusServiceRequiresIPC = errors.New("to enable the StatusService on IPC, -ipc flag must be set")
|
||||
errStatusServiceRequiresHTTP = errors.New("to enable the StatusService on HTTP, -http flag must be set")
|
||||
errStatusServiceInvalidFlag = errors.New("-status flag valid values are: ipc, http")
|
||||
)
|
||||
|
||||
// printVersion prints verbose output about version and config.
|
||||
func printVersion(config *params.NodeConfig) {
|
||||
fmt.Println(strings.Title(config.Name))
|
||||
fmt.Println("Version:", config.Version)
|
||||
fmt.Println("Network ID:", config.NetworkID)
|
||||
fmt.Println("Go Version:", runtime.Version())
|
||||
fmt.Println("OS:", runtime.GOOS)
|
||||
fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
|
||||
fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
|
||||
|
||||
fmt.Println("Loaded Config: ", config)
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
usage := `
|
||||
Usage: statusd [options]
|
||||
Examples:
|
||||
statusd # run regular Whisper node that joins Status network
|
||||
statusd -c ./default.json # run node with configuration specified in ./default.json file
|
||||
statusd -c ./default.json -c ./standalone.json # run node with configuration specified in ./default.json file, after merging ./standalone.json file
|
||||
statusd -c ./default.json -metrics # run node with configuration specified in ./default.json file, and expose ethereum metrics with debug_metrics jsonrpc call
|
||||
|
||||
Options:
|
||||
`
|
||||
fmt.Fprint(os.Stderr, usage)
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
const pathWalletRoot = "m/44'/60'/0'/0"
|
||||
const pathEIP1581 = "m/43'/60'/1581'"
|
||||
const pathDefaultChat = pathEIP1581 + "/0'/0"
|
||||
const pathDefaultWallet = pathWalletRoot + "/0"
|
||||
|
||||
var paths = []string{pathWalletRoot, pathEIP1581, pathDefaultChat, pathDefaultWallet}
|
||||
|
||||
func defaultSettings(generatedAccountInfo generator.GeneratedAccountInfo, derivedAddresses map[string]generator.AccountInfo, mnemonic *string) (*accounts.Settings, error) {
|
||||
chatKeyString := derivedAddresses[pathDefaultChat].PublicKey
|
||||
|
||||
settings := &accounts.Settings{}
|
||||
settings.KeyUID = generatedAccountInfo.KeyUID
|
||||
settings.Address = types.HexToAddress(generatedAccountInfo.Address)
|
||||
settings.WalletRootAddress = types.HexToAddress(derivedAddresses[pathWalletRoot].Address)
|
||||
|
||||
// Set chat key & name
|
||||
name, err := alias.GenerateFromPublicKeyString(chatKeyString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
settings.Name = name
|
||||
settings.PublicKey = chatKeyString
|
||||
|
||||
settings.DappsAddress = types.HexToAddress(derivedAddresses[pathDefaultWallet].Address)
|
||||
settings.EIP1581Address = types.HexToAddress(derivedAddresses[pathEIP1581].Address)
|
||||
settings.Mnemonic = mnemonic
|
||||
|
||||
signingPhrase, err := buildSigningPhrase()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
settings.SigningPhrase = signingPhrase
|
||||
|
||||
settings.SendPushNotifications = true
|
||||
settings.InstallationID = uuid.New().String()
|
||||
settings.UseMailservers = true
|
||||
|
||||
settings.PreviewPrivacy = true
|
||||
settings.Currency = "usd"
|
||||
settings.ProfilePicturesVisibility = 1
|
||||
settings.LinkPreviewRequestEnabled = true
|
||||
|
||||
visibleTokens := make(map[string][]string)
|
||||
visibleTokens["mainnet"] = []string{"SNT"}
|
||||
visibleTokensJSON, err := json.Marshal(visibleTokens)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
visibleTokenJSONRaw := json.RawMessage(visibleTokensJSON)
|
||||
settings.WalletVisibleTokens = &visibleTokenJSONRaw
|
||||
|
||||
// TODO: fix this
|
||||
networks := make([]map[string]string, 0)
|
||||
networksJSON, err := json.Marshal(networks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
networkRawMessage := json.RawMessage(networksJSON)
|
||||
settings.Networks = &networkRawMessage
|
||||
settings.CurrentNetwork = "mainnet_rpc"
|
||||
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
func defaultNodeConfig(installationID string) (*params.NodeConfig, error) {
|
||||
// Set mainnet
|
||||
nodeConfig := ¶ms.NodeConfig{}
|
||||
nodeConfig.NetworkID = 1
|
||||
nodeConfig.LogLevel = "ERROR"
|
||||
nodeConfig.DataDir = "/ethereum/mainnet_rpc"
|
||||
nodeConfig.UpstreamConfig = params.UpstreamRPCConfig{
|
||||
Enabled: true,
|
||||
URL: "https://mainnet.infura.io/v3/800c641949d64d768a5070a1b0511938",
|
||||
}
|
||||
|
||||
nodeConfig.Name = "StatusIM"
|
||||
nodeConfig.Rendezvous = true
|
||||
clusterConfig, err := params.LoadClusterConfigFromFleet("eth.prod")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodeConfig.ClusterConfig = *clusterConfig
|
||||
|
||||
nodeConfig.WalletConfig = params.WalletConfig{Enabled: true}
|
||||
nodeConfig.LocalNotificationsConfig = params.LocalNotificationsConfig{Enabled: true}
|
||||
nodeConfig.BrowsersConfig = params.BrowsersConfig{Enabled: true}
|
||||
nodeConfig.PermissionsConfig = params.PermissionsConfig{Enabled: true}
|
||||
nodeConfig.MailserversConfig = params.MailserversConfig{Enabled: true}
|
||||
nodeConfig.EnableNTPSync = true
|
||||
nodeConfig.WakuConfig = params.WakuConfig{
|
||||
Enabled: true,
|
||||
LightClient: true,
|
||||
MinimumPoW: 0.000001,
|
||||
}
|
||||
|
||||
nodeConfig.ShhextConfig = params.ShhextConfig{
|
||||
BackupDisabledDataDir: "",
|
||||
InstallationID: installationID,
|
||||
MaxMessageDeliveryAttempts: 6,
|
||||
MailServerConfirmations: true,
|
||||
VerifyTransactionURL: "",
|
||||
VerifyENSURL: "",
|
||||
VerifyENSContractAddress: "",
|
||||
VerifyTransactionChainID: 1,
|
||||
DataSyncEnabled: true,
|
||||
PFSEnabled: true,
|
||||
}
|
||||
|
||||
// TODO: check topics
|
||||
|
||||
return nodeConfig, nil
|
||||
}
|
||||
|
||||
func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error {
|
||||
backend.UpdateRootDataDir("./tmp")
|
||||
manager := backend.AccountManager()
|
||||
manager.InitKeystore("./tmp")
|
||||
err := backend.OpenAccounts()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
generator := manager.AccountsGenerator()
|
||||
generatedAccountInfo, err := generator.ImportMnemonic(seedPhrase, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
derivedAddresses, err := generator.DeriveAddresses(generatedAccountInfo.ID, paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = generator.StoreDerivedAccounts(generatedAccountInfo.ID, "", paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
account := multiaccounts.Account{
|
||||
KeyUID: generatedAccountInfo.KeyUID,
|
||||
}
|
||||
settings, err := defaultSettings(generatedAccountInfo, derivedAddresses, &seedPhrase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeConfig, err := defaultNodeConfig(settings.InstallationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
walletDerivedAccount := derivedAddresses[pathDefaultWallet]
|
||||
walletAccount := accounts.Account{
|
||||
PublicKey: types.Hex2Bytes(walletDerivedAccount.PublicKey),
|
||||
Address: types.HexToAddress(walletDerivedAccount.Address),
|
||||
Color: "",
|
||||
Wallet: true,
|
||||
Path: pathDefaultWallet,
|
||||
Name: "Ethereum account",
|
||||
}
|
||||
|
||||
chatDerivedAccount := derivedAddresses[pathDefaultChat]
|
||||
chatAccount := accounts.Account{
|
||||
PublicKey: types.Hex2Bytes(chatDerivedAccount.PublicKey),
|
||||
Address: types.HexToAddress(chatDerivedAccount.Address),
|
||||
Name: settings.Name,
|
||||
Chat: true,
|
||||
Path: pathDefaultChat,
|
||||
}
|
||||
|
||||
accounts := []accounts.Account{walletAccount, chatAccount}
|
||||
return backend.StartNodeWithAccountAndConfig(account, "", *settings, nodeConfig, accounts)
|
||||
}
|
||||
|
||||
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
|
||||
func buildMessage(chat *protocol.Chat, count int) *common.Message {
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
logger.Error("failed", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
|
||||
message := &common.Message{}
|
||||
message.Text = fmt.Sprintf("test message %d", count)
|
||||
message.ChatId = chat.ID
|
||||
message.Clock = clock
|
||||
message.Timestamp = timestamp
|
||||
message.From = common.PubkeyToHex(&key.PublicKey)
|
||||
data := []byte(uuid.New().String())
|
||||
message.ID = types.HexBytes(crypto.Keccak256(data)).String()
|
||||
message.WhisperTimestamp = clock
|
||||
message.LocalChatID = chat.ID
|
||||
message.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
||||
switch chat.ChatType {
|
||||
case protocol.ChatTypePublic, protocol.ChatTypeProfile:
|
||||
message.MessageType = protobuf.MessageType_PUBLIC_GROUP
|
||||
case protocol.ChatTypeOneToOne:
|
||||
message.MessageType = protobuf.MessageType_ONE_TO_ONE
|
||||
case protocol.ChatTypePrivateGroupChat:
|
||||
message.MessageType = protobuf.MessageType_PRIVATE_GROUP
|
||||
}
|
||||
|
||||
message.PrepareContent("")
|
||||
return message
|
||||
}
|
||||
|
||||
func randomString(n int) string {
|
||||
b := make([]rune, n)
|
||||
for i := range b {
|
||||
b[i] = letterRunes[rand.Intn(len(letterRunes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
|
@ -0,0 +1,650 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func buildSigningPhrase() (string, error) {
|
||||
length := big.NewInt(int64(len(dictionary)))
|
||||
a, err := rand.Int(rand.Reader, length)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b, err := rand.Int(rand.Reader, length)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
c, err := rand.Int(rand.Reader, length)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dictionary[a.Int64()] + " " + dictionary[b.Int64()] + " " + dictionary[c.Int64()], nil
|
||||
|
||||
}
|
||||
|
||||
var dictionary = []string{
|
||||
"acid",
|
||||
"alto",
|
||||
"apse",
|
||||
"arch",
|
||||
"area",
|
||||
"army",
|
||||
"atom",
|
||||
"aunt",
|
||||
"babe",
|
||||
"baby",
|
||||
"back",
|
||||
"bail",
|
||||
"bait",
|
||||
"bake",
|
||||
"ball",
|
||||
"band",
|
||||
"bank",
|
||||
"barn",
|
||||
"base",
|
||||
"bass",
|
||||
"bath",
|
||||
"bead",
|
||||
"beak",
|
||||
"beam",
|
||||
"bean",
|
||||
"bear",
|
||||
"beat",
|
||||
"beef",
|
||||
"beer",
|
||||
"beet",
|
||||
"bell",
|
||||
"belt",
|
||||
"bend",
|
||||
"bike",
|
||||
"bill",
|
||||
"bird",
|
||||
"bite",
|
||||
"blow",
|
||||
"blue",
|
||||
"boar",
|
||||
"boat",
|
||||
"body",
|
||||
"bolt",
|
||||
"bomb",
|
||||
"bone",
|
||||
"book",
|
||||
"boot",
|
||||
"bore",
|
||||
"boss",
|
||||
"bowl",
|
||||
"brow",
|
||||
"bulb",
|
||||
"bull",
|
||||
"burn",
|
||||
"bush",
|
||||
"bust",
|
||||
"cafe",
|
||||
"cake",
|
||||
"calf",
|
||||
"call",
|
||||
"calm",
|
||||
"camp",
|
||||
"cane",
|
||||
"cape",
|
||||
"card",
|
||||
"care",
|
||||
"carp",
|
||||
"cart",
|
||||
"case",
|
||||
"cash",
|
||||
"cast",
|
||||
"cave",
|
||||
"cell",
|
||||
"cent",
|
||||
"chap",
|
||||
"chef",
|
||||
"chin",
|
||||
"chip",
|
||||
"chop",
|
||||
"chub",
|
||||
"chug",
|
||||
"city",
|
||||
"clam",
|
||||
"clef",
|
||||
"clip",
|
||||
"club",
|
||||
"clue",
|
||||
"coal",
|
||||
"coat",
|
||||
"code",
|
||||
"coil",
|
||||
"coin",
|
||||
"coke",
|
||||
"cold",
|
||||
"colt",
|
||||
"comb",
|
||||
"cone",
|
||||
"cook",
|
||||
"cope",
|
||||
"copy",
|
||||
"cord",
|
||||
"cork",
|
||||
"corn",
|
||||
"cost",
|
||||
"crab",
|
||||
"craw",
|
||||
"crew",
|
||||
"crib",
|
||||
"crop",
|
||||
"crow",
|
||||
"curl",
|
||||
"cyst",
|
||||
"dame",
|
||||
"dare",
|
||||
"dark",
|
||||
"dart",
|
||||
"dash",
|
||||
"data",
|
||||
"date",
|
||||
"dead",
|
||||
"deal",
|
||||
"dear",
|
||||
"debt",
|
||||
"deck",
|
||||
"deep",
|
||||
"deer",
|
||||
"desk",
|
||||
"dhow",
|
||||
"diet",
|
||||
"dill",
|
||||
"dime",
|
||||
"dirt",
|
||||
"dish",
|
||||
"disk",
|
||||
"dock",
|
||||
"doll",
|
||||
"door",
|
||||
"dory",
|
||||
"drag",
|
||||
"draw",
|
||||
"drop",
|
||||
"drug",
|
||||
"drum",
|
||||
"duck",
|
||||
"dump",
|
||||
"dust",
|
||||
"duty",
|
||||
"ease",
|
||||
"east",
|
||||
"eave",
|
||||
"eddy",
|
||||
"edge",
|
||||
"envy",
|
||||
"epee",
|
||||
"exam",
|
||||
"exit",
|
||||
"face",
|
||||
"fact",
|
||||
"fail",
|
||||
"fall",
|
||||
"fame",
|
||||
"fang",
|
||||
"farm",
|
||||
"fawn",
|
||||
"fear",
|
||||
"feed",
|
||||
"feel",
|
||||
"feet",
|
||||
"file",
|
||||
"fill",
|
||||
"film",
|
||||
"find",
|
||||
"fine",
|
||||
"fire",
|
||||
"fish",
|
||||
"flag",
|
||||
"flat",
|
||||
"flax",
|
||||
"flow",
|
||||
"foam",
|
||||
"fold",
|
||||
"font",
|
||||
"food",
|
||||
"foot",
|
||||
"fork",
|
||||
"form",
|
||||
"fort",
|
||||
"fowl",
|
||||
"frog",
|
||||
"fuel",
|
||||
"full",
|
||||
"gain",
|
||||
"gale",
|
||||
"galn",
|
||||
"game",
|
||||
"garb",
|
||||
"gate",
|
||||
"gear",
|
||||
"gene",
|
||||
"gift",
|
||||
"girl",
|
||||
"give",
|
||||
"glad",
|
||||
"glen",
|
||||
"glue",
|
||||
"glut",
|
||||
"goal",
|
||||
"goat",
|
||||
"gold",
|
||||
"golf",
|
||||
"gong",
|
||||
"good",
|
||||
"gown",
|
||||
"grab",
|
||||
"gram",
|
||||
"gray",
|
||||
"grey",
|
||||
"grip",
|
||||
"grit",
|
||||
"gyro",
|
||||
"hail",
|
||||
"hair",
|
||||
"half",
|
||||
"hall",
|
||||
"hand",
|
||||
"hang",
|
||||
"harm",
|
||||
"harp",
|
||||
"hate",
|
||||
"hawk",
|
||||
"head",
|
||||
"heat",
|
||||
"heel",
|
||||
"hell",
|
||||
"helo",
|
||||
"help",
|
||||
"hemp",
|
||||
"herb",
|
||||
"hide",
|
||||
"high",
|
||||
"hill",
|
||||
"hire",
|
||||
"hive",
|
||||
"hold",
|
||||
"hole",
|
||||
"home",
|
||||
"hood",
|
||||
"hoof",
|
||||
"hook",
|
||||
"hope",
|
||||
"hops",
|
||||
"horn",
|
||||
"hose",
|
||||
"host",
|
||||
"hour",
|
||||
"hunt",
|
||||
"hurt",
|
||||
"icon",
|
||||
"idea",
|
||||
"inch",
|
||||
"iris",
|
||||
"iron",
|
||||
"item",
|
||||
"jail",
|
||||
"jeep",
|
||||
"jeff",
|
||||
"joey",
|
||||
"join",
|
||||
"joke",
|
||||
"judo",
|
||||
"jump",
|
||||
"junk",
|
||||
"jury",
|
||||
"jute",
|
||||
"kale",
|
||||
"keep",
|
||||
"kick",
|
||||
"kill",
|
||||
"kilt",
|
||||
"kind",
|
||||
"king",
|
||||
"kiss",
|
||||
"kite",
|
||||
"knee",
|
||||
"knot",
|
||||
"lace",
|
||||
"lack",
|
||||
"lady",
|
||||
"lake",
|
||||
"lamb",
|
||||
"lamp",
|
||||
"land",
|
||||
"lark",
|
||||
"lava",
|
||||
"lawn",
|
||||
"lead",
|
||||
"leaf",
|
||||
"leek",
|
||||
"lier",
|
||||
"life",
|
||||
"lift",
|
||||
"lily",
|
||||
"limo",
|
||||
"line",
|
||||
"link",
|
||||
"lion",
|
||||
"lisa",
|
||||
"list",
|
||||
"load",
|
||||
"loaf",
|
||||
"loan",
|
||||
"lock",
|
||||
"loft",
|
||||
"long",
|
||||
"look",
|
||||
"loss",
|
||||
"lout",
|
||||
"love",
|
||||
"luck",
|
||||
"lung",
|
||||
"lute",
|
||||
"lynx",
|
||||
"lyre",
|
||||
"maid",
|
||||
"mail",
|
||||
"main",
|
||||
"make",
|
||||
"male",
|
||||
"mall",
|
||||
"manx",
|
||||
"many",
|
||||
"mare",
|
||||
"mark",
|
||||
"mask",
|
||||
"mass",
|
||||
"mate",
|
||||
"math",
|
||||
"meal",
|
||||
"meat",
|
||||
"meet",
|
||||
"menu",
|
||||
"mess",
|
||||
"mice",
|
||||
"midi",
|
||||
"mile",
|
||||
"milk",
|
||||
"mime",
|
||||
"mind",
|
||||
"mine",
|
||||
"mini",
|
||||
"mint",
|
||||
"miss",
|
||||
"mist",
|
||||
"moat",
|
||||
"mode",
|
||||
"mole",
|
||||
"mood",
|
||||
"moon",
|
||||
"most",
|
||||
"moth",
|
||||
"move",
|
||||
"mule",
|
||||
"mutt",
|
||||
"nail",
|
||||
"name",
|
||||
"neat",
|
||||
"neck",
|
||||
"need",
|
||||
"neon",
|
||||
"nest",
|
||||
"news",
|
||||
"node",
|
||||
"nose",
|
||||
"note",
|
||||
"oboe",
|
||||
"okra",
|
||||
"open",
|
||||
"oval",
|
||||
"oven",
|
||||
"oxen",
|
||||
"pace",
|
||||
"pack",
|
||||
"page",
|
||||
"pail",
|
||||
"pain",
|
||||
"pair",
|
||||
"palm",
|
||||
"pard",
|
||||
"park",
|
||||
"part",
|
||||
"pass",
|
||||
"past",
|
||||
"path",
|
||||
"peak",
|
||||
"pear",
|
||||
"peen",
|
||||
"peer",
|
||||
"pelt",
|
||||
"perp",
|
||||
"pest",
|
||||
"pick",
|
||||
"pier",
|
||||
"pike",
|
||||
"pile",
|
||||
"pimp",
|
||||
"pine",
|
||||
"ping",
|
||||
"pink",
|
||||
"pint",
|
||||
"pipe",
|
||||
"piss",
|
||||
"pith",
|
||||
"plan",
|
||||
"play",
|
||||
"plot",
|
||||
"plow",
|
||||
"poem",
|
||||
"poet",
|
||||
"pole",
|
||||
"polo",
|
||||
"pond",
|
||||
"pony",
|
||||
"poof",
|
||||
"pool",
|
||||
"port",
|
||||
"post",
|
||||
"prow",
|
||||
"pull",
|
||||
"puma",
|
||||
"pump",
|
||||
"pupa",
|
||||
"push",
|
||||
"quit",
|
||||
"race",
|
||||
"rack",
|
||||
"raft",
|
||||
"rage",
|
||||
"rail",
|
||||
"rain",
|
||||
"rake",
|
||||
"rank",
|
||||
"rate",
|
||||
"read",
|
||||
"rear",
|
||||
"reef",
|
||||
"rent",
|
||||
"rest",
|
||||
"rice",
|
||||
"rich",
|
||||
"ride",
|
||||
"ring",
|
||||
"rise",
|
||||
"risk",
|
||||
"road",
|
||||
"robe",
|
||||
"rock",
|
||||
"role",
|
||||
"roll",
|
||||
"roof",
|
||||
"room",
|
||||
"root",
|
||||
"rope",
|
||||
"rose",
|
||||
"ruin",
|
||||
"rule",
|
||||
"rush",
|
||||
"ruth",
|
||||
"sack",
|
||||
"safe",
|
||||
"sage",
|
||||
"sail",
|
||||
"sale",
|
||||
"salt",
|
||||
"sand",
|
||||
"sari",
|
||||
"sash",
|
||||
"save",
|
||||
"scow",
|
||||
"seal",
|
||||
"seat",
|
||||
"seed",
|
||||
"self",
|
||||
"sell",
|
||||
"shed",
|
||||
"shin",
|
||||
"ship",
|
||||
"shoe",
|
||||
"shop",
|
||||
"shot",
|
||||
"show",
|
||||
"sick",
|
||||
"side",
|
||||
"sign",
|
||||
"silk",
|
||||
"sill",
|
||||
"silo",
|
||||
"sing",
|
||||
"sink",
|
||||
"site",
|
||||
"size",
|
||||
"skin",
|
||||
"sled",
|
||||
"slip",
|
||||
"smog",
|
||||
"snob",
|
||||
"snow",
|
||||
"soap",
|
||||
"sock",
|
||||
"soda",
|
||||
"sofa",
|
||||
"soft",
|
||||
"soil",
|
||||
"song",
|
||||
"soot",
|
||||
"sort",
|
||||
"soup",
|
||||
"spot",
|
||||
"spur",
|
||||
"stag",
|
||||
"star",
|
||||
"stay",
|
||||
"stem",
|
||||
"step",
|
||||
"stew",
|
||||
"stop",
|
||||
"stud",
|
||||
"suck",
|
||||
"suit",
|
||||
"swan",
|
||||
"swim",
|
||||
"tail",
|
||||
"tale",
|
||||
"talk",
|
||||
"tank",
|
||||
"tard",
|
||||
"task",
|
||||
"taxi",
|
||||
"team",
|
||||
"tear",
|
||||
"teen",
|
||||
"tell",
|
||||
"temp",
|
||||
"tent",
|
||||
"term",
|
||||
"test",
|
||||
"text",
|
||||
"thaw",
|
||||
"tile",
|
||||
"till",
|
||||
"time",
|
||||
"tire",
|
||||
"toad",
|
||||
"toga",
|
||||
"togs",
|
||||
"tone",
|
||||
"tool",
|
||||
"toot",
|
||||
"tote",
|
||||
"tour",
|
||||
"town",
|
||||
"tram",
|
||||
"tray",
|
||||
"tree",
|
||||
"trim",
|
||||
"trip",
|
||||
"tuba",
|
||||
"tube",
|
||||
"tuna",
|
||||
"tune",
|
||||
"turn",
|
||||
"tutu",
|
||||
"twig",
|
||||
"type",
|
||||
"unit",
|
||||
"user",
|
||||
"vane",
|
||||
"vase",
|
||||
"vast",
|
||||
"veal",
|
||||
"veil",
|
||||
"vein",
|
||||
"vest",
|
||||
"vibe",
|
||||
"view",
|
||||
"vise",
|
||||
"wait",
|
||||
"wake",
|
||||
"walk",
|
||||
"wall",
|
||||
"wash",
|
||||
"wasp",
|
||||
"wave",
|
||||
"wear",
|
||||
"weed",
|
||||
"week",
|
||||
"well",
|
||||
"west",
|
||||
"whip",
|
||||
"wife",
|
||||
"will",
|
||||
"wind",
|
||||
"wine",
|
||||
"wing",
|
||||
"wire",
|
||||
"wish",
|
||||
"wolf",
|
||||
"wood",
|
||||
"wool",
|
||||
"word",
|
||||
"work",
|
||||
"worm",
|
||||
"wrap",
|
||||
"wren",
|
||||
"yard",
|
||||
"yarn",
|
||||
"yawl",
|
||||
"year",
|
||||
"yoga",
|
||||
"yoke",
|
||||
"yurt",
|
||||
"zinc",
|
||||
"zone",
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/status-im/status-go/node"
|
||||
)
|
||||
|
||||
func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) {
|
||||
if timeout == 0 {
|
||||
return context.WithCancel(context.Background())
|
||||
}
|
||||
|
||||
return context.WithTimeout(context.Background(), time.Duration(timeout)*time.Minute)
|
||||
}
|
||||
|
||||
// syncAndStopNode tries to sync the blockchain and stop the node.
|
||||
// It returns an exit code (`0` if successful or `1` in case of error)
|
||||
// that can be used in `os.Exit` to exit immediately when the function returns.
|
||||
// The special exit code `-1` is used if execution was interrupted.
|
||||
func syncAndStopNode(interruptCh <-chan struct{}, statusNode *node.StatusNode, timeout int) (exitCode int) {
|
||||
|
||||
logger.Info("syncAndStopNode: node will synchronize the chain and exit", "timeoutInMins", timeout)
|
||||
|
||||
ctx, cancel := createContextFromTimeout(timeout)
|
||||
defer cancel()
|
||||
|
||||
doneSync := make(chan struct{})
|
||||
errSync := make(chan error)
|
||||
go func() {
|
||||
if err := statusNode.EnsureSync(ctx); err != nil {
|
||||
errSync <- err
|
||||
}
|
||||
close(doneSync)
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-errSync:
|
||||
logger.Error("syncAndStopNode: failed to sync the chain", "error", err)
|
||||
exitCode = 1
|
||||
case <-doneSync:
|
||||
case <-interruptCh:
|
||||
// cancel context and return immediately if interrupted
|
||||
// `-1` is used as a special exit code to denote interruption
|
||||
return -1
|
||||
}
|
||||
|
||||
if err := statusNode.Stop(); err != nil {
|
||||
logger.Error("syncAndStopNode: failed to stop the node", "error", err)
|
||||
return 1
|
||||
}
|
||||
return
|
||||
}
|
|
@ -302,6 +302,10 @@ func (api *PublicAPI) SaveChat(parent context.Context, chat *protocol.Chat) erro
|
|||
return api.service.messenger.SaveChat(chat)
|
||||
}
|
||||
|
||||
func (api *PublicAPI) SaveMessages(parent context.Context, messages []*common.Message) error {
|
||||
return api.service.messenger.SaveMessages(messages)
|
||||
}
|
||||
|
||||
func (api *PublicAPI) CreateOneToOneChat(parent context.Context, request *requests.CreateOneToOneChat) (*protocol.MessengerResponse, error) {
|
||||
return api.service.messenger.CreateOneToOneChat(request)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue