diff --git a/swarm/storage/resource.go b/swarm/storage/resource.go index 73efb08b5f..77942a0ccb 100644 --- a/swarm/storage/resource.go +++ b/swarm/storage/resource.go @@ -537,6 +537,7 @@ func (self *ResourceHandler) parseUpdate(chunkdata []byte) (*Signature, uint32, intdatalength = isMultihash(chunkdata[cursor:]) multihashboundary := cursor + intdatalength if len(chunkdata) != multihashboundary && len(chunkdata) < multihashboundary+signatureLength { + log.Debug("multihash error", "chunkdatalen", len(chunkdata), "multihashboundary", multihashboundary) return nil, 0, 0, "", nil, errors.New("Corrupt multihash data") } } else { @@ -768,7 +769,7 @@ func newUpdateChunk(key Key, signature *Signature, period uint32, version uint32 // if signature is present it's the last item in the chunk data if signature != nil { - cursor += datalength + cursor += actualdatalength copy(chunk.SData[cursor:], signature[:]) } diff --git a/swarm/storage/resource_test.go b/swarm/storage/resource_test.go index ef03154f06..911ad1ed90 100644 --- a/swarm/storage/resource_test.go +++ b/swarm/storage/resource_test.go @@ -264,6 +264,133 @@ func TestResourceHandler(t *testing.T) { } +func TestResourceMultihash(t *testing.T) { + + // signer containing private key + signer, err := newTestSigner() + if err != nil { + t.Fatal(err) + } + validator := newTestValidator(signer.signContent) + + // make fake backend, set up rpc and create resourcehandler + backend := &fakeBackend{ + blocknumber: int64(startBlock), + } + + // set up rpc and create resourcehandler + rh, datadir, _, teardownTest, err := setupTest(backend, nil) + if err != nil { + t.Fatal(err) + } + defer teardownTest() + + // create a new resource + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + _, err = rh.NewResource(ctx, safeName, resourceFrequency) + if err != nil { + t.Fatal(err) + } + + // we're naïvely assuming keccak256 for swarm hashes + // if it ever changes this test should also change + swarmhashbytes := rh.nameHash("foo") + swarmhashmulti, err := multihash.Encode(swarmhashbytes.Bytes(), multihash.KECCAK_256) + if err != nil { + t.Fatal(err) + } + swarmhashkey, err := rh.UpdateMultihash(ctx, safeName, swarmhashmulti) + if err != nil { + t.Fatal(err) + } + + sha1bytes := make([]byte, multihash.DefaultLengths[multihash.SHA1]) + sha1multi, err := multihash.Encode(sha1bytes, multihash.SHA1) + if err != nil { + t.Fatal(err) + } + sha1key, err := rh.UpdateMultihash(ctx, safeName, sha1multi) + if err != nil { + t.Fatal(err) + } + + // invalid multihashes + _, err = rh.UpdateMultihash(ctx, safeName, swarmhashmulti[1:]) + if err == nil { + t.Fatalf("Expected update to fail with first byte skipped") + } + _, err = rh.UpdateMultihash(ctx, safeName, swarmhashmulti[:len(swarmhashmulti)-2]) + if err == nil { + t.Fatalf("Expected update to fail with last byte skipped") + } + + data, err := getUpdateDirect(rh, swarmhashkey) + if err != nil { + t.Fatal(err) + } + swarmhashdecode, err := multihash.Decode(data) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(swarmhashdecode.Digest, swarmhashbytes.Bytes()) { + t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", swarmhashdecode.Digest, swarmhashbytes.Bytes()) + } + data, err = getUpdateDirect(rh, sha1key) + if err != nil { + t.Fatal(err) + } + sha1decode, err := multihash.Decode(data) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(sha1decode.Digest, sha1bytes) { + t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", sha1decode.Digest, sha1bytes) + } + rh.Close() + + // test with signed data + rh2, err := NewResourceHandler(datadir, &testCloudStore{}, rh.ethClient, validator) + if err != nil { + t.Fatal(err) + } + _, err = rh2.NewResource(ctx, safeName, resourceFrequency) + if err != nil { + t.Fatal(err) + } + swarmhashsignedkey, err := rh2.UpdateMultihash(ctx, safeName, swarmhashmulti) + if err != nil { + t.Fatal(err) + } + sha1signedkey, err := rh2.UpdateMultihash(ctx, safeName, sha1multi) + if err != nil { + t.Fatal(err) + } + + data, err = getUpdateDirect(rh2, swarmhashsignedkey) + if err != nil { + t.Fatal(err) + } + swarmhashdecode, err = multihash.Decode(data) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(swarmhashdecode.Digest, swarmhashbytes.Bytes()) { + t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", swarmhashdecode.Digest, swarmhashbytes.Bytes()) + } + data, err = getUpdateDirect(rh2, sha1signedkey) + if err != nil { + t.Fatal(err) + } + sha1decode, err = multihash.Decode(data) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(sha1decode.Digest, sha1bytes) { + t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", sha1decode.Digest, sha1bytes) + } +} + // create ENS enabled resource update, with and without valid owner func TestResourceENSOwner(t *testing.T) { @@ -459,98 +586,14 @@ func (self *testValidator) nameHash(name string) common.Hash { return self.hashFunc(name) } -func TestResourceMultihash(t *testing.T) { - - // signer containing private key - // signer, err := newTestSigner() - // if err != nil { - // t.Fatal(err) - // } - - // make fake backend, set up rpc and create resourcehandler - backend := &fakeBackend{ - blocknumber: int64(startBlock), - } - - // set up rpc and create resourcehandler - rh, _, _, teardownTest, err := setupTest(backend, nil) +func getUpdateDirect(rh *ResourceHandler, key Key) ([]byte, error) { + chunk, err := rh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(key) if err != nil { - t.Fatal(err) + return nil, err } - defer teardownTest() - - // create a new resource - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - _, err = rh.NewResource(ctx, safeName, resourceFrequency) + _, _, _, _, data, err := rh.parseUpdate(chunk.SData) if err != nil { - t.Fatal(err) + return nil, err } - - // we're naïvely assuming keccak256 for swarm hashes - // if it ever changes this test should also change - swarmhashbytes := rh.nameHash("foo") - swarmhashmulti, err := multihash.Encode(swarmhashbytes.Bytes(), multihash.KECCAK_256) - if err != nil { - t.Fatal(err) - } - swarmhashkey, err := rh.UpdateMultihash(ctx, safeName, swarmhashmulti) - if err != nil { - t.Fatal(err) - } - - sha1bytes := make([]byte, multihash.DefaultLengths[multihash.SHA1]) - sha1multi, err := multihash.Encode(sha1bytes, multihash.SHA1) - if err != nil { - t.Fatal(err) - } - sha1key, err := rh.UpdateMultihash(ctx, safeName, sha1multi) - if err != nil { - t.Fatal(err) - } - - // invalid multihashes - _, err = rh.UpdateMultihash(ctx, safeName, swarmhashmulti[1:]) - if err == nil { - t.Fatalf("Expected update to fail with first byte skipped") - } - _, err = rh.UpdateMultihash(ctx, safeName, swarmhashmulti[:len(swarmhashmulti)-2]) - if err == nil { - t.Fatalf("Expected update to fail with last byte skipped") - } - - swarmhashchunk, err := rh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(swarmhashkey) - if err != nil { - t.Fatal(err) - } - _, _, _, _, data, err := rh.parseUpdate(swarmhashchunk.SData) - if err != nil { - t.Fatal(err) - } - swarmhashdecode, err := multihash.Decode(data) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(swarmhashdecode.Digest, swarmhashbytes.Bytes()) { - t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", swarmhashdecode.Digest, swarmhashbytes.Bytes()) - } - sha1chunk, err := rh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(sha1key) - if err != nil { - t.Fatal(err) - } - _, _, _, _, data, err = rh.parseUpdate(sha1chunk.SData) - if err != nil { - t.Fatal(err) - } - sha1decode, err := multihash.Decode(data) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(sha1decode.Digest, sha1bytes) { - t.Fatalf("Decoded SHA1 hash '%x' does not match original hash '%x'", sha1decode.Digest, sha1bytes) - } - - // test with signed data - // rh2, err := NewResourceHandler(datadir, &testCloudStore{}, rh.ethClient, Signer) - // swarmhashsignedkey, err := rh2.UpdateMultihash(ctx, safeName, swarmhashmulti) + return data, nil }