Skip to content

Use absolute addressing in HStar2#765

Merged
gdbelvin merged 12 commits intogoogle:masterfrom
gdbelvin:map_clean
Aug 4, 2017
Merged

Use absolute addressing in HStar2#765
gdbelvin merged 12 commits intogoogle:masterfrom
gdbelvin:map_clean

Conversation

@gdbelvin
Copy link
Copy Markdown
Contributor

@gdbelvin gdbelvin commented Jul 28, 2017

Secure versions of HashEmpty take the node's address into account. See #670.
This PR modifies HStar2 and its callers to use NodeIDs for absolute addressing in order to supply full paths to the hashing functions.

HStar2 Changes

HStar2 in its current form only uses subtree relative addressing.
This PR modifies the HStar2 algorithm from operating in terms of subtree height to absolute depth.

from
hStar2b(n int, values []HStar2LeafHash, offset *big.Int)
to
hStar2b(depth, maxDepth int, values []HStar2LeafHash, offset *big.Int)

And it also provides HStar2Nodes with the prefix of the subtree it is operating on.

NodeID Changes

In order to provide correct conversions to/from Hstar2LeafHash, NodeID, Prefix and Suffix the following functions are added and tested:

  • ParseSuffix
  • NodeID.BigInt
  • NewNodeIDFromBigInt
  • NewNodeIDFromPrefixSuffix

Verifier Changes

On the verification side, the verification algorithm is also modified to provide a correct path to HashEmpty.

Closes #670
Rebased on #761 and #772

@gdbelvin gdbelvin removed the WIP label Jul 28, 2017
@gdbelvin gdbelvin changed the title Map clean Use absolute addressing in HStar2 Jul 28, 2017
desc: "maphasher batch",
HashStrategy: trillian.HashStrategy_TEST_MAP_HASHER,
batchSize: 64, numBatches: 32,
batchSize: 1, numBatches: 1,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

revert

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

merkle/hstar2.go Outdated
depth := len(prefix) * 8
totalDepth := depth + subtreeDepth
if totalDepth > s.hasher.BitLen() {
return nil, ErrNegativeTreeLevelOffset
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

change error

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

merkle/hstar2.go Outdated
func(depth int, index *big.Int, hash []byte) error {
return set(treeDepth-depth, index, hash)
})
offset := new(big.Int).SetBytes(prefix)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Use NewFromPreifx

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

return h, nil
}
}
height := s.hasher.BitLen() - depth
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TODO: convert hashers back to accepting depth arguments

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

}
ret = append(ret, HStar2LeafHash{prefix, root})

index := new(big.Int).SetBytes(prefix)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Use NewNode Functions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

return
}
leaves = append(leaves, HStar2LeafHash{Index: new(big.Int).SetBytes(ih.index), LeafHash: ih.hash})
node := storage.NewNodeIDFromPrefixSuffix(ih.index, storage.Suffix{}, s.hasher.BitLen())
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

s/node/nodeID/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

nodesToStore = append(nodesToStore,
storage.Node{
NodeID: storage.NewNodeIDFromHash(bytes.Join([][]byte{s.prefix, ih.index}, []byte{})),
NodeID: storage.NewNodeIDFromHash(ih.index),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

XXX: should this be the above node?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

@Martin2112
Copy link
Copy Markdown
Contributor

Can we drop the test timeout change from the PR?

@gdbelvin
Copy link
Copy Markdown
Contributor Author

Now that we're running BatchTest as part of the integration tests on travis, we're going to need more time. We have a couple of options:

  • Set the timeout to 9 minutes, so it's less than Travis's timeout.
  • Annotate tests with short / long and only run the short tests on travis. (use the go test -short flag)
  • Increase the Travis timeout to be > 10 min.

WDYT?

@Martin2112
Copy link
Copy Markdown
Contributor

Can we get a rough breakdown of where the time is being spent? I'm reluctant to have people waiting > 10 mins for test runs but if it's necessary to ensure correctness then we might have to.

@gdbelvin
Copy link
Copy Markdown
Contributor Author

gdbelvin commented Jul 31, 2017

Here's the output of a run on my local machine (which is a bit faster than travis). It's clear that the large batch test is taking up almost all of the time. The batch test is running 32 batches of size 64 = 2048 leaves being written and read back out.

=== RUN TestInclusion
--- PASS: TestInclusion (0.11s)
=== RUN TestInclusionBatch
--- PASS: TestInclusionBatch (30.80s)
=== RUN TestNonExistentLeaf
--- PASS: TestNonExistentLeaf (0.02s)
PASS

@Martin2112
Copy link
Copy Markdown
Contributor

Do they run at this speed on Travis? I think 30 seconds isn't unreasonable. But we keep adding tests the cumulatively take a long time to run.

@gdbelvin
Copy link
Copy Markdown
Contributor Author

They run much slower on travis. I've set the timeout back to 5 minutes and set travis to only run the short version of tests.

I should note here that the full integration tests also get run without a timeout through ./integration/integration_test.sh

@gdbelvin gdbelvin force-pushed the map_clean branch 4 times, most recently from 07bb675 to 23edc87 Compare August 2, 2017 21:04
@Martin2112
Copy link
Copy Markdown
Contributor

I think this PR needs a rebase / merge now?

@gdbelvin
Copy link
Copy Markdown
Contributor Author

gdbelvin commented Aug 3, 2017

Rebased and ready for review

func ParseSuffix(s string) (Suffix, error) {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return Suffix{}, err
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does nil, err not work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

nil doesn't work here because the return argument is Suffix rather than *Suffix.
Fear not, I have more pull requests if you so desire :-)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yep, I can't wait!

leaves: []*trillian.MapLeaf{
{Index: h2b("0000000000000000000000000000000000000000000000000000000000000000"), LeafValue: []byte("A")},
{Index: h2b("0000000000000000000000000000000000000000000000000000000000000001"), LeafValue: []byte("B")},
{Index: h2b("0000000000000000000000000000000000000000000000000000000000000002"), LeafValue: []byte("C")},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How about a multi byte leaf value test, just for paranoia. Might also want to test what happens if the leaf value is empty.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The empty leaf case is both in the just merged TestLeafHistory and in TestNonexistantLeaf. I can add here as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added

b = append([]byte{0}, b...)
subtreeDepth := s.hasher.BitLen() - prefixSize
prefix := lh[i].Index.Bytes()
// ensure we've got any chopped off leading zero bytes
Copy link
Copy Markdown
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 comment is fully clear. I know it was there before but how about "left pad prefix with any zero bytes that were previously removed".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

want []byte
}{
{h2b(""), 1, h2b("0801")},
{h2b("00"), 1, h2b("0801")},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not testing any invalid cases?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added

@gdbelvin
Copy link
Copy Markdown
Contributor Author

gdbelvin commented Aug 4, 2017

PTAL

@gdbelvin gdbelvin merged commit 0ef00b0 into google:master Aug 4, 2017
@gdbelvin gdbelvin deleted the map_clean branch August 4, 2017 12:31
@gdbelvin gdbelvin mentioned this pull request Aug 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Map: CONIKS map hasher

3 participants