Merge pull request #2448 from nspcc-dev/rpc/fix-initialgas
rpc: support InitialGasDistribution response from older Neo-Go nodes
This commit is contained in:
commit
ef93fd8cde
9 changed files with 317 additions and 14 deletions
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -137,6 +138,7 @@ func newTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch
|
||||||
}
|
}
|
||||||
|
|
||||||
serverConfig := network.NewServerConfig(cfg)
|
serverConfig := network.NewServerConfig(cfg)
|
||||||
|
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)
|
||||||
cons, err := consensus.NewService(consensus.Config{
|
cons, err := consensus.NewService(consensus.Config{
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module github.com/nspcc-dev/neo-go
|
||||||
require (
|
require (
|
||||||
github.com/btcsuite/btcd v0.22.0-beta
|
github.com/btcsuite/btcd v0.22.0-beta
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||||
|
github.com/coreos/go-semver v0.3.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -52,6 +52,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||||
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
|
|
@ -9,7 +9,14 @@ import (
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const userAgentFormat = "/NEO-GO:%s/"
|
const (
|
||||||
|
// UserAgentWrapper is a string that user agent string should be wrapped into.
|
||||||
|
UserAgentWrapper = "/"
|
||||||
|
// UserAgentPrefix is a prefix used to generate user agent string.
|
||||||
|
UserAgentPrefix = "NEO-GO:"
|
||||||
|
// UserAgentFormat is a formatted string used to generate user agent string.
|
||||||
|
UserAgentFormat = UserAgentWrapper + UserAgentPrefix + "%s" + UserAgentWrapper
|
||||||
|
)
|
||||||
|
|
||||||
// Version the version of the node, set at build time.
|
// Version the version of the node, set at build time.
|
||||||
var Version string
|
var Version string
|
||||||
|
@ -23,7 +30,7 @@ type Config struct {
|
||||||
|
|
||||||
// GenerateUserAgent creates user agent string based on build time environment.
|
// GenerateUserAgent creates user agent string based on build time environment.
|
||||||
func (c Config) GenerateUserAgent() string {
|
func (c Config) GenerateUserAgent() string {
|
||||||
return fmt.Sprintf(userAgentFormat, Version)
|
return fmt.Sprintf(UserAgentFormat, Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load attempts to load the config from the given
|
// Load attempts to load the config from the given
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/go-semver/semver"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -10,19 +17,47 @@ type (
|
||||||
Version struct {
|
Version struct {
|
||||||
// Magic contains network magic.
|
// Magic contains network magic.
|
||||||
// Deprecated: use Protocol.StateRootInHeader instead
|
// Deprecated: use Protocol.StateRootInHeader instead
|
||||||
Magic netmode.Magic `json:"network"`
|
Magic netmode.Magic
|
||||||
TCPPort uint16 `json:"tcpport"`
|
TCPPort uint16
|
||||||
WSPort uint16 `json:"wsport,omitempty"`
|
WSPort uint16
|
||||||
Nonce uint32 `json:"nonce"`
|
Nonce uint32
|
||||||
UserAgent string `json:"useragent"`
|
UserAgent string
|
||||||
Protocol Protocol `json:"protocol"`
|
Protocol Protocol
|
||||||
// StateRootInHeader is true if state root is contained in block header.
|
// StateRootInHeader is true if state root is contained in block header.
|
||||||
// Deprecated: use Protocol.StateRootInHeader instead
|
// Deprecated: use Protocol.StateRootInHeader instead
|
||||||
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
StateRootInHeader bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protocol represents network-dependent parameters.
|
// Protocol represents network-dependent parameters.
|
||||||
Protocol struct {
|
Protocol struct {
|
||||||
|
AddressVersion byte
|
||||||
|
Network netmode.Magic
|
||||||
|
MillisecondsPerBlock int
|
||||||
|
MaxTraceableBlocks uint32
|
||||||
|
MaxValidUntilBlockIncrement uint32
|
||||||
|
MaxTransactionsPerBlock uint16
|
||||||
|
MemoryPoolMaxTransactions int
|
||||||
|
ValidatorsCount byte
|
||||||
|
InitialGasDistribution fixedn.Fixed8
|
||||||
|
// StateRootInHeader is true if state root is contained in block header.
|
||||||
|
StateRootInHeader bool
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// versionMarshallerAux is an auxiliary struct used for Version JSON marshalling.
|
||||||
|
versionMarshallerAux struct {
|
||||||
|
Magic netmode.Magic `json:"network"`
|
||||||
|
TCPPort uint16 `json:"tcpport"`
|
||||||
|
WSPort uint16 `json:"wsport,omitempty"`
|
||||||
|
Nonce uint32 `json:"nonce"`
|
||||||
|
UserAgent string `json:"useragent"`
|
||||||
|
Protocol protocolMarshallerAux `json:"protocol"`
|
||||||
|
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// protocolMarshallerAux is an auxiliary struct used for Protocol JSON marshalling.
|
||||||
|
protocolMarshallerAux struct {
|
||||||
AddressVersion byte `json:"addressversion"`
|
AddressVersion byte `json:"addressversion"`
|
||||||
Network netmode.Magic `json:"network"`
|
Network netmode.Magic `json:"network"`
|
||||||
MillisecondsPerBlock int `json:"msperblock"`
|
MillisecondsPerBlock int `json:"msperblock"`
|
||||||
|
@ -32,7 +67,116 @@ type (
|
||||||
MemoryPoolMaxTransactions int `json:"memorypoolmaxtransactions"`
|
MemoryPoolMaxTransactions int `json:"memorypoolmaxtransactions"`
|
||||||
ValidatorsCount byte `json:"validatorscount"`
|
ValidatorsCount byte `json:"validatorscount"`
|
||||||
InitialGasDistribution int64 `json:"initialgasdistribution"`
|
InitialGasDistribution int64 `json:"initialgasdistribution"`
|
||||||
// StateRootInHeader is true if state root is contained in block header.
|
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
||||||
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
}
|
||||||
|
|
||||||
|
// versionUnmarshallerAux is an auxiliary struct used for Version JSON unmarshalling.
|
||||||
|
versionUnmarshallerAux struct {
|
||||||
|
Magic netmode.Magic `json:"network"`
|
||||||
|
TCPPort uint16 `json:"tcpport"`
|
||||||
|
WSPort uint16 `json:"wsport,omitempty"`
|
||||||
|
Nonce uint32 `json:"nonce"`
|
||||||
|
UserAgent string `json:"useragent"`
|
||||||
|
Protocol protocolUnmarshallerAux `json:"protocol"`
|
||||||
|
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// protocolUnmarshallerAux is an auxiliary struct used for Protocol JSON unmarshalling.
|
||||||
|
protocolUnmarshallerAux struct {
|
||||||
|
AddressVersion byte `json:"addressversion"`
|
||||||
|
Network netmode.Magic `json:"network"`
|
||||||
|
MillisecondsPerBlock int `json:"msperblock"`
|
||||||
|
MaxTraceableBlocks uint32 `json:"maxtraceableblocks"`
|
||||||
|
MaxValidUntilBlockIncrement uint32 `json:"maxvaliduntilblockincrement"`
|
||||||
|
MaxTransactionsPerBlock uint16 `json:"maxtransactionsperblock"`
|
||||||
|
MemoryPoolMaxTransactions int `json:"memorypoolmaxtransactions"`
|
||||||
|
ValidatorsCount byte `json:"validatorscount"`
|
||||||
|
InitialGasDistribution json.RawMessage `json:"initialgasdistribution"`
|
||||||
|
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// latestNonBreakingVersion is a latest NeoGo revision that keeps older RPC
|
||||||
|
// clients compatibility with newer RPC servers (https://github.com/nspcc-dev/neo-go/pull/2435).
|
||||||
|
var latestNonBreakingVersion = *semver.New("0.98.2")
|
||||||
|
|
||||||
|
// MarshalJSON implements the json marshaller interface.
|
||||||
|
func (v *Version) MarshalJSON() ([]byte, error) {
|
||||||
|
aux := versionMarshallerAux{
|
||||||
|
Magic: v.Magic,
|
||||||
|
TCPPort: v.TCPPort,
|
||||||
|
WSPort: v.WSPort,
|
||||||
|
Nonce: v.Nonce,
|
||||||
|
UserAgent: v.UserAgent,
|
||||||
|
Protocol: protocolMarshallerAux{
|
||||||
|
AddressVersion: v.Protocol.AddressVersion,
|
||||||
|
Network: v.Protocol.Network,
|
||||||
|
MillisecondsPerBlock: v.Protocol.MillisecondsPerBlock,
|
||||||
|
MaxTraceableBlocks: v.Protocol.MaxTraceableBlocks,
|
||||||
|
MaxValidUntilBlockIncrement: v.Protocol.MaxValidUntilBlockIncrement,
|
||||||
|
MaxTransactionsPerBlock: v.Protocol.MaxTransactionsPerBlock,
|
||||||
|
MemoryPoolMaxTransactions: v.Protocol.MemoryPoolMaxTransactions,
|
||||||
|
ValidatorsCount: v.Protocol.ValidatorsCount,
|
||||||
|
InitialGasDistribution: int64(v.Protocol.InitialGasDistribution),
|
||||||
|
StateRootInHeader: v.Protocol.StateRootInHeader,
|
||||||
|
},
|
||||||
|
StateRootInHeader: v.StateRootInHeader,
|
||||||
|
}
|
||||||
|
return json.Marshal(aux)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json unmarshaller interface.
|
||||||
|
func (v *Version) UnmarshalJSON(data []byte) error {
|
||||||
|
var aux versionUnmarshallerAux
|
||||||
|
err := json.Unmarshal(data, &aux)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Magic = aux.Magic
|
||||||
|
v.TCPPort = aux.TCPPort
|
||||||
|
v.WSPort = aux.WSPort
|
||||||
|
v.Nonce = aux.Nonce
|
||||||
|
v.UserAgent = aux.UserAgent
|
||||||
|
v.Protocol.AddressVersion = aux.Protocol.AddressVersion
|
||||||
|
v.Protocol.Network = aux.Protocol.Network
|
||||||
|
v.Protocol.MillisecondsPerBlock = aux.Protocol.MillisecondsPerBlock
|
||||||
|
v.Protocol.MaxTraceableBlocks = aux.Protocol.MaxTraceableBlocks
|
||||||
|
v.Protocol.MaxValidUntilBlockIncrement = aux.Protocol.MaxValidUntilBlockIncrement
|
||||||
|
v.Protocol.MaxTransactionsPerBlock = aux.Protocol.MaxTransactionsPerBlock
|
||||||
|
v.Protocol.MemoryPoolMaxTransactions = aux.Protocol.MemoryPoolMaxTransactions
|
||||||
|
v.Protocol.ValidatorsCount = aux.Protocol.ValidatorsCount
|
||||||
|
v.Protocol.StateRootInHeader = aux.Protocol.StateRootInHeader
|
||||||
|
v.StateRootInHeader = aux.StateRootInHeader
|
||||||
|
if len(aux.Protocol.InitialGasDistribution) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(v.UserAgent, config.UserAgentWrapper+config.UserAgentPrefix) {
|
||||||
|
ver, err := userAgentToVersion(v.UserAgent)
|
||||||
|
if err == nil && ver.Compare(latestNonBreakingVersion) <= 0 {
|
||||||
|
err := json.Unmarshal(aux.Protocol.InitialGasDistribution, &v.Protocol.InitialGasDistribution)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal InitialGASDistribution into fixed8: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var val int64
|
||||||
|
err = json.Unmarshal(aux.Protocol.InitialGasDistribution, &val)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal InitialGASDistribution into int64: %w", err)
|
||||||
|
}
|
||||||
|
v.Protocol.InitialGasDistribution = fixedn.Fixed8(val)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func userAgentToVersion(userAgent string) (*semver.Version, error) {
|
||||||
|
verStr := strings.Trim(userAgent, config.UserAgentWrapper)
|
||||||
|
verStr = strings.TrimPrefix(verStr, config.UserAgentPrefix)
|
||||||
|
ver, err := semver.NewVersion(verStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't retrieve neo-go version from UserAgent: %w", err)
|
||||||
|
}
|
||||||
|
return ver, nil
|
||||||
|
}
|
||||||
|
|
143
pkg/rpc/response/result/version_test.go
Normal file
143
pkg/rpc/response/result/version_test.go
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
package result
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVersion_MarshalUnmarshalJSON(t *testing.T) {
|
||||||
|
responseFromGoOld := `{
|
||||||
|
"network": 860833102,
|
||||||
|
"nonce": 1677922561,
|
||||||
|
"protocol": {
|
||||||
|
"addressversion": 53,
|
||||||
|
"initialgasdistribution": "52000000",
|
||||||
|
"maxtraceableblocks": 2102400,
|
||||||
|
"maxtransactionsperblock": 512,
|
||||||
|
"maxvaliduntilblockincrement": 5760,
|
||||||
|
"memorypoolmaxtransactions": 50000,
|
||||||
|
"msperblock": 15000,
|
||||||
|
"network": 860833102,
|
||||||
|
"validatorscount": 7
|
||||||
|
},
|
||||||
|
"tcpport": 10333,
|
||||||
|
"useragent": "/NEO-GO:0.98.2/",
|
||||||
|
"wsport": 10334
|
||||||
|
}`
|
||||||
|
responseFromGoNew := `{
|
||||||
|
"network": 860833102,
|
||||||
|
"nonce": 1677922561,
|
||||||
|
"protocol": {
|
||||||
|
"addressversion": 53,
|
||||||
|
"initialgasdistribution": 5200000000000000,
|
||||||
|
"maxtraceableblocks": 2102400,
|
||||||
|
"maxtransactionsperblock": 512,
|
||||||
|
"maxvaliduntilblockincrement": 5760,
|
||||||
|
"memorypoolmaxtransactions": 50000,
|
||||||
|
"msperblock": 15000,
|
||||||
|
"network": 860833102,
|
||||||
|
"validatorscount": 7
|
||||||
|
},
|
||||||
|
"tcpport": 10333,
|
||||||
|
"useragent": "/NEO-GO:0.98.3/",
|
||||||
|
"wsport": 10334
|
||||||
|
}`
|
||||||
|
responseFromSharp := `{
|
||||||
|
"nonce": 1677922561,
|
||||||
|
"protocol": {
|
||||||
|
"addressversion": 53,
|
||||||
|
"initialgasdistribution": 5200000000000000,
|
||||||
|
"maxtraceableblocks": 2102400,
|
||||||
|
"maxtransactionsperblock": 512,
|
||||||
|
"maxvaliduntilblockincrement": 5760,
|
||||||
|
"memorypoolmaxtransactions": 50000,
|
||||||
|
"msperblock": 15000,
|
||||||
|
"network": 860833102,
|
||||||
|
"validatorscount": 7
|
||||||
|
},
|
||||||
|
"tcpport": 10333,
|
||||||
|
"useragent": "/Neo:3.1.0/",
|
||||||
|
"wsport": 10334
|
||||||
|
}`
|
||||||
|
v := &Version{
|
||||||
|
Magic: 860833102,
|
||||||
|
TCPPort: 10333,
|
||||||
|
WSPort: 10334,
|
||||||
|
Nonce: 1677922561,
|
||||||
|
UserAgent: "/NEO-GO:0.98.3/",
|
||||||
|
Protocol: Protocol{
|
||||||
|
AddressVersion: 53,
|
||||||
|
Network: 860833102,
|
||||||
|
MillisecondsPerBlock: 15000,
|
||||||
|
MaxTraceableBlocks: 2102400,
|
||||||
|
MaxValidUntilBlockIncrement: 5760,
|
||||||
|
MaxTransactionsPerBlock: 512,
|
||||||
|
MemoryPoolMaxTransactions: 50000,
|
||||||
|
ValidatorsCount: 7,
|
||||||
|
// Unmarshalled InitialGasDistribution should always be a valid Fixed8 for both old and new clients.
|
||||||
|
InitialGasDistribution: fixedn.Fixed8FromInt64(52000000),
|
||||||
|
StateRootInHeader: false,
|
||||||
|
},
|
||||||
|
StateRootInHeader: false,
|
||||||
|
}
|
||||||
|
t.Run("MarshalJSON", func(t *testing.T) {
|
||||||
|
actual, err := json.Marshal(v)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.JSONEq(t, responseFromGoNew, string(actual))
|
||||||
|
})
|
||||||
|
t.Run("UnmarshalJSON", func(t *testing.T) {
|
||||||
|
t.Run("Go node response", func(t *testing.T) {
|
||||||
|
t.Run("old RPC server", func(t *testing.T) {
|
||||||
|
actual := &Version{}
|
||||||
|
require.NoError(t, json.Unmarshal([]byte(responseFromGoOld), actual))
|
||||||
|
expected := new(Version)
|
||||||
|
*expected = *v
|
||||||
|
expected.UserAgent = "/NEO-GO:0.98.2/"
|
||||||
|
require.Equal(t, expected, actual)
|
||||||
|
})
|
||||||
|
t.Run("new RPC server", func(t *testing.T) {
|
||||||
|
actual := &Version{}
|
||||||
|
require.NoError(t, json.Unmarshal([]byte(responseFromGoNew), actual))
|
||||||
|
require.Equal(t, v, actual)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
t.Run("Sharp node response", func(t *testing.T) {
|
||||||
|
actual := &Version{}
|
||||||
|
require.NoError(t, json.Unmarshal([]byte(responseFromSharp), actual))
|
||||||
|
expected := new(Version)
|
||||||
|
*expected = *v
|
||||||
|
expected.UserAgent = "/Neo:3.1.0/"
|
||||||
|
expected.Magic = 0 // No magic in C#.
|
||||||
|
require.Equal(t, expected, actual)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersionFromUserAgent(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
success bool
|
||||||
|
cmpWithBreaking int
|
||||||
|
}
|
||||||
|
var testcases = map[string]testCase{
|
||||||
|
"/Neo:3.1.0/": {success: false},
|
||||||
|
"/NEO-GO:0.98.4": {success: true, cmpWithBreaking: 1},
|
||||||
|
"/NEO-GO:0.98.4-pre-12344/": {success: true, cmpWithBreaking: 1},
|
||||||
|
"/NEO-GO:0.98.3/": {success: true, cmpWithBreaking: 1},
|
||||||
|
"/NEO-GO:0.98.3-pre-123/": {success: true, cmpWithBreaking: 1},
|
||||||
|
"/NEO-GO:0.98.2/": {success: true, cmpWithBreaking: 0},
|
||||||
|
"/NEO-GO:0.98.2-pre-12345/": {success: true, cmpWithBreaking: -1},
|
||||||
|
"/NEO-GO:123456": {success: false},
|
||||||
|
}
|
||||||
|
for str, tc := range testcases {
|
||||||
|
ver, err := userAgentToVersion(str)
|
||||||
|
if tc.success {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ver.Compare(latestNonBreakingVersion), tc.cmpWithBreaking)
|
||||||
|
} else {
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -536,7 +536,7 @@ func (s *Server) getVersion(_ request.Params) (interface{}, *response.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := s.chain.GetConfig()
|
cfg := s.chain.GetConfig()
|
||||||
return result.Version{
|
return &result.Version{
|
||||||
Magic: s.network,
|
Magic: s.network,
|
||||||
TCPPort: port,
|
TCPPort: port,
|
||||||
Nonce: s.coreServer.ID(),
|
Nonce: s.coreServer.ID(),
|
||||||
|
@ -551,7 +551,7 @@ func (s *Server) getVersion(_ request.Params) (interface{}, *response.Error) {
|
||||||
MaxTransactionsPerBlock: cfg.MaxTransactionsPerBlock,
|
MaxTransactionsPerBlock: cfg.MaxTransactionsPerBlock,
|
||||||
MemoryPoolMaxTransactions: cfg.MemPoolSize,
|
MemoryPoolMaxTransactions: cfg.MemPoolSize,
|
||||||
ValidatorsCount: byte(cfg.GetNumOfCNs(s.chain.BlockHeight())),
|
ValidatorsCount: byte(cfg.GetNumOfCNs(s.chain.BlockHeight())),
|
||||||
InitialGasDistribution: int64(cfg.InitialGASSupply),
|
InitialGasDistribution: cfg.InitialGASSupply,
|
||||||
StateRootInHeader: cfg.StateRootInHeader,
|
StateRootInHeader: cfg.StateRootInHeader,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -101,6 +102,7 @@ func initClearServerWithServices(t testing.TB, needOracle bool, needNotary bool)
|
||||||
chain, orc, cfg, logger := getUnitTestChain(t, needOracle, needNotary)
|
chain, orc, cfg, logger := getUnitTestChain(t, needOracle, needNotary)
|
||||||
|
|
||||||
serverConfig := network.NewServerConfig(cfg)
|
serverConfig := network.NewServerConfig(cfg)
|
||||||
|
serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.3-test")
|
||||||
serverConfig.Port = 0
|
serverConfig.Port = 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)
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/nspcc-dev/neo-go/internal/testchain"
|
"github.com/nspcc-dev/neo-go/internal/testchain"
|
||||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
"github.com/nspcc-dev/neo-go/pkg/core"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
||||||
|
@ -849,7 +850,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
check: func(t *testing.T, e *executor, ver interface{}) {
|
check: func(t *testing.T, e *executor, ver interface{}) {
|
||||||
resp, ok := ver.(*result.Version)
|
resp, ok := ver.(*result.Version)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, "/NEO-GO:/", resp.UserAgent)
|
require.Equal(t, "/NEO-GO:0.98.3-test/", resp.UserAgent)
|
||||||
|
|
||||||
cfg := e.chain.GetConfig()
|
cfg := e.chain.GetConfig()
|
||||||
require.EqualValues(t, address.NEO3Prefix, resp.Protocol.AddressVersion)
|
require.EqualValues(t, address.NEO3Prefix, resp.Protocol.AddressVersion)
|
||||||
|
@ -2605,6 +2606,7 @@ func BenchmarkHandleIn(b *testing.B) {
|
||||||
chain, orc, cfg, logger := getUnitTestChain(b, false, false)
|
chain, orc, cfg, logger := getUnitTestChain(b, false, false)
|
||||||
|
|
||||||
serverConfig := network.NewServerConfig(cfg)
|
serverConfig := network.NewServerConfig(cfg)
|
||||||
|
serverConfig.UserAgent = fmt.Sprintf(config.UserAgentFormat, "0.98.3-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)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
Loading…
Reference in a new issue