ipfs / kubo

An IPFS implementation in Go
https://docs.ipfs.tech/how-to/command-line-quick-start/
Other
16.15k stars 3.01k forks source link

ipfs object stat should print out the hash #1082

Closed whyrusleeping closed 8 years ago

whyrusleeping commented 9 years ago

it would provide an easy way to find the hash of a path:

ipfs object stat <hash>/a/b/c/d

Should tell us what the hash of 'd' is.

Alternatively (or additionally) we could have an ipfs resolve command that outputs the hash that a path resolves to.

wking commented 9 years ago

On Tue, Apr 14, 2015 at 02:11:47PM -0700, Jeromy Johnson wrote:

ipfs object stat /a/b/c/d

Alternatively (or additionally) we could have an ipfs resolve command that outputs the hash that a path resolves to.

I'm leaning toward ‘ipfs resolve’, since ‘ipfs object --help’ says:

'ipfs object' is a plumbing command used to manipulate DAG objects directly.

and “what's the hash for ?” sounds more important than plumbing (e.g. it's also useful for finding hashes to publish). How about just making ‘ipfs name resolve’ flexible enough to handle IPFS and IPNS keys and paths? For consistency with the dnslink syntax, I'd like to change the default namespace to /ipfs/ (1,2,3,4,5). Looking at that code, I'm actually not sure how /ipns/… paths are resolved :p.

Anyway, is changing the default namespace for ‘ipfs name resolve’ too invasive? I'd suggest a transition period for finger-breaking and script updates like:

This is basically the the same approach taken by Git when they adjusted their default add semantics in 2.0 (6,7,8,9).

1: https://github.com/ipfs/go-ipfs/pull/1093#issuecomment-94256919 2: https://github.com/ipfs/go-ipfs/blob/9a5bb52fcd247f8d6789290680469029b70d7a34/namesys/dns.go#L60 3: https://github.com/ipfs/go-ipfs/blob/9a5bb52fcd247f8d6789290680469029b70d7a34/path/path.go#L58 4: https://github.com/ipfs/go-ipfs/blob/9a5bb52fcd247f8d6789290680469029b70d7a34/path/path.go#L93 5: https://github.com/ipfs/go-ipfs/blob/9a5bb52fcd247f8d6789290680469029b70d7a34/path/path.go#L28 6: http://thread.gmane.org/gmane.comp.version-control.git/213988/focus=214107 7: http://git.kernel.org/cgit/git/git.git/tree/Documentation/RelNotes/1.8.3.txt?id=v2.4.0#n19 8: http://git.kernel.org/cgit/git/git.git/tree/Documentation/RelNotes/1.9.0.txt?id=v2.4.0#n52 9: http://git.kernel.org/cgit/git/git.git/tree/Documentation/RelNotes/2.0.0.txt?id=v2.4.0#n25

wking commented 9 years ago

On Mon, May 04, 2015 at 09:23:07PM -0700, W. Trevor King wrote:

On Tue, Apr 14, 2015 at 02:11:47PM -0700, Jeromy Johnson wrote:

ipfs object stat /a/b/c/d

Alternatively (or additionally) we could have an ipfs resolve command that outputs the hash that a path resolves to.

I'm leaning toward ‘ipfs resolve’, since ‘ipfs object --help’ says:

'ipfs object' is a plumbing command used to manipulate DAG objects directly.

and “what's the hash for ?” sounds more important than plumbing (e.g. it's also useful for finding hashes to publish). How about just making ‘ipfs name resolve’ flexible enough to handle IPFS and IPNS keys and paths?

Talking about this with @jbenet and @whyrusleeping on IRC 1, it's clear that @jbenet doesn't want 2:

$ ipfs name resolve <*-or-ipfs-path>

If the goal is to keep the IPFS and IPNS portions as separate as possible (a worthy goal), I'd recommend we keep:

$ ipfs name resolve [--recursive] []

for (recursive) IPNS lookups and then use:

$ ipfs resolve

