Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

swarm/hash: Custom multihash implementation #633

Merged
merged 8 commits into from
Jun 9, 2018

Conversation

nolash
Copy link
Contributor

@nolash nolash commented May 26, 2018

"fmt"
)

const (
Copy link
Member

Choose a reason for hiding this comment

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

calling this default is misleading. it is for bmt-sha3-128
not sure this should be here even

Copy link
Contributor Author

@nolash nolash May 27, 2018

Choose a reason for hiding this comment

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

I think it would be helpful if you gave me an overview of which hashing functions, one or more, will be used in the application overall.

Copy link
Member

Choose a reason for hiding this comment

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

👍 no to defaults. ideally pull this into a configuration flag

// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package swarmhash
Copy link
Member

Choose a reason for hiding this comment

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

lets not use swarm hash cos it is something else already

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But the swarmhash will be here in the end, no?

Copy link
Member

Choose a reason for hiding this comment

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

👍 please no swarmhash. use multihash or hash. in general i think that in terms of package names - either use the filename or directory name

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, we can call it something else. But hash is not good, because that's the name of a package already in use in the stack. And multihash is misleading because the package will / is indended to cover all hashing functionality in swarm.

Any other good name suggestions? hashing ? hasher?

Copy link
Member

Choose a reason for hiding this comment

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

multihash is exactly the name since it concerns a self describing hash, hence it is a multihash. or am i seeing things the wrong way?

Copy link
Contributor Author

@nolash nolash May 29, 2018

Choose a reason for hiding this comment

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

And multihash is misleading because the package will / is indended to cover all hashing functionality in swarm.

along the lines of:

hashing.Add("SHA3", SomeNewHashFunc(SHAHash)")
shinynewhash, err := hashing.Hash("foo")

Have a look at: #634

Copy link

@fjl fjl Jun 1, 2018

Choose a reason for hiding this comment

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

I vote "swarm/multihash"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fjl you would vote swarm/multihash even if it does more than just treating multihashes?

@@ -725,7 +728,14 @@ func (self *ResourceHandler) parseUpdate(chunkdata []byte) (*Signature, uint32,
var intdatalength int
var multihash bool
if datalength == 0 {
intdatalength = isMultihash(chunkdata[cursor:])
var intheaderlength int
Copy link
Member

Choose a reason for hiding this comment

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

can you please extract this to a function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why?

Copy link
Member

Choose a reason for hiding this comment

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

because it was already?

Copy link
Contributor Author

@nolash nolash May 29, 2018

Choose a reason for hiding this comment

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

sorry I read it wrong

the GetMultihashLength takes the place of the isMultihash .. that's a function..? What am I missing?

// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package swarmhash
Copy link
Member

Choose a reason for hiding this comment

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

👍 please no swarmhash. use multihash or hash. in general i think that in terms of package names - either use the filename or directory name

"fmt"
)

const (
Copy link
Member

Choose a reason for hiding this comment

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

👍 no to defaults. ideally pull this into a configuration flag

MultihashLength = defaultMultihashLength
)

func init() {
Copy link
Member

Choose a reason for hiding this comment

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

remove and replace with a constructor.

}

// check if valid swarm multihash
func isSwarmMultihashType(code uint8) bool {
Copy link
Member

Choose a reason for hiding this comment

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

as far as i know typecode 0x1b infers sha3 but does no infer swarm hash

Copy link
Contributor Author

Choose a reason for hiding this comment

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

0x1b is keccak256.

There is no "swarm hash" in mulithash (yet?)

But a swarm hash uses keccak256.

This is as close as we get for now, I think.

Copy link
Member

Choose a reason for hiding this comment

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

then for that matter swarm hash does not exist. i would get rid of as much of the multihash references as possible (except for the points where the implementation is indeed generalised) since we are just supporting 1 multihash format thus change the references to describe keccak256.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I think this all warrants further discussion. The terms are confusing.

if isMultihash(data) == 0 {
return nil, NewResourceError(ErrNothingToReturn, "Invalid multihash")
if _, _, err := swarmhash.GetMultihashLength(data); err != nil {
return nil, NewResourceError(ErrNothingToReturn, fmt.Sprintf("Invalid multihash: %v", err))
Copy link
Member

Choose a reason for hiding this comment

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

this error is not so crystal clear, why can't you just bubble the error from GetMultihashLength up?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the error texts in swarm/hash are pretty neutral, e.g "unreadable length field", not so easy to tell further up what that means.

Do you mean we should have typed error maybe?

if err != nil {
t.Fatal(err)
}
sha1bytes := make([]byte, swarmhash.MultihashLength)
Copy link
Member

Choose a reason for hiding this comment

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

are we using sha1?

if !bytes.Equal(swarmhashdecode.Digest, swarmhashbytes.Bytes()) {
t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", swarmhashdecode.Digest, swarmhashbytes.Bytes())
if !bytes.Equal(swarmhashdecode, swarmhashbytes.Bytes()) {
t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", swarmhashdecode, swarmhashbytes.Bytes())
Copy link
Member

Choose a reason for hiding this comment

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

sha1?

if !bytes.Equal(sha1decode.Digest, sha1bytes) {
t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", sha1decode.Digest, sha1bytes)
if !bytes.Equal(sha1decode, sha1bytes) {
t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", sha1decode, sha1bytes)
Copy link
Member

Choose a reason for hiding this comment

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

sha1

if !bytes.Equal(sha1decode.Digest, sha1bytes) {
t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", sha1decode.Digest, sha1bytes)
if !bytes.Equal(sha1decode, sha1bytes) {
t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", sha1decode, sha1bytes)
Copy link
Member

Choose a reason for hiding this comment

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

more of this

intdatalength, intheaderlength, err = swarmhash.GetMultihashLength(chunkdata[cursor:])
if err != nil {
log.Error("multihash parse error", "err", err)
return nil, 0, 0, "", nil, false, fmt.Errorf("Corrupt multihash data: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

no need to wrap err.

@@ -286,6 +287,7 @@ func (self *Handler) SetStore(store *storage.NetStore) {
func (self *Handler) Validate(addr storage.Address, data []byte) bool {
signature, period, version, name, parseddata, _, err := self.parseUpdate(data)
if err != nil {
log.Warn("foo", "err", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

just log.Warn(err.Error())

return nil, NewError(ErrNothingToReturn, "Invalid multihash")
// \TODO perhaps this check should be in newUpdateChunk()
if _, _, err := swarmhash.GetMultihashLength(data); err != nil {
return nil, NewError(ErrNothingToReturn, fmt.Sprintf("Invalid multihash: %v", err))
Copy link
Contributor

Choose a reason for hiding this comment

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

no need to wrap err in fmt.Sprintf - it should be clear where it is coming from and what's wrong with it.

cursor += c
hashlength, c := binary.Uvarint(data[cursor:])
if c <= 0 {
return 0, 0, fmt.Errorf("unreadable length field")
Copy link
Contributor

Choose a reason for hiding this comment

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

No format here. Just errors.New...

cursor := 0
typ, c := binary.Uvarint(data)
if c <= 0 {
return 0, 0, fmt.Errorf("unreadable hashtype field")
Copy link
Contributor

Choose a reason for hiding this comment

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

No format here.

// we cheekily assume hashlength < maxint
inthashlength := int(hashlength)
if len(data[c:]) < inthashlength {
return 0, 0, fmt.Errorf("length mismatch")
Copy link
Contributor

Choose a reason for hiding this comment

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

No format.

t.Fatalf("expected header length %d, got %d", 2, hl)
}
if _, _, err := GetMultihashLength(expected[1:]); err == nil {
t.Fatalf("expected failure on corrupt header")
Copy link
Contributor

Choose a reason for hiding this comment

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

No format.

t.Fatalf("expected failure on corrupt header")
}
if _, _, err := GetMultihashLength(expected[:len(expected)-2]); err == nil {
t.Fatalf("expected failure on short content")
Copy link
Contributor

Choose a reason for hiding this comment

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

No format.

@nolash
Copy link
Contributor Author

nolash commented Jun 6, 2018

In the spirit of the "let's just merge this as is" conclusion of yesterday's meeting I hereby submit this to another review, albeit under a new name.

swarm/api/api.go Outdated
apiGetInvalid.Inc(1)
status = http.StatusUnprocessableEntity
log.Warn(fmt.Sprintf("invalid resource multihash code: %x", decodedMultihash.Code))
log.Warn(fmt.Sprintf("invalid resource multihash: %v", err))
Copy link
Contributor

Choose a reason for hiding this comment

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

We have structured logs, no need to use fmt.Sprintf.

@nonsense
Copy link
Contributor

nonsense commented Jun 6, 2018

Linter is failing and also compilation doesn't seem to work.

Copy link
Member

@zelig zelig left a comment

Choose a reason for hiding this comment

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

if linter and travis green i am fine with this

@nolash nolash merged commit 3acc595 into swarm-network-rewrite Jun 9, 2018
@nolash nolash deleted the multihash-only branch June 9, 2018 11:48
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants