Merge pull request #2827 from nspcc-dev/multiaddr

network: support multiple bind addresses
This commit is contained in:
Roman Khimov 2022-12-07 17:15:56 +07:00 committed by GitHub
commit 90a85259a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 1301 additions and 541 deletions

View file

@ -102,3 +102,36 @@ startup to inform about this, it's very easy to deal with this configuration
change, just replace one line. change, just replace one line.
Removal of SecondsPerBlock is scheduled for May-June 2023 (~0.103.0 release). Removal of SecondsPerBlock is scheduled for May-June 2023 (~0.103.0 release).
## Services/node address and port configuration
Version 0.100.0 of NeoGo introduces a multiple binding addresses capability to
the node's services (RPC server, TLS RPC configuration, Prometheus, Pprof) and
the node itself. It allows to specify several listen addresses/ports using an
array of "address:port" pairs in the service's `Addresses` config section and
array of "address:port:announcedPort" tuples in the `ApplicationConfiguration`'s
`Addresses` node config section. Deprecated `Address` and `Port` sections of
`RPC`, `Prometheus`, `Pprof` subsections of the `ApplicationConfiguration`
as far as the one of RPC server's `TLSConfig` are still available, but will be
removed, so please convert your node configuration file to use new `P2P`-level
`Addresses` section for the node services. Deprecated `Address`, `NodePort` and
`AnnouncedPort` sections of `ApplicationConfiguration` will also be removed
eventually, so please update your node configuration file to use `Addresses`
section for the P2P addresses configuration.
Removal of these config sections is scheduled for May-June 2023 (~0.103.0 release).
## P2P application settings configuration
Version 0.100.0 of NeoGo marks the following P2P application settings as
deprecated: `AttemptConnPeers`, `BroadcastFactor`, `DialTimeout`,
`ExtensiblePoolSize`, `MaxPeers`, `MinPeers`, `PingInterval`, `PingTimeout`,
`ProtoTickInterval`. These settings are moved to a separate `P2P` section of
`ApplicationConfiguration`. The `DialTimeout`, `PingInterval`, `PingTimeout`,
`ProtoTickInterval` settings are converted to more precise `Duration` format
(allowing for subsecond time). Please, update your node configuration (all you
need is to move specified settings under the `P2P` section and convert
time-related settings to `Duration` format).
Removal of deprecated P2P related application settings is scheduled for May-June
2023 (~0.103.0 release).

View file

