Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Aura: get_validator_set built-in #10651

Closed
saschagoebel opened this issue May 13, 2019 · 10 comments
Closed

Aura: get_validator_set built-in #10651

saschagoebel opened this issue May 13, 2019 · 10 comments
Labels
F8-enhancement 🎊 An additional feature request. M4-core ⛓ Core client code / Rust. P9-somedaymaybe 🌞 Issue might be worth doing eventually. Z1-question 🙋‍♀️ Issue is a question. Closer should answer.

Comments

@saschagoebel
Copy link

Background

When running an Aura based network, the active validator set can be either a static list, or a contract based set that can change over time. On top of that, the currently active list or contract can be changed at a specified block height. It is therefore not reliably possible to get the currently active validator set from within a smart contract.

Use-Case

The trustlines blockchain will be a community managed proof of authority network with 100+ authorities. Due to pseudonymity and the sheer number of authorities, a centralized management is not feasible and also not wanted. Updates of the validator set will either happen by removing misbehaving validators or hard forking to a new validator set elected by the community.
In our specific case, we're going to run a token bridge in which only active validators should be able to sign transfers, but in a semi-trusted environment, such as a proof of authority network, a plethora of other use-cases can be imagined in which it is necessary to verify if an address is in the currently active validator set.

Implementation

It should be possible to implement a new built-in which returns the currently active validator set as an array of addresses

Alternatives

We already discussed some alternative approaches, but each one had a major drawback that kept us from going that direction.

Using a proxy contract to find the active validator set contract

Said contract needed to be manually updated whenever a new validator set is deployed. Also this update needs to be done by a trusted party. And last but not least, the validator set could also be a static list which would also need to be stored in the contract.

Using a separate validator set on-chain

Having the bridge validator set on chain would also require us to manage the set via a multisig which in itself should only allow the validators to manage the set. This requires a lot of manual coordination which is just not feasible with that many pseudonymous parties.

Updating contracts in place

It is currently already possible to deploy a new smart contract via the chainspec configuration at the genesis block. Having the option to also update existing contracts would allow to just overwrite a proxy or even the validator set contract while doing a hard fork. Obviously this comes with a lot of security and compatibility concerns.

Going Forward

We would be willing to provide a Pull Request with the necessary changes, but not being very experienced Rust developers, any help would be greatly appreciated.

@jam10o-new jam10o-new added F8-enhancement 🎊 An additional feature request. M4-core ⛓ Core client code / Rust. P9-somedaymaybe 🌞 Issue might be worth doing eventually. Z1-question 🙋‍♀️ Issue is a question. Closer should answer. labels May 13, 2019
@jam10o-new
Copy link
Contributor

jam10o-new commented May 13, 2019

I believe @weilbith (on your team I believe?) has looked into this a bit, right? maybe worthwhile to copy our discussion from riot here.

Would be a good idea to have a small list of the current hurdles stopping this kind of builtin being made.

Some of my concerns are:

  • this is not a good candidate for a builtin, as it grabs information from state and isn't a pure function
  • if we did want to implement it, it would make the codebase less modular and maintainable as it would add an extra dependency between the builtins and the engine code (this is a problem Thore ran into so he can probably elaborate a little more)
  • validatorSet contracts can implement arbitrary logic - you don't have to restrict the manipulation of the set to purely validators, but admittedly this probably requires some thought and mechanism design. I'd recommend it if you have good smart contract devs though 😅

@weilbith
Copy link

maybe worthwhile to copy our discussion from riot here

I guess such copy could not add more information than you have already provided already with your list of concerns.

@soc1c
Copy link
Contributor

soc1c commented May 13, 2019

