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

IPFS MVP #4545

Merged
merged 11 commits into from
Feb 17, 2017
Merged

IPFS MVP #4545

merged 11 commits into from
Feb 17, 2017

Conversation

maciejhirsz
Copy link
Contributor

Listening on port 5001 for IPFS-compatible calls as listed in #4172, supported thus far:

  • eth-block
  • eth-block-list
  • eth-tx
  • eth-state-trie

@maciejhirsz maciejhirsz added A0-pleasereview 🤓 Pull request needs code review. M4-core ⛓ Core client code / Rust. labels Feb 14, 2017
@NikVolf
Copy link
Contributor

NikVolf commented Feb 14, 2017

no tests ;)

@NikVolf NikVolf added A4-gotissues 💥 Pull request is reviewed and has significant issues which must be addressed. and removed A0-pleasereview 🤓 Pull request needs code review. labels Feb 14, 2017

#[test]
fn test_get_param() {
let query = "foo=100&bar=200&qux=300";
Copy link
Contributor

Choose a reason for hiding this comment

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

can't it be encoded like
foo%20bar=200?

Copy link
Contributor

Choose a reason for hiding this comment

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

indentation on #[test] seen here is also wrong

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@NikVolf I've switched the function to be private, so that it can only be consumed within the module.

I think that as long as the consumer is aware that no URL encoding or decoding is performed it should be quite fine. It's unlikely that this crate will ever have a need for URL-encoded query strings by the virtue of all things IPFS going through multibase, specifically base58btc. Even if it ever does, it shouldn't be difficult to replace this by an external crate that can do it.

ipfs/src/lib.rs Outdated

res.headers_mut().set(ContentLength(reason.len() as u64));
res.headers_mut().set(ContentType("text/plain".parse()
.expect("Static content type; qed")));
Copy link
Contributor

Choose a reason for hiding this comment

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

i don't think that any request handling that can be triggered by arbitrary third party should ever contain expect or unwrap

Copy link
Contributor

@NikVolf NikVolf Feb 14, 2017

Choose a reason for hiding this comment

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

But yeah... that's surely cant fail

Still there should be test that triggers this execution path (implementation of the ContentType::from_str can change and the test should catch it)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can change that to use a macro for mime types.

parity/run.rs Outdated
@@ -420,6 +421,10 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
};
let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?;


Copy link
Contributor

Choose a reason for hiding this comment

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

redundant empty line

ipfs/src/lib.rs Outdated

listening
})
.map_err(Into::into)
Copy link
Contributor

@NikVolf NikVolf Feb 14, 2017

Choose a reason for hiding this comment

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

with the introduction of Carrier maybe construction a-la

Ok(
	hyper::Server::http(&addr)?
		.handle(move |_| IpfsHandler::new(client.clone()))
		.map(|(listening, srv)| {
			::std::thread::spawn(move || {
				srv.run();
			});

			listening
		})?
)

is better?

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.

Couple of grumbles.

ipfs/src/lib.rs Outdated
match *self.out() {
OctetStream(ref bytes) => {
// Nothing to do here
let _ = transport.write(&bytes);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Write might not succeed in a single attempt. It will return how many bytes were written, you should keep a pointer and write the rest in next invocation of the handler.

ipfs/src/lib.rs Outdated
},
NotFound(reason) | Bad(reason) => {
// Nothing to do here
let _ = transport.write(reason.as_bytes());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above.

let block_id = BlockId::Hash(hash);
let block = self.client.block_header(block_id).ok_or(Error::BlockNotFound)?;

self.out = Out::OctetStream(block.into_inner());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not return Out instead? Methods wouldn't have to be &mut and assignment would happen in a single place.

}
}

fn get_block(&mut self, hash: H256) -> Result<()> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

get_ prefix is not necessary in all methods.

ipfs/src/lib.rs Outdated

impl Handler<HttpStream> for IpfsHandler {
fn on_request(&mut self, req: Request<HttpStream>) -> Next {
if *req.method() != Method::Get {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we know from what context this server will be used?

Currently any website can access this API and trigger arbitrary load on the node, might be worth to limit access somehow, or disallow Origin header if it's not mean to be read by websites.

let tx_id = TransactionId::Hash(hash);
let tx = self.client.transaction(tx_id).ok_or(Error::TransactionNotFound)?;

self.out = Out::OctetStream(rlp::encode(tx.deref()).to_vec());
Copy link
Collaborator

Choose a reason for hiding this comment

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

tx.deref() -> &*tx

/// Get a query parameter's value by name.
pub fn get_param<'a>(query: &'a str, name: &str) -> Option<&'a str> {
query.split('&')
.find(|part| part.starts_with(name) && part[name.len()..].starts_with("="))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Will panic when part == name, no?

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 no, it will create an empty slice and starts_with can't panic. I added a test for it now just in case.

Err(err) => {
self.out = err.into();

Next::write()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems like Next::write() is the only result of this function, maybe it's possible to use and_then instead of conditionals?

@arkpar
Copy link
Collaborator

arkpar commented Feb 15, 2017

There should also be a CLI option disabling the server. I also suggest it should be disabled by default as most people don't really need this and it only increases attack surface.

@rphmeier
Copy link
Contributor

Agreed, the overhead of starting up the server here shouldn't be incurred unless in-use (and AFAIK Metamask will be the one user of this feature)

ipfs/Cargo.toml Outdated
ethcore-util = { path = "../util" }
rlp = { path = "../util/rlp" }
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
cid = "~0.2.0"
Copy link
Contributor

Choose a reason for hiding this comment

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

i believe we use like cid = "0.2" everywhere which is almost equivalent to cid = "~0.2.0" ?

@maciejhirsz
Copy link
Contributor Author

maciejhirsz commented Feb 15, 2017

Think I got most of the grumbles so far, TODO:

  • CLI switch, disabled by default.
  • Origin header checking.

@maciejhirsz maciejhirsz added A0-pleasereview 🤓 Pull request needs code review. and removed A4-gotissues 💥 Pull request is reviewed and has significant issues which must be addressed. labels Feb 16, 2017
This is done by requests sending CID with raw binary codec (0x55).
Note: this functionality is exactly the same as fetching state-trie
due to how db internals work in Parity atm.
@NikVolf
Copy link
Contributor

NikVolf commented Feb 16, 2017

looks cool to me
other guys have to look also

@arkpar arkpar added A8-looksgood 🦄 Pull request is reviewed well. and removed A0-pleasereview 🤓 Pull request needs code review. labels Feb 17, 2017
@rphmeier rphmeier merged commit 39237e9 into master Feb 17, 2017
@rphmeier rphmeier deleted the mh-ipfs branch February 17, 2017 16:20
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A8-looksgood 🦄 Pull request is reviewed well. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants