github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/neorpc/result/version.go (about)

     1  package result
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/nspcc-dev/neo-go/pkg/config"
     9  	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
    10  	"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
    11  )
    12  
    13  type (
    14  	// Version model used for reporting server version
    15  	// info.
    16  	Version struct {
    17  		TCPPort   uint16   `json:"tcpport"`
    18  		WSPort    uint16   `json:"wsport,omitempty"`
    19  		Nonce     uint32   `json:"nonce"`
    20  		UserAgent string   `json:"useragent"`
    21  		Protocol  Protocol `json:"protocol"`
    22  		RPC       RPC      `json:"rpc"`
    23  	}
    24  
    25  	// RPC represents the RPC server configuration.
    26  	RPC struct {
    27  		MaxIteratorResultItems int  `json:"maxiteratorresultitems"`
    28  		SessionEnabled         bool `json:"sessionenabled"`
    29  	}
    30  
    31  	// Protocol represents network-dependent parameters.
    32  	Protocol struct {
    33  		AddressVersion              byte
    34  		Network                     netmode.Magic
    35  		MillisecondsPerBlock        int
    36  		MaxTraceableBlocks          uint32
    37  		MaxValidUntilBlockIncrement uint32
    38  		MaxTransactionsPerBlock     uint16
    39  		MemoryPoolMaxTransactions   int
    40  		ValidatorsCount             byte
    41  		InitialGasDistribution      fixedn.Fixed8
    42  		// Hardforks is the map of network hardforks with the enabling height.
    43  		Hardforks map[config.Hardfork]uint32
    44  
    45  		// Below are NeoGo-specific extensions to the protocol that are
    46  		// returned by the server in case they're enabled.
    47  
    48  		// CommitteeHistory stores height:size map of the committee size.
    49  		CommitteeHistory map[uint32]uint32
    50  		// P2PSigExtensions is true when Notary subsystem is enabled on the network.
    51  		P2PSigExtensions bool
    52  		// StateRootInHeader is true if state root is contained in block header.
    53  		StateRootInHeader bool
    54  		// ValidatorsHistory stores height:size map of the validators count.
    55  		ValidatorsHistory map[uint32]uint32
    56  	}
    57  
    58  	// protocolMarshallerAux is an auxiliary struct used for Protocol JSON marshalling.
    59  	protocolMarshallerAux struct {
    60  		AddressVersion              byte          `json:"addressversion"`
    61  		Network                     netmode.Magic `json:"network"`
    62  		MillisecondsPerBlock        int           `json:"msperblock"`
    63  		MaxTraceableBlocks          uint32        `json:"maxtraceableblocks"`
    64  		MaxValidUntilBlockIncrement uint32        `json:"maxvaliduntilblockincrement"`
    65  		MaxTransactionsPerBlock     uint16        `json:"maxtransactionsperblock"`
    66  		MemoryPoolMaxTransactions   int           `json:"memorypoolmaxtransactions"`
    67  		ValidatorsCount             byte          `json:"validatorscount"`
    68  		InitialGasDistribution      int64         `json:"initialgasdistribution"`
    69  		Hardforks                   []hardforkAux `json:"hardforks"`
    70  
    71  		CommitteeHistory  map[uint32]uint32 `json:"committeehistory,omitempty"`
    72  		P2PSigExtensions  bool              `json:"p2psigextensions,omitempty"`
    73  		StateRootInHeader bool              `json:"staterootinheader,omitempty"`
    74  		ValidatorsHistory map[uint32]uint32 `json:"validatorshistory,omitempty"`
    75  	}
    76  
    77  	// hardforkAux is an auxiliary struct used for Hardfork JSON marshalling.
    78  	hardforkAux struct {
    79  		Name   string `json:"name"`
    80  		Height uint32 `json:"blockheight"`
    81  	}
    82  )
    83  
    84  // prefixHardfork is a prefix used for hardfork names in C# node.
    85  const prefixHardfork = "HF_"
    86  
    87  // MarshalJSON implements the JSON marshaler interface.
    88  func (p Protocol) MarshalJSON() ([]byte, error) {
    89  	// Keep hardforks sorted by name in the result.
    90  	hfs := make([]hardforkAux, 0, len(p.Hardforks))
    91  	for _, hf := range config.Hardforks {
    92  		if h, ok := p.Hardforks[hf]; ok {
    93  			hfs = append(hfs, hardforkAux{
    94  				Name:   hf.String(),
    95  				Height: h,
    96  			})
    97  		}
    98  	}
    99  	aux := protocolMarshallerAux{
   100  		AddressVersion:              p.AddressVersion,
   101  		Network:                     p.Network,
   102  		MillisecondsPerBlock:        p.MillisecondsPerBlock,
   103  		MaxTraceableBlocks:          p.MaxTraceableBlocks,
   104  		MaxValidUntilBlockIncrement: p.MaxValidUntilBlockIncrement,
   105  		MaxTransactionsPerBlock:     p.MaxTransactionsPerBlock,
   106  		MemoryPoolMaxTransactions:   p.MemoryPoolMaxTransactions,
   107  		ValidatorsCount:             p.ValidatorsCount,
   108  		InitialGasDistribution:      int64(p.InitialGasDistribution),
   109  		Hardforks:                   hfs,
   110  
   111  		CommitteeHistory:  p.CommitteeHistory,
   112  		P2PSigExtensions:  p.P2PSigExtensions,
   113  		StateRootInHeader: p.StateRootInHeader,
   114  		ValidatorsHistory: p.ValidatorsHistory,
   115  	}
   116  	return json.Marshal(aux)
   117  }
   118  
   119  // UnmarshalJSON implements the JSON unmarshaler interface.
   120  func (p *Protocol) UnmarshalJSON(data []byte) error {
   121  	var aux protocolMarshallerAux
   122  	err := json.Unmarshal(data, &aux)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	p.AddressVersion = aux.AddressVersion
   127  	p.Network = aux.Network
   128  	p.MillisecondsPerBlock = aux.MillisecondsPerBlock
   129  	p.MaxTraceableBlocks = aux.MaxTraceableBlocks
   130  	p.MaxValidUntilBlockIncrement = aux.MaxValidUntilBlockIncrement
   131  	p.MaxTransactionsPerBlock = aux.MaxTransactionsPerBlock
   132  	p.MemoryPoolMaxTransactions = aux.MemoryPoolMaxTransactions
   133  	p.ValidatorsCount = aux.ValidatorsCount
   134  	p.CommitteeHistory = aux.CommitteeHistory
   135  	p.P2PSigExtensions = aux.P2PSigExtensions
   136  	p.StateRootInHeader = aux.StateRootInHeader
   137  	p.ValidatorsHistory = aux.ValidatorsHistory
   138  	p.InitialGasDistribution = fixedn.Fixed8(aux.InitialGasDistribution)
   139  
   140  	// Filter out unknown hardforks.
   141  	for i := range aux.Hardforks {
   142  		aux.Hardforks[i].Name = strings.TrimPrefix(aux.Hardforks[i].Name, prefixHardfork)
   143  		if !config.IsHardforkValid(aux.Hardforks[i].Name) {
   144  			return fmt.Errorf("unexpected hardfork: %s", aux.Hardforks[i].Name)
   145  		}
   146  	}
   147  	p.Hardforks = make(map[config.Hardfork]uint32, len(aux.Hardforks))
   148  	for _, cfgHf := range config.Hardforks {
   149  		for _, auxHf := range aux.Hardforks {
   150  			if auxHf.Name == cfgHf.String() {
   151  				p.Hardforks[cfgHf] = auxHf.Height
   152  			}
   153  		}
   154  	}
   155  
   156  	return nil
   157  }