for just the IPFS portion. That means:

$ ipfs resolve /ipns/

would error out and you'd have to use:

$ ipfs resolve $(ipfs name resolve --recursive )

that draws a good line between IPFS and IPNS, but it does mean you'd have to do some hoop-jumping to handle paths that go back and forth between the two worlds. For example, ifyou have a certificate-authority vouching for the example.net ↔ QmExampleKey association, and the example.net folks are linking to ae.io asset, you could start with an IP*S path like:

/ipns/some.ca/example.net/static/ae.io/css/beautiful.css

Resolving that with disjoint dns/IPFS/IPNS tooling would look like:

$ ipfs dns resolve some.ca /ipns/QmSomeCAKey $ ipfs name resolve --recursive QmSomeCAKey /ipfs/QmCurrentCARoot $ ipfs resolve /ipfs/QmCurrentCARoot/example.net/static/ae.io/css/beautiful.css /ipns/QmExampleKey/static/ae.io/css/beautiful.css $ ipfs name resolve --recursive /ipns/QmExampleKey /ipfs/QmExampleRoot $ ipfs resolve /ipfs/QmExampleRoot/static/ae.io/css/beautiful.css /ipns/QmAEIOKey/css/beautiful.css $ ipfs name resolve --recursive QmAEIOKey /ipfs/QmAEIORoot $ ipfs resolve /ipfs/QmAEOIRoot/css/beautiful.css QmBeautifulCSS

You could write a shell script to handle that automatically, although I'm not sure how we currently decide what gets a DNS lookup in /ipns/. Is it “everything that's not a valid multihash goes through DNS”?

I'm also not clear on whether the tightly focused resolution here is worth the trouble. I agree that it's good to distinguish between IPFS, IPNS, and DNS lookups within the library, but invoking a new process for every IPFS ↔ IPNS crossing seems pretty heavy. Still, that sounds like the interface @jbenet is asking for.

In this version of the future, we don't need to migrate the ‘ipfs name resolve’ argument (yay!) but I would like an optional --recursive option to control whether we just make a single IPNS resolution or keep going until we get a non-IPNS reference back. I'd also like to adjust the output of the command to return the prefixed-reference (currently just /ipfs/…) but that would allow forward-compatibility for doing things like storing a /dnslink/ae.io reference in IPNS (or pointing out to some other protocol).

jbenet commented 9 years ago

I think we should have:

# ipfs only resolution
# `ipfs object` planned to be renamed `ipfs dag`
ipfs dag resolve <ipfs-path>

# ipns only resolution
ipfs name resolve <ipns-path>

# porcelain combining the others
ipfs resolve <ipfs-or-ipns-path>

which i think covers your concerns.

ipfs dns resolve <dns>

:+1: to this. having dns inside ipns is a convenience hack, but we should also have this.

We should publish it as a standalone tool too.

(need to make the cmds lib less of a mess for this to be easy)

but invoking a new process for every IPFS ↔ IPNS crossing seems pretty heavy.

don't have to, with ipfs resolve resolving for all.

