mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-16 18:37:51 +01:00
added new REST API for config file
This commit is contained in:
@@ -7,151 +7,136 @@ Author: Peter Kleissner
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/PeernetOfficial/core/blockchain"
|
"github.com/PeernetOfficial/core/blockchain"
|
||||||
"github.com/PeernetOfficial/core/protocol"
|
"github.com/PeernetOfficial/core/protocol"
|
||||||
"github.com/enfipy/locker"
|
"github.com/enfipy/locker"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The blockchain cache stores blockchains.
|
// The blockchain cache stores blockchains.
|
||||||
type BlockchainCache struct {
|
type BlockchainCache struct {
|
||||||
BlockchainDirectory string // The directory for storing blockchains in a key-value store.
|
BlockchainDirectory string // The directory for storing blockchains in a key-value store.
|
||||||
MaxBlockSize uint64 // Max block size to accept.
|
MaxBlockSize uint64 // Max block size to accept.
|
||||||
MaxBlockCount uint64 // Max block count to cache per peer.
|
MaxBlockCount uint64 // Max block count to cache per peer.
|
||||||
LimitTotalRecords uint64 // Max count of blocks and header in total to keep across all blockchains. 0 = unlimited. Max Records * Max Block Size = Size Limit.
|
LimitTotalRecords uint64 // Max count of blocks and header in total to keep across all blockchains. 0 = unlimited. Max Records * Max Block Size = Size Limit.
|
||||||
ReadOnly bool // Whether the cache is read only.
|
ReadOnly bool // Whether the cache is read only.
|
||||||
|
|
||||||
Store *blockchain.MultiStore
|
Store *blockchain.MultiStore
|
||||||
peerLock *locker.Locker
|
peerLock *locker.Locker
|
||||||
|
|
||||||
backend *Backend
|
backend *Backend
|
||||||
}
|
}
|
||||||
|
|
||||||
func (backend *Backend) initBlockchainCache() {
|
func (backend *Backend) initBlockchainCache() {
|
||||||
if backend.Config.BlockchainGlobal == "" {
|
if backend.Config.BlockchainGlobal == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
backend.GlobalBlockchainCache = &BlockchainCache{
|
backend.GlobalBlockchainCache = &BlockchainCache{
|
||||||
backend: backend,
|
backend: backend,
|
||||||
BlockchainDirectory: backend.Config.BlockchainGlobal,
|
BlockchainDirectory: backend.Config.BlockchainGlobal,
|
||||||
MaxBlockSize: backend.Config.CacheMaxBlockSize,
|
MaxBlockSize: backend.Config.CacheMaxBlockSize,
|
||||||
MaxBlockCount: backend.Config.CacheMaxBlockCount,
|
MaxBlockCount: backend.Config.CacheMaxBlockCount,
|
||||||
LimitTotalRecords: backend.Config.LimitTotalRecords,
|
LimitTotalRecords: backend.Config.LimitTotalRecords,
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
backend.GlobalBlockchainCache.Store, err = blockchain.InitMultiStore(backend.Config.BlockchainGlobal)
|
backend.GlobalBlockchainCache.Store, err = blockchain.InitMultiStore(backend.Config.BlockchainGlobal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
backend.LogError("initBlockchainCache", "initializing database '%s': %s", backend.Config.BlockchainGlobal, err.Error())
|
backend.LogError("initBlockchainCache", "initializing database '%s': %s", backend.Config.BlockchainGlobal, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
backend.GlobalBlockchainCache.peerLock = locker.Initialize()
|
backend.GlobalBlockchainCache.peerLock = locker.Initialize()
|
||||||
|
|
||||||
// Set the blockchain cache to read-only if the record limit is reached.
|
// Set the blockchain cache to read-only if the record limit is reached.
|
||||||
if backend.Config.LimitTotalRecords > 0 && backend.GlobalBlockchainCache.Store.Database.Count() >= backend.Config.LimitTotalRecords {
|
if backend.Config.LimitTotalRecords > 0 && backend.GlobalBlockchainCache.Store.Database.Count() >= backend.Config.LimitTotalRecords {
|
||||||
backend.GlobalBlockchainCache.ReadOnly = true
|
backend.GlobalBlockchainCache.ReadOnly = true
|
||||||
}
|
}
|
||||||
|
|
||||||
backend.GlobalBlockchainCache.Store.FilterStatisticUpdate = backend.Filters.GlobalBlockchainCacheStatistic
|
backend.GlobalBlockchainCache.Store.FilterStatisticUpdate = backend.Filters.GlobalBlockchainCacheStatistic
|
||||||
backend.GlobalBlockchainCache.Store.FilterBlockchainDelete = backend.Filters.GlobalBlockchainCacheDelete
|
backend.GlobalBlockchainCache.Store.FilterBlockchainDelete = backend.Filters.GlobalBlockchainCacheDelete
|
||||||
}
|
}
|
||||||
|
|
||||||
// SeenBlockchainVersion shall be called with information about another peer's blockchain.
|
// SeenBlockchainVersion shall be called with information about another peer's blockchain.
|
||||||
// If the reported version number is newer, all existing blocks are immediately deleted.
|
// If the reported version number is newer, all existing blocks are immediately deleted.
|
||||||
func (cache *BlockchainCache) SeenBlockchainVersion(peer *PeerInfo) {
|
func (cache *BlockchainCache) SeenBlockchainVersion(peer *PeerInfo) {
|
||||||
cache.peerLock.Lock(string(peer.PublicKey.SerializeCompressed()))
|
cache.peerLock.Lock(string(peer.PublicKey.SerializeCompressed()))
|
||||||
defer cache.peerLock.Unlock(string(peer.PublicKey.SerializeCompressed()))
|
defer cache.peerLock.Unlock(string(peer.PublicKey.SerializeCompressed()))
|
||||||
|
|
||||||
// intermediate function to download and process blocks
|
// intermediate function to download and process blocks
|
||||||
downloadAndProcessBlocks := func(peer *PeerInfo, header *blockchain.MultiBlockchainHeader, offset, limit uint64) {
|
downloadAndProcessBlocks := func(peer *PeerInfo, header *blockchain.MultiBlockchainHeader, offset, limit uint64) {
|
||||||
if limit > cache.MaxBlockCount {
|
if limit > cache.MaxBlockCount {
|
||||||
limit = cache.MaxBlockCount
|
limit = cache.MaxBlockCount
|
||||||
}
|
}
|
||||||
|
|
||||||
peer.BlockDownload(peer.PublicKey, cache.MaxBlockCount, cache.MaxBlockSize, []protocol.BlockRange{{Offset: offset, Limit: limit}}, func(data []byte, targetBlock protocol.BlockRange, blockSize uint64, availability uint8) {
|
peer.BlockDownload(peer.PublicKey, cache.MaxBlockCount, cache.MaxBlockSize, []protocol.BlockRange{{Offset: offset, Limit: limit}}, func(data []byte, targetBlock protocol.BlockRange, blockSize uint64, availability uint8) {
|
||||||
if availability != protocol.GetBlockStatusAvailable {
|
if availability != protocol.GetBlockStatusAvailable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if decoded, _ := cache.Store.IngestBlock(header, targetBlock.Offset, data, true); decoded != nil {
|
if decoded, _ := cache.Store.IngestBlock(header, targetBlock.Offset, data, true); decoded != nil {
|
||||||
// index it for search
|
// index it for search
|
||||||
cache.backend.SearchIndex.IndexNewBlockDecoded(peer.PublicKey, peer.BlockchainVersion, targetBlock.Offset, decoded.RecordsDecoded)
|
cache.backend.SearchIndex.IndexNewBlockDecoded(peer.PublicKey, peer.BlockchainVersion, targetBlock.Offset, decoded.RecordsDecoded)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the old header
|
// get the old header
|
||||||
header, status, err := cache.Store.AssessBlockchainHeader(peer.PublicKey, peer.BlockchainVersion, peer.BlockchainHeight)
|
header, status, err := cache.Store.AssessBlockchainHeader(peer.PublicKey, peer.BlockchainVersion, peer.BlockchainHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch status {
|
switch status {
|
||||||
case blockchain.MultiStatusEqual:
|
case blockchain.MultiStatusEqual:
|
||||||
return
|
return
|
||||||
|
|
||||||
case blockchain.MultiStatusInvalidRemote:
|
case blockchain.MultiStatusInvalidRemote:
|
||||||
cache.Store.DeleteBlockchain(header)
|
cache.Store.DeleteBlockchain(header)
|
||||||
|
|
||||||
cache.backend.SearchIndex.UnindexBlockchain(peer.PublicKey)
|
cache.backend.SearchIndex.UnindexBlockchain(peer.PublicKey)
|
||||||
|
|
||||||
case blockchain.MultiStatusHeaderNA:
|
case blockchain.MultiStatusHeaderNA:
|
||||||
if header, err = cache.Store.NewBlockchainHeader(peer.PublicKey, peer.BlockchainVersion, peer.BlockchainHeight); err != nil {
|
if header, err = cache.Store.NewBlockchainHeader(peer.PublicKey, peer.BlockchainVersion, peer.BlockchainHeight); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadAndProcessBlocks(peer, header, 0, peer.BlockchainHeight)
|
downloadAndProcessBlocks(peer, header, 0, peer.BlockchainHeight)
|
||||||
|
|
||||||
case blockchain.MultiStatusNewVersion:
|
case blockchain.MultiStatusNewVersion:
|
||||||
// delete existing data first, then create it new
|
// delete existing data first, then create it new
|
||||||
cache.Store.DeleteBlockchain(header)
|
cache.Store.DeleteBlockchain(header)
|
||||||
|
|
||||||
cache.backend.SearchIndex.UnindexBlockchain(peer.PublicKey)
|
cache.backend.SearchIndex.UnindexBlockchain(peer.PublicKey)
|
||||||
|
|
||||||
if header, err = cache.Store.NewBlockchainHeader(peer.PublicKey, peer.BlockchainVersion, peer.BlockchainHeight); err != nil {
|
if header, err = cache.Store.NewBlockchainHeader(peer.PublicKey, peer.BlockchainVersion, peer.BlockchainHeight); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadAndProcessBlocks(peer, header, 0, peer.BlockchainHeight)
|
downloadAndProcessBlocks(peer, header, 0, peer.BlockchainHeight)
|
||||||
|
|
||||||
case blockchain.MultiStatusNewBlocks:
|
case blockchain.MultiStatusNewBlocks:
|
||||||
//offset := header.Height
|
offset := header.Height
|
||||||
//limit := peer.BlockchainHeight - header.Height
|
limit := peer.BlockchainHeight - header.Height
|
||||||
//
|
header.Height = peer.BlockchainHeight
|
||||||
//header.Height = peer.BlockchainHeight
|
downloadAndProcessBlocks(peer, header, offset, limit)
|
||||||
//
|
|
||||||
//fmt.Println("new peer height")
|
|
||||||
//
|
|
||||||
//downloadAndProcessBlocks(peer, header, offset, limit)
|
|
||||||
// delete existing data first, then create it new
|
|
||||||
// Temporary Fix to force update the public key
|
|
||||||
cache.Store.DeleteBlockchain(header)
|
|
||||||
|
|
||||||
cache.backend.SearchIndex.UnindexBlockchain(peer.PublicKey)
|
}
|
||||||
|
|
||||||
if header, err = cache.Store.NewBlockchainHeader(peer.PublicKey, peer.BlockchainVersion, peer.BlockchainHeight); err != nil {
|
if cache.LimitTotalRecords > 0 {
|
||||||
return
|
// Bug: This code is currently never reached if ReadOnly is true.
|
||||||
}
|
cache.ReadOnly = cache.Store.Database.Count() >= cache.LimitTotalRecords
|
||||||
|
}
|
||||||
downloadAndProcessBlocks(peer, header, 0, peer.BlockchainHeight)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if cache.LimitTotalRecords > 0 {
|
|
||||||
// Bug: This code is currently never reached if ReadOnly is true.
|
|
||||||
cache.ReadOnly = cache.Store.Database.Count() >= cache.LimitTotalRecords
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remoteBlockchainUpdate shall be called to indicate a potential update of the remotes blockchain.
|
// remoteBlockchainUpdate shall be called to indicate a potential update of the remotes blockchain.
|
||||||
// It will use the blockchain version and height to update the data lake as appropriate.
|
// It will use the blockchain version and height to update the data lake as appropriate.
|
||||||
// This function is called in the Go routine of the packet worker and therefore must not stall.
|
// This function is called in the Go routine of the packet worker and therefore must not stall.
|
||||||
func (peer *PeerInfo) remoteBlockchainUpdate() {
|
func (peer *PeerInfo) remoteBlockchainUpdate() {
|
||||||
if peer.Backend.GlobalBlockchainCache == nil || peer.Backend.GlobalBlockchainCache.ReadOnly || peer.BlockchainVersion == 0 && peer.BlockchainHeight == 0 {
|
if peer.Backend.GlobalBlockchainCache == nil || peer.Backend.GlobalBlockchainCache.ReadOnly || peer.BlockchainVersion == 0 && peer.BlockchainHeight == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This entire function should be instead a non-blocking message via a buffer channel.
|
// TODO: This entire function should be instead a non-blocking message via a buffer channel.
|
||||||
go peer.Backend.GlobalBlockchainCache.SeenBlockchainVersion(peer)
|
go peer.Backend.GlobalBlockchainCache.SeenBlockchainVersion(peer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,6 @@ LocalFirewall: false # Indicates that a local firewall may drop unsolicited i
|
|||||||
PortForward: 0 # Default not set.
|
PortForward: 0 # Default not set.
|
||||||
|
|
||||||
# Global blockchain cache limits
|
# Global blockchain cache limits
|
||||||
CacheMaxBlockSize: 4096 # Max block size to accept in bytes.
|
CacheMaxBlockSize: 50096 # Max block size to accept in bytes.
|
||||||
CacheMaxBlockCount: 256 # Max block count to cache per peer.
|
CacheMaxBlockCount: 256 # Max block count to cache per peer.
|
||||||
LimitTotalRecords: 0 # Record count limit. 0 = unlimited. Max Records * Max Block Size = Size Limit.
|
LimitTotalRecords: 0 # Record count limit. 0 = unlimited. Max Records * Max Block Size = Size Limit.
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ func Start(Backend *core.Backend, ListenAddresses []string, UseSSL bool, Certifi
|
|||||||
api.Router.HandleFunc("/test", apiTest).Methods("GET")
|
api.Router.HandleFunc("/test", apiTest).Methods("GET")
|
||||||
api.Router.HandleFunc("/status", api.apiStatus).Methods("GET")
|
api.Router.HandleFunc("/status", api.apiStatus).Methods("GET")
|
||||||
api.Router.HandleFunc("/status/peers", api.apiStatusPeers).Methods("GET")
|
api.Router.HandleFunc("/status/peers", api.apiStatusPeers).Methods("GET")
|
||||||
|
api.Router.HandleFunc("/status/config", api.apiStatusConfig).Methods("GET")
|
||||||
api.Router.HandleFunc("/account/info", api.apiAccountInfo).Methods("GET")
|
api.Router.HandleFunc("/account/info", api.apiAccountInfo).Methods("GET")
|
||||||
api.Router.HandleFunc("/account/delete", api.apiAccountDelete).Methods("GET")
|
api.Router.HandleFunc("/account/delete", api.apiAccountDelete).Methods("GET")
|
||||||
api.Router.HandleFunc("/blockchain/header", api.apiBlockchainHeaderFunc).Methods("GET")
|
api.Router.HandleFunc("/blockchain/header", api.apiBlockchainHeaderFunc).Methods("GET")
|
||||||
|
|||||||
132
webapi/Status.go
132
webapi/Status.go
@@ -7,24 +7,24 @@ Author: Peter Kleissner
|
|||||||
package webapi
|
package webapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func apiTest(w http.ResponseWriter, r *http.Request) {
|
func apiTest(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte("ok"))
|
w.Write([]byte("ok"))
|
||||||
}
|
}
|
||||||
|
|
||||||
type apiResponseStatus struct {
|
type apiResponseStatus struct {
|
||||||
Status int `json:"status"` // Status code: 0 = Ok.
|
Status int `json:"status"` // Status code: 0 = Ok.
|
||||||
IsConnected bool `json:"isconnected"` // Whether connected to Peernet.
|
IsConnected bool `json:"isconnected"` // Whether connected to Peernet.
|
||||||
CountPeerList int `json:"countpeerlist"` // Count of peers in the peer list. Note that this contains peers that are considered inactive, but have not yet been removed from the list.
|
CountPeerList int `json:"countpeerlist"` // Count of peers in the peer list. Note that this contains peers that are considered inactive, but have not yet been removed from the list.
|
||||||
CountNetwork int `json:"countnetwork"` // Count of total peers in the network.
|
CountNetwork int `json:"countnetwork"` // Count of total peers in the network.
|
||||||
// This is usually a higher number than CountPeerList, which just represents the current number of connected peers.
|
// This is usually a higher number than CountPeerList, which just represents the current number of connected peers.
|
||||||
// The CountNetwork number is going to be queried from root peers which may or may not have a limited view.
|
// The CountNetwork number is going to be queried from root peers which may or may not have a limited view.
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -33,20 +33,20 @@ Request: GET /status
|
|||||||
Result: 200 with JSON structure Status
|
Result: 200 with JSON structure Status
|
||||||
*/
|
*/
|
||||||
func (api *WebapiInstance) apiStatus(w http.ResponseWriter, r *http.Request) {
|
func (api *WebapiInstance) apiStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
status := apiResponseStatus{Status: 0, CountPeerList: api.Backend.PeerlistCount()}
|
status := apiResponseStatus{Status: 0, CountPeerList: api.Backend.PeerlistCount()}
|
||||||
status.CountNetwork = status.CountPeerList // For now always same as CountPeerList, until native Statistics message to root peers is available.
|
status.CountNetwork = status.CountPeerList // For now always same as CountPeerList, until native Statistics message to root peers is available.
|
||||||
|
|
||||||
// Connected: If at leat 2 peers.
|
// Connected: If at leat 2 peers.
|
||||||
// This metric needs to be improved in the future, as root peers never disconnect.
|
// This metric needs to be improved in the future, as root peers never disconnect.
|
||||||
// Instead, the core should keep a count of "active peers".
|
// Instead, the core should keep a count of "active peers".
|
||||||
status.IsConnected = status.CountPeerList >= 2
|
status.IsConnected = status.CountPeerList >= 2
|
||||||
|
|
||||||
EncodeJSON(api.Backend, w, r, status)
|
EncodeJSON(api.Backend, w, r, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
type apiResponsePeerSelf struct {
|
type apiResponsePeerSelf struct {
|
||||||
PeerID string `json:"peerid"` // Peer ID. This is derived from the public in compressed form.
|
PeerID string `json:"peerid"` // Peer ID. This is derived from the public in compressed form.
|
||||||
NodeID string `json:"nodeid"` // Node ID. This is the blake3 hash of the peer ID and used in the DHT.
|
NodeID string `json:"nodeid"` // Node ID. This is the blake3 hash of the peer ID and used in the DHT.
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -55,13 +55,13 @@ Request: GET /account/info
|
|||||||
Result: 200 with JSON structure apiResponsePeerSelf
|
Result: 200 with JSON structure apiResponsePeerSelf
|
||||||
*/
|
*/
|
||||||
func (api *WebapiInstance) apiAccountInfo(w http.ResponseWriter, r *http.Request) {
|
func (api *WebapiInstance) apiAccountInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
response := apiResponsePeerSelf{}
|
response := apiResponsePeerSelf{}
|
||||||
response.NodeID = hex.EncodeToString(api.Backend.SelfNodeID())
|
response.NodeID = hex.EncodeToString(api.Backend.SelfNodeID())
|
||||||
|
|
||||||
_, publicKey := api.Backend.ExportPrivateKey()
|
_, publicKey := api.Backend.ExportPrivateKey()
|
||||||
response.PeerID = hex.EncodeToString(publicKey.SerializeCompressed())
|
response.PeerID = hex.EncodeToString(publicKey.SerializeCompressed())
|
||||||
|
|
||||||
EncodeJSON(api.Backend, w, r, response)
|
EncodeJSON(api.Backend, w, r, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -72,15 +72,15 @@ Result: 204 if the user choses not to delete the account
|
|||||||
200 if successfully deleted
|
200 if successfully deleted
|
||||||
*/
|
*/
|
||||||
func (api *WebapiInstance) apiAccountDelete(w http.ResponseWriter, r *http.Request) {
|
func (api *WebapiInstance) apiAccountDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
if confirm, _ := strconv.ParseBool(r.Form.Get("confirm")); !confirm {
|
if confirm, _ := strconv.ParseBool(r.Form.Get("confirm")); !confirm {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
api.Backend.DeleteAccount()
|
api.Backend.DeleteAccount()
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -92,35 +92,53 @@ Request: GET /status/peers
|
|||||||
Result: 200 with JSON array apiResponsePeerInfo
|
Result: 200 with JSON array apiResponsePeerInfo
|
||||||
*/
|
*/
|
||||||
func (api *WebapiInstance) apiStatusPeers(w http.ResponseWriter, r *http.Request) {
|
func (api *WebapiInstance) apiStatusPeers(w http.ResponseWriter, r *http.Request) {
|
||||||
var peers []apiResponsePeerInfo
|
var peers []apiResponsePeerInfo
|
||||||
|
|
||||||
// query all nodes
|
// query all nodes
|
||||||
for _, peer := range api.Backend.PeerlistGet() {
|
for _, peer := range api.Backend.PeerlistGet() {
|
||||||
peerInfo := apiResponsePeerInfo{
|
peerInfo := apiResponsePeerInfo{
|
||||||
PeerID: peer.PublicKey.SerializeCompressed(),
|
PeerID: peer.PublicKey.SerializeCompressed(),
|
||||||
NodeID: peer.NodeID,
|
NodeID: peer.NodeID,
|
||||||
UserAgent: peer.UserAgent,
|
UserAgent: peer.UserAgent,
|
||||||
IsRoot: peer.IsRootPeer,
|
IsRoot: peer.IsRootPeer,
|
||||||
BlockchainHeight: peer.BlockchainHeight,
|
BlockchainHeight: peer.BlockchainHeight,
|
||||||
BlockchainVersion: peer.BlockchainVersion,
|
BlockchainVersion: peer.BlockchainVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
if latitude, longitude, valid := api.Peer2GeoIP(peer); valid {
|
if latitude, longitude, valid := api.Peer2GeoIP(peer); valid {
|
||||||
peerInfo.GeoIP = fmt.Sprintf("%.4f", latitude) + "," + fmt.Sprintf("%.4f", longitude)
|
peerInfo.GeoIP = fmt.Sprintf("%.4f", latitude) + "," + fmt.Sprintf("%.4f", longitude)
|
||||||
}
|
}
|
||||||
|
|
||||||
peers = append(peers, peerInfo)
|
peers = append(peers, peerInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
EncodeJSON(api.Backend, w, r, peers)
|
EncodeJSON(api.Backend, w, r, peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
type apiResponsePeerInfo struct {
|
type apiResponsePeerInfo struct {
|
||||||
PeerID []byte `json:"peerid"` // Peer ID. This is derived from the public in compressed form.
|
PeerID []byte `json:"peerid"` // Peer ID. This is derived from the public in compressed form.
|
||||||
NodeID []byte `json:"nodeid"` // Node ID. This is the blake3 hash of the peer ID and used in the DHT.
|
NodeID []byte `json:"nodeid"` // Node ID. This is the blake3 hash of the peer ID and used in the DHT.
|
||||||
GeoIP string `json:"geoip"` // GeoIP location as "Latitude,Longitude" CSV format. Empty if location not available.
|
GeoIP string `json:"geoip"` // GeoIP location as "Latitude,Longitude" CSV format. Empty if location not available.
|
||||||
UserAgent string `json:"useragent"` // User Agent.
|
UserAgent string `json:"useragent"` // User Agent.
|
||||||
IsRoot bool `json:"isroot"` // If the peer is a root peer.
|
IsRoot bool `json:"isroot"` // If the peer is a root peer.
|
||||||
BlockchainHeight uint64 `json:"blockchainheight"` // Blockchain height
|
BlockchainHeight uint64 `json:"blockchainheight"` // Blockchain height
|
||||||
BlockchainVersion uint64 `json:"blockchainversion"` // Blockchain version
|
BlockchainVersion uint64 `json:"blockchainversion"` // Blockchain version
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
apiConfigPeers return the appropriate config information of the current Peer
|
||||||
|
connected.
|
||||||
|
|
||||||
|
Request: GET /status/config
|
||||||
|
Result: 200 with JSON apiResponseConfig
|
||||||
|
*/
|
||||||
|
func (api *WebapiInstance) apiStatusConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var peer apiResponseConfig
|
||||||
|
peer.BlockSize = api.Backend.Config.CacheMaxBlockSize
|
||||||
|
|
||||||
|
EncodeJSON(api.Backend, w, r, peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
type apiResponseConfig struct {
|
||||||
|
BlockSize uint64 `json:"blockSize"`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user