Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup ten config library to replace our flags approach #2115

Merged
merged 29 commits into from
Nov 6, 2024

Conversation

BedrockSquirrel
Copy link
Collaborator

Why this change is needed

We are moving away from flags based config to a systematic yaml/environment variable based config that will be used across all our go processes. This will make our config play more nicely with standard orchestration tooling (kubernetes etc.) and reduce duplication and magic in our config.

What changes were made as part of this PR

This first PR adds the config structure, the loading mechanism and sets it up for used by the enclave and host processes.

All other Go processes (including the node and testnet launcher orchestration processes) are still configured with flags. They will be migrated shortly.

Short term while both systems are in place this may seem to be making things worse but when the node and testnet launchers are replaced with the infra tooling that is being worked on then a lot of code and magic will be removed.

PR checks pre-merging

Please indicate below by ticking the checkbox that you have read and performed the required
PR checks

  • PR checks reviewed and performed

Copy link
Collaborator

@tudor-malene tudor-malene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!
Makes everything much clearer.

I left a few comments.

go/config/defaults/0-base-config.yaml Outdated Show resolved Hide resolved
go/config/loader.go Show resolved Hide resolved
go/enclave/main/enclave-test.json Outdated Show resolved Hide resolved
if err != nil {
panic(fmt.Errorf("unable to create config from flags - %w", err))
}
enclaveConfig := enclaveconfig.EnclaveConfigFromTenConfig(tenCfg)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow here how the config is read from enclave.json

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enclave config is read the same as the host and other processes: base yaml file(s) + environment variables

In enclave.json the "fromHost" flag allows you to whitelist env variable keys so their values can be passed in from the host machine.

E.g. if this was in the enclave.json then NETWORK_CHAINID=1337 would be set and ENCLAVE_DB_EDGELESSDBHOST value would be passed through if the runner set it as an environment variable.

"env": [
    { "name": "ENCLAVE_DB_EDGELESSDBHOST",  "fromHost": true },

    { "name": "NETWORK_CHAINID", value: 1337 },
]

So for now I'm just letting it pass through all the env variables. For tagged public releases we can hardcode values.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what confuses me is that I don't see anywhere in the code how "fromHost" is resolved.
I don't follow how the right values end up in the enclave.json file that is passed to ego

testnet/launcher/docker.go Show resolved Hide resolved
Copy link
Contributor

@StefanIliev545 StefanIliev545 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of changes that seem like grunt work I glanced over, but this is my first (prolly final) pass

P.S. Ask copilot for any improvements and see if anything is reasonable; obviously as you've written he code you're best placed to know if it's bullshitting or legit suggestion

Ten config has a hierarchical structure, so every field has a unique field name. Some fields are used by multiple processes,
while others are only used by a single process.

For example, `network.chainId` is a field that might be used by multiple processes, but `host.rpc.httpPort` is only used by the host processes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

the mapstructure annotation that gives their yaml field name and any comments about their usage.

This library provides a loading mechanism powered by viper, it reads 0-base-config.yaml to initialise the config and then
overrides fields with any other yaml files provided and finally overrides with environment variables.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this ok for production? ENV variable overrides should be disabled in enclave IMO? Or at least disabled for anything baked into the image

we want to make sure that all fields are defined in the base config file even if just with trivial or empty values.

- The ego enclave restricts the environment variables that can be accessed by the enclave process. This means that the enclave
process will not be able to access environment variables that are not whitelisted. This is a security feature of the ego enclave.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

go/config/decoding.go Show resolved Hide resolved

network:
chainId: 443
genesis: "{}" # json string of genesis block, used for configuring prefunded accounts etc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still rely on genesis override in sim tests? Perhaps a good opportunity to have test/1-sim.yaml that showcases overrides

maxSize: 56320 # 55kb
rollup:
interval: 5s
maxInterval: 10m # rollups will be produced after this time even if the data blob is not full
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this identical for local testnet or is it the sepolia time?

rpcTimeout: 10s
l1:
wsURL: ws://localhost:8546 # websocket URL for L1 RPC service
beaconURL: eth2network:12600 # websocket URL for L1 beacon service
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay this cfg looks to be a mix of what we have right now (unless I'm wrong, which is quite possible).
Maybe we should have one for each environment (basic matches local testnet, overrides only for environments)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I started doing one for each environment but I think it's a waste of time because we'll be throwing it away in a couple of weeks. We don't want environmental config in our repo and it will live in Krish's kubernetes config stores.

So for now all these config values are still coming from github in the testnet environments. For sims and local networks we use yaml file overrides (or set the values dynamically in the code where that makes sense).

Happy to be convinced otherwise though, I have gone around in circles on this. Originally I had the environment passed to the main as a flag, like -env=uat and then it would auto-load 1-env-uat.yaml.

But anyway, if we get the core process in we can iterate on how it's used, for now I just want it in without breaking anything so Krish can start testing against it.

nodeType: validator
isGenesis: false
id: 0x2f7fCaA34b38871560DaAD6Db4596860744e1e8A
privateKey: ebca545772d6438bbbe1a16afbed455733eccf96157b52384f1722ea65ccfa89
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we going to leave this as is? Perhaps this field should either be a key or somewhere to load it from ( or off chain signing )
Maybe a todo with a ticket

Copy link
Collaborator

@tudor-malene tudor-malene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow up question

if err != nil {
panic(fmt.Errorf("unable to create config from flags - %w", err))
}
enclaveConfig := enclaveconfig.EnclaveConfigFromTenConfig(tenCfg)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what confuses me is that I don't see anywhere in the code how "fromHost" is resolved.
I don't follow how the right values end up in the enclave.json file that is passed to ego

@BedrockSquirrel
Copy link
Collaborator Author

@tudor-malene The values don't get set into the enclave.json (unless they're hardcoded values which we're not doing at this stage). The fromHost flag is part of the enclave.json spec from ego to whitelist those env var keys: https://docs.edgeless.systems/ego/reference/config#environment-variables

So we pass the values to the enclave process with env variables in docker like normal. So when you start the docker container you set the env variables (that's what @pkrishnath 's kubernetes set up will do, and temporarily that's what the docker_node launcher thing is doing).

Copy link
Collaborator

@tudor-malene tudor-malene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@BedrockSquirrel BedrockSquirrel merged commit 9618a79 into main Nov 6, 2024
11 checks passed
@BedrockSquirrel BedrockSquirrel deleted the matt/config-viper branch November 6, 2024 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants