Skip to content

Commit

Permalink
Serialize network constants and logging with anchors (#153)
Browse files Browse the repository at this point in the history
* Serialize network constants with anchors

* Add an anchor serialization helper + add anchors to logging

* Fix lint

* Add basic tests for marshalling with anchors
  • Loading branch information
cmmarslender authored Sep 13, 2024
1 parent 8cf47f9 commit b97b0b2
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 39 deletions.
54 changes: 54 additions & 0 deletions pkg/config/anchors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package config

import (
"reflect"

"gopkg.in/yaml.v3"
)

// MarshalYAML marshals the NetworkOverrides value to yaml handling anchors where necessary
func (nc *NetworkOverrides) MarshalYAML() (interface{}, error) {
return anchorHelper(nc, "network_overrides")
}

// MarshalYAML marshals the LoggingConfig value to yaml handling anchors where necessary
func (lc *LoggingConfig) MarshalYAML() (interface{}, error) {
return anchorHelper(lc, "logging")
}

// Anchorable defines the methods a type must implement to support anchors
type Anchorable interface {
AnchorNode() *yaml.Node
SetAnchorNode(*yaml.Node)
}

func anchorHelper(in Anchorable, tag string) (*yaml.Node, error) {
if in.AnchorNode() != nil {
node := &yaml.Node{
Kind: yaml.AliasNode,
Alias: in.AnchorNode(),
Value: tag,
}
return node, nil
}

// Get the underlying value of 'in' for marshalling or else we end up recursively in this function
value := reflect.ValueOf(in)
if value.Kind() == reflect.Ptr {
// Dereference if it's a pointer
value = value.Elem()
}

// Marshal the struct to a yaml.Node
var node yaml.Node
if err := node.Encode(value.Interface()); err != nil {
return nil, err
}
node.Anchor = tag

// Store the node as the anchor for future iterations
in.SetAnchorNode(&node)

// Return the node to be marshalled
return &node, nil
}
80 changes: 80 additions & 0 deletions pkg/config/anchors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package config_test

import (
"testing"

"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"

"github.com/chia-network/go-chia-libs/pkg/config"
)

// TestLoggingConfigAnchors verifies that logging is serialized with anchors
func TestLoggingConfigAnchors(t *testing.T) {
type testStruct struct {
LoggingConfig1 *config.LoggingConfig `yaml:"logging1"`
LoggingConfig2 *config.LoggingConfig `yaml:"logging2"`
}
loggingCfg := config.LoggingConfig{}
testInstance := &testStruct{
LoggingConfig1: &loggingCfg,
LoggingConfig2: &loggingCfg,
}

expected := `logging1: &logging
log_stdout: false
log_filename: ""
log_level: ""
log_maxfilesrotation: 0
log_maxbytesrotation: 0
log_use_gzip: false
log_syslog: false
log_syslog_host: ""
log_syslog_port: 0
logging2: *logging
`

out, err := yaml.Marshal(testInstance)
assert.NoError(t, err)
assert.Equal(t, expected, string(out))
}

// TestNetworkOverridesAnchors verifies that logging is serialized with anchors
func TestNetworkOverridesAnchors(t *testing.T) {
type testStruct struct {
Network1 *config.NetworkOverrides `yaml:"network_overrides1"`
Network2 *config.NetworkOverrides `yaml:"network_overrides2"`
}
no := config.NetworkOverrides{
Constants: map[string]config.NetworkConstants{
"mainnet": {},
},
Config: map[string]config.NetworkConfig{
"mainnet": {
AddressPrefix: "xch",
DefaultFullNodePort: 8444,
},
},
}
testInstance := &testStruct{
Network1: &no,
Network2: &no,
}

expected := `network_overrides1: &network_overrides
constants:
mainnet:
GENESIS_CHALLENGE: ""
GENESIS_PRE_FARM_POOL_PUZZLE_HASH: ""
GENESIS_PRE_FARM_FARMER_PUZZLE_HASH: ""
config:
mainnet:
address_prefix: xch
default_full_node_port: 8444
network_overrides2: *network_overrides
`

out, err := yaml.Marshal(testInstance)
assert.NoError(t, err)
assert.Equal(t, expected, string(out))
}
102 changes: 63 additions & 39 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import (
"gopkg.in/yaml.v3"

"github.com/chia-network/go-chia-libs/pkg/types"
)

Expand All @@ -25,7 +27,7 @@ type ChiaConfig struct {
PrivateSSLCA CAConfig `yaml:"private_ssl_ca"`
ChiaSSLCA CAConfig `yaml:"chia_ssl_ca"`
DaemonSSL SSLConfig `yaml:"daemon_ssl"`
Logging LoggingConfig `yaml:"logging"` // @TODO this would usually be an anchor
Logging *LoggingConfig `yaml:"logging"`
Seeder SeederConfig `yaml:"seeder"`
Harvester HarvesterConfig `yaml:"harvester"`
Pool PoolConfig `yaml:"pool"`
Expand Down Expand Up @@ -69,8 +71,19 @@ type Peer struct {

// NetworkOverrides is all network settings
type NetworkOverrides struct {
Constants map[string]NetworkConstants `yaml:"constants"`
Config map[string]NetworkConfig `yaml:"config"`
yamlAnchor *yaml.Node `yaml:"-"` // Helps with serializing the anchors to yaml
Constants map[string]NetworkConstants `yaml:"constants"`
Config map[string]NetworkConfig `yaml:"config"`
}

// AnchorNode returns the node to be used in yaml anchors
func (nc *NetworkOverrides) AnchorNode() *yaml.Node {
return nc.yamlAnchor
}

// SetAnchorNode sets the yaml.Node reference when marshaling
func (nc *NetworkOverrides) SetAnchorNode(node *yaml.Node) {
nc.yamlAnchor = node
}

// NetworkConstants the constants for each network
Expand Down Expand Up @@ -102,15 +115,26 @@ type NetworkConfig struct {

// LoggingConfig configuration settings for the logger
type LoggingConfig struct {
LogStdout bool `yaml:"log_stdout"`
LogFilename string `yaml:"log_filename"`
LogLevel string `yaml:"log_level"`
LogMaxFilesRotation uint8 `yaml:"log_maxfilesrotation"`
LogMaxBytesRotation uint32 `yaml:"log_maxbytesrotation"`
LogUseGzip bool `yaml:"log_use_gzip"`
LogSyslog bool `yaml:"log_syslog"`
LogSyslogHost string `yaml:"log_syslog_host"`
LogSyslogPort uint16 `yaml:"log_syslog_port"`
yamlAnchor *yaml.Node `yaml:"-"` // Helps with serializing the anchors to yaml
LogStdout bool `yaml:"log_stdout"`
LogFilename string `yaml:"log_filename"`
LogLevel string `yaml:"log_level"`
LogMaxFilesRotation uint8 `yaml:"log_maxfilesrotation"`
LogMaxBytesRotation uint32 `yaml:"log_maxbytesrotation"`
LogUseGzip bool `yaml:"log_use_gzip"`
LogSyslog bool `yaml:"log_syslog"`
LogSyslogHost string `yaml:"log_syslog_host"`
LogSyslogPort uint16 `yaml:"log_syslog_port"`
}

// AnchorNode returns the node to be used in yaml anchors
func (lc *LoggingConfig) AnchorNode() *yaml.Node {
return lc.yamlAnchor
}

// SetAnchorNode sets the yaml.Node reference when marshaling
func (lc *LoggingConfig) SetAnchorNode(node *yaml.Node) {
lc.yamlAnchor = node
}

// SeederConfig seeder configuration section
Expand All @@ -129,7 +153,7 @@ type SeederConfig struct {
SOA SeederSOA `yaml:"soa"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
CrawlerConfig CrawlerConfig `yaml:"crawler"`
}

Expand Down Expand Up @@ -157,7 +181,7 @@ type HarvesterConfig struct {
NumThreads uint8 `yaml:"num_threads"`
PlotsRefreshParameter PlotsRefreshParameter `yaml:"plots_refresh_parameter"`
ParallelRead bool `yaml:"parallel_read"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
PlotDirectories []string `yaml:"plot_directories"`
Expand Down Expand Up @@ -187,7 +211,7 @@ type PlotsRefreshParameter struct {
// PoolConfig configures pool settings
type PoolConfig struct {
XCHTargetAddress string `yaml:"xch_target_address,omitempty"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
}
Expand All @@ -200,7 +224,7 @@ type FarmerConfig struct {
StartRPCServer bool `yaml:"start_rpc_server"`
EnableProfiler bool `yaml:"enable_profiler"`
PoolShareThreshold uint32 `yaml:"pool_share_threshold"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
PortConfig `yaml:",inline"`
Expand All @@ -209,10 +233,10 @@ type FarmerConfig struct {

// TimelordLauncherConfig settings for vdf_client launcher
type TimelordLauncherConfig struct {
Host string `yaml:"host"`
Port uint16 `yaml:"port"`
ProcessCount uint8 `yaml:"process_count"`
Logging LoggingConfig `yaml:"logging"`
Host string `yaml:"host"`
Port uint16 `yaml:"port"`
ProcessCount uint8 `yaml:"process_count"`
Logging *LoggingConfig `yaml:"logging"`
}

// TimelordConfig timelord configuration section
Expand All @@ -221,7 +245,7 @@ type TimelordConfig struct {
FullNodePeers []Peer `yaml:"full_node_peers"`
MaxConnectionTime uint16 `yaml:"max_connection_time"`
VDFServer Peer `yaml:"vdf_server"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
FastAlgorithm bool `yaml:"fast_algorithm"`
Expand Down Expand Up @@ -282,7 +306,7 @@ type FullNodeConfig struct {
TrustedMaxSubscribeResponseItems uint32 `yaml:"trusted_max_subscribe_response_items"`
DNSServers []string `yaml:"dns_servers"`
IntroducerPeer Peer `yaml:"introducer_peer"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
TrustedPeers map[string]string `yaml:"trusted_peers"`
Expand All @@ -294,7 +318,7 @@ type FullNodeConfig struct {
type UIConfig struct {
PortConfig `yaml:",inline"`
SSHFilename string `yaml:"ssh_filename"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
DaemonHost string `yaml:"daemon_host"`
Expand All @@ -308,7 +332,7 @@ type IntroducerConfig struct {
PortConfig `yaml:",inline"`
MaxPeersToSend uint16 `yaml:"max_peers_to_send"`
RecentPeerThreshold uint16 `yaml:"recent_peer_threshold"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
SSL SSLConfig `yaml:"ssl"`
Expand All @@ -334,7 +358,7 @@ type WalletConfig struct {
WalletPeersPath string `yaml:"wallet_peers_path"`
WalletPeersFilePath string `yaml:"wallet_peers_file_path"`
LogSqliteCmds bool `yaml:"log_sqlite_cmds"`
Logging LoggingConfig `yaml:"logging"`
Logging *LoggingConfig `yaml:"logging"`
NetworkOverrides *NetworkOverrides `yaml:"network_overrides"`
SelectedNetwork *string `yaml:"selected_network"`
TargetPeerCount uint16 `yaml:"target_peer_count"`
Expand Down Expand Up @@ -370,20 +394,20 @@ type AutoClaim struct {

// DataLayerConfig datalayer configuration section
type DataLayerConfig struct {
WalletPeer Peer `yaml:"wallet_peer"`
DatabasePath string `yaml:"database_path"`
ServerFilesLocation string `yaml:"server_files_location"`
ClientTimeout uint16 `yaml:"client_timeout"`
ProxyURL string `yaml:"proxy_url,omitempty"`
HostIP string `yaml:"host_ip"`
HostPort uint16 `yaml:"host_port"`
ManageDataInterval uint16 `yaml:"manage_data_interval"`
SelectedNetwork *string `yaml:"selected_network"`
StartRPCServer bool `yaml:"start_rpc_server"`
RPCServerMaxRequestBodySize uint32 `yaml:"rpc_server_max_request_body_size"`
LogSqliteCmds bool `yaml:"log_sqlite_cmds"`
EnableBatchAutoinsert bool `yaml:"enable_batch_autoinsert"`
Logging LoggingConfig `yaml:"logging"`
WalletPeer Peer `yaml:"wallet_peer"`
DatabasePath string `yaml:"database_path"`
ServerFilesLocation string `yaml:"server_files_location"`
ClientTimeout uint16 `yaml:"client_timeout"`
ProxyURL string `yaml:"proxy_url,omitempty"`
HostIP string `yaml:"host_ip"`
HostPort uint16 `yaml:"host_port"`
ManageDataInterval uint16 `yaml:"manage_data_interval"`
SelectedNetwork *string `yaml:"selected_network"`
StartRPCServer bool `yaml:"start_rpc_server"`
RPCServerMaxRequestBodySize uint32 `yaml:"rpc_server_max_request_body_size"`
LogSqliteCmds bool `yaml:"log_sqlite_cmds"`
EnableBatchAutoinsert bool `yaml:"enable_batch_autoinsert"`
Logging *LoggingConfig `yaml:"logging"`
PortConfig `yaml:",inline"`
SSL SSLConfig `yaml:"ssl"`
Plugins DataLayerPlugins `yaml:"plugins"`
Expand Down
15 changes: 15 additions & 0 deletions pkg/config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,19 @@ func (c *ChiaConfig) dealWithAnchors() {
c.Introducer.SelectedNetwork = c.SelectedNetwork
c.Wallet.SelectedNetwork = c.SelectedNetwork
c.DataLayer.SelectedNetwork = c.SelectedNetwork

if c.Logging == nil {
c.Logging = &LoggingConfig{}
}
c.Seeder.Logging = c.Logging
c.Harvester.Logging = c.Logging
c.Pool.Logging = c.Logging
c.Farmer.Logging = c.Logging
c.TimelordLauncher.Logging = c.Logging
c.Timelord.Logging = c.Logging
c.FullNode.Logging = c.Logging
c.UI.Logging = c.Logging
c.Introducer.Logging = c.Logging
c.Wallet.Logging = c.Logging
c.DataLayer.Logging = c.Logging
}

0 comments on commit b97b0b2

Please sign in to comment.