@ -47,7 +47,7 @@ func TestNEP11Import(t *testing.T) {
args := []string{ args := []string{
"neo-go", "wallet", "nep11", "import", "neo-go", "wallet", "nep11", "import",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", walletPath, "--wallet", walletPath,
} }
// missing token hash // missing token hash
@ -123,7 +123,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// transfer funds to contract owner // transfer funds to contract owner
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", nftOwnerAddr, "--to", nftOwnerAddr,
"--token", "GAS", "--token", "GAS",
@ -139,7 +139,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// mint 1 HASHY token by transferring 10 GAS to HASHY contract // mint 1 HASHY token by transferring 10 GAS to HASHY contract
e.In.WriteString(nftOwnerPass + "\r") e.In.WriteString(nftOwnerPass + "\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--to", h.StringLE(), "--to", h.StringLE(),
"--token", "GAS", "--token", "GAS",
@ -166,7 +166,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// check the balance // check the balance
cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance", cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--address", nftOwnerAddr} "--address", nftOwnerAddr}
checkBalanceResult := func(t *testing.T, acc string, ids ...[]byte) { checkBalanceResult := func(t *testing.T, acc string, ids ...[]byte) {
@ -201,7 +201,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// import token // import token
e.Run(t, "neo-go", "wallet", "nep11", "import", e.Run(t, "neo-go", "wallet", "nep11", "import",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--token", h.StringLE()) "--token", h.StringLE())
@ -211,7 +211,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// balance check: all accounts // balance check: all accounts
e.Run(t, "neo-go", "wallet", "nep11", "balance", e.Run(t, "neo-go", "wallet", "nep11", "balance",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--token", h.StringLE()) "--token", h.StringLE())
checkBalanceResult(t, nftOwnerAddr, tokenID) checkBalanceResult(t, nftOwnerAddr, tokenID)
@ -223,7 +223,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// ownerOf: missing contract hash // ownerOf: missing contract hash
cmdOwnerOf := []string{"neo-go", "wallet", "nep11", "ownerOf", cmdOwnerOf := []string{"neo-go", "wallet", "nep11", "ownerOf",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdOwnerOf...) e.RunWithError(t, cmdOwnerOf...)
cmdOwnerOf = append(cmdOwnerOf, "--token", h.StringLE()) cmdOwnerOf = append(cmdOwnerOf, "--token", h.StringLE())
@ -238,7 +238,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// tokensOf: missing contract hash // tokensOf: missing contract hash
cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf", cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdTokensOf...) e.RunWithError(t, cmdTokensOf...)
cmdTokensOf = append(cmdTokensOf, "--token", h.StringLE()) cmdTokensOf = append(cmdTokensOf, "--token", h.StringLE())
@ -254,7 +254,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// properties: no contract // properties: no contract
cmdProperties := []string{ cmdProperties := []string{
"neo-go", "wallet", "nep11", "properties", "neo-go", "wallet", "nep11", "properties",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdProperties...) e.RunWithError(t, cmdProperties...)
cmdProperties = append(cmdProperties, "--token", h.StringLE()) cmdProperties = append(cmdProperties, "--token", h.StringLE())
@ -280,7 +280,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// tokens: missing contract hash // tokens: missing contract hash
cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens", cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdTokens...) e.RunWithError(t, cmdTokens...)
cmdTokens = append(cmdTokens, "--token", h.StringLE()) cmdTokens = append(cmdTokens, "--token", h.StringLE())
@ -298,7 +298,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
cmdTransfer := []string{ cmdTransfer := []string{
"neo-go", "wallet", "nep11", "transfer", "neo-go", "wallet", "nep11", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--to", testcli.ValidatorAddr, "--to", testcli.ValidatorAddr,
"--from", nftOwnerAddr, "--from", nftOwnerAddr,
@ -328,7 +328,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
verifyH := deployVerifyContract(t, e) verifyH := deployVerifyContract(t, e)
cmdTransfer = []string{ cmdTransfer = []string{
"neo-go", "wallet", "nep11", "transfer", "neo-go", "wallet", "nep11", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--to", verifyH.StringLE(), "--to", verifyH.StringLE(),
"--from", nftOwnerAddr, "--from", nftOwnerAddr,
@ -398,7 +398,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// mint 1.00 NFSO token by transferring 10 GAS to NFSO contract // mint 1.00 NFSO token by transferring 10 GAS to NFSO contract
e.In.WriteString(testcli.ValidatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--to", h.StringLE(), "--to", h.StringLE(),
"--token", "GAS", "--token", "GAS",
@ -432,7 +432,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// check properties // check properties
e.Run(t, "neo-go", "wallet", "nep11", "properties", e.Run(t, "neo-go", "wallet", "nep11", "properties",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--token", h.StringLE(), "--token", h.StringLE(),
"--id", hex.EncodeToString(token1ID)) "--id", hex.EncodeToString(token1ID))
jProps := e.GetNextLine(t) jProps := e.GetNextLine(t)
@ -449,7 +449,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// check the balance // check the balance
cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance", cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--address", testcli.ValidatorAddr} "--address", testcli.ValidatorAddr}
checkBalanceResult := func(t *testing.T, acc string, objs ...idAmount) { checkBalanceResult := func(t *testing.T, acc string, objs ...idAmount) {
@ -481,7 +481,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// import token // import token
e.Run(t, "neo-go", "wallet", "nep11", "import", e.Run(t, "neo-go", "wallet", "nep11", "import",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--token", h.StringLE()) "--token", h.StringLE())
@ -500,7 +500,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// ownerOfD: missing contract hash // ownerOfD: missing contract hash
cmdOwnerOf := []string{"neo-go", "wallet", "nep11", "ownerOfD", cmdOwnerOf := []string{"neo-go", "wallet", "nep11", "ownerOfD",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdOwnerOf...) e.RunWithError(t, cmdOwnerOf...)
cmdOwnerOf = append(cmdOwnerOf, "--token", h.StringLE()) cmdOwnerOf = append(cmdOwnerOf, "--token", h.StringLE())
@ -515,7 +515,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// tokensOf: missing contract hash // tokensOf: missing contract hash
cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf", cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdTokensOf...) e.RunWithError(t, cmdTokensOf...)
cmdTokensOf = append(cmdTokensOf, "--token", h.StringLE()) cmdTokensOf = append(cmdTokensOf, "--token", h.StringLE())
@ -533,7 +533,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// properties: no contract // properties: no contract
cmdProperties := []string{ cmdProperties := []string{
"neo-go", "wallet", "nep11", "properties", "neo-go", "wallet", "nep11", "properties",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdProperties...) e.RunWithError(t, cmdProperties...)
cmdProperties = append(cmdProperties, "--token", h.StringLE()) cmdProperties = append(cmdProperties, "--token", h.StringLE())
@ -566,7 +566,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// tokens: missing contract hash // tokens: missing contract hash
cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens", cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
} }
e.RunWithError(t, cmdTokens...) e.RunWithError(t, cmdTokens...)
cmdTokens = append(cmdTokens, "--token", h.StringLE()) cmdTokens = append(cmdTokens, "--token", h.StringLE())
@ -582,7 +582,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
cmdTransfer := []string{ cmdTransfer := []string{
"neo-go", "wallet", "nep11", "transfer", "neo-go", "wallet", "nep11", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--to", nftOwnerAddr, "--to", nftOwnerAddr,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
@ -612,7 +612,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
verifyH := deployVerifyContract(t, e) verifyH := deployVerifyContract(t, e)
cmdTransfer = []string{ cmdTransfer = []string{
"neo-go", "wallet", "nep11", "transfer", "neo-go", "wallet", "nep11", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", wall, "--wallet", wall,
"--to", verifyH.StringLE(), "--to", verifyH.StringLE(),
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,

View file

@ -21,7 +21,7 @@ func TestNEP17Balance(t *testing.T) {
e := testcli.NewExecutor(t, true) e := testcli.NewExecutor(t, true)
cmdbalance := []string{"neo-go", "wallet", "nep17", "balance"} cmdbalance := []string{"neo-go", "wallet", "nep17", "balance"}
cmdbase := append(cmdbalance, cmdbase := append(cmdbalance,
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
) )
cmd := append(cmdbase, "--address", testcli.ValidatorAddr) cmd := append(cmdbase, "--address", testcli.ValidatorAddr)
@ -122,7 +122,7 @@ func TestNEP17Transfer(t *testing.T) {
e := testcli.NewExecutor(t, true) e := testcli.NewExecutor(t, true)
args := []string{ args := []string{
"neo-go", "wallet", "nep17", "transfer", "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", w.Accounts[0].Address, "--to", w.Accounts[0].Address,
"--token", "NEO", "--token", "NEO",
@ -182,7 +182,7 @@ func TestNEP17Transfer(t *testing.T) {
t.Run("default address", func(t *testing.T) { t.Run("default address", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
@ -208,7 +208,7 @@ func TestNEP17Transfer(t *testing.T) {
t.Run("with signers", func(t *testing.T) { t.Run("with signers", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
@ -221,7 +221,7 @@ func TestNEP17Transfer(t *testing.T) {
validTil := e.Chain.BlockHeight() + 100 validTil := e.Chain.BlockHeight() + 100
cmd := []string{ cmd := []string{
"neo-go", "wallet", "nep17", "transfer", "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()), "--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()),
"--token", "GAS", "--token", "GAS",
@ -262,7 +262,7 @@ func TestNEP17MultiTransfer(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
args := []string{ args := []string{
"neo-go", "wallet", "nep17", "multitransfer", "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
@ -318,26 +318,26 @@ func TestNEP17ImportToken(t *testing.T) {
// missing token hash // missing token hash
e.RunWithError(t, "neo-go", "wallet", "nep17", "import", e.RunWithError(t, "neo-go", "wallet", "nep17", "import",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath) "--wallet", walletPath)
// additional parameter // additional parameter
e.RunWithError(t, "neo-go", "wallet", "nep17", "import", e.RunWithError(t, "neo-go", "wallet", "nep17", "import",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--wallet", walletPath,
"--token", gasContractHash.StringLE(), "useless") "--token", gasContractHash.StringLE(), "useless")
e.Run(t, "neo-go", "wallet", "nep17", "import", e.Run(t, "neo-go", "wallet", "nep17", "import",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--wallet", walletPath,
"--token", gasContractHash.StringLE()) "--token", gasContractHash.StringLE())
e.Run(t, "neo-go", "wallet", "nep17", "import", e.Run(t, "neo-go", "wallet", "nep17", "import",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--wallet", walletPath,
"--token", address.Uint160ToString(neoContractHash)) // try address instead of sh "--token", address.Uint160ToString(neoContractHash)) // try address instead of sh
// not a NEP-17 token // not a NEP-17 token
e.RunWithError(t, "neo-go", "wallet", "nep17", "import", e.RunWithError(t, "neo-go", "wallet", "nep17", "import",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--wallet", walletPath,
"--token", nnsContractHash.StringLE()) "--token", nnsContractHash.StringLE())

View file

@ -24,7 +24,7 @@ func TestGetRPCClient(t *testing.T) {
t.Run("success", func(t *testing.T) { t.Run("success", func(t *testing.T) {
set := flag.NewFlagSet("flagSet", flag.ExitOnError) set := flag.NewFlagSet("flagSet", flag.ExitOnError)
set.String(options.RPCEndpointFlag, "http://"+e.RPC.Addr, "") set.String(options.RPCEndpointFlag, "http://"+e.RPC.Addresses()[0], "")
ctx := cli.NewContext(app.New(), set, nil) ctx := cli.NewContext(app.New(), set, nil)
gctx, _ := options.GetTimeoutContext(ctx) gctx, _ := options.GetTimeoutContext(ctx)
_, ec := options.GetRPCClient(gctx, ctx) _, ec := options.GetRPCClient(gctx, ctx)

View file

@ -30,7 +30,7 @@ func TestQueryTx(t *testing.T) {
transferArgs := []string{ transferArgs := []string{
"neo-go", "wallet", "nep17", "transfer", "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", w.Accounts[0].Address, "--to", w.Accounts[0].Address,
"--token", "NEO", "--token", "NEO",
@ -47,7 +47,7 @@ func TestQueryTx(t *testing.T) {
tx, ok := e.Chain.GetMemPool().TryGetValue(txHash) tx, ok := e.Chain.GetMemPool().TryGetValue(txHash)
require.True(t, ok) require.True(t, ok)
args := []string{"neo-go", "query", "tx", "--rpc-endpoint", "http://" + e.RPC.Addr} args := []string{"neo-go", "query", "tx", "--rpc-endpoint", "http://" + e.RPC.Addresses()[0]}
e.Run(t, append(args, txHash.StringLE())...) e.Run(t, append(args, txHash.StringLE())...)
e.CheckNextLine(t, `Hash:\s+`+txHash.StringLE()) e.CheckNextLine(t, `Hash:\s+`+txHash.StringLE())
e.CheckNextLine(t, `OnChain:\s+false`) e.CheckNextLine(t, `OnChain:\s+false`)
@ -74,7 +74,7 @@ func TestQueryTx(t *testing.T) {
t.Run("FAULT", func(t *testing.T) { t.Run("FAULT", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "invokefunction", e.Run(t, "neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", testcli.ValidatorAddr, "--address", testcli.ValidatorAddr,
"--force", "--force",
@ -144,7 +144,7 @@ func compareQueryTxVerbose(t *testing.T, e *testcli.Executor, tx *transaction.Tr
func TestQueryHeight(t *testing.T) { func TestQueryHeight(t *testing.T) {
e := testcli.NewExecutor(t, true) e := testcli.NewExecutor(t, true)
args := []string{"neo-go", "query", "height", "--rpc-endpoint", "http://" + e.RPC.Addr} args := []string{"neo-go", "query", "height", "--rpc-endpoint", "http://" + e.RPC.Addresses()[0]}
e.Run(t, args...) e.Run(t, args...)
e.CheckNextLine(t, `^Latest block: [0-9]+$`) e.CheckNextLine(t, `^Latest block: [0-9]+$`)
e.CheckNextLine(t, `^Validated state: [0-9]+$`) e.CheckNextLine(t, `^Validated state: [0-9]+$`)

View file

@ -141,8 +141,14 @@ func initBCWithMetrics(cfg config.Config, log *zap.Logger) (*core.Blockchain, *m
pprof := metrics.NewPprofService(cfg.ApplicationConfiguration.Pprof, log) pprof := metrics.NewPprofService(cfg.ApplicationConfiguration.Pprof, log)
go chain.Run() go chain.Run()
go prometheus.Start() err = prometheus.Start()
go pprof.Start() if err != nil {
return nil, nil, nil, cli.NewExitError(fmt.Errorf("failed to start Prometheus service: %w", err), 1)
}
err = pprof.Start()
if err != nil {
return nil, nil, nil, cli.NewExitError(fmt.Errorf("failed to start Pprof service: %w", err), 1)
}
return chain, prometheus, pprof, nil return chain, prometheus, pprof, nil
} }
@ -440,7 +446,10 @@ func startServer(ctx *cli.Context) error {
grace, cancel := context.WithCancel(newGraceContext()) grace, cancel := context.WithCancel(newGraceContext())
defer cancel() defer cancel()
serverConfig := network.NewServerConfig(cfg) serverConfig, err := network.NewServerConfig(cfg)
if err != nil {
return cli.NewExitError(err, 1)
}
chain, prometheus, pprof, err := initBCWithMetrics(cfg, log) chain, prometheus, pprof, err := initBCWithMetrics(cfg, log)
if err != nil { if err != nil {
@ -540,10 +549,18 @@ Main:
} }
pprof.ShutDown() pprof.ShutDown()
pprof = metrics.NewPprofService(cfgnew.ApplicationConfiguration.Pprof, log) pprof = metrics.NewPprofService(cfgnew.ApplicationConfiguration.Pprof, log)
go pprof.Start() err = pprof.Start()
if err != nil {
shutdownErr = fmt.Errorf("failed to start Pprof service: %w", err)
cancel() // Fatal error, like for RPC server.
}
prometheus.ShutDown() prometheus.ShutDown()
prometheus = metrics.NewPrometheusService(cfgnew.ApplicationConfiguration.Prometheus, log) prometheus = metrics.NewPrometheusService(cfgnew.ApplicationConfiguration.Prometheus, log)
go prometheus.Start() err = prometheus.Start()
if err != nil {
shutdownErr = fmt.Errorf("failed to start Prometheus service: %w", err)
cancel() // Fatal error, like for RPC server.
}
case sigusr1: case sigusr1:
if oracleSrv != nil { if oracleSrv != nil {
serv.DelService(oracleSrv) serv.DelService(oracleSrv)
@ -621,15 +638,15 @@ Main:
// In case global Address (of the node) provided and RPC/Prometheus/Pprof don't have configured addresses they will // In case global Address (of the node) provided and RPC/Prometheus/Pprof don't have configured addresses they will
// use global one. So Node and RPC and Prometheus and Pprof will run on one address. // use global one. So Node and RPC and Prometheus and Pprof will run on one address.
func configureAddresses(cfg *config.ApplicationConfiguration) { func configureAddresses(cfg *config.ApplicationConfiguration) {
if cfg.Address != "" { if cfg.Address != nil && *cfg.Address != "" { //nolint:staticcheck // SA1019: cfg.Address is deprecated
if cfg.RPC.Address == "" { if cfg.RPC.Address == nil || *cfg.RPC.Address == "" { //nolint:staticcheck // SA1019: cfg.RPC.Address is deprecated
cfg.RPC.Address = cfg.Address cfg.RPC.Address = cfg.Address //nolint:staticcheck // SA1019: cfg.RPC.Address is deprecated
} }
if cfg.Prometheus.Address == "" { if cfg.Prometheus.Address == nil || *cfg.Prometheus.Address == "" { //nolint:staticcheck // SA1019: cfg.Prometheus.Address is deprecated
cfg.Prometheus.Address = cfg.Address cfg.Prometheus.Address = cfg.Address //nolint:staticcheck // SA1019: cfg.Prometheus.Address is deprecated
} }
if cfg.Pprof.Address == "" { if cfg.Pprof.Address == nil || *cfg.Pprof.Address == "" { //nolint:staticcheck // SA1019: cfg.Pprof.Address is deprecated
cfg.Pprof.Address = cfg.Address cfg.Pprof.Address = cfg.Address //nolint:staticcheck // SA1019: cfg.Pprof.Address is deprecated
} }
} }
} }

View file

@ -312,57 +312,61 @@ func TestRestoreDB(t *testing.T) {
require.NoError(t, restoreDB(ctx)) require.NoError(t, restoreDB(ctx))
} }
// TestConfigureAddresses checks deprecated code compatibility, it should be removed
// along with deprecated `Address` field removal.
func TestConfigureAddresses(t *testing.T) { func TestConfigureAddresses(t *testing.T) {
defaultAddress := "http://localhost:10333" defaultAddress := "http://localhost:10333"
customAddress := "http://localhost:10334" customAddress := "http://localhost:10334"
t.Run("default addresses", func(t *testing.T) { t.Run("default addresses", func(t *testing.T) {
cfg := &config.ApplicationConfiguration{ cfg := &config.ApplicationConfiguration{
Address: defaultAddress, Address: &defaultAddress, //nolint:staticcheck // SA1019: Address is deprecated
} }
configureAddresses(cfg) configureAddresses(cfg)
require.Equal(t, defaultAddress, cfg.RPC.Address) require.Equal(t, defaultAddress, *cfg.RPC.Address) //nolint:staticcheck // SA1019: cfg.RPC.Address is deprecated
require.Equal(t, defaultAddress, cfg.Prometheus.Address) require.Equal(t, defaultAddress, *cfg.Prometheus.Address) //nolint:staticcheck // SA1019: cfg.Prometheus.Address is deprecated
require.Equal(t, defaultAddress, cfg.Pprof.Address) require.Equal(t, defaultAddress, *cfg.Pprof.Address) //nolint:staticcheck // SA1019: cfg.Pprof.Address is deprecated
}) })
t.Run("custom RPC address", func(t *testing.T) { t.Run("custom RPC address", func(t *testing.T) {
cfg := &config.ApplicationConfiguration{ cfg := &config.ApplicationConfiguration{
Address: defaultAddress, Address: &defaultAddress, //nolint:staticcheck // SA1019: Address is deprecated
RPC: config.RPC{ RPC: config.RPC{
Address: customAddress, BasicService: config.BasicService{
Address: &customAddress, //nolint:staticcheck // SA1019: Address is deprecated
},
}, },
} }
configureAddresses(cfg) configureAddresses(cfg)
require.Equal(t, cfg.RPC.Address, customAddress) require.Equal(t, *cfg.RPC.Address, customAddress) //nolint:staticcheck // SA1019: cfg.RPC.Address is deprecated
require.Equal(t, cfg.Prometheus.Address, defaultAddress) require.Equal(t, *cfg.Prometheus.Address, defaultAddress) //nolint:staticcheck // SA1019: cfg.Prometheus.Address is deprecated
require.Equal(t, cfg.Pprof.Address, defaultAddress) require.Equal(t, *cfg.Pprof.Address, defaultAddress) //nolint:staticcheck // SA1019: cfg.Pprof.Address is deprecated
}) })
t.Run("custom Pprof address", func(t *testing.T) { t.Run("custom Pprof address", func(t *testing.T) {
cfg := &config.ApplicationConfiguration{ cfg := &config.ApplicationConfiguration{
Address: defaultAddress, Address: &defaultAddress, //nolint:staticcheck // SA1019: Address is deprecated
Pprof: config.BasicService{ Pprof: config.BasicService{
Address: customAddress, Address: &customAddress, //nolint:staticcheck // SA1019: Address is deprecated
}, },
} }
configureAddresses(cfg) configureAddresses(cfg)
require.Equal(t, cfg.RPC.Address, defaultAddress) require.Equal(t, *cfg.RPC.Address, defaultAddress) //nolint:staticcheck // SA1019: cfg.RPC.Address is deprecated
require.Equal(t, cfg.Prometheus.Address, defaultAddress) require.Equal(t, *cfg.Prometheus.Address, defaultAddress) //nolint:staticcheck // SA1019: cfg.Prometheus.Address is deprecated
require.Equal(t, cfg.Pprof.Address, customAddress) require.Equal(t, *cfg.Pprof.Address, customAddress) //nolint:staticcheck // SA1019: cfg.Pprof.Address is deprecated
}) })
t.Run("custom Prometheus address", func(t *testing.T) { t.Run("custom Prometheus address", func(t *testing.T) {
cfg := &config.ApplicationConfiguration{ cfg := &config.ApplicationConfiguration{
Address: defaultAddress, Address: &defaultAddress, //nolint:staticcheck // SA1019: Address is deprecated
Prometheus: config.BasicService{ Prometheus: config.BasicService{
Address: customAddress, Address: &customAddress, //nolint:staticcheck // SA1019: Address is deprecated
}, },
} }
configureAddresses(cfg) configureAddresses(cfg)
require.Equal(t, cfg.RPC.Address, defaultAddress) require.Equal(t, *cfg.RPC.Address, defaultAddress) //nolint:staticcheck // SA1019: cfg.RPC.Address is deprecated
require.Equal(t, cfg.Prometheus.Address, customAddress) require.Equal(t, *cfg.Prometheus.Address, customAddress) //nolint:staticcheck // SA1019: cfg.Prometheus.Address is deprecated
require.Equal(t, cfg.Pprof.Address, defaultAddress) require.Equal(t, *cfg.Pprof.Address, defaultAddress) //nolint:staticcheck // SA1019: cfg.Pprof.Address is deprecated
}) })
} }

View file

@ -310,7 +310,7 @@ func TestDeployBigContract(t *testing.T) {
e.In.WriteString(testcli.ValidatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName) "--in", nefName, "--manifest", manifestName)
} }
@ -333,7 +333,7 @@ func TestContractDeployWithData(t *testing.T) {
e := testcli.NewExecutor(t, true) e := testcli.NewExecutor(t, true)
cmd := []string{ cmd := []string{
"neo-go", "contract", "deploy", "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"--force", "--force",
@ -363,7 +363,7 @@ func TestContractDeployWithData(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
e.Run(t, "neo-go", "contract", "testinvokefunction", e.Run(t, "neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
h.StringLE(), h.StringLE(),
"getValueWithKey", "key1", "getValueWithKey", "key1",
) )
@ -375,7 +375,7 @@ func TestContractDeployWithData(t *testing.T) {
require.Equal(t, []byte{12}, res.Stack[0].Value()) require.Equal(t, []byte{12}, res.Stack[0].Value())
e.Run(t, "neo-go", "contract", "testinvokefunction", e.Run(t, "neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
h.StringLE(), h.StringLE(),
"getValueWithKey", "key2", "getValueWithKey", "key2",
) )
@ -408,33 +408,33 @@ func TestDeployWithSigners(t *testing.T) {
t.Run("missing nef", func(t *testing.T) { t.Run("missing nef", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", "", "--manifest", manifestName) "--in", "", "--manifest", manifestName)
}) })
t.Run("missing manifest", func(t *testing.T) { t.Run("missing manifest", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", "") "--in", nefName, "--manifest", "")
}) })
t.Run("corrupted data", func(t *testing.T) { t.Run("corrupted data", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"[", "str1") "[", "str1")
}) })
t.Run("invalid data", func(t *testing.T) { t.Run("invalid data", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"str1", "str2") "str1", "str2")
}) })
t.Run("missing wallet", func(t *testing.T) { t.Run("missing wallet", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--address", testcli.ValidatorAddr, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"[", "str1", "str2", "]") "[", "str1", "str2", "]")
@ -447,7 +447,7 @@ func TestDeployWithSigners(t *testing.T) {
}) })
e.In.WriteString(testcli.ValidatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, "neo-go", "contract", "deploy", e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"--force", "--force",
@ -534,7 +534,7 @@ func TestContractManifestGroups(t *testing.T) {
e.In.WriteString(testcli.ValidatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, "neo-go", "contract", "deploy", e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"--force", "--force",
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr) "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr)
@ -557,22 +557,22 @@ func TestContract_TestInvokeScript(t *testing.T) {
t.Run("missing in", func(t *testing.T) { t.Run("missing in", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "testinvokescript", e.RunWithError(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addresses()[0])
}) })
t.Run("unexisting in", func(t *testing.T) { t.Run("unexisting in", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "testinvokescript", e.RunWithError(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--in", badNef) "--in", badNef)
}) })
t.Run("invalid nef", func(t *testing.T) { t.Run("invalid nef", func(t *testing.T) {
require.NoError(t, os.WriteFile(badNef, []byte("qwer"), os.ModePerm)) require.NoError(t, os.WriteFile(badNef, []byte("qwer"), os.ModePerm))
e.RunWithError(t, "neo-go", "contract", "testinvokescript", e.RunWithError(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--in", badNef) "--in", badNef)
}) })
t.Run("invalid signers", func(t *testing.T) { t.Run("invalid signers", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "testinvokescript", e.RunWithError(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--in", goodNef, "--", "not-a-valid-signer") "--in", goodNef, "--", "not-a-valid-signer")
}) })
t.Run("no RPC endpoint", func(t *testing.T) { t.Run("no RPC endpoint", func(t *testing.T) {
@ -582,34 +582,34 @@ func TestContract_TestInvokeScript(t *testing.T) {
}) })
t.Run("good", func(t *testing.T) { t.Run("good", func(t *testing.T) {
e.Run(t, "neo-go", "contract", "testinvokescript", e.Run(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--in", goodNef) "--in", goodNef)
}) })
t.Run("good with hashed signer", func(t *testing.T) { t.Run("good with hashed signer", func(t *testing.T) {
e.Run(t, "neo-go", "contract", "testinvokescript", e.Run(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--in", goodNef, "--", util.Uint160{1, 2, 3}.StringLE()) "--in", goodNef, "--", util.Uint160{1, 2, 3}.StringLE())
}) })
t.Run("good with addressed signer", func(t *testing.T) { t.Run("good with addressed signer", func(t *testing.T) {
e.Run(t, "neo-go", "contract", "testinvokescript", e.Run(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--in", goodNef, "--", address.Uint160ToString(util.Uint160{1, 2, 3})) "--in", goodNef, "--", address.Uint160ToString(util.Uint160{1, 2, 3}))
}) })
t.Run("historic, invalid", func(t *testing.T) { t.Run("historic, invalid", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "testinvokescript", e.RunWithError(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--historic", "bad", "--historic", "bad",
"--in", goodNef) "--in", goodNef)
}) })
t.Run("historic, index", func(t *testing.T) { t.Run("historic, index", func(t *testing.T) {
e.Run(t, "neo-go", "contract", "testinvokescript", e.Run(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--historic", "0", "--historic", "0",
"--in", goodNef) "--in", goodNef)
}) })
t.Run("historic, hash", func(t *testing.T) { t.Run("historic, hash", func(t *testing.T) {
e.Run(t, "neo-go", "contract", "testinvokescript", e.Run(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--historic", e.Chain.GetHeaderHash(0).StringLE(), "--historic", e.Chain.GetHeaderHash(0).StringLE(),
"--in", goodNef) "--in", goodNef)
}) })
@ -639,7 +639,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, os.WriteFile(configPath, yml, 0666)) require.NoError(t, os.WriteFile(configPath, yml, 0666))
e.Run(t, "neo-go", "contract", "deploy", e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--force", "--rpc-endpoint", "http://"+e.RPC.Addresses()[0], "--force",
"--wallet-config", configPath, "--address", testcli.ValidatorAddr, "--wallet-config", configPath, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName) "--in", nefName, "--manifest", manifestName)
@ -663,7 +663,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
}) })
cmd := []string{"neo-go", "contract", "testinvokefunction", cmd := []string{"neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr} "--rpc-endpoint", "http://" + e.RPC.Addresses()[0]}
t.Run("missing hash", func(t *testing.T) { t.Run("missing hash", func(t *testing.T) {
e.RunWithError(t, cmd...) e.RunWithError(t, cmd...)
}) })
@ -704,7 +704,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
t.Run("real invoke", func(t *testing.T) { t.Run("real invoke", func(t *testing.T) {
cmd := []string{"neo-go", "contract", "invokefunction", cmd := []string{"neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr} "--rpc-endpoint", "http://" + e.RPC.Addresses()[0]}
t.Run("missing wallet", func(t *testing.T) { t.Run("missing wallet", func(t *testing.T) {
cmd := append(cmd, h.StringLE(), "getValue") cmd := append(cmd, h.StringLE(), "getValue")
e.RunWithError(t, cmd...) e.RunWithError(t, cmd...)
@ -778,7 +778,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
txout := filepath.Join(tmpDir, "test_contract_tx.json") txout := filepath.Join(tmpDir, "test_contract_tx.json")
cmd = []string{"neo-go", "contract", "invokefunction", cmd = []string{"neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--out", txout, "--out", txout,
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
} }
@ -837,7 +837,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
t.Run("test Storage.Find", func(t *testing.T) { t.Run("test Storage.Find", func(t *testing.T) {
cmd := []string{"neo-go", "contract", "testinvokefunction", cmd := []string{"neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
h.StringLE(), "testFind"} h.StringLE(), "testFind"}
t.Run("keys only", func(t *testing.T) { t.Run("keys only", func(t *testing.T) {
@ -901,7 +901,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
stateBeforeUpdate = mptBeforeUpdate.Root stateBeforeUpdate = mptBeforeUpdate.Root
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "invokefunction", e.Run(t, "neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--force", "--force",
h.StringLE(), "update", h.StringLE(), "update",
@ -913,14 +913,14 @@ func TestComlileAndInvokeFunction(t *testing.T) {
indexAfterUpdate = e.Chain.BlockHeight() indexAfterUpdate = e.Chain.BlockHeight()
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "testinvokefunction", e.Run(t, "neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
h.StringLE(), "getValue") h.StringLE(), "getValue")
checkGetValueOut("on update|sub update") checkGetValueOut("on update|sub update")
}) })
t.Run("historic", func(t *testing.T) { t.Run("historic", func(t *testing.T) {
t.Run("bad ref", func(t *testing.T) { t.Run("bad ref", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "testinvokefunction", e.RunWithError(t, "neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--historic", "bad", "--historic", "bad",
h.StringLE(), "getValue") h.StringLE(), "getValue")
}) })
@ -931,7 +931,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
} { } {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
e.Run(t, "neo-go", "contract", "testinvokefunction", e.Run(t, "neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--historic", ref, "--historic", ref,
h.StringLE(), "getValue") h.StringLE(), "getValue")
}) })
@ -939,7 +939,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
} }
t.Run("updated historic", func(t *testing.T) { t.Run("updated historic", func(t *testing.T) {
e.Run(t, "neo-go", "contract", "testinvokefunction", e.Run(t, "neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--historic", strconv.FormatUint(uint64(indexAfterUpdate), 10), "--historic", strconv.FormatUint(uint64(indexAfterUpdate), 10),
h.StringLE(), "getValue") h.StringLE(), "getValue")
checkGetValueOut("on update|sub update") checkGetValueOut("on update|sub update")

View file

@ -22,7 +22,7 @@ func TestRegisterCandidate(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
@ -31,29 +31,29 @@ func TestRegisterCandidate(t *testing.T) {
e.CheckTxPersisted(t) e.CheckTxPersisted(t)
e.Run(t, "neo-go", "query", "committee", e.Run(t, "neo-go", "query", "committee",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addresses()[0])
e.CheckNextLine(t, "^\\s*"+validatorHex) e.CheckNextLine(t, "^\\s*"+validatorHex)
e.Run(t, "neo-go", "query", "candidates", e.Run(t, "neo-go", "query", "candidates",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addresses()[0])
e.CheckNextLine(t, "^\\s*Key.+$") // Header. e.CheckNextLine(t, "^\\s*Key.+$") // Header.
e.CheckEOF(t) e.CheckEOF(t)
// missing address // missing address
e.RunWithError(t, "neo-go", "wallet", "candidate", "register", e.RunWithError(t, "neo-go", "wallet", "candidate", "register",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet) "--wallet", testcli.ValidatorWallet)
// additional parameter // additional parameter
e.RunWithError(t, "neo-go", "wallet", "candidate", "register", e.RunWithError(t, "neo-go", "wallet", "candidate", "register",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddress, "--address", validatorAddress,
"error") "error")
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "register", e.Run(t, "neo-go", "wallet", "candidate", "register",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddress, "--address", validatorAddress,
"--force") "--force")
@ -68,14 +68,14 @@ func TestRegisterCandidate(t *testing.T) {
t.Run("VoteUnvote", func(t *testing.T) { t.Run("VoteUnvote", func(t *testing.T) {
// positional instead of a flag. // positional instead of a flag.
e.RunWithError(t, "neo-go", "wallet", "candidate", "vote", e.RunWithError(t, "neo-go", "wallet", "candidate", "vote",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddress, "--address", validatorAddress,
validatorHex) // not "--candidate hex", but "hex". validatorHex) // not "--candidate hex", but "hex".
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "vote", e.Run(t, "neo-go", "wallet", "candidate", "vote",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddress, "--address", validatorAddress,
"--candidate", validatorHex, "--candidate", validatorHex,
@ -89,18 +89,18 @@ func TestRegisterCandidate(t *testing.T) {
require.Equal(t, b, vs[0].Votes) require.Equal(t, b, vs[0].Votes)
e.Run(t, "neo-go", "query", "committee", e.Run(t, "neo-go", "query", "committee",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addresses()[0])
e.CheckNextLine(t, "^\\s*"+validatorHex) e.CheckNextLine(t, "^\\s*"+validatorHex)
e.Run(t, "neo-go", "query", "candidates", e.Run(t, "neo-go", "query", "candidates",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addresses()[0])
e.CheckNextLine(t, "^\\s*Key.+$") // Header. e.CheckNextLine(t, "^\\s*Key.+$") // Header.
e.CheckNextLine(t, "^\\s*"+validatorHex+"\\s*"+b.String()+"\\s*true\\s*true$") e.CheckNextLine(t, "^\\s*"+validatorHex+"\\s*"+b.String()+"\\s*true\\s*true$")
e.CheckEOF(t) e.CheckEOF(t)
// check state // check state
e.Run(t, "neo-go", "query", "voter", e.Run(t, "neo-go", "query", "voter",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
validatorAddress) validatorAddress)
e.CheckNextLine(t, "^\\s*Voted:\\s+"+validatorHex+"\\s+\\("+validatorAddress+"\\)$") e.CheckNextLine(t, "^\\s*Voted:\\s+"+validatorHex+"\\s+\\("+validatorAddress+"\\)$")
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$")
@ -110,7 +110,7 @@ func TestRegisterCandidate(t *testing.T) {
// unvote // unvote
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "vote", e.Run(t, "neo-go", "wallet", "candidate", "vote",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddress, "--address", validatorAddress,
"--force") "--force")
@ -123,7 +123,7 @@ func TestRegisterCandidate(t *testing.T) {
// check state // check state
e.Run(t, "neo-go", "query", "voter", e.Run(t, "neo-go", "query", "voter",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
validatorAddress) validatorAddress)
e.CheckNextLine(t, "^\\s*Voted:\\s+"+"null") // no vote. e.CheckNextLine(t, "^\\s*Voted:\\s+"+"null") // no vote.
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$")
@ -133,18 +133,18 @@ func TestRegisterCandidate(t *testing.T) {
// missing address // missing address
e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister", e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet) "--wallet", testcli.ValidatorWallet)
// additional argument // additional argument
e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister", e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddress, "--address", validatorAddress,
"argument") "argument")
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "unregister", e.Run(t, "neo-go", "wallet", "candidate", "unregister",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddress, "--address", validatorAddress,
"--force") "--force")
@ -156,7 +156,7 @@ func TestRegisterCandidate(t *testing.T) {
// query voter: missing address // query voter: missing address
e.RunWithError(t, "neo-go", "query", "voter") e.RunWithError(t, "neo-go", "query", "voter")
// Excessive parameters. // Excessive parameters.
e.RunWithError(t, "neo-go", "query", "voter", "--rpc-endpoint", "http://"+e.RPC.Addr, validatorAddress, validatorAddress) e.RunWithError(t, "neo-go", "query", "voter", "--rpc-endpoint", "http://"+e.RPC.Addresses()[0], validatorAddress, validatorAddress)
e.RunWithError(t, "neo-go", "query", "committee", "--rpc-endpoint", "http://"+e.RPC.Addr, "something") e.RunWithError(t, "neo-go", "query", "committee", "--rpc-endpoint", "http://"+e.RPC.Addresses()[0], "something")
e.RunWithError(t, "neo-go", "query", "candidates", "--rpc-endpoint", "http://"+e.RPC.Addr, "something") e.RunWithError(t, "neo-go", "query", "candidates", "--rpc-endpoint", "http://"+e.RPC.Addresses()[0], "something")
} }

View file

@ -55,7 +55,7 @@ func TestSignMultisigTx(t *testing.T) {
// Transfer funds to the multisig. // Transfer funds to the multisig.
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
@ -74,7 +74,7 @@ func TestSignMultisigTx(t *testing.T) {
}) })
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet1Path, "--from", multisigAddr, "--wallet", wallet1Path, "--from", multisigAddr,
"--to", priv.Address(), "--token", "NEO", "--amount", "1", "--to", priv.Address(), "--token", "NEO", "--amount", "1",
"--out", txPath) "--out", txPath)
@ -99,7 +99,7 @@ func TestSignMultisigTx(t *testing.T) {
// invalid out // invalid out
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.RunWithError(t, "neo-go", "wallet", "sign", e.RunWithError(t, "neo-go", "wallet", "sign",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet2Path, "--address", multisigAddr, "--wallet", wallet2Path, "--address", multisigAddr,
"--in", txPath, "--out", t.TempDir()) "--in", txPath, "--out", t.TempDir())
@ -118,7 +118,7 @@ func TestSignMultisigTx(t *testing.T) {
}) })
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet1Path, "--from", multisigAddr, "--wallet", wallet1Path, "--from", multisigAddr,
"--to", priv.Address(), "--token", "NEO", "--amount", "1", "--to", priv.Address(), "--token", "NEO", "--amount", "1",
"--out", txPath) "--out", txPath)
@ -152,11 +152,11 @@ func TestSignMultisigTx(t *testing.T) {
t.Run("excessive parameters", func(t *testing.T) { t.Run("excessive parameters", func(t *testing.T) {
e.RunWithError(t, "neo-go", "util", "txdump", e.RunWithError(t, "neo-go", "util", "txdump",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
txPath, "garbage") txPath, "garbage")
}) })
e.Run(t, "neo-go", "util", "txdump", e.Run(t, "neo-go", "util", "txdump",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
txPath) txPath)
e.CheckTxTestInvokeOutput(t, 11) e.CheckTxTestInvokeOutput(t, 11)
res := new(result.Invoke) res := new(result.Invoke)
@ -194,7 +194,7 @@ func TestSignMultisigTx(t *testing.T) {
t.Run("sign, save and send", func(t *testing.T) { t.Run("sign, save and send", func(t *testing.T) {
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "sign", e.Run(t, "neo-go", "wallet", "sign",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet2Path, "--address", multisigAddr, "--wallet", wallet2Path, "--address", multisigAddr,
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
e.CheckTxPersisted(t) e.CheckTxPersisted(t)
@ -202,7 +202,7 @@ func TestSignMultisigTx(t *testing.T) {
t.Run("double-sign", func(t *testing.T) { t.Run("double-sign", func(t *testing.T) {
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.RunWithError(t, "neo-go", "wallet", "sign", e.RunWithError(t, "neo-go", "wallet", "sign",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet2Path, "--address", multisigAddr, "--wallet", wallet2Path, "--address", multisigAddr,
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
}) })
@ -217,13 +217,13 @@ func TestSignMultisigTx(t *testing.T) {
e.In.WriteString("acc\rpass\rpass\r") e.In.WriteString("acc\rpass\rpass\r")
e.Run(t, "neo-go", "wallet", "import-deployed", e.Run(t, "neo-go", "wallet", "import-deployed",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet1Path, "--wif", simplePriv.WIF(), "--wallet", wallet1Path, "--wif", simplePriv.WIF(),
"--contract", h.StringLE()) "--contract", h.StringLE())
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.Run(t, "neo-go", "contract", "invokefunction", e.Run(t, "neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet1Path, "--address", multisigHash.StringLE(), // test with scripthash instead of address "--wallet", wallet1Path, "--address", multisigHash.StringLE(), // test with scripthash instead of address
"--out", txPath, "--out", txPath,
e.Chain.GoverningTokenHash().StringLE(), "transfer", e.Chain.GoverningTokenHash().StringLE(), "transfer",
@ -249,7 +249,7 @@ func TestSignMultisigTx(t *testing.T) {
// Contract. // Contract.
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "sign", e.Run(t, "neo-go", "wallet", "sign",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet1Path, "--address", address.Uint160ToString(h), "--wallet", wallet1Path, "--address", address.Uint160ToString(h),
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
tx, _ := e.CheckTxPersisted(t) tx, _ := e.CheckTxPersisted(t)

View file

@ -470,17 +470,17 @@ func TestWalletClaimGas(t *testing.T) {
t.Run("missing wallet path", func(t *testing.T) { t.Run("missing wallet path", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--address", testcli.TestWalletAccount) "--address", testcli.TestWalletAccount)
}) })
t.Run("missing address", func(t *testing.T) { t.Run("missing address", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.TestWalletPath) "--wallet", testcli.TestWalletPath)
}) })
t.Run("invalid address", func(t *testing.T) { t.Run("invalid address", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.TestWalletPath, "--wallet", testcli.TestWalletPath,
"--address", util.Uint160{}.StringLE()) "--address", util.Uint160{}.StringLE())
}) })
@ -493,14 +493,14 @@ func TestWalletClaimGas(t *testing.T) {
t.Run("insufficient funds", func(t *testing.T) { t.Run("insufficient funds", func(t *testing.T) {
e.In.WriteString("testpass\r") e.In.WriteString("testpass\r")
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.TestWalletPath, "--wallet", testcli.TestWalletPath,
"--address", testcli.TestWalletAccount) "--address", testcli.TestWalletAccount)
}) })
args := []string{ args := []string{
"neo-go", "wallet", "nep17", "multitransfer", "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
@ -522,7 +522,7 @@ func TestWalletClaimGas(t *testing.T) {
e.In.WriteString("testpass\r") e.In.WriteString("testpass\r")
e.Run(t, "neo-go", "wallet", "claim", e.Run(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.TestWalletPath, "--wallet", testcli.TestWalletPath,
"--address", testcli.TestWalletAccount, "--address", testcli.TestWalletAccount,
"--force") "--force")
@ -570,7 +570,7 @@ func TestWalletImportDeployed(t *testing.T) {
t.Run("unknown contract", func(t *testing.T) { t.Run("unknown contract", func(t *testing.T) {
e.In.WriteString("acc\rpass\rpass\r") e.In.WriteString("acc\rpass\rpass\r")
e.RunWithError(t, "neo-go", "wallet", "import-deployed", e.RunWithError(t, "neo-go", "wallet", "import-deployed",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--contract", util.Uint160{}.StringLE(), "--wallet", walletPath, "--contract", util.Uint160{}.StringLE(),
"--wif", priv.WIF()) "--wif", priv.WIF())
}) })
@ -578,14 +578,14 @@ func TestWalletImportDeployed(t *testing.T) {
badH := deployNNSContract(t, e) // wrong contract with no `verify` method badH := deployNNSContract(t, e) // wrong contract with no `verify` method
e.In.WriteString("acc\rpass\rpass\r") e.In.WriteString("acc\rpass\rpass\r")
e.RunWithError(t, "neo-go", "wallet", "import-deployed", e.RunWithError(t, "neo-go", "wallet", "import-deployed",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--contract", badH.StringLE(), "--wallet", walletPath, "--contract", badH.StringLE(),
"--wif", priv.WIF()) "--wif", priv.WIF())
}) })
e.In.WriteString("acc\rpass\rpass\r") e.In.WriteString("acc\rpass\rpass\r")
e.Run(t, "neo-go", "wallet", "import-deployed", e.Run(t, "neo-go", "wallet", "import-deployed",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--wif", priv.WIF(), "--name", "my_acc", "--wallet", walletPath, "--wif", priv.WIF(), "--name", "my_acc",
"--contract", h.StringLE()) "--contract", h.StringLE())
@ -599,7 +599,7 @@ func TestWalletImportDeployed(t *testing.T) {
t.Run("re-importing", func(t *testing.T) { t.Run("re-importing", func(t *testing.T) {
e.In.WriteString("acc\rpass\rpass\r") e.In.WriteString("acc\rpass\rpass\r")
e.RunWithError(t, "neo-go", "wallet", "import-deployed", e.RunWithError(t, "neo-go", "wallet", "import-deployed",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--wif", priv.WIF(), "--name", "my_acc", "--wallet", walletPath, "--wif", priv.WIF(), "--name", "my_acc",
"--contract", h.StringLE()) "--contract", h.StringLE())
}) })
@ -607,7 +607,7 @@ func TestWalletImportDeployed(t *testing.T) {
t.Run("Sign", func(t *testing.T) { t.Run("Sign", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--from", testcli.ValidatorAddr, "--wallet", testcli.ValidatorWallet, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:"+contractAddr+":10", "NEO:"+contractAddr+":10",
@ -619,7 +619,7 @@ func TestWalletImportDeployed(t *testing.T) {
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--from", contractAddr, "--wallet", walletPath, "--from", contractAddr,
"--force", "--force",
"--to", privTo.Address(), "--token", "NEO", "--amount", "1") "--to", privTo.Address(), "--token", "NEO", "--amount", "1")
@ -680,7 +680,7 @@ func TestOfflineSigning(t *testing.T) {
t.Run("1/1 multisig", func(t *testing.T) { t.Run("1/1 multisig", func(t *testing.T) {
args := []string{"neo-go", "wallet", "nep17", "transfer", args := []string{"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", walletPath, "--wallet", walletPath,
"--from", testcli.ValidatorAddr, "--from", testcli.ValidatorAddr,
"--to", w.Accounts[0].Address, "--to", w.Accounts[0].Address,
@ -699,15 +699,15 @@ func TestOfflineSigning(t *testing.T) {
t.Run("sendtx", func(t *testing.T) { t.Run("sendtx", func(t *testing.T) {
// And it can't be sent. // And it can't be sent.
e.RunWithError(t, "neo-go", "util", "sendtx", e.RunWithError(t, "neo-go", "util", "sendtx",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
txPath) txPath)
// Even with too many arguments. // Even with too many arguments.
e.RunWithError(t, "neo-go", "util", "sendtx", e.RunWithError(t, "neo-go", "util", "sendtx",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
txPath, txPath) txPath, txPath)
// Or no arguments at all. // Or no arguments at all.
e.RunWithError(t, "neo-go", "util", "sendtx", e.RunWithError(t, "neo-go", "util", "sendtx",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addresses()[0])
}) })
// But it can be signed with a proper wallet. // But it can be signed with a proper wallet.
e.In.WriteString("one\r") e.In.WriteString("one\r")
@ -716,7 +716,7 @@ func TestOfflineSigning(t *testing.T) {
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
// And then anyone can send (even via wallet sign). // And then anyone can send (even via wallet sign).
e.Run(t, "neo-go", "wallet", "sign", e.Run(t, "neo-go", "wallet", "sign",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", walletPath, "--address", testcli.ValidatorAddr, "--wallet", walletPath, "--address", testcli.ValidatorAddr,
"--in", txPath) "--in", txPath)
}) })
@ -724,7 +724,7 @@ func TestOfflineSigning(t *testing.T) {
t.Run("simple signature", func(t *testing.T) { t.Run("simple signature", func(t *testing.T) {
simpleAddr := w.Accounts[0].Address simpleAddr := w.Accounts[0].Address
args := []string{"neo-go", "wallet", "nep17", "transfer", args := []string{"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", walletPath, "--wallet", walletPath,
"--from", simpleAddr, "--from", simpleAddr,
"--to", testcli.ValidatorAddr, "--to", testcli.ValidatorAddr,
@ -749,7 +749,7 @@ func TestOfflineSigning(t *testing.T) {
e.RunWithError(t, "neo-go", "util", "sendtx", txPath) e.RunWithError(t, "neo-go", "util", "sendtx", txPath)
// But it requires no wallet at all. // But it requires no wallet at all.
e.Run(t, "neo-go", "util", "sendtx", e.Run(t, "neo-go", "util", "sendtx",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
txPath) txPath)
}) })
} }

View file

@ -47,34 +47,38 @@ ApplicationConfiguration:
DataDirectoryPath: "./chains/mainnet.neofs" DataDirectoryPath: "./chains/mainnet.neofs"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/mainnet.bolt" # FilePath: "./chains/mainnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 40333 - ":40333" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 5
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 5
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
- application/json - application/json
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":40332"
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 40332
TLSConfig: TLSConfig:
Enabled: false Enabled: false
Port: 40331 Addresses:
- ":40331"
CertFile: serv.crt CertFile: serv.crt
KeyFile: serv.key KeyFile: serv.key
Prometheus: Prometheus:
Enabled: false Enabled: false
Port: 2112 Addresses:
- ":2112"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 2113 Addresses:
- ":2113"

View file

@ -59,17 +59,17 @@ ApplicationConfiguration:
DataDirectoryPath: "./chains/mainnet" DataDirectoryPath: "./chains/mainnet"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/mainnet.bolt" # FilePath: "./chains/mainnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 10333 - ":10333" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 10
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 10
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
@ -82,17 +82,21 @@ ApplicationConfiguration:
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":10332"
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 10332
TLSConfig: TLSConfig:
Enabled: false Enabled: false
Port: 10331 Addresses:
- ":10331"
CertFile: serv.crt CertFile: serv.crt
KeyFile: serv.key KeyFile: serv.key
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 2112 Addresses:
- ":2112"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 2113 Addresses:
- ":2113"

View file

@ -38,17 +38,17 @@ ApplicationConfiguration:
DataDirectoryPath: "/chains/four" DataDirectoryPath: "/chains/four"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/privnet.bolt" # FilePath: "./chains/privnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20336 - ":20336" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
@ -69,15 +69,18 @@ ApplicationConfiguration:
Password: "pass" Password: "pass"
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":30336"
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 30336
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 20004 Addresses:
- ":20004"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 20014 Addresses:
- ":20014"
UnlockWallet: UnlockWallet:
Path: "/wallet4.json" Path: "/wallet4.json"
Password: "four" Password: "four"

View file

@ -38,17 +38,17 @@ ApplicationConfiguration:
DataDirectoryPath: "/chains/one" DataDirectoryPath: "/chains/one"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/privnet.bolt" # FilePath: "./chains/privnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20333 - ":20333" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
@ -69,12 +69,14 @@ ApplicationConfiguration:
Password: "pass" Password: "pass"
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":30333"
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 30333
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 20001 Addresses:
- ":20001"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 20011 Port: 20011

View file

@ -32,17 +32,17 @@ ApplicationConfiguration:
DataDirectoryPath: "/chains/single" DataDirectoryPath: "/chains/single"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/privnet.bolt" # FilePath: "./chains/privnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20333 - ":20333" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 0
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 0
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
@ -60,15 +60,18 @@ ApplicationConfiguration:
Password: "pass" Password: "pass"
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":30333"
EnableCORSWorkaround: false EnableCORSWorkaround: false
MaxGasInvoke: 15 MaxGasInvoke: 15
Port: 30333
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 20001 Addresses:
- ":20001"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 20011 Addresses:
- ":20011"
UnlockWallet: UnlockWallet:
Path: "/wallet1.json" Path: "/wallet1.json"
Password: "one" Password: "one"

View file

@ -38,17 +38,17 @@ ApplicationConfiguration:
DataDirectoryPath: "/chains/three" DataDirectoryPath: "/chains/three"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/privnet.bolt" # FilePath: "./chains/privnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20335 - ":20335" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
@ -69,15 +69,18 @@ ApplicationConfiguration:
Password: "pass" Password: "pass"
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":30335"
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 30335
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 20003 Addresses:
- ":20003"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 20013 Addresses:
- ":20013"
UnlockWallet: UnlockWallet:
Path: "/wallet3.json" Path: "/wallet3.json"
Password: "three" Password: "three"

View file

@ -38,17 +38,17 @@ ApplicationConfiguration:
DataDirectoryPath: "/chains/two" DataDirectoryPath: "/chains/two"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/privnet.bolt" # FilePath: "./chains/privnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20334 - ":20334" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
@ -71,13 +71,16 @@ ApplicationConfiguration:
Enabled: true Enabled: true
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 30334 Addresses:
- ":30334"
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 20002 Addresses:
- ":20002"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 20012 Addresses:
- ":20012"
UnlockWallet: UnlockWallet:
Path: "/wallet2.json" Path: "/wallet2.json"
Password: "two" Password: "two"

View file

@ -38,17 +38,17 @@ ApplicationConfiguration:
DataDirectoryPath: "./chains/privnet" DataDirectoryPath: "./chains/privnet"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/privnet.bolt" # FilePath: "./chains/privnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20332 - ":20332" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 10
AttemptConnPeers: 5
MinPeers: 3
P2PNotary: P2PNotary:
Enabled: false Enabled: false
UnlockWallet: UnlockWallet:
@ -56,19 +56,23 @@ ApplicationConfiguration:
Password: "pass" Password: "pass"
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":20331"
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 20331
SessionEnabled: true SessionEnabled: true
SessionExpirationTime: 180 # higher expiration time for manual requests and tests. SessionExpirationTime: 180 # higher expiration time for manual requests and tests.
TLSConfig: TLSConfig:
Enabled: false Enabled: false
Port: 20330 Addresses:
- ":20330"
CertFile: serv.crt CertFile: serv.crt
KeyFile: serv.key KeyFile: serv.key
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 2112 Addresses:
- ":2112"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 2113 Addresses:
- ":2113"

View file

@ -47,32 +47,34 @@ ApplicationConfiguration:
DataDirectoryPath: "./chains/testnet.neofs" DataDirectoryPath: "./chains/testnet.neofs"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/testnet.bolt" # FilePath: "./chains/testnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 50333 - ":50333" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 5
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 5
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
- application/json - application/json
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":50332"
EnableCORSWorkaround: false EnableCORSWorkaround: false
MaxGasInvoke: 100 MaxGasInvoke: 100
Port: 50332
StartWhenSynchronized: false StartWhenSynchronized: false
TLSConfig: TLSConfig:
Enabled: false Enabled: false
Addresses:
- ":50331"
CertFile: server.crt CertFile: server.crt
KeyFile: server.key KeyFile: server.key
Port: 50331
P2PNotary: P2PNotary:
Enabled: false Enabled: false
UnlockWallet: UnlockWallet:
@ -80,7 +82,9 @@ ApplicationConfiguration:
Path: "/notary_wallet.json" Path: "/notary_wallet.json"
Prometheus: Prometheus:
Enabled: false Enabled: false
Port: 2112 Addresses:
- ":2112"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 2113 Addresses:
- ":2113"

View file

@ -62,17 +62,17 @@ ApplicationConfiguration:
DataDirectoryPath: "./chains/testnet" DataDirectoryPath: "./chains/testnet"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/testnet.bolt" # FilePath: "./chains/testnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20333 - ":20333" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 10
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 100
AttemptConnPeers: 20
MinPeers: 10
Oracle: Oracle:
Enabled: false Enabled: false
AllowedContentTypes: AllowedContentTypes:
@ -84,17 +84,21 @@ ApplicationConfiguration:
Password: "pass" Password: "pass"
RPC: RPC:
Enabled: true Enabled: true
Addresses:
- ":20332"
MaxGasInvoke: 15 MaxGasInvoke: 15
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 20332
TLSConfig: TLSConfig:
Enabled: false Enabled: false
Port: 20331 Addresses:
- ":20331"
CertFile: serv.crt CertFile: serv.crt
KeyFile: serv.key KeyFile: serv.key
Prometheus: Prometheus:
Enabled: true Enabled: true
Port: 2112 Addresses:
- ":2112"
Pprof: Pprof:
Enabled: false Enabled: false
Port: 2113 Addresses:
- ":2113"

View file

@ -33,17 +33,17 @@ ApplicationConfiguration:
# DataDirectoryPath: "./chains/unit_testnet" # DataDirectoryPath: "./chains/unit_testnet"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/unit_testnet.bolt" # FilePath: "./chains/unit_testnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 0 - ":0" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MinPeers: 0
MaxPeers: 10
AttemptConnPeers: 5
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MinPeers: 0
MaxPeers: 10
AttemptConnPeers: 5
UnlockWallet: UnlockWallet:
Path: "../testdata/wallet1_solo.json" Path: "../testdata/wallet1_solo.json"
Password: "one" Password: "one"
@ -53,14 +53,16 @@ ApplicationConfiguration:
Path: "/notary_wallet.json" Path: "/notary_wallet.json"
Password: "pass" Password: "pass"
RPC: RPC:
Address: localhost
MaxGasInvoke: 15 MaxGasInvoke: 15
Enabled: true Enabled: true
Addresses:
- "localhost:0" # let the system choose port dynamically
EnableCORSWorkaround: false EnableCORSWorkaround: false
Port: 0 # let the system choose port dynamically
Prometheus: Prometheus:
Enabled: false #since it's not useful for unit tests. Enabled: false #since it's not useful for unit tests.
Port: 2112 Addresses:
- ":2112"
Pprof: Pprof:
Enabled: false #since it's not useful for unit tests. Enabled: false #since it's not useful for unit tests.
Port: 2113 Addresses:
- ":2113"

View file

@ -42,33 +42,35 @@ ApplicationConfiguration:
# DataDirectoryPath: "./chains/unit_testnet" # DataDirectoryPath: "./chains/unit_testnet"
# BoltDBOptions: # BoltDBOptions:
# FilePath: "./chains/unit_testnet.bolt" # FilePath: "./chains/unit_testnet.bolt"
# Uncomment in order to set up custom address for node. P2P:
# Address: localhost Addresses:
NodePort: 20333 - ":20333" # in form of "[host]:[port][:announcedPort]"
DialTimeout: 3s
ProtoTickInterval: 2s
PingInterval: 30s
PingTimeout: 90s
MaxPeers: 50
AttemptConnPeers: 5
MinPeers: 0
Relay: true Relay: true
DialTimeout: 3
ProtoTickInterval: 2
PingInterval: 30
PingTimeout: 90
MaxPeers: 50
AttemptConnPeers: 5
MinPeers: 0
P2PNotary: P2PNotary:
Enabled: false Enabled: false
UnlockWallet: UnlockWallet:
Path: "/notary_wallet.json" Path: "/notary_wallet.json"
Password: "pass" Password: "pass"
RPC: RPC:
Address: localhost
MaxGasInvoke: 15 MaxGasInvoke: 15
Enabled: true Enabled: true
Addresses:
- "localhost:0" # let the system choose port dynamically
EnableCORSWorkaround: false EnableCORSWorkaround: false
SessionEnabled: true SessionEnabled: true
SessionExpirationTime: 2 # enough for tests as they run locally. SessionExpirationTime: 2 # enough for tests as they run locally.
Port: 0 # let the system choose port dynamically
Prometheus: Prometheus:
Enabled: false #since it's not useful for unit tests. Enabled: false #since it's not useful for unit tests.
Port: 2112 Addresses:
- ":2112"
Pprof: Pprof:
Enabled: false #since it's not useful for unit tests. Enabled: false #since it's not useful for unit tests.
Port: 2113 Addresses:
- ":2113"

View file

@ -16,30 +16,77 @@ node-related settings described in the table below.
| Section | Type | Default value | Description | | Section | Type | Default value | Description |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| Address | `string` | `0.0.0.0` | Node address that P2P protocol handler binds to. | | Address | `string` | `0.0.0.0` | Node address that P2P protocol handler binds to. Warning: this field is deprecated, please, use `Addresses` instead. |
| AnnouncedPort | `uint16` | Same as `NodePort` | Node port which should be used to announce node's port on P2P layer, it can differ from the `NodePort` the node is bound to (for example, if your node is behind NAT). | | AnnouncedPort | `uint16` | Same as `NodePort` | Node port which should be used to announce node's port on P2P layer, it can differ from the `NodePort` the node is bound to (for example, if your node is behind NAT). Warning: this field is deprecated, please, use `Addresses` instead. |
| AttemptConnPeers | `int` | `20` | Number of connection to try to establish when the connection count drops below the `MinPeers` value.| | AttemptConnPeers | `int` | `20` | Number of connection to try to establish when the connection count drops below the `MinPeers` value. Warning: this field is deprecated and moved to `P2P` section. |
| BroadcastFactor | `int` | `0` | Multiplier that is used to determine the number of optimal gossip fan-out peer number for broadcasted messages (0-100). By default it's zero, node uses the most optimized value depending on the estimated network size (`2.5×log(size)`), so the node may have 20 peers and calculate that it needs to broadcast messages to just 10 of them. With BroadcastFactor set to 100 it will always send messages to all peers, any value in-between 0 and 100 is used for weighted calculation, for example if it's 30 then 13 neighbors will be used in the previous case. | | BroadcastFactor | `int` | `0` | Multiplier that is used to determine the number of optimal gossip fan-out peer number for broadcasted messages (0-100). By default it's zero, node uses the most optimized value depending on the estimated network size (`2.5×log(size)`), so the node may have 20 peers and calculate that it needs to broadcast messages to just 10 of them. With BroadcastFactor set to 100 it will always send messages to all peers, any value in-between 0 and 100 is used for weighted calculation, for example if it's 30 then 13 neighbors will be used in the previous case. Warning: this field is deprecated and moved to `P2P` section. |
| DBConfiguration | [DB Configuration](#DB-Configuration) | | Describes configuration for database. See the [DB Configuration](#DB-Configuration) section for details. | | DBConfiguration | [DB Configuration](#DB-Configuration) | | Describes configuration for database. See the [DB Configuration](#DB-Configuration) section for details. |
| DialTimeout | `int64` | `0` | Maximum duration a single dial may take in seconds. | | DialTimeout | `int64` | `0` | Maximum duration a single dial may take in seconds. Warning: this field is deprecated and moved to `P2P` section. |
| ExtensiblePoolSize | `int` | `20` | Maximum amount of the extensible payloads from a single sender stored in a local pool. | | ExtensiblePoolSize | `int` | `20` | Maximum amount of the extensible payloads from a single sender stored in a local pool. Warning: this field is deprecated and moved to `P2P` section. |
| LogLevel | `string` | "info" | Minimal logged messages level (can be "debug", "info", "warn", "error", "dpanic", "panic" or "fatal"). | | LogLevel | `string` | "info" | Minimal logged messages level (can be "debug", "info", "warn", "error", "dpanic", "panic" or "fatal"). |
| LogPath | `string` | "", so only console logging | File path where to store node logs. | | LogPath | `string` | "", so only console logging | File path where to store node logs. |
| MaxPeers | `int` | `100` | Maximum numbers of peers that can be connected to the server. | | MaxPeers | `int` | `100` | Maximum numbers of peers that can be connected to the server. Warning: this field is deprecated and moved to `P2P` section. |
| MinPeers | `int` | `5` | Minimum number of peers for normal operation; when the node has less than this number of peers it tries to connect with some new ones. | | MinPeers | `int` | `5` | Minimum number of peers for normal operation; when the node has less than this number of peers it tries to connect with some new ones. Warning: this field is deprecated and moved to `P2P` section. |
| NodePort | `uint16` | `0`, which is any free port | The actual node port it is bound to. | | NodePort | `uint16` | `0`, which is any free port | The actual node port it is bound to. Warning: this field is deprecated, please, use `Addresses` instead. |
| Oracle | [Oracle Configuration](#Oracle-Configuration) | | Oracle module configuration. See the [Oracle Configuration](#Oracle-Configuration) section for details. | | Oracle | [Oracle Configuration](#Oracle-Configuration) | | Oracle module configuration. See the [Oracle Configuration](#Oracle-Configuration) section for details. |
| P2P | [P2P Configuration](#P2P-Configuration) | | Configuration values for P2P network interaction. See the [P2P Configuration](#P2P-Configuration) section for details. |
| P2PNotary | [P2P Notary Configuration](#P2P-Notary-Configuration) | | P2P Notary module configuration. See the [P2P Notary Configuration](#P2P-Notary-Configuration) section for details. | | P2PNotary | [P2P Notary Configuration](#P2P-Notary-Configuration) | | P2P Notary module configuration. See the [P2P Notary Configuration](#P2P-Notary-Configuration) section for details. |
| PingInterval | `int64` | `30` | Interval in seconds used in pinging mechanism for syncing blocks. | | PingInterval | `int64` | `30` | Interval in seconds used in pinging mechanism for syncing blocks. Warning: this field is deprecated and moved to `P2P` section. |
| PingTimeout | `int64` | `90` | Time to wait for pong (response for sent ping request). | | PingTimeout | `int64` | `90` | Time to wait for pong (response for sent ping request). Warning: this field is deprecated and moved to `P2P` section. |
| Pprof | [Metrics Services Configuration](#Metrics-Services-Configuration) | | Configuration for pprof service (profiling statistics gathering). See the [Metrics Services Configuration](#Metrics-Services-Configuration) section for details. | | Pprof | [Metrics Services Configuration](#Metrics-Services-Configuration) | | Configuration for pprof service (profiling statistics gathering). See the [Metrics Services Configuration](#Metrics-Services-Configuration) section for details. |
| Prometheus | [Metrics Services Configuration](#Metrics-Services-Configuration) | | Configuration for Prometheus (monitoring system). See the [Metrics Services Configuration](#Metrics-Services-Configuration) section for details | | Prometheus | [Metrics Services Configuration](#Metrics-Services-Configuration) | | Configuration for Prometheus (monitoring system). See the [Metrics Services Configuration](#Metrics-Services-Configuration) section for details |
| ProtoTickInterval | `int64` | `5` | Duration in seconds between protocol ticks with each connected peer. | | ProtoTickInterval | `int64` | `5` | Duration in seconds between protocol ticks with each connected peer. Warning: this field is deprecated and moved to `P2P` section. |
| Relay | `bool` | `true` | Determines whether the server is forwarding its inventory. | | Relay | `bool` | `true` | Determines whether the server is forwarding its inventory. |
| RPC | [RPC Configuration](#RPC-Configuration) | | Describes [RPC subsystem](rpc.md) configuration. See the [RPC Configuration](#RPC-Configuration) for details. | | RPC | [RPC Configuration](#RPC-Configuration) | | Describes [RPC subsystem](rpc.md) configuration. See the [RPC Configuration](#RPC-Configuration) for details. |
| StateRoot | [State Root Configuration](#State-Root-Configuration) | | State root module configuration. See the [State Root Configuration](#State-Root-Configuration) section for details. | | StateRoot | [State Root Configuration](#State-Root-Configuration) | | State root module configuration. See the [State Root Configuration](#State-Root-Configuration) section for details. |
| UnlockWallet | [Unlock Wallet Configuration](#Unlock-Wallet-Configuration) | | Node wallet configuration used for consensus (dBFT) operation. See the [Unlock Wallet Configuration](#Unlock-Wallet-Configuration) section for details. | | UnlockWallet | [Unlock Wallet Configuration](#Unlock-Wallet-Configuration) | | Node wallet configuration used for consensus (dBFT) operation. See the [Unlock Wallet Configuration](#Unlock-Wallet-Configuration) section for details. |
### P2P Configuration
`P2P` section contains configuration for peer-to-peer node communications and has
the following format:
```
P2P:
Addresses:
- "0.0.0.0:0" # any free port on all available addresses (in form of "[host]:[port][:announcedPort]")
AttemptConnPeers: 20
BroadcastFactor: 0
DialTimeout: 0s
MaxPeers: 100
MinPeers: 5
PingInterval: 30s
PingTimeout: 90s
ProtoTickInterval: 5s
ExtensiblePoolSize: 20
```
where:
- `Addresses` (`[]string`) is the list of the node addresses that P2P protocol
handler binds to. Each address has the form of `[address]:[nodePort][:announcedPort]`
where `address` is the address itself, `nodePort` is the actual P2P port node listens at;
`announcedPort` is the node port which should be used to announce node's port on P2P layer,
it can differ from the `nodePort` the node is bound to if specified (for example, if your
node is behind NAT).
- `AttemptConnPeers` (`int`) is the number of connection to try to establish when the
connection count drops below the `MinPeers` value.
- `BroadcastFactor` (`int`) is the multiplier that is used to determine the number of
optimal gossip fan-out peer number for broadcasted messages (0-100). By default, it's
zero, node uses the most optimized value depending on the estimated network size
(`2.5×log(size)`), so the node may have 20 peers and calculate that it needs to broadcast
messages to just 10 of them. With BroadcastFactor set to 100 it will always send messages
to all peers, any value in-between 0 and 100 is used for weighted calculation, for example
if it's 30 then 13 neighbors will be used in the previous case.
- `DialTimeout` (`Duration`) is the maximum duration a single dial may take.
- `ExtensiblePoolSize` (`int`) is the maximum amount of the extensible payloads from a single
sender stored in a local pool.
- `MaxPeers` (`int`) is the maximum numbers of peers that can be connected to the server.
- `MinPeers` (`int`) is the minimum number of peers for normal operation; when the node has
less than this number of peers it tries to connect with some new ones.
- `PingInterval` (`Duration`) is the interval used in pinging mechanism for syncing
blocks.
- `PingTimeout` (`Duration`) is the time to wait for pong (response for sent ping request).
- `ProtoTickInterval` (`Duration`) is the duration between protocol ticks with each
connected peer.
### DB Configuration ### DB Configuration
`DBConfiguration` section describes configuration for node database and has `DBConfiguration` section describes configuration for node database and has
@ -118,17 +165,21 @@ Prometheus) and has the following structure:
``` ```
Pprof: Pprof:
Enabled: false Enabled: false
Address: "" Addresses:
Port: "30001" - ":30001"
Prometheus: Prometheus:
Enabled: false Enabled: false
Address: "" Addresses:
Port: "40001" - ":40001"
``` ```
where: where:
- `Enabled` denotes whether the service is enabled. - `Enabled` denotes whether the service is enabled.
- `Address` is a service address to be running at. - `Address` is a service address to be running at. Warning: this field is deprecated,
- `Port` is a service port to be bound to. please, use `Addresses` instead.
- `Port` is a service port to be bound to. Warning: this field is deprecated, please,
use `Addresses` instead.
- `Addresses` is a list of service addresses to be running at and listen to in
the form of "host:port".
### RPC Configuration ### RPC Configuration
@ -137,29 +188,32 @@ the following structure:
``` ```
RPC: RPC:
Enabled: true Enabled: true
Address: "" Addresses:
- ":10332"
EnableCORSWorkaround: false EnableCORSWorkaround: false
MaxGasInvoke: 50 MaxGasInvoke: 50
MaxIteratorResultItems: 100 MaxIteratorResultItems: 100
MaxFindResultItems: 100 MaxFindResultItems: 100
MaxNEP11Tokens: 100 MaxNEP11Tokens: 100
MaxWebSocketClients: 64 MaxWebSocketClients: 64
Port: 10332
SessionEnabled: false SessionEnabled: false
SessionExpirationTime: 15 SessionExpirationTime: 15
SessionBackedByMPT: false SessionBackedByMPT: false
SessionPoolSize: 20 SessionPoolSize: 20
StartWhenSynchronized: false StartWhenSynchronized: false
TLSConfig: TLSConfig:
Address: "" Addresses:
- ":10331"
CertFile: serv.crt CertFile: serv.crt
Enabled: true Enabled: true
Port: 10331
KeyFile: serv.key KeyFile: serv.key
``` ```
where: where:
- `Enabled` denotes whether an RPC server should be started. - `Enabled` denotes whether an RPC server should be started.
- `Address` is an RPC server address to be running at. - `Address` is an RPC server address to be running at. Warning: this field is
deprecated, please, use `Addresses` instead.
- `Addresses` is a list of RPC server addresses to be running at and listen to in
the form of "host:port".
- `EnableCORSWorkaround` turns on a set of origin-related behaviors that make - `EnableCORSWorkaround` turns on a set of origin-related behaviors that make
RPC server wide open for connections from any origins. It enables OPTIONS RPC server wide open for connections from any origins. It enables OPTIONS
request handling for pre-flight CORS and makes the server send request handling for pre-flight CORS and makes the server send
@ -182,7 +236,8 @@ where:
number (64 by default). Attempts to establish additional connections will number (64 by default). Attempts to establish additional connections will
lead to websocket handshake failures. Use "-1" to disable websocket lead to websocket handshake failures. Use "-1" to disable websocket
connections (0 will lead to using the default value). connections (0 will lead to using the default value).
- `Port` is an RPC server port it should be bound to. - `Port` is an RPC server port it should be bound to. Warning: this field is
deprecated, please, use `Addresses` instead.
- `SessionEnabled` denotes whether session-based iterator JSON-RPC API is enabled. - `SessionEnabled` denotes whether session-based iterator JSON-RPC API is enabled.
If true, then all iterators got from `invoke*` calls will be stored as sessions If true, then all iterators got from `invoke*` calls will be stored as sessions
on the server side available for further traverse. `traverseiterator` and on the server side available for further traverse. `traverseiterator` and

View file

@ -146,7 +146,8 @@ func NewTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch
go chain.Run() go chain.Run()
} }
serverConfig := network.NewServerConfig(cfg) serverConfig, err := network.NewServerConfig(cfg)
require.NoError(t, err)
serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.3-test") serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.3-test")
netSrv, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), zap.NewNop()) netSrv, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), zap.NewNop())
require.NoError(t, err) require.NoError(t, err)
@ -348,7 +349,7 @@ func DeployContract(t *testing.T, e *Executor, inPath, configPath, wallet, addre
"--out", nefName, "--manifest", manifestName) "--out", nefName, "--manifest", manifestName)
e.In.WriteString(pass + "\r") e.In.WriteString(pass + "\r")
e.Run(t, "neo-go", "contract", "deploy", e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", wallet, "--address", address, "--wallet", wallet, "--address", address,
"--force", "--force",
"--in", nefName, "--manifest", manifestName) "--in", nefName, "--manifest", manifestName)

View file

@ -7,6 +7,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
) )
// MarshalUnmarshalJSON checks if the expected stays the same after // MarshalUnmarshalJSON checks if the expected stays the same after
@ -18,6 +19,15 @@ func MarshalUnmarshalJSON(t *testing.T, expected, actual interface{}) {
require.Equal(t, expected, actual) require.Equal(t, expected, actual)
} }
// MarshalUnmarshalYAML checks if the expected stays the same after
// marshal/unmarshal via YAML.
func MarshalUnmarshalYAML(t *testing.T, expected, actual interface{}) {
data, err := yaml.Marshal(expected)
require.NoError(t, err)
require.NoError(t, yaml.Unmarshal(data, actual))
require.Equal(t, expected, actual)
}
// EncodeDecodeBinary checks if the expected stays the same after // EncodeDecodeBinary checks if the expected stays the same after
// serializing/deserializing via io.Serializable methods. // serializing/deserializing via io.Serializable methods.
func EncodeDecodeBinary(t *testing.T, expected, actual io.Serializable) { func EncodeDecodeBinary(t *testing.T, expected, actual io.Serializable) {

View file

@ -1,35 +1,56 @@
package config package config
import ( import (
"fmt"
"net"
"sort"
"strconv"
"strings"
"github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig" "github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig"
) )
// ApplicationConfiguration config specific to the node. // ApplicationConfiguration config specific to the node.
type ApplicationConfiguration struct { type ApplicationConfiguration struct {
Address string `yaml:"Address"` // Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions.
AnnouncedNodePort uint16 `yaml:"AnnouncedPort"` Address *string `yaml:"Address,omitempty"`
AttemptConnPeers int `yaml:"AttemptConnPeers"` // Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions.
AnnouncedNodePort *uint16 `yaml:"AnnouncedPort,omitempty"`
// Deprecated: this option is moved to the P2P section.
AttemptConnPeers int `yaml:"AttemptConnPeers"`
// BroadcastFactor is the factor (0-100) controlling gossip fan-out number optimization. // BroadcastFactor is the factor (0-100) controlling gossip fan-out number optimization.
BroadcastFactor int `yaml:"BroadcastFactor"` //
DBConfiguration dbconfig.DBConfiguration `yaml:"DBConfiguration"` // Deprecated: this option is moved to the P2P section.
DialTimeout int64 `yaml:"DialTimeout"` BroadcastFactor int `yaml:"BroadcastFactor"`
LogLevel string `yaml:"LogLevel"` DBConfiguration dbconfig.DBConfiguration `yaml:"DBConfiguration"`
LogPath string `yaml:"LogPath"` // Deprecated: this option is moved to the P2P section.
MaxPeers int `yaml:"MaxPeers"` DialTimeout int64 `yaml:"DialTimeout"`
MinPeers int `yaml:"MinPeers"` LogLevel string `yaml:"LogLevel"`
NodePort uint16 `yaml:"NodePort"` LogPath string `yaml:"LogPath"`
PingInterval int64 `yaml:"PingInterval"` // Deprecated: this option is moved to the P2P section.
PingTimeout int64 `yaml:"PingTimeout"` MaxPeers int `yaml:"MaxPeers"`
Pprof BasicService `yaml:"Pprof"` // Deprecated: this option is moved to the P2P section.
Prometheus BasicService `yaml:"Prometheus"` MinPeers int `yaml:"MinPeers"`
ProtoTickInterval int64 `yaml:"ProtoTickInterval"` // Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions.
Relay bool `yaml:"Relay"` NodePort *uint16 `yaml:"NodePort,omitempty"`
RPC RPC `yaml:"RPC"` P2P P2P `yaml:"P2P"`
UnlockWallet Wallet `yaml:"UnlockWallet"` // Deprecated: this option is moved to the P2P section.
Oracle OracleConfiguration `yaml:"Oracle"` PingInterval int64 `yaml:"PingInterval"`
P2PNotary P2PNotary `yaml:"P2PNotary"` // Deprecated: this option is moved to the P2P section.
StateRoot StateRoot `yaml:"StateRoot"` PingTimeout int64 `yaml:"PingTimeout"`
Pprof BasicService `yaml:"Pprof"`
Prometheus BasicService `yaml:"Prometheus"`
// Deprecated: this option is moved to the P2P section.
ProtoTickInterval int64 `yaml:"ProtoTickInterval"`
Relay bool `yaml:"Relay"`
RPC RPC `yaml:"RPC"`
UnlockWallet Wallet `yaml:"UnlockWallet"`
Oracle OracleConfiguration `yaml:"Oracle"`
P2PNotary P2PNotary `yaml:"P2PNotary"`
StateRoot StateRoot `yaml:"StateRoot"`
// ExtensiblePoolSize is the maximum amount of the extensible payloads from a single sender. // ExtensiblePoolSize is the maximum amount of the extensible payloads from a single sender.
//
// Deprecated: this option is moved to the P2P section.
ExtensiblePoolSize int `yaml:"ExtensiblePoolSize"` ExtensiblePoolSize int `yaml:"ExtensiblePoolSize"`
} }
@ -37,22 +58,143 @@ type ApplicationConfiguration struct {
// (Oracle, P2PNotary, Pprof, Prometheus, RPC, StateRoot and UnlockWallet sections) // (Oracle, P2PNotary, Pprof, Prometheus, RPC, StateRoot and UnlockWallet sections)
// and LogLevel field. // and LogLevel field.
func (a *ApplicationConfiguration) EqualsButServices(o *ApplicationConfiguration) bool { func (a *ApplicationConfiguration) EqualsButServices(o *ApplicationConfiguration) bool {
if a.Address != o.Address || if len(a.P2P.Addresses) != len(o.P2P.Addresses) {
a.AnnouncedNodePort != o.AnnouncedNodePort || return false
a.AttemptConnPeers != o.AttemptConnPeers || }
a.BroadcastFactor != o.BroadcastFactor || aCp := make([]string, len(a.P2P.Addresses))
oCp := make([]string, len(o.P2P.Addresses))
copy(aCp, a.P2P.Addresses)
copy(oCp, o.P2P.Addresses)
sort.Strings(aCp)
sort.Strings(oCp)
for i := range aCp {
if aCp[i] != oCp[i] {
return false
}
}
if a.Address != o.Address || //nolint:staticcheck // SA1019: a.Address is deprecated
a.AnnouncedNodePort != o.AnnouncedNodePort || //nolint:staticcheck // SA1019: a.AnnouncedNodePort is deprecated
a.AttemptConnPeers != o.AttemptConnPeers || //nolint:staticcheck // SA1019: a.AttemptConnPeers is deprecated
a.P2P.AttemptConnPeers != o.P2P.AttemptConnPeers ||
a.BroadcastFactor != o.BroadcastFactor || //nolint:staticcheck // SA1019: a.BroadcastFactor is deprecated
a.P2P.BroadcastFactor != o.P2P.BroadcastFactor ||
a.DBConfiguration != o.DBConfiguration || a.DBConfiguration != o.DBConfiguration ||
a.DialTimeout != o.DialTimeout || a.DialTimeout != o.DialTimeout || //nolint:staticcheck // SA1019: a.DialTimeout is deprecated
a.ExtensiblePoolSize != o.ExtensiblePoolSize || a.P2P.DialTimeout != o.P2P.DialTimeout ||
a.ExtensiblePoolSize != o.ExtensiblePoolSize || //nolint:staticcheck // SA1019: a.ExtensiblePoolSize is deprecated
a.P2P.ExtensiblePoolSize != o.P2P.ExtensiblePoolSize ||
a.LogPath != o.LogPath || a.LogPath != o.LogPath ||
a.MaxPeers != o.MaxPeers || a.MaxPeers != o.MaxPeers || //nolint:staticcheck // SA1019: a.MaxPeers is deprecated
a.MinPeers != o.MinPeers || a.P2P.MaxPeers != o.P2P.MaxPeers ||
a.NodePort != o.NodePort || a.MinPeers != o.MinPeers || //nolint:staticcheck // SA1019: a.MinPeers is deprecated
a.PingInterval != o.PingInterval || a.P2P.MinPeers != o.P2P.MinPeers ||
a.PingTimeout != o.PingTimeout || a.NodePort != o.NodePort || //nolint:staticcheck // SA1019: a.NodePort is deprecated
a.ProtoTickInterval != o.ProtoTickInterval || a.PingInterval != o.PingInterval || //nolint:staticcheck // SA1019: a.PingInterval is deprecated
a.P2P.PingInterval != o.P2P.PingInterval ||
a.PingTimeout != o.PingTimeout || //nolint:staticcheck // SA1019: a.PingTimeout is deprecated
a.P2P.PingTimeout != o.P2P.PingTimeout ||
a.ProtoTickInterval != o.ProtoTickInterval || //nolint:staticcheck // SA1019: a.ProtoTickInterval is deprecated
a.P2P.ProtoTickInterval != o.P2P.ProtoTickInterval ||
a.Relay != o.Relay { a.Relay != o.Relay {
return false return false
} }
return true return true
} }
// AnnounceableAddress is a pair of node address in the form of "[host]:[port]"
// with optional corresponding announced port to be used in version exchange.
type AnnounceableAddress struct {
Address string
AnnouncedPort uint16
}
// GetAddresses parses returns the list of AnnounceableAddress containing information
// gathered from both deprecated Address / NodePort / AnnouncedNodePort and newly
// created Addresses fields.
func (a *ApplicationConfiguration) GetAddresses() ([]AnnounceableAddress, error) {
addrs := make([]AnnounceableAddress, 0, len(a.P2P.Addresses)+1)
if a.Address != nil || a.NodePort != nil || a.AnnouncedNodePort != nil { //nolint:staticcheck // SA1019: a.Address is deprecated
var (
host string
nodePort uint16
)
if a.Address != nil { //nolint:staticcheck // SA1019: a.Address is deprecated
host = *a.Address //nolint:staticcheck // SA1019: a.Address is deprecated
}
if a.NodePort != nil { //nolint:staticcheck // SA1019: a.NodePort is deprecated
nodePort = *a.NodePort //nolint:staticcheck // SA1019: a.NodePort is deprecated
}
addr := AnnounceableAddress{Address: net.JoinHostPort(host, strconv.Itoa(int(nodePort)))}
if a.AnnouncedNodePort != nil { //nolint:staticcheck // SA1019: a.AnnouncedNodePort is deprecated
addr.AnnouncedPort = *a.AnnouncedNodePort //nolint:staticcheck // SA1019: a.AnnouncedNodePort is deprecated
}
addrs = append(addrs, addr)
}
for i, addrStr := range a.P2P.Addresses {
if len(addrStr) == 0 {
return nil, fmt.Errorf("address #%d is empty", i)
}
lastCln := strings.LastIndex(addrStr, ":")
if lastCln == -1 {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr, // Plain IPv4 address without port.
})
continue
}
lastPort, err := strconv.ParseUint(addrStr[lastCln+1:], 10, 16)
if err != nil {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr, // Still may be a valid IPv4 of the form "X.Y.Z.Q:" or plain IPv6 "A:B::", keep it.
})
continue
}
penultimateCln := strings.LastIndex(addrStr[:lastCln], ":")
if penultimateCln == -1 {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr, // IPv4 address with port "X.Y.Z.Q:123"
})
continue
}
isV6 := strings.Count(addrStr, ":") > 2
hasBracket := strings.Contains(addrStr, "]")
if penultimateCln == lastCln-1 {
if isV6 && !hasBracket {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr, // Plain IPv6 of the form "A:B::123"
})
} else {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr[:lastCln], // IPv4 with empty port and non-empty announced port "X.Y.Z.Q::123" or IPv6 with non-empty announced port "[A:B::]::123".
AnnouncedPort: uint16(lastPort),
})
}
continue
}
_, err = strconv.ParseUint(addrStr[penultimateCln+1:lastCln], 10, 16)
if err != nil {
if isV6 {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr, // Still may be a valid plain IPv6 of the form "A::B:123" or IPv6 with single port [A:B::]:123, keep it.
})
continue
}
return nil, fmt.Errorf("failed to parse port from %s: %w", addrStr, err) // Some garbage.
}
if isV6 && !hasBracket {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr, // Plain IPv6 of the form "A::1:1"
})
} else {
addrs = append(addrs, AnnounceableAddress{
Address: addrStr[:lastCln], // IPv4 with both ports or IPv6 with both ports specified.
AnnouncedPort: uint16(lastPort),
})
}
}
if len(addrs) == 0 {
addrs = append(addrs, AnnounceableAddress{
Address: ":0",
})
}
return addrs, nil
}

View file

@ -20,3 +20,168 @@ func TestApplicationConfigurationEquals(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.False(t, cfg1.ApplicationConfiguration.EqualsButServices(&cfg2.ApplicationConfiguration)) require.False(t, cfg1.ApplicationConfiguration.EqualsButServices(&cfg2.ApplicationConfiguration))
} }
func TestGetAddresses(t *testing.T) {
type testcase struct {
cfg *ApplicationConfiguration
expected []AnnounceableAddress
shouldFail bool
}
addr1 := "1.2.3.4"
addr2 := "5.6.7.8"
addr3 := "4.3.2.1"
v6Plain0 := "3731:54:65fe:2::a7"
v6Plain1 := "3731:54:65fe:2::1"
v6Plain2 := "3731:54:65fe::a:1"
v6Plain3 := "3731:54:65fe::1:1"
v6Plain4 := "3731:54:65fe:2::"
port1 := uint16(1)
port2 := uint16(2)
port3 := uint16(3)
cases := []testcase{
// Compatibility with the old behaviour.
{
cfg: &ApplicationConfiguration{},
expected: []AnnounceableAddress{{Address: ":0"}},
},
{
cfg: &ApplicationConfiguration{Address: &addr1},
expected: []AnnounceableAddress{{Address: addr1 + ":0"}},
},
{
cfg: &ApplicationConfiguration{NodePort: &port1},
expected: []AnnounceableAddress{{Address: ":1"}},
},
{
cfg: &ApplicationConfiguration{AnnouncedNodePort: &port1},
expected: []AnnounceableAddress{{Address: ":0", AnnouncedPort: port1}},
},
{
cfg: &ApplicationConfiguration{Address: &addr1, NodePort: &port1},
expected: []AnnounceableAddress{{Address: addr1 + ":1"}},
},
{
cfg: &ApplicationConfiguration{Address: &addr1, AnnouncedNodePort: &port1},
expected: []AnnounceableAddress{{Address: addr1 + ":0", AnnouncedPort: port1}},
},
{
cfg: &ApplicationConfiguration{NodePort: &port1, AnnouncedNodePort: &port2},
expected: []AnnounceableAddress{{Address: ":1", AnnouncedPort: port2}},
},
{
cfg: &ApplicationConfiguration{NodePort: &port1, AnnouncedNodePort: &port2},
expected: []AnnounceableAddress{{Address: ":1", AnnouncedPort: port2}},
},
{
cfg: &ApplicationConfiguration{Address: &addr1, NodePort: &port1, AnnouncedNodePort: &port2},
expected: []AnnounceableAddress{{Address: addr1 + ":1", AnnouncedPort: port2}},
},
// Compatibility with new multi-addresses.
{
cfg: &ApplicationConfiguration{
Address: &addr1, NodePort: &port1, AnnouncedNodePort: &port2,
P2P: P2P{Addresses: []string{addr1, addr2 + ":3", addr3 + ":1:3"}},
},
expected: []AnnounceableAddress{
{Address: addr1 + ":1", AnnouncedPort: port2},
{Address: addr1},
{Address: addr2 + ":3"},
{Address: addr3 + ":1", AnnouncedPort: port3},
},
},
// Multi-addresses checks.
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{addr1}},
},
expected: []AnnounceableAddress{
{Address: addr1},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{":1"}},
},
expected: []AnnounceableAddress{
{Address: ":1"},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{"::1"}},
},
expected: []AnnounceableAddress{
{Address: ":", AnnouncedPort: port1},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{addr1 + ":1"}},
},
expected: []AnnounceableAddress{
{Address: addr1 + ":1"},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{addr1 + "::1"}},
},
expected: []AnnounceableAddress{
{Address: addr1 + ":", AnnouncedPort: port1},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{addr1 + ":1:2"}},
},
expected: []AnnounceableAddress{
{Address: addr1 + ":1", AnnouncedPort: port2},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{addr1 + ":1", addr2 + "::2"}},
},
expected: []AnnounceableAddress{
{Address: addr1 + ":1"},
{Address: addr2 + ":", AnnouncedPort: port2},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{v6Plain0, v6Plain1, v6Plain2, v6Plain3, v6Plain4}},
},
expected: []AnnounceableAddress{
{Address: v6Plain0},
{Address: v6Plain1},
{Address: v6Plain2},
{Address: v6Plain3},
{Address: v6Plain4},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{"[3731:54:65fe:2::]:123", "[3731:54:65fe:2::]:123:124"}},
},
expected: []AnnounceableAddress{
{Address: "[3731:54:65fe:2::]:123"},
{Address: "[3731:54:65fe:2::]:123", AnnouncedPort: 124},
},
},
{
cfg: &ApplicationConfiguration{
P2P: P2P{Addresses: []string{"127.0.0.1:QWER:123"}},
},
shouldFail: true,
},
}
for i, c := range cases {
actual, err := c.cfg.GetAddresses()
if c.shouldFail {
require.Error(t, err, i)
} else {
require.NoError(t, err)
require.Equal(t, c.expected, actual, i)
}
}
}

View file

@ -1,8 +1,39 @@
package config package config
// BasicService is used for simple services like Pprof or Prometheus monitoring. import (
"net"
"strconv"
)
// BasicService is used as a simple base for node services like Pprof, RPC or
// Prometheus monitoring.
type BasicService struct { type BasicService struct {
Enabled bool `yaml:"Enabled"` Enabled bool `yaml:"Enabled"`
Address string `yaml:"Address"` // Deprecated: please, use Addresses section instead. This field will be removed later.
Port string `yaml:"Port"` Address *string `yaml:"Address,omitempty"`
// Deprecated: please, use Addresses section instead. This field will be removed later.
Port *uint16 `yaml:"Port,omitempty"`
// Addresses holds the list of bind addresses in the form of "address:port".
Addresses []string `yaml:"Addresses"`
}
// GetAddresses returns the set of unique (in terms of raw strings) pairs host:port
// for the given basic service.
func (s BasicService) GetAddresses() []string {
addrs := make([]string, len(s.Addresses), len(s.Addresses)+1)
copy(addrs, s.Addresses)
if s.Address != nil || s.Port != nil { //nolint:staticcheck // SA1019: s.Address is deprecated
var (
addr string
port uint16
)
if s.Address != nil { //nolint:staticcheck // SA1019: s.Address is deprecated
addr = *s.Address //nolint:staticcheck // SA1019: s.Address is deprecated
}
if s.Port != nil { //nolint:staticcheck // SA1019: s.Port is deprecated
port = *s.Port //nolint:staticcheck // SA1019: s.Port is deprecated
}
addrs = append(addrs, net.JoinHostPort(addr, strconv.FormatUint(uint64(port), 10)))
}
return addrs
} }

View file

@ -0,0 +1,29 @@
package config
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestBasicService_GetAddresses(t *testing.T) {
addr := "1.2.3.4"
port := uint16(1234)
s := BasicService{
Enabled: false,
Address: &addr,
Port: &port,
Addresses: []string{"1.2.3.4:1234", /* same as Address:Port */
"3.4.5.6:1234", "2.3.4.5", ":1235", "2.3.4.5:1234",
"3.4.5.6:1234" /* already in list */},
}
require.Equal(t, []string{
"1.2.3.4:1234",
"3.4.5.6:1234",
"2.3.4.5",
":1235",
"2.3.4.5:1234",
"3.4.5.6:1234",
"1.2.3.4:1234",
}, s.GetAddresses())
}

View file

@ -55,8 +55,10 @@ func LoadFile(configPath string) (Config, error) {
config := Config{ config := Config{
ApplicationConfiguration: ApplicationConfiguration{ ApplicationConfiguration: ApplicationConfiguration{
PingInterval: 30, P2P: P2P{
PingTimeout: 90, PingInterval: 30,
PingTimeout: 30,
},
RPC: RPC{ RPC: RPC{
MaxIteratorResultItems: DefaultMaxIteratorResultItems, MaxIteratorResultItems: DefaultMaxIteratorResultItems,
MaxFindResultItems: 100, MaxFindResultItems: 100,

19
pkg/config/p2p.go Normal file
View file

@ -0,0 +1,19 @@
package config
import "time"
// P2P holds P2P node settings.
type P2P struct {
// Addresses stores the node address list in the form of "[host]:[port][:announcedPort]".
Addresses []string `yaml:"Addresses"`
AttemptConnPeers int `yaml:"AttemptConnPeers"`
// BroadcastFactor is the factor (0-100) controlling gossip fan-out number optimization.
BroadcastFactor int `yaml:"BroadcastFactor"`
DialTimeout time.Duration `yaml:"DialTimeout"`
ExtensiblePoolSize int `yaml:"ExtensiblePoolSize"`
MaxPeers int `yaml:"MaxPeers"`
MinPeers int `yaml:"MinPeers"`
PingInterval time.Duration `yaml:"PingInterval"`
PingTimeout time.Duration `yaml:"PingTimeout"`
ProtoTickInterval time.Duration `yaml:"ProtoTickInterval"`
}

View file

@ -7,9 +7,8 @@ import (
type ( type (
// RPC is an RPC service configuration information. // RPC is an RPC service configuration information.
RPC struct { RPC struct {
Address string `yaml:"Address"` BasicService `yaml:",inline"`
Enabled bool `yaml:"Enabled"` EnableCORSWorkaround bool `yaml:"EnableCORSWorkaround"`
EnableCORSWorkaround bool `yaml:"EnableCORSWorkaround"`
// MaxGasInvoke is the maximum amount of GAS which // MaxGasInvoke is the maximum amount of GAS which
// can be spent during an RPC call. // can be spent during an RPC call.
MaxGasInvoke fixedn.Fixed8 `yaml:"MaxGasInvoke"` MaxGasInvoke fixedn.Fixed8 `yaml:"MaxGasInvoke"`
@ -17,7 +16,6 @@ type (
MaxFindResultItems int `yaml:"MaxFindResultItems"` MaxFindResultItems int `yaml:"MaxFindResultItems"`
MaxNEP11Tokens int `yaml:"MaxNEP11Tokens"` MaxNEP11Tokens int `yaml:"MaxNEP11Tokens"`
MaxWebSocketClients int `yaml:"MaxWebSocketClients"` MaxWebSocketClients int `yaml:"MaxWebSocketClients"`
Port uint16 `yaml:"Port"`
SessionEnabled bool `yaml:"SessionEnabled"` SessionEnabled bool `yaml:"SessionEnabled"`
SessionExpirationTime int `yaml:"SessionExpirationTime"` SessionExpirationTime int `yaml:"SessionExpirationTime"`
SessionBackedByMPT bool `yaml:"SessionBackedByMPT"` SessionBackedByMPT bool `yaml:"SessionBackedByMPT"`
@ -28,10 +26,8 @@ type (
// TLS describes SSL/TLS configuration. // TLS describes SSL/TLS configuration.
TLS struct { TLS struct {
Address string `yaml:"Address"` BasicService `yaml:",inline"`
CertFile string `yaml:"CertFile"` CertFile string `yaml:"CertFile"`
Enabled bool `yaml:"Enabled"` KeyFile string `yaml:"KeyFile"`
Port uint16 `yaml:"Port"`
KeyFile string `yaml:"KeyFile"`
} }
) )

View file

@ -0,0 +1,24 @@
package config
import (
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
// TestRPC_UnmarshalBasicService is aimed to check that BasicService config of
// RPC service can be properly unmarshalled. This test may be removed after
// Address and Port config fields removal.
func TestRPC_UnmarshalBasicService(t *testing.T) {
data := `
Enabled: true
Port: 10332
MaxGasInvoke: 15
`
cfg := &RPC{}
err := yaml.Unmarshal([]byte(data), &cfg)
require.NoError(t, err)
require.True(t, cfg.Enabled)
require.Equal(t, uint16(10332), *cfg.Port)
}

View file

@ -20,7 +20,8 @@ type fakeTransp struct {
started atomic2.Bool started atomic2.Bool
closed atomic2.Bool closed atomic2.Bool
dialCh chan string dialCh chan string
addr string host string
port string
} }
type fakeAPeer struct { type fakeAPeer struct {
@ -45,8 +46,14 @@ func (f *fakeAPeer) Version() *payload.Version {
return f.version return f.version
} }
func newFakeTransp(s *Server) Transporter { func newFakeTransp(s *Server, addr string) Transporter {
return &fakeTransp{} tr := &fakeTransp{}
h, p, err := net.SplitHostPort(addr)
if err == nil {
tr.host = h
tr.port = p
}
return tr
} }
func (ft *fakeTransp) Dial(addr string, timeout time.Duration) (AddressablePeer, error) { func (ft *fakeTransp) Dial(addr string, timeout time.Duration) (AddressablePeer, error) {
@ -62,14 +69,15 @@ func (ft *fakeTransp) Accept() {
if ft.started.Load() { if ft.started.Load() {
panic("started twice") panic("started twice")
} }
ft.addr = net.JoinHostPort("0.0.0.0", "42") ft.host = "0.0.0.0"
ft.port = "42"
ft.started.Store(true) ft.started.Store(true)
} }
func (ft *fakeTransp) Proto() string { func (ft *fakeTransp) Proto() string {
return "" return ""
} }
func (ft *fakeTransp) Address() string { func (ft *fakeTransp) HostPort() (string, string) {
return ft.addr return ft.host, ft.port
} }
func (ft *fakeTransp) Close() { func (ft *fakeTransp) Close() {
if ft.closed.Load() { if ft.closed.Load() {

View file

@ -158,7 +158,7 @@ func (p *localPeer) HandleVersion(v *payload.Version) error {
return nil return nil
} }
func (p *localPeer) SendVersion() error { func (p *localPeer) SendVersion() error {
m, err := p.server.getVersionMsg() m, err := p.server.getVersionMsg(nil)
if err != nil { if err != nil {
return err return err
} }
@ -208,6 +208,10 @@ func newTestServer(t *testing.T, serverConfig ServerConfig) *Server {
} }
func newTestServerWithCustomCfg(t *testing.T, serverConfig ServerConfig, protocolCfg func(*config.ProtocolConfiguration)) *Server { func newTestServerWithCustomCfg(t *testing.T, serverConfig ServerConfig, protocolCfg func(*config.ProtocolConfiguration)) *Server {
if len(serverConfig.Addresses) == 0 {
// Normally it will be done by ApplicationConfiguration.GetAddresses().
serverConfig.Addresses = []config.AnnounceableAddress{{Address: ":0"}}
}
s, err := newServerFromConstructors(serverConfig, fakechain.NewFakeChainWithCustomCfg(protocolCfg), new(fakechain.FakeStateSync), zaptest.NewLogger(t), s, err := newServerFromConstructors(serverConfig, fakechain.NewFakeChainWithCustomCfg(protocolCfg), new(fakechain.FakeStateSync), zaptest.NewLogger(t),
newFakeTransp, newTestDiscovery) newFakeTransp, newTestDiscovery)
require.NoError(t, err) require.NoError(t, err)

View file

@ -97,7 +97,7 @@ type (
// A copy of the Ledger's config. // A copy of the Ledger's config.
config config.ProtocolConfiguration config config.ProtocolConfiguration
transport Transporter transports []Transporter
discovery Discoverer discovery Discoverer
chain Ledger chain Ledger
bQueue *blockQueue bQueue *blockQueue
@ -154,13 +154,13 @@ func randomID() uint32 {
// NewServer returns a new Server, initialized with the given configuration. // NewServer returns a new Server, initialized with the given configuration.
func NewServer(config ServerConfig, chain Ledger, stSync StateSync, log *zap.Logger) (*Server, error) { func NewServer(config ServerConfig, chain Ledger, stSync StateSync, log *zap.Logger) (*Server, error) {
return newServerFromConstructors(config, chain, stSync, log, func(s *Server) Transporter { return newServerFromConstructors(config, chain, stSync, log, func(s *Server, addr string) Transporter {
return NewTCPTransport(s, net.JoinHostPort(s.ServerConfig.Address, strconv.Itoa(int(s.ServerConfig.Port))), s.log) return NewTCPTransport(s, addr, s.log)
}, newDefaultDiscovery) }, newDefaultDiscovery)
} }
func newServerFromConstructors(config ServerConfig, chain Ledger, stSync StateSync, log *zap.Logger, func newServerFromConstructors(config ServerConfig, chain Ledger, stSync StateSync, log *zap.Logger,
newTransport func(*Server) Transporter, newTransport func(*Server, string) Transporter,
newDiscovery func([]string, time.Duration, Transporter) Discoverer, newDiscovery func([]string, time.Duration, Transporter) Discoverer,
) (*Server, error) { ) (*Server, error) {
if log == nil { if log == nil {
@ -238,11 +238,20 @@ func newServerFromConstructors(config ServerConfig, chain Ledger, stSync StateSy
s.BroadcastFactor = defaultBroadcastFactor s.BroadcastFactor = defaultBroadcastFactor
} }
s.transport = newTransport(s) if len(s.ServerConfig.Addresses) == 0 {
return nil, errors.New("no bind addresses configured")
}
transports := make([]Transporter, len(s.ServerConfig.Addresses))
for i, addr := range s.ServerConfig.Addresses {
transports[i] = newTransport(s, addr.Address)
}
s.transports = transports
s.discovery = newDiscovery( s.discovery = newDiscovery(
s.Seeds, s.Seeds,
s.DialTimeout, s.DialTimeout,
s.transport, // Here we need to pick up a single transporter, it will be used to
// dial, and it doesn't matter which one.
s.transports[0],
) )
return s, nil return s, nil
@ -271,7 +280,9 @@ func (s *Server) Start(errChan chan error) {
go s.relayBlocksLoop() go s.relayBlocksLoop()
go s.bQueue.run() go s.bQueue.run()
go s.bSyncQueue.run() go s.bSyncQueue.run()
go s.transport.Accept() for _, tr := range s.transports {
go tr.Accept()
}
setServerAndNodeVersions(s.UserAgent, strconv.FormatUint(uint64(s.id), 10)) setServerAndNodeVersions(s.UserAgent, strconv.FormatUint(uint64(s.id), 10))
s.run() s.run()
} }
@ -280,7 +291,9 @@ func (s *Server) Start(errChan chan error) {
// once stopped the same intance of the Server can't be started again by calling Start. // once stopped the same intance of the Server can't be started again by calling Start.
func (s *Server) Shutdown() { func (s *Server) Shutdown() {
s.log.Info("shutting down server", zap.Int("peers", s.PeerCount())) s.log.Info("shutting down server", zap.Int("peers", s.PeerCount()))
s.transport.Close() for _, tr := range s.transports {
tr.Close()
}
for _, p := range s.getPeers(nil) { for _, p := range s.getPeers(nil) {
p.Disconnect(errServerShutdown) p.Disconnect(errServerShutdown)
} }
@ -600,11 +613,12 @@ func (s *Server) HandshakedPeersCount() int {
return count return count
} }
// getVersionMsg returns the current version message. // getVersionMsg returns the current version message generated for the specified
func (s *Server) getVersionMsg() (*Message, error) { // connection.
port, err := s.Port() func (s *Server) getVersionMsg(localAddr net.Addr) (*Message, error) {
port, err := s.Port(localAddr)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to fetch server port: %w", err)
} }
capabilities := []capability.Capability{ capabilities := []capability.Capability{
@ -1654,26 +1668,42 @@ func (s *Server) broadcastTxLoop() {
} }
} }
// Port returns a server port that should be used in P2P version exchange. In // Port returns a server port that should be used in P2P version exchange with the
// case `AnnouncedPort` is set in the server.Config, the announced node port // peer connected on the given localAddr. In case if announced node port is set
// will be returned (e.g. consider the node running behind NAT). If `AnnouncedPort` // in the server.Config for the given bind address, the announced node port will
// isn't set, the port returned may still differs from that of server.Config. // be returned (e.g. consider the node running behind NAT). If `AnnouncedPort`
func (s *Server) Port() (uint16, error) { // isn't set, the port returned may still differ from that of server.Config. If
if s.AnnouncedPort != 0 { // no localAddr is given, then the first available port will be returned.
return s.ServerConfig.AnnouncedPort, nil func (s *Server) Port(localAddr net.Addr) (uint16, error) {
var connIP string
if localAddr != nil {
connIP, _, _ = net.SplitHostPort(localAddr.String()) // Ignore error and provide info if possible.
} }
var port uint16 var defaultPort *uint16
_, portStr, err := net.SplitHostPort(s.transport.Address()) for i, tr := range s.transports {
if err != nil { listenIP, listenPort := tr.HostPort()
port = s.ServerConfig.Port if listenIP == "::" || listenIP == "" || localAddr == nil || connIP == "" || connIP == listenIP {
} else { var res uint16
p, err := strconv.ParseUint(portStr, 10, 16) if s.ServerConfig.Addresses[i].AnnouncedPort != 0 {
if err != nil { res = s.ServerConfig.Addresses[i].AnnouncedPort
return 0, err } else {
p, err := strconv.ParseUint(listenPort, 10, 16)
if err != nil {
return 0, fmt.Errorf("failed to parse bind port from '%s': %w", listenPort, err)
}
res = uint16(p)
}
if localAddr == nil || // no local address is specified => take the first port available
(listenIP != "::" && listenIP != "") { // direct match is always preferable
return res, nil
}
defaultPort = &res
} }
port = uint16(p)
} }
return port, nil if defaultPort != nil {
return *defaultPort, nil
}
return 0, fmt.Errorf("bind address for connection '%s' is not registered", localAddr.String())
} }
// optimalNumOfThreads returns the optimal number of processing threads to create // optimalNumOfThreads returns the optimal number of processing threads to create

View file

@ -1,6 +1,7 @@
package network package network
import ( import (
"fmt"
"time" "time"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
@ -28,14 +29,8 @@ type (
// The user agent of the server. // The user agent of the server.
UserAgent string UserAgent string
// Address. Example: "localhost". // Addresses stores the list of bind addresses for the node.
Address string Addresses []config.AnnounceableAddress
// AnnouncedPort is an announced node port for P2P version exchange.
AnnouncedPort uint16
// Port is the actual node port it is bound to. Example: 20332.
Port uint16
// The network mode the server will operate on. // The network mode the server will operate on.
// ModePrivNet docker private network. // ModePrivNet docker private network.
@ -86,34 +81,72 @@ type (
// NewServerConfig creates a new ServerConfig struct // NewServerConfig creates a new ServerConfig struct
// using the main applications config. // using the main applications config.
func NewServerConfig(cfg config.Config) ServerConfig { func NewServerConfig(cfg config.Config) (ServerConfig, error) {
appConfig := cfg.ApplicationConfiguration appConfig := cfg.ApplicationConfiguration
protoConfig := cfg.ProtocolConfiguration protoConfig := cfg.ProtocolConfiguration
timePerBlock := protoConfig.TimePerBlock timePerBlock := protoConfig.TimePerBlock
if timePerBlock == 0 && protoConfig.SecondsPerBlock > 0 { //nolint:staticcheck // SA1019: protoConfig.SecondsPerBlock is deprecated if timePerBlock == 0 && protoConfig.SecondsPerBlock > 0 { //nolint:staticcheck // SA1019: protoConfig.SecondsPerBlock is deprecated
timePerBlock = time.Duration(protoConfig.SecondsPerBlock) * time.Second //nolint:staticcheck // SA1019: protoConfig.SecondsPerBlock is deprecated timePerBlock = time.Duration(protoConfig.SecondsPerBlock) * time.Second //nolint:staticcheck // SA1019: protoConfig.SecondsPerBlock is deprecated
} }
dialTimeout := appConfig.P2P.DialTimeout
return ServerConfig{ if dialTimeout == 0 && appConfig.DialTimeout > 0 { //nolint:staticcheck // SA1019: appConfig.DialTimeout is deprecated
dialTimeout = time.Duration(appConfig.DialTimeout) * time.Second //nolint:staticcheck // SA1019: appConfig.DialTimeout is deprecated
}
protoTickInterval := appConfig.P2P.ProtoTickInterval
if protoTickInterval == 0 && appConfig.ProtoTickInterval > 0 { //nolint:staticcheck // SA1019: appConfig.ProtoTickInterval is deprecated
protoTickInterval = time.Duration(appConfig.ProtoTickInterval) * time.Second //nolint:staticcheck // SA1019: appConfig.ProtoTickInterval is deprecated
}
pingInterval := appConfig.P2P.PingInterval
if pingInterval == 0 && appConfig.PingInterval > 0 { //nolint:staticcheck // SA1019: appConfig.PingInterval is deprecated
pingInterval = time.Duration(appConfig.PingInterval) * time.Second //nolint:staticcheck // SA1019: appConfig.PingInterval is deprecated
}
pingTimeout := appConfig.P2P.PingTimeout
if pingTimeout == 0 && appConfig.PingTimeout > 0 { //nolint:staticcheck // SA1019: appConfig.PingTimeout is deprecated
pingTimeout = time.Duration(appConfig.PingTimeout) * time.Second //nolint:staticcheck // SA1019: appConfig.PingTimeout is deprecated
}
maxPeers := appConfig.P2P.MaxPeers
if maxPeers == 0 && appConfig.MaxPeers > 0 { //nolint:staticcheck // SA1019: appConfig.MaxPeers is deprecated
maxPeers = appConfig.MaxPeers //nolint:staticcheck // SA1019: appConfig.MaxPeers is deprecated
}
attemptConnPeers := appConfig.P2P.AttemptConnPeers
if attemptConnPeers == 0 && appConfig.AttemptConnPeers > 0 { //nolint:staticcheck // SA1019: appConfig.AttemptConnPeers is deprecated
attemptConnPeers = appConfig.AttemptConnPeers //nolint:staticcheck // SA1019: appConfig.AttemptConnPeers is deprecated
}
minPeers := appConfig.P2P.MinPeers
if minPeers == 0 && appConfig.MinPeers > 0 { //nolint:staticcheck // SA1019: appConfig.MinPeers is deprecated
minPeers = appConfig.MinPeers //nolint:staticcheck // SA1019: appConfig.MinPeers is deprecated
}
extPoolSize := appConfig.P2P.ExtensiblePoolSize
if extPoolSize == 0 && appConfig.ExtensiblePoolSize > 0 { //nolint:staticcheck // SA1019: appConfig.ExtensiblePoolSize is deprecated
extPoolSize = appConfig.ExtensiblePoolSize //nolint:staticcheck // SA1019: appConfig.ExtensiblePoolSize is deprecated
}
broadcastFactor := appConfig.P2P.BroadcastFactor
if broadcastFactor > 0 && appConfig.BroadcastFactor > 0 { //nolint:staticcheck // SA1019: appConfig.BroadcastFactor is deprecated
broadcastFactor = appConfig.BroadcastFactor //nolint:staticcheck // SA1019: appConfig.BroadcastFactor is deprecated
}
addrs, err := appConfig.GetAddresses()
if err != nil {
return ServerConfig{}, fmt.Errorf("failed to parse addresses: %w", err)
}
c := ServerConfig{
UserAgent: cfg.GenerateUserAgent(), UserAgent: cfg.GenerateUserAgent(),
Address: appConfig.Address, Addresses: addrs,
AnnouncedPort: appConfig.AnnouncedNodePort,
Port: appConfig.NodePort,
Net: protoConfig.Magic, Net: protoConfig.Magic,
Relay: appConfig.Relay, Relay: appConfig.Relay,
Seeds: protoConfig.SeedList, Seeds: protoConfig.SeedList,
DialTimeout: time.Duration(appConfig.DialTimeout) * time.Second, DialTimeout: dialTimeout,
ProtoTickInterval: time.Duration(appConfig.ProtoTickInterval) * time.Second, ProtoTickInterval: protoTickInterval,
PingInterval: time.Duration(appConfig.PingInterval) * time.Second, PingInterval: pingInterval,
PingTimeout: time.Duration(appConfig.PingTimeout) * time.Second, PingTimeout: pingTimeout,
MaxPeers: appConfig.MaxPeers, MaxPeers: maxPeers,
AttemptConnPeers: appConfig.AttemptConnPeers, AttemptConnPeers: attemptConnPeers,
MinPeers: appConfig.MinPeers, MinPeers: minPeers,
TimePerBlock: timePerBlock, TimePerBlock: timePerBlock,
OracleCfg: appConfig.Oracle, OracleCfg: appConfig.Oracle,
P2PNotaryCfg: appConfig.P2PNotary, P2PNotaryCfg: appConfig.P2PNotary,
StateRootCfg: appConfig.StateRoot, StateRootCfg: appConfig.StateRoot,
ExtensiblePoolSize: appConfig.ExtensiblePoolSize, ExtensiblePoolSize: extPoolSize,
BroadcastFactor: appConfig.BroadcastFactor, BroadcastFactor: broadcastFactor,
} }
return c, nil
} }

View file

@ -104,13 +104,13 @@ func TestServerStartAndShutdown(t *testing.T) {
s.register <- p s.register <- p
require.Eventually(t, func() bool { return 1 == s.PeerCount() }, time.Second, time.Millisecond*10) require.Eventually(t, func() bool { return 1 == s.PeerCount() }, time.Second, time.Millisecond*10)
assert.True(t, s.transport.(*fakeTransp).started.Load()) assert.True(t, s.transports[0].(*fakeTransp).started.Load())
assert.Nil(t, s.txCallback) assert.Nil(t, s.txCallback)
s.Shutdown() s.Shutdown()
<-ch <-ch
require.True(t, s.transport.(*fakeTransp).closed.Load()) require.True(t, s.transports[0].(*fakeTransp).closed.Load())
err, ok := p.droppedWith.Load().(error) err, ok := p.droppedWith.Load().(error)
require.True(t, ok) require.True(t, ok)
require.True(t, errors.Is(err, errServerShutdown)) require.True(t, errors.Is(err, errServerShutdown))
@ -191,7 +191,7 @@ func TestGetBlocksByIndex(t *testing.T) {
} }
func testGetBlocksByIndex(t *testing.T, cmd CommandType) { func testGetBlocksByIndex(t *testing.T, cmd CommandType) {
s := newTestServer(t, ServerConfig{Port: 0, UserAgent: "/test/"}) s := newTestServer(t, ServerConfig{UserAgent: "/test/"})
start := s.chain.BlockHeight() start := s.chain.BlockHeight()
if cmd == CMDGetHeaders { if cmd == CMDGetHeaders {
start = s.chain.HeaderHeight() start = s.chain.HeaderHeight()
@ -217,7 +217,7 @@ func testGetBlocksByIndex(t *testing.T, cmd CommandType) {
expectsCmd[i] = cmd expectsCmd[i] = cmd
expectedHeight[i] = []uint32{start + 1} expectedHeight[i] = []uint32{start + 1}
} }
go s.transport.Accept() go s.transports[0].Accept()
nonce := uint32(0) nonce := uint32(0)
checkPingRespond := func(t *testing.T, peerIndex int, peerHeight uint32, hs ...uint32) { checkPingRespond := func(t *testing.T, peerIndex int, peerHeight uint32, hs ...uint32) {
@ -250,16 +250,15 @@ func testGetBlocksByIndex(t *testing.T, cmd CommandType) {
func TestSendVersion(t *testing.T) { func TestSendVersion(t *testing.T) {
var ( var (
s = newTestServer(t, ServerConfig{Port: 0, UserAgent: "/test/"}) s = newTestServer(t, ServerConfig{UserAgent: "/test/"})
p = newLocalPeer(t, s) p = newLocalPeer(t, s)
) )
// we need to set listener at least to handle dynamic port correctly // we need to set listener at least to handle dynamic port correctly
s.transport.Accept() s.transports[0].Accept()
p.messageHandler = func(t *testing.T, msg *Message) { p.messageHandler = func(t *testing.T, msg *Message) {
// listener is already set, so Address() gives us proper address with port // listener is already set, so Addresses(nil) gives us proper address with port
_, p, err := net.SplitHostPort(s.transport.Address()) _, prt := s.transports[0].HostPort()
assert.NoError(t, err) port, err := strconv.ParseUint(prt, 10, 16)
port, err := strconv.ParseUint(p, 10, 16)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, CMDVersion, msg.Command) assert.Equal(t, CMDVersion, msg.Command)
assert.IsType(t, msg.Payload, &payload.Version{}) assert.IsType(t, msg.Payload, &payload.Version{})
@ -390,7 +389,7 @@ func (s *Server) testHandleMessage(t *testing.T, p Peer, cmd CommandType, pl pay
func startTestServer(t *testing.T, protocolCfg ...func(*config.ProtocolConfiguration)) *Server { func startTestServer(t *testing.T, protocolCfg ...func(*config.ProtocolConfiguration)) *Server {
var s *Server var s *Server
srvCfg := ServerConfig{Port: 0, UserAgent: "/test/"} srvCfg := ServerConfig{UserAgent: "/test/"}
if protocolCfg != nil { if protocolCfg != nil {
s = newTestServerWithCustomCfg(t, srvCfg, protocolCfg[0]) s = newTestServerWithCustomCfg(t, srvCfg, protocolCfg[0])
} else { } else {
@ -849,7 +848,7 @@ func TestHandleMPTData(t *testing.T) {
t.Run("good", func(t *testing.T) { t.Run("good", func(t *testing.T) {
expected := [][]byte{{1, 2, 3}, {2, 3, 4}} expected := [][]byte{{1, 2, 3}, {2, 3, 4}}
s := newTestServer(t, ServerConfig{Port: 0, UserAgent: "/test/"}) s := newTestServer(t, ServerConfig{UserAgent: "/test/"})
s.config.P2PStateExchangeExtensions = true s.config.P2PStateExchangeExtensions = true
s.stateSync = &fakechain.FakeStateSync{ s.stateSync = &fakechain.FakeStateSync{
AddMPTNodesFunc: func(nodes [][]byte) error { AddMPTNodesFunc: func(nodes [][]byte) error {
@ -1044,7 +1043,7 @@ func TestVerifyNotaryRequest(t *testing.T) {
bc := fakechain.NewFakeChain() bc := fakechain.NewFakeChain()
bc.MaxVerificationGAS = 10 bc.MaxVerificationGAS = 10
bc.NotaryContractScriptHash = util.Uint160{1, 2, 3} bc.NotaryContractScriptHash = util.Uint160{1, 2, 3}
s, err := newServerFromConstructors(ServerConfig{}, bc, new(fakechain.FakeStateSync), zaptest.NewLogger(t), newFakeTransp, newTestDiscovery) s, err := newServerFromConstructors(ServerConfig{Addresses: []config.AnnounceableAddress{{Address: ":0"}}}, bc, new(fakechain.FakeStateSync), zaptest.NewLogger(t), newFakeTransp, newTestDiscovery)
require.NoError(t, err) require.NoError(t, err)
newNotaryRequest := func() *payload.P2PNotaryRequest { newNotaryRequest := func() *payload.P2PNotaryRequest {
return &payload.P2PNotaryRequest{ return &payload.P2PNotaryRequest{
@ -1123,3 +1122,33 @@ func TestTryInitStateSync(t *testing.T) {
s.tryInitStateSync() s.tryInitStateSync()
}) })
} }
func TestServer_Port(t *testing.T) {
s := newTestServer(t, ServerConfig{
Addresses: []config.AnnounceableAddress{
{Address: "1.2.3.4:10"}, // some random address
{Address: ":1"}, // listen all IPs
{Address: "127.0.0.1:2"}, // address without announced port
{Address: "123.123.0.123:3", AnnouncedPort: 123}}, // address with announced port
})
// Default addr => first port available
actual, err := s.Port(nil)
require.NoError(t, err)
require.Equal(t, uint16(10), actual)
// Specified address with direct match => port of matched address
actual, err = s.Port(&net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 123})
require.NoError(t, err)
require.Equal(t, uint16(2), actual)
// No address match => 0.0.0.0's port
actual, err = s.Port(&net.TCPAddr{IP: net.IPv4(5, 6, 7, 8), Port: 123})
require.NoError(t, err)
require.Equal(t, uint16(1), actual)
// Specified address with match on announceable address => announced port
actual, err = s.Port(&net.TCPAddr{IP: net.IPv4(123, 123, 0, 123), Port: 123})
require.NoError(t, err)
require.Equal(t, uint16(123), actual)
}

View file

@ -307,7 +307,7 @@ func (p *TCPPeer) IsFullNode() bool {
// SendVersion checks for the handshake state and sends a message to the peer. // SendVersion checks for the handshake state and sends a message to the peer.
func (p *TCPPeer) SendVersion() error { func (p *TCPPeer) SendVersion() error {
msg, err := p.server.getVersionMsg() msg, err := p.server.getVersionMsg(p.conn.LocalAddr())
if err != nil { if err != nil {
return err return err
} }

View file

@ -19,7 +19,9 @@ func TestPeerHandshake(t *testing.T) {
server, client := net.Pipe() server, client := net.Pipe()
tcpS := NewTCPPeer(server, "", newTestServer(t, ServerConfig{})) tcpS := NewTCPPeer(server, "", newTestServer(t, ServerConfig{}))
tcpS.server.transports[0].Accept() // properly initialize the address list
tcpC := NewTCPPeer(client, "", newTestServer(t, ServerConfig{})) tcpC := NewTCPPeer(client, "", newTestServer(t, ServerConfig{}))
tcpC.server.transports[0].Accept()
// Something should read things written into the pipe. // Something should read things written into the pipe.
go connReadStub(tcpS.conn) go connReadStub(tcpS.conn)

View file

@ -15,17 +15,32 @@ type TCPTransport struct {
server *Server server *Server
listener net.Listener listener net.Listener
bindAddr string bindAddr string
hostPort hostPort
lock sync.RWMutex lock sync.RWMutex
quit bool quit bool
} }
type hostPort struct {
Host string
Port string
}
// NewTCPTransport returns a new TCPTransport that will listen for // NewTCPTransport returns a new TCPTransport that will listen for
// new incoming peer connections. // new incoming peer connections.
func NewTCPTransport(s *Server, bindAddr string, log *zap.Logger) *TCPTransport { func NewTCPTransport(s *Server, bindAddr string, log *zap.Logger) *TCPTransport {
host, port, err := net.SplitHostPort(bindAddr)
if err != nil {
// Only host can be provided, it's OK.
host = bindAddr
}
return &TCPTransport{ return &TCPTransport{
log: log, log: log,
server: s, server: s,
bindAddr: bindAddr, bindAddr: bindAddr,
hostPort: hostPort{
Host: host,
Port: port,
},
} }
} }
@ -55,6 +70,8 @@ func (t *TCPTransport) Accept() {
return return
} }
t.listener = l t.listener = l
t.bindAddr = l.Addr().String()
t.hostPort.Host, t.hostPort.Port, _ = net.SplitHostPort(t.bindAddr) // no error expected as l.Addr() is a valid address.
t.lock.Unlock() t.lock.Unlock()
for { for {
@ -66,7 +83,7 @@ func (t *TCPTransport) Accept() {
if errors.Is(err, net.ErrClosed) && quit { if errors.Is(err, net.ErrClosed) && quit {
break break
} }
t.log.Warn("TCP accept error", zap.Error(err)) t.log.Warn("TCP accept error", zap.String("address", l.Addr().String()), zap.Error(err))
continue continue
} }
p := NewTCPPeer(conn, "", t.server) p := NewTCPPeer(conn, "", t.server)
@ -89,12 +106,10 @@ func (t *TCPTransport) Proto() string {
return "tcp" return "tcp"
} }
// Address implements the Transporter interface. // HostPort implements the Transporter interface.
func (t *TCPTransport) Address() string { func (t *TCPTransport) HostPort() (string, string) {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
if t.listener != nil {
return t.listener.Addr().String() return t.hostPort.Host, t.hostPort.Port
}
return ""
} }

View file

@ -8,6 +8,6 @@ type Transporter interface {
Dial(addr string, timeout time.Duration) (AddressablePeer, error) Dial(addr string, timeout time.Duration) (AddressablePeer, error)
Accept() Accept()
Proto() string Proto() string
Address() string HostPort() (string, string)
Close() Close()
} }

View file

@ -3,31 +3,62 @@ package metrics
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"net"
"net/http" "net/http"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"go.uber.org/atomic"
"go.uber.org/zap" "go.uber.org/zap"
) )
// Service serves metrics. // Service serves metrics.
type Service struct { type Service struct {
*http.Server http []*http.Server
config config.BasicService config config.BasicService
log *zap.Logger log *zap.Logger
serviceType string serviceType string
started *atomic.Bool
}
// NewService configures logger and returns new service instance.
func NewService(name string, httpServers []*http.Server, cfg config.BasicService, log *zap.Logger) *Service {
return &Service{
http: httpServers,
config: cfg,
serviceType: name,
log: log.With(zap.String("service", name)),
started: atomic.NewBool(false),
}
} }
// Start runs http service with the exposed endpoint on the configured port. // Start runs http service with the exposed endpoint on the configured port.
func (ms *Service) Start() { func (ms *Service) Start() error {
if ms.config.Enabled { if ms.config.Enabled {
ms.log.Info("service is running", zap.String("endpoint", ms.Addr)) if !ms.started.CAS(false, true) {
err := ms.ListenAndServe() ms.log.Info("service already started")
if err != nil && !errors.Is(err, http.ErrServerClosed) { return nil
ms.log.Warn("service couldn't start on configured port") }
for _, srv := range ms.http {
ms.log.Info("starting service", zap.String("endpoint", srv.Addr))
ln, err := net.Listen("tcp", srv.Addr)
if err != nil {
return fmt.Errorf("failed to listen on %s: %w", srv.Addr, err)
}
srv.Addr = ln.Addr().String() // set Addr to the actual address
go func(s *http.Server) {
err = s.Serve(ln)
if !errors.Is(err, http.ErrServerClosed) {
ms.log.Error("failed to start service", zap.String("endpoint", s.Addr), zap.Error(err))
}
}(srv)
} }
} else { } else {
ms.log.Info("service hasn't started since it's disabled") ms.log.Info("service hasn't started since it's disabled")
} }
return nil
} }
// ShutDown stops the service. // ShutDown stops the service.
@ -35,9 +66,14 @@ func (ms *Service) ShutDown() {
if !ms.config.Enabled { if !ms.config.Enabled {
return return
} }
ms.log.Info("shutting down service", zap.String("endpoint", ms.Addr)) if !ms.started.CAS(true, false) {
err := ms.Shutdown(context.Background()) return
if err != nil { }
ms.log.Error("can't shut service down", zap.Error(err)) for _, srv := range ms.http {
ms.log.Info("shutting down service", zap.String("endpoint", srv.Addr))
err := srv.Shutdown(context.Background())
if err != nil {
ms.log.Error("can't shut service down", zap.String("endpoint", srv.Addr), zap.Error(err))
}
} }
} }

View file

@ -24,13 +24,13 @@ func NewPprofService(cfg config.BasicService, log *zap.Logger) *Service {
handler.HandleFunc("/debug/pprof/symbol", pprof.Symbol) handler.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
handler.HandleFunc("/debug/pprof/trace", pprof.Trace) handler.HandleFunc("/debug/pprof/trace", pprof.Trace)
return &Service{ addrs := cfg.GetAddresses()
Server: &http.Server{ srvs := make([]*http.Server, len(addrs))
Addr: cfg.Address + ":" + cfg.Port, for i, addr := range addrs {
srvs[i] = &http.Server{
Addr: addr,
Handler: handler, Handler: handler,
}, }
config: cfg,
serviceType: "Pprof",
log: log.With(zap.String("service", "Pprof")),
} }
return NewService("Pprof", srvs, cfg, log)
} }

View file

@ -17,13 +17,13 @@ func NewPrometheusService(cfg config.BasicService, log *zap.Logger) *Service {
return nil return nil
} }
return &Service{ addrs := cfg.GetAddresses()
Server: &http.Server{ srvs := make([]*http.Server, len(addrs))
Addr: cfg.Address + ":" + cfg.Port, for i, addr := range addrs {
Handler: promhttp.Handler(), srvs[i] = &http.Server{
}, Addr: addr,
config: cfg, Handler: promhttp.Handler(), // share metrics between multiple prometheus handlers
serviceType: "Prometheus", }
log: log.With(zap.String("service", "Prometheus")),
} }
return NewService("Prometheus", srvs, cfg, log)
} }

View file

@ -1923,9 +1923,10 @@ func TestClient_Iterator_SessionConfigVariations(t *testing.T) {
cfg.ApplicationConfiguration.RPC.SessionEnabled = true cfg.ApplicationConfiguration.RPC.SessionEnabled = true
cfg.ApplicationConfiguration.RPC.SessionBackedByMPT = true cfg.ApplicationConfiguration.RPC.SessionBackedByMPT = true
}) })
serverConfig := network.NewServerConfig(cfg) serverConfig, err := network.NewServerConfig(cfg)
require.NoError(t, err)
serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.6-test") serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.6-test")
serverConfig.Port = 0 serverConfig.Addresses = []config.AnnounceableAddress{{Address: ":0"}}
server, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), logger) server, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), logger)
require.NoError(t, err) require.NoError(t, err)
errCh := make(chan error, 2) errCh := make(chan error, 2)

View file

@ -117,7 +117,9 @@ type (
// Server represents the JSON-RPC 2.0 server. // Server represents the JSON-RPC 2.0 server.
Server struct { Server struct {
*http.Server http []*http.Server
https []*http.Server
chain Ledger chain Ledger
config config.RPC config config.RPC
// wsReadLimit represents web-socket message limit for a receiving side. // wsReadLimit represents web-socket message limit for a receiving side.
@ -128,7 +130,6 @@ type (
coreServer *network.Server coreServer *network.Server
oracle *atomic.Value oracle *atomic.Value
log *zap.Logger log *zap.Logger
https *http.Server
shutdown chan struct{} shutdown chan struct{}
started *atomic.Bool started *atomic.Bool
errChan chan error errChan chan error
@ -254,14 +255,22 @@ var invalidBlockHeightError = func(index int, height int) *neorpc.Error {
// New creates a new Server struct. // New creates a new Server struct.
func New(chain Ledger, conf config.RPC, coreServer *network.Server, func New(chain Ledger, conf config.RPC, coreServer *network.Server,
orc OracleHandler, log *zap.Logger, errChan chan error) Server { orc OracleHandler, log *zap.Logger, errChan chan error) Server {
httpServer := &http.Server{ addrs := conf.GetAddresses()
Addr: conf.Address + ":" + strconv.FormatUint(uint64(conf.Port), 10), httpServers := make([]*http.Server, len(addrs))
for i, addr := range addrs {
httpServers[i] = &http.Server{
Addr: addr,
}
} }
var tlsServer *http.Server var tlsServers []*http.Server
if cfg := conf.TLSConfig; cfg.Enabled { if cfg := conf.TLSConfig; cfg.Enabled {
tlsServer = &http.Server{ addrs := cfg.GetAddresses()
Addr: net.JoinHostPort(cfg.Address, strconv.FormatUint(uint64(cfg.Port), 10)), tlsServers = make([]*http.Server, len(addrs))
for i, addr := range addrs {
tlsServers[i] = &http.Server{
Addr: addr,
}
} }
} }
@ -289,7 +298,9 @@ func New(chain Ledger, conf config.RPC, coreServer *network.Server,
wsOriginChecker = func(_ *http.Request) bool { return true } wsOriginChecker = func(_ *http.Request) bool { return true }
} }
return Server{ return Server{
Server: httpServer, http: httpServers,
https: tlsServers,
chain: chain, chain: chain,
config: conf, config: conf,
wsReadLimit: int64(protoCfg.MaxBlockSize*4)/3 + 1024, // Enough for Base64-encoded content of `submitblock` and `submitp2pnotaryrequest`. wsReadLimit: int64(protoCfg.MaxBlockSize*4)/3 + 1024, // Enough for Base64-encoded content of `submitblock` and `submitp2pnotaryrequest`.
@ -299,7 +310,6 @@ func New(chain Ledger, conf config.RPC, coreServer *network.Server,
coreServer: coreServer, coreServer: coreServer,
log: log, log: log,
oracle: oracleWrapped, oracle: oracleWrapped,
https: tlsServer,
shutdown: make(chan struct{}), shutdown: make(chan struct{}),
started: atomic.NewBool(false), started: atomic.NewBool(false),
errChan: errChan, errChan: errChan,
@ -333,40 +343,48 @@ func (s *Server) Start() {
s.log.Info("RPC server already started") s.log.Info("RPC server already started")
return return
} }
s.Handler = http.HandlerFunc(s.handleHTTPRequest) for _, srv := range s.http {
s.log.Info("starting rpc-server", zap.String("endpoint", s.Addr)) srv.Handler = http.HandlerFunc(s.handleHTTPRequest)
s.log.Info("starting rpc-server", zap.String("endpoint", srv.Addr))
ln, err := net.Listen("tcp", srv.Addr)
if err != nil {
s.errChan <- fmt.Errorf("failed to listen on %s: %w", srv.Addr, err)
return
}
srv.Addr = ln.Addr().String() // set Addr to the actual address
go func(server *http.Server) {
err = server.Serve(ln)
if !errors.Is(err, http.ErrServerClosed) {
s.log.Error("failed to start RPC server", zap.Error(err))
s.errChan <- err
}
}(srv)
}
go s.handleSubEvents() go s.handleSubEvents()
if cfg := s.config.TLSConfig; cfg.Enabled { if cfg := s.config.TLSConfig; cfg.Enabled {
s.https.Handler = http.HandlerFunc(s.handleHTTPRequest) for _, srv := range s.https {
s.log.Info("starting rpc-server (https)", zap.String("endpoint", s.https.Addr)) srv.Handler = http.HandlerFunc(s.handleHTTPRequest)
go func() { s.log.Info("starting rpc-server (https)", zap.String("endpoint", srv.Addr))
ln, err := net.Listen("tcp", s.https.Addr)
ln, err := net.Listen("tcp", srv.Addr)
if err != nil { if err != nil {
s.errChan <- err s.errChan <- err
return return
} }
s.https.Addr = ln.Addr().String() srv.Addr = ln.Addr().String()
err = s.https.ServeTLS(ln, cfg.CertFile, cfg.KeyFile)
if !errors.Is(err, http.ErrServerClosed) { go func(srv *http.Server) {
s.log.Error("failed to start TLS RPC server", zap.Error(err)) err = srv.ServeTLS(ln, cfg.CertFile, cfg.KeyFile)
s.errChan <- err if !errors.Is(err, http.ErrServerClosed) {
} s.log.Error("failed to start TLS RPC server",
}() zap.String("endpoint", srv.Addr), zap.Error(err))
} s.errChan <- err
ln, err := net.Listen("tcp", s.Addr) }
if err != nil { }(srv)
s.errChan <- err
return
}
s.Addr = ln.Addr().String() // set Addr to the actual address
go func() {
err = s.Serve(ln)
if !errors.Is(err, http.ErrServerClosed) {
s.log.Error("failed to start RPC server", zap.Error(err))
s.errChan <- err
} }
}() }
} }
// Shutdown stops the RPC server if it's running. It can only be called once, // Shutdown stops the RPC server if it's running. It can only be called once,
@ -381,17 +399,23 @@ func (s *Server) Shutdown() {
close(s.shutdown) close(s.shutdown)
if s.config.TLSConfig.Enabled { if s.config.TLSConfig.Enabled {
s.log.Info("shutting down RPC server (https)", zap.String("endpoint", s.https.Addr)) for _, srv := range s.https {
err := s.https.Shutdown(context.Background()) s.log.Info("shutting down RPC server (https)", zap.String("endpoint", srv.Addr))
if err != nil { err := srv.Shutdown(context.Background())
s.log.Warn("error during RPC (https) server shutdown", zap.Error(err)) if err != nil {
s.log.Warn("error during RPC (https) server shutdown",
zap.String("endpoint", srv.Addr), zap.Error(err))
}
} }
} }
s.log.Info("shutting down RPC server", zap.String("endpoint", s.Addr)) for _, srv := range s.http {
err := s.Server.Shutdown(context.Background()) s.log.Info("shutting down RPC server", zap.String("endpoint", srv.Addr))
if err != nil { err := srv.Shutdown(context.Background())
s.log.Warn("error during RPC (http) server shutdown", zap.Error(err)) if err != nil {
s.log.Warn("error during RPC (http) server shutdown",
zap.String("endpoint", srv.Addr), zap.Error(err))
}
} }
// Perform sessions finalisation. // Perform sessions finalisation.
@ -693,7 +717,7 @@ func (s *Server) getBlockHash(reqParams params.Params) (interface{}, *neorpc.Err
} }
func (s *Server) getVersion(_ params.Params) (interface{}, *neorpc.Error) { func (s *Server) getVersion(_ params.Params) (interface{}, *neorpc.Error) {
port, err := s.coreServer.Port() port, err := s.coreServer.Port(nil) // any port will suite
if err != nil { if err != nil {
return nil, neorpc.NewInternalServerError(fmt.Sprintf("cannot fetch tcp port: %s", err)) return nil, neorpc.NewInternalServerError(fmt.Sprintf("cannot fetch tcp port: %s", err))
} }
@ -2790,3 +2814,13 @@ func escapeForLog(in string) string {
return c return c
}, in) }, in)
} }
// Addresses returns the list of addresses RPC server is listening to in the form of
// address:port.
func (s *Server) Addresses() []string {
res := make([]string, len(s.http))
for i, srv := range s.http {
res[i] = srv.Addr
}
return res
}

View file

@ -116,9 +116,10 @@ func initClearServerWithServices(t testing.TB, needOracle bool, needNotary bool,
} }
func wrapUnitTestChain(t testing.TB, chain *core.Blockchain, orc *oracle.Oracle, cfg config.Config, logger *zap.Logger) (*core.Blockchain, *Server, *httptest.Server) { func wrapUnitTestChain(t testing.TB, chain *core.Blockchain, orc *oracle.Oracle, cfg config.Config, logger *zap.Logger) (*core.Blockchain, *Server, *httptest.Server) {
serverConfig := network.NewServerConfig(cfg) serverConfig, err := network.NewServerConfig(cfg)
require.NoError(t, err)
serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.6-test") serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.6-test")
serverConfig.Port = 0 serverConfig.Addresses = []config.AnnounceableAddress{{Address: ":0"}}
server, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), logger) server, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), logger)
require.NoError(t, err) require.NoError(t, err)
errCh := make(chan error, 2) errCh := make(chan error, 2)

View file

@ -3278,7 +3278,8 @@ func TestEscapeForLog(t *testing.T) {
func BenchmarkHandleIn(b *testing.B) { func BenchmarkHandleIn(b *testing.B) {
chain, orc, cfg, logger := getUnitTestChain(b, false, false, false) chain, orc, cfg, logger := getUnitTestChain(b, false, false, false)
serverConfig := network.NewServerConfig(cfg) serverConfig, err := network.NewServerConfig(cfg)
require.NoError(b, err)
serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.6-test") serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.6-test")
serverConfig.LogLevel = zapcore.FatalLevel serverConfig.LogLevel = zapcore.FatalLevel
server, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), logger) server, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), logger)