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

Public node with accounts and signing in Frontend #5304

Merged
merged 2 commits into from
Mar 29, 2017
Merged

Conversation

maciejhirsz
Copy link
Contributor

Disclaimer: The PR includes a copy of the dictionary for the frontend, hence the crazy diff. It's not that big.

Start parity with --public-node (suggestions for a better flag open):

  • Disables account managing RPCs.
  • UI account management is replicated in frontend. Accounts are stored in local storage in keythereum dump format.
  • Creating accounts, recovering accounts from phrases and signing transactions all happens in the browser.

Some concerns and general notes:

  • Generating keys in pure JS tends to be slow, and although there are avenues for optimization open there, a solution that re-uses Rust codebase via wasm or asm.js could potentially be better (less code to maintain). For the most part the UX feels fine as-is, although that's on a reasonable CPU, wouldn't try it on a phone.
  • UI currently does a lot of requests, which might be both noticeable over the wire and reduce the amount of traffic the node can handle. Throttling things would be nice.
  • Missing features, e.g. vaults, should either be hidden or implemented, although there seems to be little point to vaults in local storage?

@maciejhirsz maciejhirsz added A0-pleasereview 🤓 Pull request needs code review. M4-core ⛓ Core client code / Rust. M7-ui labels Mar 27, 2017
@rphmeier
Copy link
Contributor

While throttling the amount of requests the UI can make to the web node is definitely important, we should also be able to throttle the amount (and intensity) of RPC requests in general. It's fair to assume that any publicly-available RPC will be pummeled mercilessly sometimes by malicious actors.

Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

Looks good! I love the way you handled unsupported requests with AccountProvider, very clean!

Most important issue is that only a whitelist of APIs should be enabled, listed them in comment. Not sure how well GUI will work without those APIs.

const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
const LOCAL_STORAGE_KEY = '_parity::localAccounts';

function fromLocalStorage () {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think UI code uses store library exactly for that.


const account = this._store.find((account) => account.address === address);

if (account == null) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

=== null? Should be caught by linter anyway.

Copy link
Contributor Author

@maciejhirsz maciejhirsz Mar 28, 2017

Choose a reason for hiding this comment

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

I tend to use == null as an existence check, since the only values it can coerce to are null and undefined. if (!account) would also work. Is there a specific way to catch existence of a value that fits the code style?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think if (!account) { is used everywhere.

return false;
}

if (address === this._last) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a guarantee that this._last will be lowercased? I think it would be safer to do: address === this._last.toLowerCase()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should be guaranteed to be lowercase as any inputs where address is passed are forced to lowercase before anything is done with it. That said, I'll add a setter to make it clearer it's an expected behavior.

clearTimeout(this._persistTimer);

// Throttle persisting the accounts
this._persistTimer = setTimeout(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

_.debounce?

@@ -0,0 +1,7778 @@
export default [
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we push the dictionary as a separate library (JS and Rust?) It's already duplicated in native-signerand parity.
Will prepare a repo.


// Maps transaction requests to transaction hashes.
// This allows the locally-signed transactions to emulate the signer.
const transactionHashes = {};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is it not part of the instance? Or at least static fields if we want to share it between instances.

const middleware = this.parity
.nodeKind()
.then((nodeKind) => {
if (nodeKind.availability === 'public') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

What if nodeKind is changed during lifetime of the UI (e.g. Parity being restarted without closing tab window)?

match *provider {
Some(ref weak) => weak.upgrade().ok_or_else(Error::internal_error),
None => Err(Error {
code: ErrorCode::InvalidRequest,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I tried to use helpers::errors::codes::UNSUPPORTED_REQUEST for such stuff in the past, might be good to stay consistent with the error codes.

use ethcore::account_provider::AccountProvider;
use jsonrpc_core::{Error, ErrorCode};

pub fn unwrap_provider(provider: &Option<Weak<AccountProvider>>) -> Result<Arc<AccountProvider>, Error> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

That's pretty clever solution! :) Loving it 👍

@@ -128,6 +128,7 @@ impl Configuration {
Some(true) if pruning == Pruning::Specific(Algorithm::Archive) => writeln!(&mut stderr(), "Warning: Warp Sync is disabled because pruning mode is set to archive").expect("Error writing to stderr"),
_ => {},
};
let public_node = self.args.flag_public_node;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Public node should have only subset of APIs enabled:
eth,net,parity,rpc,web3

Some of the disabled APIs are already useless because AccountProvider is missing, but stuff like parity_stopNetwork should also be disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tomusdrw tomusdrw added A5-grumble 🔥 Pull request has minor issues that must be addressed before merging. A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. and removed A0-pleasereview 🤓 Pull request needs code review. A5-grumble 🔥 Pull request has minor issues that must be addressed before merging. labels Mar 28, 2017
Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

Just a grumble regarding nodeKind being changed during the lifetime of a website.

@gavofyork gavofyork added A7-looksgoodcantmerge 🙄 Pull request is reviewed well, but cannot be merged due to conflicts. A7-looksgoodtestsfail 🤖 Pull request is reviewed well, but cannot be merged due to tests failing. and removed A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. A7-looksgoodcantmerge 🙄 Pull request is reviewed well, but cannot be merged due to conflicts. labels Mar 29, 2017
@gavofyork
Copy link
Contributor

tests failing.

@maciejhirsz
Copy link
Contributor Author

Yeah, not sure what's up with the tests:

ERROR: Job failed (system failure): Error response from daemon: invalid header field value "oci runtime error: container_linux.go:247: starting container process caused \"process_linux.go:258: applying cgroup configuration for process caused \\\"failed to write 15099 to cgroup.procs: write /sys/fs/cgroup/cpu,cpuacct/docker/8aa02970dbeed05350837980f150e91c801cdfde378419435f2ece4eb1b7af21/cgroup.procs: invalid argument\\\"\"\n"

@tomusdrw I talked about this with Jaco, will bundle it with network change in the FE, which triggers a full reload. UX shouldn't really be an issue as that's pretty far from standard behavior.

@maciejhirsz maciejhirsz merged commit ab2c346 into master Mar 29, 2017
@maciejhirsz maciejhirsz deleted the mh-webserver branch March 29, 2017 15:48
@maciejhirsz maciejhirsz mentioned this pull request Mar 29, 2017
@tomusdrw tomusdrw mentioned this pull request May 9, 2017
4 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A7-looksgoodtestsfail 🤖 Pull request is reviewed well, but cannot be merged due to tests failing. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants