Merge pull request #3160 from nspcc-dev/add-version-hf
rpcsrv: add hardforks to `getversion` response
This commit is contained in:
commit
a9a848a306
5 changed files with 77 additions and 3 deletions
|
@ -2,7 +2,10 @@ package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
)
|
)
|
||||||
|
@ -29,6 +32,8 @@ type (
|
||||||
MemoryPoolMaxTransactions int
|
MemoryPoolMaxTransactions int
|
||||||
ValidatorsCount byte
|
ValidatorsCount byte
|
||||||
InitialGasDistribution fixedn.Fixed8
|
InitialGasDistribution fixedn.Fixed8
|
||||||
|
// Hardforks is the map of network hardforks with the enabling height.
|
||||||
|
Hardforks map[config.Hardfork]uint32
|
||||||
|
|
||||||
// Below are NeoGo-specific extensions to the protocol that are
|
// Below are NeoGo-specific extensions to the protocol that are
|
||||||
// returned by the server in case they're enabled.
|
// returned by the server in case they're enabled.
|
||||||
|
@ -54,16 +59,36 @@ 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"`
|
||||||
|
Hardforks []hardforkAux `json:"hardforks"`
|
||||||
|
|
||||||
CommitteeHistory map[uint32]uint32 `json:"committeehistory,omitempty"`
|
CommitteeHistory map[uint32]uint32 `json:"committeehistory,omitempty"`
|
||||||
P2PSigExtensions bool `json:"p2psigextensions,omitempty"`
|
P2PSigExtensions bool `json:"p2psigextensions,omitempty"`
|
||||||
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
StateRootInHeader bool `json:"staterootinheader,omitempty"`
|
||||||
ValidatorsHistory map[uint32]uint32 `json:"validatorshistory,omitempty"`
|
ValidatorsHistory map[uint32]uint32 `json:"validatorshistory,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hardforkAux is an auxiliary struct used for Hardfork JSON marshalling.
|
||||||
|
hardforkAux struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Height uint32 `json:"blockheight"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// prefixHardfork is a prefix used for hardfork names in C# node.
|
||||||
|
const prefixHardfork = "HF_"
|
||||||
|
|
||||||
// MarshalJSON implements the JSON marshaler interface.
|
// MarshalJSON implements the JSON marshaler interface.
|
||||||
func (p Protocol) MarshalJSON() ([]byte, error) {
|
func (p Protocol) MarshalJSON() ([]byte, error) {
|
||||||
|
// Keep hardforks sorted by name in the result.
|
||||||
|
hfs := make([]hardforkAux, 0, len(p.Hardforks))
|
||||||
|
for _, hf := range config.Hardforks {
|
||||||
|
if h, ok := p.Hardforks[hf]; ok {
|
||||||
|
hfs = append(hfs, hardforkAux{
|
||||||
|
Name: hf.String(),
|
||||||
|
Height: h,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
aux := protocolMarshallerAux{
|
aux := protocolMarshallerAux{
|
||||||
AddressVersion: p.AddressVersion,
|
AddressVersion: p.AddressVersion,
|
||||||
Network: p.Network,
|
Network: p.Network,
|
||||||
|
@ -74,6 +99,7 @@ func (p Protocol) MarshalJSON() ([]byte, error) {
|
||||||
MemoryPoolMaxTransactions: p.MemoryPoolMaxTransactions,
|
MemoryPoolMaxTransactions: p.MemoryPoolMaxTransactions,
|
||||||
ValidatorsCount: p.ValidatorsCount,
|
ValidatorsCount: p.ValidatorsCount,
|
||||||
InitialGasDistribution: int64(p.InitialGasDistribution),
|
InitialGasDistribution: int64(p.InitialGasDistribution),
|
||||||
|
Hardforks: hfs,
|
||||||
|
|
||||||
CommitteeHistory: p.CommitteeHistory,
|
CommitteeHistory: p.CommitteeHistory,
|
||||||
P2PSigExtensions: p.P2PSigExtensions,
|
P2PSigExtensions: p.P2PSigExtensions,
|
||||||
|
@ -104,5 +130,21 @@ func (p *Protocol) UnmarshalJSON(data []byte) error {
|
||||||
p.ValidatorsHistory = aux.ValidatorsHistory
|
p.ValidatorsHistory = aux.ValidatorsHistory
|
||||||
p.InitialGasDistribution = fixedn.Fixed8(aux.InitialGasDistribution)
|
p.InitialGasDistribution = fixedn.Fixed8(aux.InitialGasDistribution)
|
||||||
|
|
||||||
|
// Filter out unknown hardforks.
|
||||||
|
for i := range aux.Hardforks {
|
||||||
|
aux.Hardforks[i].Name = strings.TrimPrefix(aux.Hardforks[i].Name, prefixHardfork)
|
||||||
|
if !config.IsHardforkValid(aux.Hardforks[i].Name) {
|
||||||
|
return fmt.Errorf("unexpected hardfork: %s", aux.Hardforks[i].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Hardforks = make(map[config.Hardfork]uint32, len(aux.Hardforks))
|
||||||
|
for _, cfgHf := range config.Hardforks {
|
||||||
|
for _, auxHf := range aux.Hardforks {
|
||||||
|
if auxHf.Name == cfgHf.String() {
|
||||||
|
p.Hardforks[cfgHf] = auxHf.Height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -38,7 +39,8 @@ func TestVersion_MarshalUnmarshalJSON(t *testing.T) {
|
||||||
"memorypoolmaxtransactions": 50000,
|
"memorypoolmaxtransactions": 50000,
|
||||||
"msperblock": 15000,
|
"msperblock": 15000,
|
||||||
"network": 860833102,
|
"network": 860833102,
|
||||||
"validatorscount": 7
|
"validatorscount": 7,
|
||||||
|
"hardforks": [{"name": "Aspidochelone", "blockheight": 123}, {"name": "Basilisk", "blockheight": 1234}]
|
||||||
},
|
},
|
||||||
"tcpport": 10333,
|
"tcpport": 10333,
|
||||||
"useragent": "/NEO-GO:0.98.6/",
|
"useragent": "/NEO-GO:0.98.6/",
|
||||||
|
@ -55,7 +57,8 @@ func TestVersion_MarshalUnmarshalJSON(t *testing.T) {
|
||||||
"memorypoolmaxtransactions": 50000,
|
"memorypoolmaxtransactions": 50000,
|
||||||
"msperblock": 15000,
|
"msperblock": 15000,
|
||||||
"network": 860833102,
|
"network": 860833102,
|
||||||
"validatorscount": 7
|
"validatorscount": 7,
|
||||||
|
"hardforks": [{"name": "HF_Aspidochelone", "blockheight": 123}, {"name": "HF_Basilisk", "blockheight": 1234}]
|
||||||
},
|
},
|
||||||
"tcpport": 10333,
|
"tcpport": 10333,
|
||||||
"useragent": "/Neo:3.1.0/",
|
"useragent": "/Neo:3.1.0/",
|
||||||
|
@ -78,6 +81,7 @@ func TestVersion_MarshalUnmarshalJSON(t *testing.T) {
|
||||||
// Unmarshalled InitialGasDistribution should always be a valid Fixed8 for both old and new clients.
|
// Unmarshalled InitialGasDistribution should always be a valid Fixed8 for both old and new clients.
|
||||||
InitialGasDistribution: fixedn.Fixed8FromInt64(52000000),
|
InitialGasDistribution: fixedn.Fixed8FromInt64(52000000),
|
||||||
StateRootInHeader: false,
|
StateRootInHeader: false,
|
||||||
|
Hardforks: map[config.Hardfork]uint32{config.HFAspidochelone: 123, config.HFBasilisk: 1234},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
t.Run("MarshalJSON", func(t *testing.T) {
|
t.Run("MarshalJSON", func(t *testing.T) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"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/config/netmode"
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||||
"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/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
@ -1032,6 +1033,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
UserAgent: "/NEO-GO:0.73.1-pre-273-ge381358/",
|
UserAgent: "/NEO-GO:0.73.1-pre-273-ge381358/",
|
||||||
Protocol: result.Protocol{
|
Protocol: result.Protocol{
|
||||||
Network: netmode.UnitTestNet,
|
Network: netmode.UnitTestNet,
|
||||||
|
Hardforks: map[config.Hardfork]uint32{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -2356,3 +2356,20 @@ func TestClient_GetStorageHistoric(t *testing.T) {
|
||||||
_, err = c.GetStorageByHashHistoric(earlyRoot.Root, h, key)
|
_, err = c.GetStorageByHashHistoric(earlyRoot.Root, h, key)
|
||||||
require.ErrorIs(t, neorpc.ErrUnknownStorageItem, err)
|
require.ErrorIs(t, neorpc.ErrUnknownStorageItem, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClient_GetVersion_Hardforks(t *testing.T) {
|
||||||
|
chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t)
|
||||||
|
defer chain.Close()
|
||||||
|
defer rpcSrv.Shutdown()
|
||||||
|
|
||||||
|
c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, c.Init())
|
||||||
|
|
||||||
|
v, err := c.GetVersion()
|
||||||
|
require.NoError(t, err)
|
||||||
|
expected := map[config.Hardfork]uint32{
|
||||||
|
config.HFAspidochelone: 25,
|
||||||
|
}
|
||||||
|
require.InDeltaMapValues(t, expected, v.Protocol.Hardforks, 0)
|
||||||
|
}
|
||||||
|
|
|
@ -838,6 +838,14 @@ func (s *Server) getVersion(_ params.Params) (any, *neorpc.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := s.chain.GetConfig()
|
cfg := s.chain.GetConfig()
|
||||||
|
hfs := make(map[config.Hardfork]uint32, len(cfg.Hardforks))
|
||||||
|
for _, cfgHf := range config.Hardforks {
|
||||||
|
height, ok := cfg.Hardforks[cfgHf.String()]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hfs[cfgHf] = height
|
||||||
|
}
|
||||||
return &result.Version{
|
return &result.Version{
|
||||||
TCPPort: port,
|
TCPPort: port,
|
||||||
Nonce: s.coreServer.ID(),
|
Nonce: s.coreServer.ID(),
|
||||||
|
@ -852,6 +860,7 @@ func (s *Server) getVersion(_ params.Params) (any, *neorpc.Error) {
|
||||||
MemoryPoolMaxTransactions: cfg.MemPoolSize,
|
MemoryPoolMaxTransactions: cfg.MemPoolSize,
|
||||||
ValidatorsCount: byte(cfg.GetNumOfCNs(s.chain.BlockHeight())),
|
ValidatorsCount: byte(cfg.GetNumOfCNs(s.chain.BlockHeight())),
|
||||||
InitialGasDistribution: cfg.InitialGASSupply,
|
InitialGasDistribution: cfg.InitialGASSupply,
|
||||||
|
Hardforks: hfs,
|
||||||
|
|
||||||
CommitteeHistory: cfg.CommitteeHistory,
|
CommitteeHistory: cfg.CommitteeHistory,
|
||||||
P2PSigExtensions: cfg.P2PSigExtensions,
|
P2PSigExtensions: cfg.P2PSigExtensions,
|
||||||
|
|
Loading…
Reference in a new issue