Skip to content

Commit

Permalink
rpcsrv: add hardforks to getversion response
Browse files Browse the repository at this point in the history
Port neo-project/neo-modules#823.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
  • Loading branch information
AnnaShaleva committed Oct 12, 2023
1 parent b284b90 commit 556a1d4
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
44 changes: 44 additions & 0 deletions pkg/neorpc/result/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package result

import (
"encoding/json"
"fmt"

"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
)
Expand All @@ -18,6 +20,12 @@ type (
Protocol Protocol `json:"protocol"`
}

// Hardfork represents network hardfork.
Hardfork struct {
Name config.Hardfork
Height uint32
}

// Protocol represents network-dependent parameters.
Protocol struct {
AddressVersion byte
Expand All @@ -29,6 +37,8 @@ type (
MemoryPoolMaxTransactions int
ValidatorsCount byte
InitialGasDistribution fixedn.Fixed8
// Hardforks is the list of network hardforks sorted by name.
Hardforks []Hardfork

// Below are NeoGo-specific extensions to the protocol that are
// returned by the server in case they're enabled.
Expand All @@ -54,16 +64,30 @@ type (
MemoryPoolMaxTransactions int `json:"memorypoolmaxtransactions"`
ValidatorsCount byte `json:"validatorscount"`
InitialGasDistribution int64 `json:"initialgasdistribution"`
Hardforks []hardforkAux `json:"hardforks"`

CommitteeHistory map[uint32]uint32 `json:"committeehistory,omitempty"`
P2PSigExtensions bool `json:"p2psigextensions,omitempty"`
StateRootInHeader bool `json:"staterootinheader,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"`
}
)

// MarshalJSON implements the JSON marshaler interface.
func (p Protocol) MarshalJSON() ([]byte, error) {
hf := make([]hardforkAux, len(p.Hardforks))
for i := range hf {
hf[i] = hardforkAux{
Name: p.Hardforks[i].Name.String(),
Height: p.Hardforks[i].Height,
}
}
aux := protocolMarshallerAux{
AddressVersion: p.AddressVersion,
Network: p.Network,
Expand All @@ -74,6 +98,7 @@ func (p Protocol) MarshalJSON() ([]byte, error) {
MemoryPoolMaxTransactions: p.MemoryPoolMaxTransactions,
ValidatorsCount: p.ValidatorsCount,
InitialGasDistribution: int64(p.InitialGasDistribution),
Hardforks: hf,

CommitteeHistory: p.CommitteeHistory,
P2PSigExtensions: p.P2PSigExtensions,
Expand Down Expand Up @@ -104,5 +129,24 @@ func (p *Protocol) UnmarshalJSON(data []byte) error {
p.ValidatorsHistory = aux.ValidatorsHistory
p.InitialGasDistribution = fixedn.Fixed8(aux.InitialGasDistribution)

// Filter out unknown hardforks.
for _, hf := range aux.Hardforks {
if !config.IsHardforkValid(hf.Name) {
return fmt.Errorf("unexpected hardfork: %s", hf.Name)
}
}
// Keep them sorted.
p.Hardforks = make([]Hardfork, 0, len(aux.Hardforks))
for _, cfgHf := range config.Hardforks {
for _, auxHf := range aux.Hardforks {
if auxHf.Name == cfgHf.String() {
p.Hardforks = append(p.Hardforks, Hardfork{
Name: cfgHf,
Height: auxHf.Height,
})
}
}
}

return nil
}
8 changes: 6 additions & 2 deletions pkg/neorpc/result/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"testing"

"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -38,7 +39,8 @@ func TestVersion_MarshalUnmarshalJSON(t *testing.T) {
"memorypoolmaxtransactions": 50000,
"msperblock": 15000,
"network": 860833102,
"validatorscount": 7
"validatorscount": 7,
"hardforks": [{"name": "Aspidochelone", "blockheight": 123}, {"name": "Basilisk", "blockheight": 1234}]
},
"tcpport": 10333,
"useragent": "/NEO-GO:0.98.6/",
Expand All @@ -55,7 +57,8 @@ func TestVersion_MarshalUnmarshalJSON(t *testing.T) {
"memorypoolmaxtransactions": 50000,
"msperblock": 15000,
"network": 860833102,
"validatorscount": 7
"validatorscount": 7,
"hardforks": [{"name": "Aspidochelone", "blockheight": 123}, {"name": "Basilisk", "blockheight": 1234}]
},
"tcpport": 10333,
"useragent": "/Neo:3.1.0/",
Expand All @@ -78,6 +81,7 @@ func TestVersion_MarshalUnmarshalJSON(t *testing.T) {
// Unmarshalled InitialGasDistribution should always be a valid Fixed8 for both old and new clients.
InitialGasDistribution: fixedn.Fixed8FromInt64(52000000),
StateRootInHeader: false,
Hardforks: []Hardfork{{Name: config.HFAspidochelone, Height: 123}, {Name: config.HFBasilisk, Height: 1234}},
},
}
t.Run("MarshalJSON", func(t *testing.T) {
Expand Down
20 changes: 20 additions & 0 deletions pkg/services/rpcsrv/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2356,3 +2356,23 @@ func TestClient_GetStorageHistoric(t *testing.T) {
_, err = c.GetStorageByHashHistoric(earlyRoot.Root, h, key)
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 := []result.Hardfork{
{
Name: config.HFAspidochelone,
Height: 25,
},
}
require.Equal(t, expected, v.Protocol.Hardforks)
}
12 changes: 12 additions & 0 deletions pkg/services/rpcsrv/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,17 @@ func (s *Server) getVersion(_ params.Params) (any, *neorpc.Error) {
}

cfg := s.chain.GetConfig()
hfs := make([]result.Hardfork, 0, len(cfg.Hardforks))
for _, cfgHf := range config.Hardforks {
height, ok := cfg.Hardforks[cfgHf.String()]
if !ok {
continue
}
hfs = append(hfs, result.Hardfork{
Name: cfgHf,
Height: height,
})
}
return &result.Version{
TCPPort: port,
Nonce: s.coreServer.ID(),
Expand All @@ -853,6 +864,7 @@ func (s *Server) getVersion(_ params.Params) (any, *neorpc.Error) {
MemoryPoolMaxTransactions: cfg.MemPoolSize,
ValidatorsCount: byte(cfg.GetNumOfCNs(s.chain.BlockHeight())),
InitialGasDistribution: cfg.InitialGASSupply,
Hardforks: hfs,

CommitteeHistory: cfg.CommitteeHistory,
P2PSigExtensions: cfg.P2PSigExtensions,
Expand Down

0 comments on commit 556a1d4

Please sign in to comment.