I agree with @joshua-mir this is not a candidate for a built-in or doing so would be rather hacky. finding an on-chain solution sounds feasible though, i.e., building a proxy contract with some validator governance, or extending the validator contract with some logic that allows validators to mark it as obsolete and pointing to a new contract. technically, each new validator contract is a hard fork, so you could also just tamper with the state directly (ref #8406).

@saschagoebel
Copy link
Author

First of all, thanks for the quick feedback! It's not the answer we were hoping for, but we can agree with the raised concerns regarding our proposed solution.

Allow me to go into some more depth regarding the other options:

tamper with the state directly

Actually we'd love to do that, as it would allow the community to just release an updated chainspec with the new validator set and update the proxy in one go, but if I read the PR correctly, this change has been shelved for now, right? Is there any way in the current client to update a contract / the state with a hard fork config-wise?

building a proxy contract with some validator governance, or extending the validator contract with some logic that allows validators to mark it as obsolete and pointing to a new contract

The main issue with this approach is, that we / the community can not get ahold of or even know the identity of the individual validators due to the decentralized election process. Therefore it's really hard to form a majority in order to update any contract or data.

Do you know of a way to send a transaction at a specific block height as part of the chainspec maybe?

if you have good smart contract devs though

I'd say the fine folks here at brainbot know what they are doing ;-)

@jam10o-new
Copy link
Contributor

Is there any way in the current client to update a contract / the state with a hard fork config-wise?

Not cleanly, no. My first thought was to use a multi-set and point at contracts that you add to the genesis accounts in order to accomplish this, but that would change the genesis block and break sync.

... due to the decentralized election process. Therefore it's really hard to form a majority in order to update any contract or data.

Yes, the suggestion is to consider doing the election process on-chain ("validator governance"), and write it into the validatorSet contract, so you don't need to have the entire community update any configuration files or software.

Do you know of a way to send a transaction at a specific block height as part of the chainspec maybe?

No clean way to do this at the moment, you might be able to use a multi-set validatorSet and a system transaction to the finalizeChange method will occur when the block defined in your chain specification is finalized - which you might be able to use to call out to other parts of the chain.

@soc1c
Copy link
Contributor

soc1c commented May 14, 2019

if I read the PR correctly, this change has been shelved for now, right?

yes, due to the controversy around EIP-999 this was never merged, however, the underlying logic around non-canonical state-change parameters that can be added to chain specs to modify state is something we would consider useful if anyone wants to pick up the work on it. the code #8406 is a good starting point and the discussion has some insights on how this can be useful for many different use-cases.

@saschagoebel
Copy link
Author

you might be able to use a multi-set validatorSet and a system transaction to the finalizeChange method will occur when the block defined in your chain specification is finalized

That's exactly what we're testing right now. Trying to update the proxy contract from within the finalizeChange method.

the underlying logic around non-canonical state-change parameters that can be added to chain specs to modify state is something we would consider useful if anyone wants to pick up the work on it.

We basically all agree, but this would break compatibility with all clients not implementing this functionality, right?

I'd assume if we get the finalizeChange solution working, we'd prefer not to maintain a parity-ethereum fork. Or would this be something to be considered for upstream merging?

@jam10o-new
Copy link
Contributor

jam10o-new commented May 14, 2019

It's a useful feature that people have certainly asked for before, and it's not at all controversial in the usecase of PoA networks (or really, any network that isn't mainnet that wants the ability to write their own hardforks without trying to get it merged in our codebase), so if someone picked up the work on it there'd be no problem in merging it.

@weilbith
Copy link

That's exactly what we're testing right now. Trying to update the proxy contract from within the finalizeChange method.

This simple but effective approach seems to work. Just tested it locally so that I'm sure it allows us to do what we plan for.

@adria0
Copy link

adria0 commented Jul 27, 2020

Closing issue due to its stale state.

@adria0 adria0 closed this as completed Jul 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
F8-enhancement 🎊 An additional feature request. M4-core ⛓ Core client code / Rust. P9-somedaymaybe 🌞 Issue might be worth doing eventually. Z1-question 🙋‍♀️ Issue is a question. Closer should answer.
Projects
None yet
Development

No branches or pull requests

5 participants