not meaning to force things to be in multiple processes (i'd prefer not, given the state of kernel process costs), but to make the toolchain very granular so users can take + hack only the parts they need.

--recursive

Agreed, this is needed.

I'd also like to adjust the output of the command to return the prefixed-reference (currently just /ipfs/…) but that would allow forward-compatibility for doing things like storing a /dnslink/ae.io reference in IPNS (or pointing out to some other protocol).

More concrete example?

wking commented 9 years ago

On Wed, May 06, 2015 at 03:56:18AM -0700, Juan Batiz-Benet wrote:

porcelain combining the others

ipfs resolve

but invoking a new process for every IPFS ↔ IPNS crossing seems pretty heavy.

don't have to, with ipfs resolve resolving for all.

So my concern here is that if you compile a porcelain ‘ipfs resolve …’, then folks who want to slot in an alternative IPFS/IPNS/DNS/… resolver will need to have match some Go API and recompile the porcelain to get it to use their replacement. While if the porcelain is a shell script (or some other tool using the PATH to invoke child processes) adjusting the porcelain to use your preferred resolver just means dropping your preferred resolver into the PATH. Or do you have some slick way around that problem that doesn't involve parallel compiled and shell-script versions of ‘ipfs resolve’?

I'd also like to adjust the output of the command to return the prefixed-reference (currently just /ipfs/…) but that would allow forward-compatibility for doing things like storing a /dnslink/ae.io reference in IPNS (or pointing out to some other protocol).

More concrete example?

You could have multi-step IPNS references:

$ ipfs name resolve QmKey1 /ipns/QmKey2 $ ipfs name resolve QmKey2 /ipfs/QmObject

which you could resolve with --recursive:

$ ipfs name resolve --recursive QmKey1 /ipfs/QmObject

And once you sprinkle in DNS links, you could have:

$ ipfs name resolve QmKey1 /ipns/QmKey2 $ ipfs name resolve QmKey2 /dnslink/example.com $ ipfs dns resolve example.com /ipns/QmKey3 $ ipfs name resolve QmKey3 /ipfs/QmObject

Without the prefix, if you do a non-recursive:

$ ipfs name resolve QmKey1 QmKey2

(vs. /ipns/QmKey2), there's no way to decide the protocol. Is that a DNS domain? IPFS ID? IPNS key? Parsing the syntax until you find something that matches (“no periods, so it's probably not a DNS link. Parses as a multihash, so I guess I'll just hit IPNS and see if it resolves as a key…”). I think it's a lot more straightforward to just provide the intended protocol with the result:

$ ipfs name resolve QmKey1 /ipns/QmKey2

So you can say, “Ah, it starts with ‘/ipns/’. I bet the next segment is an IPNS key.”

The current interface mostly works because (1) we always do recursive IPNS resolution, and (2) the only other supported IPNS-referenced protocol is IPFS. So you know the key you get back is going to be IPFS. But I don't think either of those constraints are things we want to saddle ourselves with long-term.

jbenet commented 9 years ago

@wking small note: github doesn't like the inlined emails. it hides them under [...]. i think most people will miss your comments. maybe copy over the quoted section to the top? see


I think it's a lot more straightforward to just provide the intended protocol with the result:

Yeah i agree. which is why ipns should take pat as a value (including the prefix).

> ipfs name resolve <ipns-path>
<path>

> ipfs name resolve /ipns/QmSomeIPNSKey1
/ipns/QmSomeIPNSKey2
> ipfs name resolve /ipns/QmSomeIPNSKey2
/ipfs/QmSomeIPFSKey
wking commented 9 years ago

On Wed, May 06, 2015 at 03:47:09PM -0700, Juan Batiz-Benet wrote:

small note: github doesn't like the inlined emails…

They don't like PGP/MIME email either, and they occasionally drop my emailed comments completely because of that (at least, that's what the GitHub folks I talk to blame for occasionally dropping my emailed comments). Still, it works most of the time, and like inline comments, it's just so useful… ;)

… maybe copy over the quoted section to the top?

Top-posting makes it hard to figure out what I'm responding to though.

I think it's a lot more straightforward to just provide the intended protocol with the result:

Yeah i agree. which is why ipns should take pat as a value (including the prefix).

> ipfs name resolve <ipns-path>
<path>

> ipfs name resolve /ipns/QmSomeIPNSKey1
/ipns/QmSomeIPNSKey2
> ipfs name resolve /ipns/QmSomeIPNSKey2
/ipfs/QmSomeIPFSKey

Ok, the output from those I agree with. But if ‘ipfs name resolve …’ only works with IPNS keys I see no need for the namespaced argument. On the other hand, I'm fine supporting both:

$ ipfs name resolve /ipns/QmSomeIPNSKey1 $ ipfs name resolve QmSomeIPNSKey1

whyrusleeping commented 8 years ago

ipfs block stat shows the resolved hash, thats good enough for me