Comments (8)
raising another concern where some networks are going to be deprecated.
Can you say more what you mean here?
If I understand correctly, this kind of flexibilty can be accomplished (approximately) with existing functionality:
We take an existing chain config singleton, eg. params.RopstenChainConfig
, and can transform it into an equivalent configuration for any other config struct supporting type Configurator interface
, here coregeth.CoreGethChainConfig
.
func Test1(t *testing.T) {
ropstenConfig := params.RopstenChainConfig
var emptyConfig = new(coregeth.CoreGethChainConfig)
err := confp.Convert(ropstenConfig, emptyConfig)
if err != nil {
t.Fatal(err)
}
t.Log(emptyConfig.String())
}
=== RUN Test1
--- PASS: Test1 (0.00s)
configurator_test.go:259: NetworkID: 3, ChainID: 3 Engine: ethash EIP1014: 4230000 EIP1052: 4230000 EIP1108: 6485846 EIP1283Disable: 4939394 EIP1283: 4230000 EIP1344: 6485846 EIP140: 1700000 EIP145: 4230000 EIP150: 0 EIP152: 6485846 EIP155: 10 EIP160: 10 EIP161abc: 10 EIP161d: 10 EIP170: 10 EIP1884: 6485846 EIP198: 1700000 EIP2028: 6485846 EIP211: 1700000 EIP212: 1700000 EIP213: 1700000 EIP214: 1700000 EIP2200: 6485846 EIP2: 0 EIP658: 1700000 EIP7: 0 EthashEIP100B: 1700000 EthashEIP1234: 4230000 EthashEIP2384: 7117117 EthashEIP649: 1700000 EthashHomestead: 0
PASS
✏️ Just brainstorming here, I had been thinking of something along the lines of something like
package params // or somewhere else?
type ConfigManager struct {
// some fields probably, not sure what... maybe including a map of name:config
}
func (m *ConfigManager) ConfigByName(name string) (config ctypes.ChainConfigurator, err error) {
switch name {
// ...
}
}
func (m *ConfigManager) Configs() []ctypes.ChainConfigurator {
// ...
}
Although, working through the thinking on this now, while it seems convenient and "nice" to have wrappers like this, I think it may be worth stepping back and make sure we understand what problem we're solving.
The primary motivator for this issue is not that existing switch
-style code (as above) is ugly, but that it is fragile to upstream merges because of differences in availability of chain options. This could be solved with tests checking that all expected options for core-geth are in place. Granted, this would create yet another case of a "hardcoded list", but it could be far less prone to merge conflict or errors, and would solve the problem without having to diverge more than we already have from upstream.
Another smaller reason being that these ugly sets of switch
-style chain option lists occur in several places, and can be difficult/painstaking to make sure all have been updated in case, say, a chain is added or removed. This could be solved again with a few more tests added.
Beyond being "convenient" and "nice," it seems to me that the best argument for some kind of "chain manager"/wrapper would be the ability to programmatically list and iterate all or some chains... and although I have a vague idea that we might be able to build some strong tests on top of that, I'm not really sure yet exactly what or where I would want to do that.
Curious your thoughts.
from core-geth.
I'd love this one from go-libp2p
:
https://github.com/libp2p/go-libp2p/blob/master/config/config.go#L358
A singleton state management looks reasonable to me.
from core-geth.
Indeed, good idea! A global singleton is one option. One priority to keep in mind is that we'll want to integrate cleanly with the existing parallelized tests (and there are a lot of of those ;)
In fact, core-geth already uses a similar pattern with it's Configurator
interface (and interface implementations), for example:
func (c *CoreGethChainConfig) SetEIP155Transition(n *uint64) error {
c.EIP155Block = setBig(c.EIP155Block, n)
return nil
}
I'm afraid this issue isn't very well written, and the link has become stale. I'll try to regroup on the main point here:
Problem:
- Chain flags like
--ropsten
and--classic
and--kotti
each signal the activation of a certain chain configuration. - In many places, the set of these flags occur together, but there is no concept for the group of these options. For example, below.
- Since these flags evolve differently at core-geth than at go-ethereum, these are often places of conflict and can be prone to error.
- Without a concept of "available chain configurations" (as a set), there is not way to communicate this to the user, or to validate the inclusion (or exclusion) of a configuration against a set. For example, we could make some tests a lot more thorough by being able to say "Run this test against all of the test configurations," or, "Run this test against all production configurations," and so forth.
// setBootstrapNodes creates a list of bootstrap nodes from the command line
// flags, reverting to pre-configured ones if none have been specified.
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
urls := params.MainnetBootnodes
switch {
case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(LegacyBootnodesV4Flag.Name):
if ctx.GlobalIsSet(LegacyBootnodesV4Flag.Name) {
urls = splitAndTrim(ctx.GlobalString(LegacyBootnodesV4Flag.Name))
} else {
urls = splitAndTrim(ctx.GlobalString(BootnodesFlag.Name))
}
case ctx.GlobalBool(ClassicFlag.Name):
urls = params.ClassicBootnodes
case ctx.GlobalBool(MordorFlag.Name):
urls = params.MordorBootnodes
case ctx.GlobalBool(SocialFlag.Name):
urls = params.SocialBootnodes
case ctx.GlobalBool(MixFlag.Name):
urls = params.MixBootnodes
case ctx.GlobalBool(EthersocialFlag.Name):
urls = params.EthersocialBootnodes
case ctx.GlobalBool(LegacyTestnetFlag.Name) || ctx.GlobalBool(RopstenFlag.Name):
urls = params.RopstenBootnodes
case ctx.GlobalBool(RinkebyFlag.Name):
urls = params.RinkebyBootnodes
case ctx.GlobalBool(KottiFlag.Name):
urls = params.KottiBootnodes
case ctx.GlobalBool(GoerliFlag.Name):
urls = params.GoerliBootnodes
case ctx.GlobalBool(YoloV1Flag.Name):
urls = params.YoloV1Bootnodes
case cfg.BootstrapNodes != nil:
return // already set, don't apply defaults.
}
https://github.com/etclabscore/core-geth/blob/master/cmd/utils/flags.go#L805
and here
func dataDirPathForCtxChainConfig(ctx *cli.Context, baseDataDirPath string) string {
switch {
case ctx.GlobalBool(RopstenFlag.Name):
return filepath.Join(baseDataDirPath, "ropsten")
case ctx.GlobalBool(ClassicFlag.Name):
return filepath.Join(baseDataDirPath, "classic")
case ctx.GlobalBool(MordorFlag.Name):
return filepath.Join(baseDataDirPath, "mordor")
case ctx.GlobalBool(SocialFlag.Name):
return filepath.Join(baseDataDirPath, "social")
case ctx.GlobalBool(MixFlag.Name):
return filepath.Join(baseDataDirPath, "mix")
case ctx.GlobalBool(EthersocialFlag.Name):
return filepath.Join(baseDataDirPath, "ethersocial")
case ctx.GlobalBool(RinkebyFlag.Name):
return filepath.Join(baseDataDirPath, "rinkeby")
case ctx.GlobalBool(KottiFlag.Name):
return filepath.Join(baseDataDirPath, "kotti")
case ctx.GlobalBool(GoerliFlag.Name):
return filepath.Join(baseDataDirPath, "goerli")
case ctx.GlobalBool(YoloV1Flag.Name):
return filepath.Join(baseDataDirPath, "yolo-v1")
}
return baseDataDirPath
}
https://github.com/etclabscore/core-geth/blob/master/cmd/utils/flags.go#L1294
Possible Solution:
- A flag
--chain=<name>
that would deprecate and eventually supersede the cases of--goerli
,--kotti
, etc.- Might use a singleton to handle options and activation.
from core-geth.
The solution looks great but It's also raising another concern where some networks are going to be deprecated. If we add another wrapper on top of configuration for each network so it would be more flexible.
E.g:
package ropsten-config;
func (c *Config) getRopsten() RopstenConfig;
This approach could help us to derive configuration of each network from the "global" configuration.
from core-geth.
Can you say more what you mean here?
I meant, might be in the future we could stop supporting some networks.
If I understand correctly, this kind of flexibilty can be accomplished (approximately) with existing functionality:
We take an existing chain config singleton, eg. params.RopstenChainConfig, and can transform it into an equivalent configuration for any other config struct supporting type Configurator interface, here coregeth.CoreGethChainConfig
Yes, I think those configurations should share the same interface or able to derive an equivalent.
Thanks for your clarification,
To me, singleton management help us manage configuration more consistent meanwhile chain of configuration help us manipulate parameters munch more easier. The configuration wrappers should contain hard-code of chains, networks...etc.
from core-geth.
Here are dummy code:
package configuration
import "sync"
// Configuration structure, might key value based
type Configuration struct {
items map[string]interface{}
lock sync.RWMutex
}
// Config interface shared between packages
type Config interface {
getByName(key string) interface{}
}
// Option that's function that able to attach config to *config pointer
type Option func(cfg *Configuration) error
// Apply config from opts
func (cfg *Configuration) Apply(opts ...Option) error {
for _, opt := range opts {
if opt == nil {
continue
}
if err := opt(cfg); err != nil {
return err
}
}
return nil
}
// Derive subset of configuration
func (cfg *Configuration) DeriveConfig(keys ...string) Config {}
// GetCfgInstance return singleton instance of configuration
func GetCfgInstance() *Configuration {}
Here are how do I supposed to grouping hardcode:
import "configuration"
package rinkeby-configuration
func ChainHardcode(cfg *configuration.Configuration) error {
// Apply chain hard code here and do manipulate configuration here
cfg.Apply(enableEIP155);
}
from core-geth.
Thanks your time putting this together! This is very helpful.
I think the package-ized chain configuration idea is quite interesting (package rinkeby-configuration
), but am not sure exactly what benefits it brings.
In your example, do you mean that type Configuration struct
would replace type Configurator interface
eventually?
from core-geth.
That's very kind of you!,
But am not sure exactly what benefits it brings.
I'm try to bring up these things:
- All chain's hardcode could be "packaged", that would be easier to maintenance.
- All options are methods (
type Option func(cfg *Configuration) error
) that's allowed us to manipulate configuration and handle exceptions cases better. - We could derive a subset of configuration that's needed.
In your example, do you mean that type Configuration struct would replace type Configurator interface eventually?
Yes, I think so.
from core-geth.
Related Issues (20)
- Make geth failure on ubuntu HOT 2
- Iris (v1.12.11) Fatal: Failed to start mining: ether base missing: ether base must be explicitly specified HOT 3
- Synchronisation failed, dropping peer err=timeout Iris (v1.12.11) HOT 2
- Mordor Testnet Synchronisation failed HOT 6
- Poseidon (v1.12.14) Make geth failure.
- My nodes are unable to synchronize HOT 4
- Recommended to use fork-diff for the transparent view with upstream geth HOT 1
- Could you please confirm whether it is mandatory to update to the latest release, Real Eris (v1.12.16), or if the previous version is sufficient for the mainet client? HOT 2
- Node does not commit new sealing work when it should HOT 3
- Probably on my end, can't seem to find any solutions for restoring the missing dependancy HOT 2
- Adjust Default Mordor gas limit from 30M to 8M to match Mainnet limits
- deactivate MESS on Mordor HOT 2
- only audit ETC-relevant bootnodes
- Why was UDP closed in the latest update? HOT 9
- Synchronisation failed HOT 10
- Bootloader nodes with DNS off will stop nodes the moment of reading. HOT 4
- dumpconfig creates an invalid config.toml (ECBP1100 cannot umarshal <nil> into a *big.Int) HOT 1
- Synchronisation failed-Persiphone (v1.12.19) HOT 20
- unreachable bootloaders stop node process HOT 4
- fatal error: index out of range HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from core-geth.