From 66013a059e39e49cc42146bd5e0ec845e944beae Mon Sep 17 00:00:00 2001 From: JoeGruff Date: Fri, 3 Feb 2023 15:49:44 +0900 Subject: [PATCH] client/eth: Remove non compliant providers. Check all providers that are not known to be good. Check them on reconfigure as well. Also use WebSocket with full nodes rather than the light node. --- client/asset/eth/eth.go | 37 +--- client/asset/eth/multirpc.go | 241 +++++++++++++++++-------- client/asset/eth/multirpc_live_test.go | 26 +-- client/cmd/dexcctl/simnet-setup.sh | 3 +- dex/testing/eth/create-node.sh | 14 +- dex/testing/eth/harness.sh | 30 ++- 6 files changed, 214 insertions(+), 137 deletions(-) diff --git a/client/asset/eth/eth.go b/client/asset/eth/eth.go index c68876c623..b33444c0bb 100644 --- a/client/asset/eth/eth.go +++ b/client/asset/eth/eth.go @@ -596,7 +596,6 @@ func createWallet(createWalletParams *asset.CreateWalletParams, skipConnect bool return errors.New("no providers specified") } endpoints := strings.Split(providerDef, providerDelimiter) - n := len(endpoints) // TODO: This procedure may actually work for walletTypeGeth too. ks := keystore.NewKeyStore(filepath.Join(walletDir, "keystore"), keystore.LightScryptN, keystore.LightScryptP) @@ -607,36 +606,9 @@ func createWallet(createWalletParams *asset.CreateWalletParams, skipConnect bool } if !skipConnect { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - - var unknownEndpoints []string - - for _, endpoint := range endpoints { - known, compliant := providerIsCompliant(endpoint) - if known && !compliant { - return fmt.Errorf("provider %q is known to have an insufficient API for DEX", endpoint) - } else if !known { - unknownEndpoints = append(unknownEndpoints, endpoint) - } - } - - if len(unknownEndpoints) > 0 && createWalletParams.Net == dex.Mainnet { - providers, err := connectProviders(ctx, unknownEndpoints, createWalletParams.Logger, big.NewInt(chainIDs[createWalletParams.Net]), createWalletParams.Net) - if err != nil { - return err - } - defer func() { - for _, p := range providers { - p.ec.Close() - } - }() - if len(providers) != n { - return fmt.Errorf("Could not connect to all providers") - } - if err := checkProvidersCompliance(ctx, walletDir, providers, createWalletParams.Logger); err != nil { - return err - } + if err := createAndCheckProviders(context.Background(), walletDir, endpoints, + createWalletParams.Net, createWalletParams.Logger); err != nil { + return fmt.Errorf("create and check providers problem: %v", err) } } return importKeyToKeyStore(ks, priv, createWalletParams.Pass) @@ -893,7 +865,8 @@ func (w *ETHWallet) Reconfigure(ctx context.Context, cfg *asset.WalletConfig, cu } if rpc, is := w.node.(*multiRPCClient); is { - if err := rpc.reconfigure(ctx, cfg.Settings); err != nil { + walletDir := getWalletDir(w.dir, w.net) + if err := rpc.reconfigure(ctx, cfg.Settings, walletDir); err != nil { return false, err } } diff --git a/client/asset/eth/multirpc.go b/client/asset/eth/multirpc.go index 0b975ba474..2d3f518ce9 100644 --- a/client/asset/eth/multirpc.go +++ b/client/asset/eth/multirpc.go @@ -84,12 +84,13 @@ type provider struct { // host is the domain and tld of the provider, and is used as a identifier // in logs and as a unique, path- and subdomain-independent ID for e.g. map // keys. - host string - ec *combinedRPCClient - ws bool - net dex.Network - tipCapV atomic.Value // *cachedTipCap - stop func() + host string + endpointAddr string + ec *combinedRPCClient + ws bool + net dex.Network + tipCapV atomic.Value // *cachedTipCap + stop func() // tip tracks the best known header as well as any error encountered tip struct { @@ -395,8 +396,8 @@ func newMultiRPCClient(dir string, endpoints []string, log dex.Logger, cfg *para // connectProviders attempts to connect to the list of endpoints, returning a // list of providers that were successfully connected. It is not an error for a -// connection to fail. The caller can infer failed connections from the length -// and contents of the returned provider list. +// connection to fail, unless all endpoints fail. The caller can infer failed +// connections from the length and contents of the returned provider list. func connectProviders(ctx context.Context, endpoints []string, log dex.Logger, chainID *big.Int, net dex.Network) ([]*provider, error) { providers := make([]*provider, 0, len(endpoints)) var success bool @@ -409,12 +410,12 @@ func connectProviders(ctx context.Context, endpoints []string, log dex.Logger, c } }() - // addEnpoint only returns errors that should be propagated immediately. + // addEndpoint only returns errors that should be propagated immediately. addEndpoint := func(endpoint string) error { // Give ourselves a limited time to resolve a connection. timedCtx, cancel := context.WithTimeout(ctx, defaultRequestTimeout) defer cancel() - // First try to get a websocket connection. Websockets have a header + // First try to get a websocket connection. WebSockets have a header // feed, so are much preferred to http connections. So much so, that // we'll do some path inspection here and make an attempt to find a // websocket server, even if the user requested http. @@ -510,9 +511,10 @@ func connectProviders(ctx context.Context, endpoints []string, log dex.Logger, c } p := &provider{ - host: host, - ws: sub != nil, - net: net, + host: host, + endpointAddr: endpoint, + ws: sub != nil, + net: net, ec: &combinedRPCClient{ Client: ec, rpc: rpcClient, @@ -634,12 +636,93 @@ func (m *multiRPCClient) voidUnusedNonce() { m.lastNonce.stamp = time.Time{} } -func (m *multiRPCClient) reconfigure(ctx context.Context, settings map[string]string) error { +// createAndCheckProviders creates and connects to providers. It checks that +// unknown providers have a sufficient api to trade and saves good providers to +// file. One bad provider or connect problem will cause this to error. +func createAndCheckProviders(ctx context.Context, walletDir string, endpoints []string, net dex.Network, + log dex.Logger) error { + var localCP map[string]bool + path := filepath.Join(walletDir, "compliant-providers.json") + b, err := os.ReadFile(path) + if err == nil { + if err := json.Unmarshal(b, &localCP); err != nil { + log.Warnf("Couldn't parse compliant providers file: %v", err) + } + } else if !errors.Is(err, os.ErrNotExist) { + log.Warnf("Error reading providers file: %v", err) + } + if localCP == nil { + localCP = make(map[string]bool) + } + + var writeLocalCP bool + + var unknownEndpoints []string + for _, p := range endpoints { + d := domain(p) + if localCP[d] { + continue + } + writeLocalCP = true + localCP[d] = true + if _, known := compliantProviders[d]; !known { + unknownEndpoints = append(unknownEndpoints, p) + } + } + + if len(unknownEndpoints) > 0 { + providersErr := func(providers []*provider) error { + // Remove connected providers from the unknown endpoints for + // printing. + for i := len(unknownEndpoints) - 1; i >= 0; i-- { + for _, p := range providers { + if p.endpointAddr == unknownEndpoints[i] { + unknownEndpoints = append(unknownEndpoints[:i], unknownEndpoints[i+1:]...) + break + } + } + } + return fmt.Errorf("could not connect to the following providers: %v", strings.Join(unknownEndpoints, " ")) + } + + providers, err := connectProviders(ctx, unknownEndpoints, log, big.NewInt(chainIDs[net]), net) + if err != nil { + return fmt.Errorf("%v: %v", providersErr(providers), err) + } + defer func() { + for _, p := range providers { + p.shutdown() + } + }() + if len(providers) != len(unknownEndpoints) { + return providersErr(providers) + } + if err := checkProvidersCompliance(ctx, providers, net, log); err != nil { + return err + } + } + if writeLocalCP { + // All unknown providers were checked. + b, err := json.Marshal(localCP) + if err != nil { + return err + } + if err := os.WriteFile(path, b, 0644); err != nil { + log.Errorf("Failed to write compliant providers file: %v", err) + } + } + return nil +} + +func (m *multiRPCClient) reconfigure(ctx context.Context, settings map[string]string, walletDir string) error { providerDef := settings[providersKey] if len(providerDef) == 0 { return errors.New("no providers specified") } endpoints := strings.Split(providerDef, " ") + if err := createAndCheckProviders(ctx, walletDir, endpoints, m.net, m.log); err != nil { + return fmt.Errorf("create and check providers problem: %v", err) + } providers, err := connectProviders(ctx, endpoints, m.log, m.chainID, m.net) if err != nil { return err @@ -1294,7 +1377,7 @@ const ( providerBlast = "blastapi.io" // Non-compliant providers - providerCloudflareETH = "cloudflare-eth.com" // "SuggestGasTipCap" error: Method not found + // providerCloudflareETH = "cloudflare-eth.com" // "SuggestGasTipCap" error: Method not found ) var compliantProviders = map[string]struct{}{ @@ -1310,19 +1393,6 @@ var compliantProviders = map[string]struct{}{ providerBlast: {}, } -var nonCompliantProviders = map[string]struct{}{ - providerCloudflareETH: {}, -} - -func providerIsCompliant(addr string) (known, compliant bool) { - addr = domain(addr) - if _, known = compliantProviders[addr]; known { - return true, true - } - _, known = nonCompliantProviders[addr] - return known, false -} - type rpcTest struct { name string f func(context.Context, *provider) error @@ -1330,17 +1400,57 @@ type rpcTest struct { // newCompatibilityTests returns a list of RPC tests to run to determine API // compatibility. -func newCompatibilityTests(cb bind.ContractBackend, log slog.Logger) []*rpcTest { +func newCompatibilityTests(cb bind.ContractBackend, net dex.Network, log slog.Logger) []*rpcTest { var ( // Vitalik's address from https://twitter.com/VitalikButerin/status/1050126908589887488 mainnetAddr = common.HexToAddress("0xab5801a7d398351b8be11c439e05c5b3259aec9b") mainnetUSDC = common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48") mainnetTxHash = common.HexToHash("0xea1a717af9fad5702f189d6f760bb9a5d6861b4ee915976fe7732c0c95cd8a0e") mainnetBlockHash = common.HexToHash("0x44ebd6f66b4fd546bccdd700869f6a433ef9a47e296a594fa474228f86eeb353") + + testnetAddr = common.HexToAddress("0x8879F72728C5eaf5fB3C55e6C3245e97601FBa32") + testnetUSDC = common.HexToAddress("0x07865c6E87B9F70255377e024ace6630C1Eaa37F") + testnetTxHash = common.HexToHash("0x4e1d455f7eac7e3a5f7c1e0989b637002755eaee3a262f90b0f3aef1f1c4dcf0") + testnetBlockHash = common.HexToHash("0x8896021c2666303a85b7e4a6a6f2b075bc705d4e793bf374cd44b83bca23ef9a") + + simnetAddr = common.HexToAddress("18d65fb8d60c1199bb1ad381be47aa692b482605") + addr, usdc common.Address + txHash, blockHash common.Hash ) - if log == nil { // Logging detail is for testing. - log = slog.Disabled + + switch net { + case dex.Mainnet: + addr = mainnetAddr + usdc = mainnetUSDC + txHash = mainnetTxHash + blockHash = mainnetBlockHash + case dex.Testnet: + addr = testnetAddr + usdc = testnetUSDC + txHash = testnetTxHash + blockHash = testnetBlockHash + case dex.Simnet: + addr = simnetAddr + var ( + tDir = filepath.Join(os.Getenv("HOME"), "dextest", "eth") + tTxHashFile = filepath.Join(tDir, "test_tx_hash.txt") + tBlockHashFile = filepath.Join(tDir, "test_block10_hash.txt") + tContractFile = filepath.Join(tDir, "test_token_contract_address.txt") + ) + readIt := func(path string) string { + b, err := os.ReadFile(path) + if err != nil { + log.Errorf("Problem reading simnet testing file: %v", err) + } + return strings.TrimRight(string(b), "\r\n") + } + usdc = common.HexToAddress(readIt(tContractFile)) + txHash = common.HexToHash(readIt(tTxHashFile)) + blockHash = common.HexToHash(readIt(tBlockHashFile)) + default: + log.Errorf("Unknown net %v in compatibility tests. Testing data not initiated.", net) } + return []*rpcTest{ { name: "HeaderByNumber", @@ -1352,21 +1462,21 @@ func newCompatibilityTests(cb bind.ContractBackend, log slog.Logger) []*rpcTest { name: "HeaderByHash", f: func(ctx context.Context, p *provider) error { - _, err := p.ec.HeaderByHash(ctx, mainnetBlockHash) + _, err := p.ec.HeaderByHash(ctx, blockHash) return err }, }, { name: "TransactionReceipt", f: func(ctx context.Context, p *provider) error { - _, err := p.ec.TransactionReceipt(ctx, mainnetTxHash) + _, err := p.ec.TransactionReceipt(ctx, txHash) return err }, }, { name: "PendingNonceAt", f: func(ctx context.Context, p *provider) error { - _, err := p.ec.PendingNonceAt(ctx, mainnetAddr) + _, err := p.ec.PendingNonceAt(ctx, addr) return err }, }, @@ -1384,18 +1494,18 @@ func newCompatibilityTests(cb bind.ContractBackend, log slog.Logger) []*rpcTest { name: "BalanceAt", f: func(ctx context.Context, p *provider) error { - bal, err := p.ec.BalanceAt(ctx, mainnetAddr, nil) + bal, err := p.ec.BalanceAt(ctx, addr, nil) if err != nil { return err } - log.Infof("#### Vitalik's balance retrieved: %.9f", float64(dexeth.WeiToGwei(bal))/1e9) + log.Infof("#### Balance retrieved: %.9f", float64(dexeth.WeiToGwei(bal))/1e9) return nil }, }, { name: "CodeAt", f: func(ctx context.Context, p *provider) error { - code, err := p.ec.CodeAt(ctx, mainnetUSDC, nil) + code, err := p.ec.CodeAt(ctx, usdc, nil) if err != nil { return err } @@ -1406,14 +1516,14 @@ func newCompatibilityTests(cb bind.ContractBackend, log slog.Logger) []*rpcTest { name: "CallContract(balanceOf)", f: func(ctx context.Context, p *provider) error { - caller, err := erc20.NewIERC20(mainnetUSDC, cb) + caller, err := erc20.NewIERC20(usdc, cb) if err != nil { return err } bal, err := caller.BalanceOf(&bind.CallOpts{ - From: mainnetAddr, + From: addr, Context: ctx, - }, mainnetAddr) + }, addr) if err != nil { return err } @@ -1438,7 +1548,7 @@ func newCompatibilityTests(cb bind.ContractBackend, log slog.Logger) []*rpcTest { name: "PendingNonceAt", f: func(ctx context.Context, p *provider) error { - n, err := p.ec.PendingNonceAt(ctx, mainnetAddr) + n, err := p.ec.PendingNonceAt(ctx, addr) if err != nil { return err } @@ -1449,7 +1559,7 @@ func newCompatibilityTests(cb bind.ContractBackend, log slog.Logger) []*rpcTest { name: "getRPCTransaction", f: func(ctx context.Context, p *provider) error { - rpcTx, err := getRPCTransaction(ctx, p, mainnetTxHash) + rpcTx, err := getRPCTransaction(ctx, p, txHash) if err != nil { return err } @@ -1473,49 +1583,22 @@ func domain(host string) string { return parts[n-2] + "." + parts[n-1] } -// checkProvidersCompliance verifies that a provider supports the API that DEX +// checkProvidersCompliance verifies that providers support the API that DEX // requires by sending a series of requests and verifying the responses. If a // provider is found to be compliant, their domain name is added to a list and -// stored in a file on disk, so that future checks can be short-circuited. -func checkProvidersCompliance(ctx context.Context, walletDir string, providers []*provider, log dex.Logger) error { - var compliantProviders map[string]bool - path := filepath.Join(walletDir, "compliant-providers.json") - b, err := os.ReadFile(path) - if err == nil { - if err := json.Unmarshal(b, &compliantProviders); err != nil { - log.Warn("Couldn't parse compliant providers file") - } - } - if compliantProviders == nil { - compliantProviders = make(map[string]bool) - } - - n := len(compliantProviders) - +// stored in a file on disk so that future checks can be short-circuited. +func checkProvidersCompliance(ctx context.Context, providers []*provider, net dex.Network, log slog.Logger) error { for _, p := range providers { - if compliantProviders[domain(p.host)] { - continue - } - - if known, _ := providerIsCompliant(p.host); !known { - // Need to run API tests on this endpoint. - for _, t := range newCompatibilityTests(p.ec, nil /* logger is for testing only */) { - if err := t.f(ctx, p); err != nil { - log.Errorf("RPC Provider @ %q has a non-compliant API: %v", err) - return fmt.Errorf("RPC Provider @ %q has a non-compliant API", p.host) - } + // Need to run API tests on this endpoint. + for _, t := range newCompatibilityTests(p.ec, net, log) { + ctx, cancel := context.WithTimeout(ctx, defaultRequestTimeout) + err := t.f(ctx, p) + cancel() + if err != nil { + return fmt.Errorf("RPC Provider @ %q has a non-compliant API: %v", p.host, err) } - compliantProviders[domain(p.host)] = true } } - - if len(compliantProviders) != n { - b, _ /* c'mon */ := json.Marshal(compliantProviders) - if err := os.WriteFile(path, b, 0644); err != nil { - log.Errorf("Failed to write compliant providers file: %v", err) - } - } - return nil } diff --git a/client/asset/eth/multirpc_live_test.go b/client/asset/eth/multirpc_live_test.go index fcfeb16b35..f72e1f6768 100644 --- a/client/asset/eth/multirpc_live_test.go +++ b/client/asset/eth/multirpc_live_test.go @@ -267,7 +267,7 @@ func TestRPC(t *testing.T) { t.Fatalf("connect error: %v", err) } - for _, tt := range newCompatibilityTests(cl, cl.log) { + for _, tt := range newCompatibilityTests(cl, dex.Mainnet, cl.log) { tStart := time.Now() if err := cl.withAny(ctx, tt.f); err != nil { t.Fatalf("%q: %v", tt.name, err) @@ -297,15 +297,13 @@ func TestFreeServers(t *testing.T) { if err := cl.connect(ctx); err != nil { return fmt.Errorf("connect error: %v", err) } - return cl.withAny(ctx, func(ctx context.Context, p *provider) error { - for _, tt := range newCompatibilityTests(cl, cl.log) { - if err := tt.f(ctx, p); err != nil { - return fmt.Errorf("%q error: %v", tt.name, err) - } - fmt.Printf("#### %q passed %q \n", endpoint, tt.name) + for _, tt := range newCompatibilityTests(cl, dex.Mainnet, cl.log) { + if err := cl.withAny(ctx, tt.f); err != nil { + return fmt.Errorf("%q error: %v", tt.name, err) } - return nil - }) + fmt.Printf("#### %q passed %q \n", endpoint, tt.name) + } + return nil } passes, fails := make([]string, 0), make(map[string]error, 0) @@ -326,20 +324,26 @@ func TestFreeServers(t *testing.T) { func TestMainnetCompliance(t *testing.T) { providerFile := readProviderFile(t, dex.Mainnet) - dir, _ := os.MkdirTemp("", "") + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() log := dex.StdOutLogger("T", dex.LevelTrace) providers, err := connectProviders(ctx, providerFile.Providers, log, big.NewInt(chainIDs[dex.Mainnet]), dex.Mainnet) if err != nil { t.Fatal(err) } - err = checkProvidersCompliance(ctx, dir, providers, log) + err = checkProvidersCompliance(ctx, providers, dex.Mainnet, log) if err != nil { t.Fatal(err) } } func tRPCClient(dir string, seed []byte, endpoints []string, net dex.Network, skipConnect bool) (*multiRPCClient, error) { + wDir := getWalletDir(dir, net) + err := os.MkdirAll(wDir, 0755) + if err != nil { + return nil, fmt.Errorf("os.Mkdir error: %w", err) + } log := dex.StdOutLogger("T", dex.LevelTrace) if err := createWallet(&asset.CreateWalletParams{ Type: walletTypeRPC, diff --git a/client/cmd/dexcctl/simnet-setup.sh b/client/cmd/dexcctl/simnet-setup.sh index 88bada74fe..3dea0ca851 100755 --- a/client/cmd/dexcctl/simnet-setup.sh +++ b/client/cmd/dexcctl/simnet-setup.sh @@ -48,7 +48,8 @@ fi if [ $ETH_ON -eq 0 ]; then echo configuring Eth and dextt.eth wallets - ./dexcctl -p abc -p "" --simnet newwallet 60 rpc "" "{\"providers\":\"${HOME}/dextest/eth/alpha/node/geth.ipc\"}" + # Connecting to the simnet beta node over WebSocket. + ./dexcctl -p abc -p "" --simnet newwallet 60 rpc "" "{\"providers\":\"ws://localhost:38559\"}" ./dexcctl -p abc -p "" --simnet newwallet 60000 rpc fi diff --git a/dex/testing/eth/create-node.sh b/dex/testing/eth/create-node.sh index ee2857e908..209166b820 100755 --- a/dex/testing/eth/create-node.sh +++ b/dex/testing/eth/create-node.sh @@ -15,6 +15,9 @@ ADDRESS_JSON_FILE_NAME=$9 NODE_KEY=${10} SYNC_MODE=${11} AUTHRPC_PORT=${12} +HTTP_PORT=${13} +WS_PORT=${14} +WS_MODULES=${15} GROUP_DIR="${NODES_ROOT}/${NAME}" MINE_JS="${GROUP_DIR}/mine.js" @@ -30,11 +33,6 @@ geth --datadir="${NODE_DIR}" \$* EOF chmod +x "${NODES_ROOT}/harness-ctl/${NAME}" -HTTP_OPT="" -if [ "$NAME" = "delta" ]; then - HTTP_OPT="--http --http.port ${DELTA_HTTP_PORT} --ws --ws.port ${DELTA_WS_PORT} --ws.api \"db,eth,net,web3,personal,txpool,admin\"" -fi - # Write mine script if CHAIN_ADDRESS is present. if [ "${CHAIN_ADDRESS}" != "_" ]; then # The mining script may end up mining more or less blocks than specified. @@ -137,8 +135,10 @@ if [ "${SYNC_MODE}" = "snap" ]; then tmux send-keys -t "$TMUX_WIN_ID" "${NODES_ROOT}/harness-ctl/${NAME} --nodiscover " \ "--config ${NODE_DIR}/eth.conf --unlock ${CHAIN_ADDRESS} " \ "--password ${GROUP_DIR}/password --light.serve 25 --datadir.ancient " \ - "${NODE_DIR}/geth-ancient --verbosity 5 --vmdebug 2>&1 | tee " \ - "${NODE_DIR}/${NAME}.log" C-m + "${NODE_DIR}/geth-ancient --verbosity 5 --vmdebug --http --http.port " \ + "${HTTP_PORT} --ws --ws.port ${WS_PORT} --ws.api " \ + "${WS_MODULES} --allow-insecure-unlock " \ + "2>&1 | tee ${NODE_DIR}/${NAME}.log" C-m else # Start the eth node listening restricted to localhost and our custom diff --git a/dex/testing/eth/harness.sh b/dex/testing/eth/harness.sh index a8b2229ffd..384f4b57bf 100755 --- a/dex/testing/eth/harness.sh +++ b/dex/testing/eth/harness.sh @@ -20,6 +20,9 @@ ALPHA_NODE_KEY="71d810d39333296b518c846a3e49eca55f998fd7994998bb3e5048567f2f073c ALPHA_ENODE="897c84f6e4f18195413c1d02927e6a4093f5e7574b52bdec6f20844c4f1f6dd3f16036a9e600bd8681ab50fd8dd144df4a6ba9dd8722bb578a86aaa8222c964f" ALPHA_NODE_PORT="30304" ALPHA_AUTHRPC_PORT="8552" +ALPHA_HTTP_PORT="38556" +ALPHA_WS_PORT="38557" +ALPHA_WS_MODULES="eth" # BETA_ADDRESS="4f8ef3892b65ed7fc356ff473a2ef2ae5ec27a06" BETA_ADDRESS_JSON_FILE_NAME="UTC--2021-01-27T08-20-58.179642501Z--4f8ef3892b65ed7fc356ff473a2ef2ae5ec27a06" @@ -28,6 +31,9 @@ BETA_NODE_KEY="0f3f23a0f14202da009bd59a96457098acea901986629e54d5be1eea32fc404a" BETA_ENODE="b1d3e358ee5c9b268e911f2cab47bc12d0e65c80a6d2b453fece34facc9ac3caed14aa3bc7578166bb08c5bc9719e5a2267ae14e0b42da393f4d86f6d5829061" BETA_NODE_PORT="30305" BETA_AUTHRPC_PORT="8553" +BETA_HTTP_PORT="38558" +BETA_WS_PORT="38559" +BETA_WS_MODULES="eth,txpool" GAMMA_ADDRESS="41293c2032bac60aa747374e966f79f575d42379" GAMMA_ADDRESS_JSON_FILE_NAME="UTC--2021-03-01T02-12-42.714340074Z--41293c2032bac60aa747374e966f79f575d42379" @@ -44,8 +50,6 @@ DELTA_NODE_KEY="725394672587b34bbf15580c59e5199c75c2c7e998ba8df3cb38cc4347d46e2b DELTA_ENODE="ca414c361d1a38716170923e4900d9dc9203dbaf8fdcaee73e1f861df9fdf20a1453b76fd218c18bc6f3c7e13cbca0b3416af02a53b8e31188faa45aab398d1c" DELTA_NODE_PORT="30307" DELTA_AUTHRPC_PORT="8555" -export DELTA_HTTP_PORT="38556" -export DELTA_WS_PORT="38557" # TESTING_ADDRESS is used by the client's internal node. TESTING_ADDRESS="b6de8bb5ed28e6be6d671975cad20c03931be981" @@ -264,23 +268,25 @@ echo "Starting simnet alpha node" "${HARNESS_DIR}/create-node.sh" "$SESSION:1" "alpha" "$ALPHA_NODE_PORT" \ "$CHAIN_ADDRESS" "$PASSWORD" "$CHAIN_ADDRESS_JSON" \ "$CHAIN_ADDRESS_JSON_FILE_NAME" "$ALPHA_ADDRESS_JSON" "$ALPHA_ADDRESS_JSON_FILE_NAME" \ - "$ALPHA_NODE_KEY" "snap" "$ALPHA_AUTHRPC_PORT" + "$ALPHA_NODE_KEY" "snap" "$ALPHA_AUTHRPC_PORT" "$ALPHA_HTTP_PORT" "$ALPHA_WS_PORT" \ + "$ALPHA_WS_MODULES" echo "Starting simnet beta node" "${HARNESS_DIR}/create-node.sh" "$SESSION:2" "beta" "$BETA_NODE_PORT" \ "$CHAIN_ADDRESS" "$PASSWORD" "$CHAIN_ADDRESS_JSON" \ "$CHAIN_ADDRESS_JSON_FILE_NAME" "$BETA_ADDRESS_JSON" "$BETA_ADDRESS_JSON_FILE_NAME" \ - "$BETA_NODE_KEY" "snap" "$BETA_AUTHRPC_PORT" + "$BETA_NODE_KEY" "snap" "$BETA_AUTHRPC_PORT" "$BETA_HTTP_PORT" "$BETA_WS_PORT" \ + "$BETA_WS_MODULES" echo "Starting simnet gamma node" "${HARNESS_DIR}/create-node.sh" "$SESSION:3" "gamma" "$GAMMA_NODE_PORT" \ "_" "_" "_" "_" "$GAMMA_ADDRESS_JSON" "$GAMMA_ADDRESS_JSON_FILE_NAME" \ - "$GAMMA_NODE_KEY" "light" "$GAMMA_AUTHRPC_PORT" + "$GAMMA_NODE_KEY" "light" "$GAMMA_AUTHRPC_PORT" "_" "_" "_" echo "Starting simnet delta node" "${HARNESS_DIR}/create-node.sh" "$SESSION:4" "delta" "$DELTA_NODE_PORT" \ "_" "_" "_" "_" "$DELTA_ADDRESS_JSON" "$DELTA_ADDRESS_JSON_FILE_NAME" \ - "$DELTA_NODE_KEY" "light" "$DELTA_AUTHRPC_PORT" + "$DELTA_NODE_KEY" "light" "$DELTA_AUTHRPC_PORT" "_" "_" "_" sleep 1 @@ -305,7 +311,11 @@ SEND_AMT=5000000000000000000000 echo "Sending 5000 eth to delta and gamma and testing." "${NODES_ROOT}/harness-ctl/alpha" "attach --preload ${NODES_ROOT}/harness-ctl/send.js --exec send(\"${ALPHA_ADDRESS}\",\"${GAMMA_ADDRESS}\",${SEND_AMT})" "${NODES_ROOT}/harness-ctl/alpha" "attach --preload ${NODES_ROOT}/harness-ctl/send.js --exec send(\"${ALPHA_ADDRESS}\",\"${DELTA_ADDRESS}\",${SEND_AMT})" -"${NODES_ROOT}/harness-ctl/alpha" "attach --preload ${NODES_ROOT}/harness-ctl/send.js --exec send(\"${ALPHA_ADDRESS}\",\"${TESTING_ADDRESS}\",${SEND_AMT})" +TEST_TX_HASH=$("${NODES_ROOT}/harness-ctl/alpha" "attach --preload ${NODES_ROOT}/harness-ctl/send.js --exec send(\"${ALPHA_ADDRESS}\",\"${TESTING_ADDRESS}\",${SEND_AMT})" | sed 's/"//g') +echo "ETH transaction to use in tests is ${TEST_TX_HASH}. Saving to ${NODES_ROOT}/test_tx_hash.txt" +cat > "${NODES_ROOT}/test_tx_hash.txt" < "${NODES_ROOT}/test_block10_hash.txt" <