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 }