Skip to content

Commit

Permalink
wip/saving work: refactorings for TC-2
Browse files Browse the repository at this point in the history
  • Loading branch information
gnahraf committed Apr 15, 2024
1 parent 951b02e commit 461467c
Show file tree
Hide file tree
Showing 17 changed files with 1,132 additions and 81 deletions.
2 changes: 1 addition & 1 deletion mrsl/src/main/java/io/crums/sldg/cli/mrsl/Mrsl.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import io.crums.model.CrumTrail;
import io.crums.sldg.ByteFormatException;
import io.crums.sldg.HashConflictException;
import io.crums.sldg.bags.RowBag;
import io.crums.sldg.RowBag;
import io.crums.sldg.json.MorselDumpWriter;
import io.crums.sldg.json.SourceInfoParser;
import io.crums.sldg.json.SourceRowParser;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
/*
* Copyright 2021 Babak Farhang
*/
package io.crums.sldg.bags;
package io.crums.sldg;

import java.nio.ByteBuffer;
import java.util.Objects;

import io.crums.sldg.Path;
import io.crums.sldg.Row;
import io.crums.sldg.SkipLedger;

/**
* Row backed by data in a {@linkplain RowBag}. This is a departure
* (loosening up) from previous guarantees. Oh well, it's convenient,
* plus other classes like {@linkplain Path} validate data on construction,
* besides.
* Row backed by data in a {@linkplain RowBag}.
* Note the base implementation computes the row's hash
* from the input hash and previous rows' hashes.
* It does not memo-ise the result.
*/
public class BaggedRow extends Row {

Expand Down
118 changes: 118 additions & 0 deletions skipledger-base/src/main/java/io/crums/sldg/MemoPathPack.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2024 Babak Farhang
*/
package io.crums.sldg;

import java.nio.ByteBuffer;
import java.util.Collections;

import io.crums.io.buffer.BufferUtils;

/**
* Speeds up look-ups in a {@code PathPack} by
* memo-ising the hashes of full row numbers.
*/
public class MemoPathPack extends PathPack {

private ByteBuffer memoedHashes;

/**
* Constructs a memo-ised version of the given pack.
*
* @param promo
*/
public MemoPathPack(PathPack promo) {
super(promo);
var inputRns = getFullRowNumbers();
if (inputRns.isEmpty()) {
this.memoedHashes = BufferUtils.NULL_BUFFER;
return;
}
this.memoedHashes = ByteBuffer.allocate(inputRns.size());

var view = memoedHashes.slice();
final int count = inputRns.size();
// compute the hash of each memo-ed row
// using a BaggedRow.hash() taking *this*
// instance as the RowBag. It doesn't run
// into to trouble since we write it from
// the bottom no.s up: the BaggedRow never
// accesses what's not already written as
// we build it.
for (int index = 0; index < count; ++index) {
long rn = inputRns.get(index);
var hash = new BaggedRow(rn, this).hash();
view.put(hash);
}
assert !view.hasRemaining();
}



@Override
public Row getRow(long rowNumber) {

int index = Collections.binarySearch(
getFullRowNumbers(), rowNumber);
if (index < 0)
throw new IllegalArgumentException(
"row " + rowNumber + " is not in pack");

return new MemoRow(rowNumber, index);
}



@Override
public ByteBuffer rowHash(long rowNumber) {
if (rowNumber <= 0) {
if (rowNumber == 0)
return SldgConstants.DIGEST.sentinelHash();

throw new IllegalArgumentException(
"negative row number: " + rowNumber);
}

ByteBuffer refOnlyHash = refOnlyHash(rowNumber);
if (refOnlyHash != null)
return refOnlyHash;

return getMemoedRowHash(rowNumber);
}





private ByteBuffer getMemoedRowHash(long rn) {
int index = Collections.binarySearch(
getFullRowNumbers(), rn);
if (index < 0)
throw new IllegalArgumentException(
"row " + rn + " is not in pack");
return memoedHash(index);
}


private ByteBuffer memoedHash(int index) {
return emit(memoedHashes, index);
}


private class MemoRow extends BaggedRow {

private final int index;

MemoRow(long rn, int index) {
super(rn, MemoPathPack.this);
this.index = index;
}

@Override
public ByteBuffer hash() {
return memoedHash(index);
}

}

}
127 changes: 81 additions & 46 deletions skipledger-base/src/main/java/io/crums/sldg/Path.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@


import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -45,7 +44,7 @@
* Serialization footprint, maybe; clock-cycles NO(!).
* </p>
*/
public class Path implements Digest {
public class Path /* implements Digest */ {


/**
Expand All @@ -64,7 +63,7 @@ public Path(List<Row> path) throws IllegalArgumentException, HashConflictExcepti



Path(List<Row> path, boolean copy) {
public Path(List<Row> path, boolean copy) {

if (Objects.requireNonNull(path, "null path").isEmpty())
throw new IllegalArgumentException("empth path");
Expand All @@ -83,6 +82,9 @@ else if (path.size() > MAX_ROWS)
}


Path(List<Row> rows, Object trustMe) {
this.rows = Objects.requireNonNull(rows);
}



Expand All @@ -93,18 +95,18 @@ protected Path(Path copy) {
this.rows = Objects.requireNonNull(copy, "null copy").rows;
}


// D I G E S T M E T H O D S

@Override
public final int hashWidth() {
return rows.get(0).hashWidth();
}

@Override
public final String hashAlgo() {
return rows.get(0).hashAlgo();
}
//
// // D I G E S T M E T H O D S
//
// @Override
// public final int hashWidth() {
// return rows.get(0).hashWidth();
// }
//
// @Override
// public final String hashAlgo() {
// return rows.get(0).hashAlgo();
// }



Expand Down Expand Up @@ -197,10 +199,30 @@ public final List<Long> rowNumbers() {
/**
* Determines if this path has a (full) row with this row-number (not just a reference to it).
*/
public final boolean hasRow(long rowNumber) {
public boolean hasRow(long rowNumber) {
return Collections.binarySearch(rowNumbers(), rowNumber) >= 0;
}



public boolean hasRowCovered(long rowNumber) {
int searchIndex = Collections.binarySearch(rowNumbers(), rowNumber);
if (searchIndex >= 0)
return true;
searchIndex = -1 - searchIndex;
if (searchIndex == rows.size())
return false;
Row candidateRef = rows.get(searchIndex);
final int levels = candidateRef.prevLevels();
for (int level = 0; level < levels; ++level) {
long refRn = candidateRef.prevRowNumber(level);
if (refRn > rowNumber)
continue;
return refRn == rowNumber;
}
return false;
}


/**
* Returns all the row numbers referenced in this path. This collection includes
Expand All @@ -212,10 +234,11 @@ public final boolean hasRow(long rowNumber) {
*
* @see #getRowHash(long)
*/
public final SortedSet<Long> rowNumbersCovered() {
public SortedSet<Long> rowNumbersCovered() {
return SkipLedger.coverage(rowNumbers());
}


/**
* Returns the hash of the row with the given <code>rowNumber</code>. This is not
* just a convenience for getting the {@linkplain Row#hash() hash} of one of the
Expand All @@ -226,10 +249,10 @@ public final SortedSet<Long> rowNumbersCovered() {
* @throws IllegalArgumentException if <code>rowNumber</code> is not a member of the
* set returned by {@linkplain #rowNumbersCovered()}
*/
public final ByteBuffer getRowHash(long rowNumber) throws IllegalArgumentException {
public ByteBuffer getRowHash(long rowNumber) throws IllegalArgumentException {
return
rowNumber == 0 ?
sentinelHash() :
SldgConstants.DIGEST.sentinelHash() :
getRowOrReferringRow(rowNumber).hash(rowNumber);
}

Expand All @@ -244,7 +267,7 @@ public Row getRowByNumber(long rowNumber) throws IllegalArgumentException {
if (index < 0)
throw new IllegalArgumentException("no such row [" + rowNumber + "]");

return rows().get(index);
return rows.get(index);
}


Expand All @@ -262,7 +285,7 @@ public Row getRowByNumber(long rowNumber) throws IllegalArgumentException {
*
* @see #getRowHash(long)
*/
public final Row getRowOrReferringRow(long rowNumber) throws IllegalArgumentException {
public Row getRowOrReferringRow(long rowNumber) throws IllegalArgumentException {

final List<Long> rowNumbers = rowNumbers();
{
Expand All @@ -271,28 +294,16 @@ public final Row getRowOrReferringRow(long rowNumber) throws IllegalArgumentExce
if (index >= 0)
return rows().get(index);

else if (-1 - index == rowNumbers.size())
index = -1 - index;
if (index == rowNumbers.size())
throw new IllegalArgumentException("rowNumber " + rowNumber + " not covered");
}

final int pointerLevels = SkipLedger.skipCount(rowNumber);

for (int exp = 0; exp < pointerLevels; ++exp) {

long referrerNum = rowNumber + (1L << exp);
int index = Collections.binarySearch(rowNumbers, referrerNum);

if (index >= 0) {
Row row = rows.get(index);
assert row.prevLevels() > exp;
return row;

} else if (-1 - index == rowNumbers.size())
break;
Row row = rows.get(index);
if (SkipLedger.rowsLinked(rowNumber, row.rowNumber()))
throw new IllegalArgumentException("rowNumber " + rowNumber + " not covered");
return row;
}


throw new IllegalArgumentException("rowNumber " + rowNumber + " not covered");
}


Expand All @@ -302,11 +313,35 @@ else if (-1 - index == rowNumbers.size())



/**
* Instances are equal if they have the same rows. This only needs
* to verify 2 paths have the same row numbers and that the
* hash of their <em>last</em> rows are the same.
*/
@Override
public final boolean equals(Object o) {
return
o == this ||
o instanceof Path other
&& rows.size() == other.rows.size()
&& loRowNumber() == other.loRowNumber()
&& last().equals(other.last())
// this last check is also necessary
&& rowNumbers().equals(other.rowNumbers());
}





/**
* Consistent with {@link #equals(Object)}.
*/
@Override
public final int hashCode() {
long lhash = hiRowNumber();
lhash = lhash * 255 + rows.size();
int cryptFuzz = last().hash().limit(16).hashCode();
return Long.hashCode(lhash) ^ cryptFuzz;
}



Expand All @@ -327,7 +362,7 @@ else if (-1 - index == rowNumbers.size())

private void verify() {

MessageDigest digest = rows.get(0).newDigest();
var digest = SldgConstants.DIGEST.newDigest();

// artifact of deciding to reverse the order of the displayed rows
List<Row> rpath = Lists.reverse(this.rows);
Expand All @@ -336,10 +371,10 @@ private void verify() {
Row row = rpath.get(index);
Row prev = rpath.get(index + 1);

if (!Digest.equal(row, prev))
throw new IllegalArgumentException(
"digest conflict at index " + index + ": " +
rpath.subList(index, index + 2));
// if (!Digest.equal(row, prev))
// throw new IllegalArgumentException(
// "digest conflict at index " + index + ": " +
// rpath.subList(index, index + 2));

long rowNumber = row.rowNumber();
long prevNumber = prev.rowNumber();
Expand Down

0 comments on commit 461467c

Please sign in to comment.