Skip to content

Commit

Permalink
cooking on createCommitment
Browse files Browse the repository at this point in the history
  • Loading branch information
S1nus committed Aug 7, 2024
1 parent bdf6d18 commit 9ecf545
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 32 deletions.
86 changes: 57 additions & 29 deletions src/lib/commitment/Commitment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,30 @@
pragma solidity ^0.8.22;

import {Namespace, isReservedNamespace} from "../tree/Types.sol";
import "openzeppelin-contracts/contracts/utils/math/Math.sol";
import "../../../lib/openzeppelin-contracts/contracts/utils/math/Math.sol";
import "../../../lib/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.sol";
import "forge-std/console.sol";

uint256 constant SUBTREE_ROOT_THRESHOLD = 64;

function divCeil(uint256 x, uint256 y) pure returns (uint256 z) {
function _divCeil(uint256 x, uint256 y) pure returns (uint256 z) {
z = x / y + (x % y == 0 ? 0 : 1);
}

function num_shares(uint256 blobSize) pure returns (uint256) {
return divCeil((Math.max(blobSize, 478) - 478), 482) + 1;
function _numShares(uint256 blobSize) pure returns (uint256) {
return _divCeil((MathUpgradeable.max(blobSize, 478) - 478), 482) + 1;
}

function copyNamespace(bytes memory share, bytes29 namespaceBytes) pure {
function _copyNamespace(bytes memory share, bytes29 namespaceBytes) pure {
for (uint256 i = 0; i < namespaceBytes.length; i++) {
share[i] = namespaceBytes[i];
}
}

function writeInfoByteV0(bytes memory share, bool startingSequence) pure {
function _writeInfoByteV0(bytes memory share, bool startingSequence) pure {
share[29] = bytes1(startingSequence ? 1 : 0);
}

function writeSequenceLength(bytes memory share, uint32 sequenceLength) pure {
function _writeSequenceLength(bytes memory share, uint32 sequenceLength) pure {
// Removed the "reverse", because it didn't work- maybe it's already big-endian?
//bytes4 sequenceLengthBigEndianBytes = bytes4(abi.encodePacked(reverse(sequenceLength)));
bytes4 sequenceLengthBigEndianBytes = bytes4(abi.encodePacked(sequenceLength));
Expand All @@ -36,7 +35,7 @@ function writeSequenceLength(bytes memory share, uint32 sequenceLength) pure {
share[33] = sequenceLengthBigEndianBytes[3];
}

function copyBytes(bytes memory buffer, uint32 cursor, bytes memory data, uint32 length) pure returns (uint32) {
function _copyBytes(bytes memory buffer, uint32 cursor, bytes memory data, uint32 length) pure returns (uint32) {

uint256 start = buffer.length - length;
for (uint256 i = start; i < buffer.length; i++) {
Expand All @@ -51,7 +50,7 @@ function copyBytes(bytes memory buffer, uint32 cursor, bytes memory data, uint32
return cursor;
}

function bytesToHexString(bytes memory buffer) pure returns (string memory) {
function _bytesToHexString(bytes memory buffer) pure returns (string memory) {

// Fixed buffer size for hexadecimal convertion
bytes memory converted = new bytes(buffer.length * 2);
Expand All @@ -67,15 +66,15 @@ function bytesToHexString(bytes memory buffer) pure returns (string memory) {
}

// Share Version 0
function bytesToSharesV0(bytes memory blobData, Namespace memory namespace) pure returns (bytes[] memory shares, bool err) {
function _bytesToSharesV0(bytes memory blobData, Namespace memory namespace) pure returns (bytes[] memory shares, bool err) {
if (namespace.version != 0) {
return (new bytes[](0), true);
}
if (isReservedNamespace(namespace)) {
return (new bytes[](0), true);
}
// Allocate memory for the shares
uint256 numShares = num_shares(blobData.length);
uint256 numShares = _numShares(blobData.length);
bytes[] memory _shares = new bytes[](numShares);
for (uint256 i = 0; i < _shares.length; i++) {
_shares[i] = new bytes(512);
Expand All @@ -84,51 +83,80 @@ function bytesToSharesV0(bytes memory blobData, Namespace memory namespace) pure
bytes29 namespaceBytes = namespace.toBytes();

// The first share is special, because it has startingSequence set to true and the 4-byte sequence length
copyNamespace(_shares[0], namespaceBytes);
writeInfoByteV0(_shares[0], true);
writeSequenceLength(_shares[0], uint32(blobData.length));
_copyNamespace(_shares[0], namespaceBytes);
_writeInfoByteV0(_shares[0], true);
_writeSequenceLength(_shares[0], uint32(blobData.length));
uint32 cursor = 0;
cursor = copyBytes(_shares[0], cursor, blobData, uint32(478)); //only 478 bytes, because 4 bytes are used for the sequence length
cursor = _copyBytes(_shares[0], cursor, blobData, uint32(478)); //only 478 bytes, because 4 bytes are used for the sequence length

if (shares.length != 1) {
// The remaining shares are all the same
for (uint256 i = 1; i < _shares.length; i++) {
// Copy the namespace
copyNamespace(_shares[i], namespaceBytes);
_copyNamespace(_shares[i], namespaceBytes);
// Write the info byte
writeInfoByteV0(_shares[i], false);
_writeInfoByteV0(_shares[i], false);
// Copy the data
cursor = copyBytes(_shares[i], cursor, blobData, uint32(482)); // copy the full 482 bytes
cursor = _copyBytes(_shares[i], cursor, blobData, uint32(482)); // copy the full 482 bytes
}
}

shares = _shares;
err = false;
}

function roundUpPowerOfTwo(uint256 x) pure returns (uint256) {
function _roundDownPowerOfTwo(uint256 x) pure returns (uint256) {
uint256 result = 1;
while (result * 2 <= x) {
result *= 2;
}
return result;
}

function _roundUpPowerOfTwo(uint256 x) pure returns (uint256) {
uint256 result = 1;
while (result < x) {
result *= 2;
}
return result;
}

function blobMinSquareSize(uint256 shareCount) pure returns (uint256) {
return roundUpPowerOfTwo(Math.sqrt(shareCount, Math.Rounding.Ceil));
function _blobMinSquareSize(uint256 shareCount) pure returns (uint256) {
return _roundUpPowerOfTwo(MathUpgradeable.sqrt(shareCount, MathUpgradeable.Rounding.Ceil));
}

function subtreeWidth(uint256 shareCount, uint256 subtreeRootThreshold) pure returns (uint256) {
uint256 s = shareCount / SUBTREE_ROOT_THRESHOLD;
function _subtreeWidth(uint256 shareCount, uint256 subtreeRootThreshold) pure returns (uint256) {
uint256 s = shareCount / subtreeRootThreshold;
if (s != 0) {
s++;
}
s = roundUpPowerOfTwo(s);
return Math.min(s, blobMinSquareSize(shareCount));
s = _roundUpPowerOfTwo(s);
return MathUpgradeable.min(s, _blobMinSquareSize(shareCount));
}

function createCommitment(bytes[] memory shares) pure returns (bytes32 commitment) {
function _merkleMountainRangeSizes(uint256 totalSize, maxTreeSize) pure returns (uint256[] memory) {
uint256[] treeSizes = new uint256[](0);
while (totalSize != 0) {
if (totalSize >= maxTreeSize) {
treeSizes.push(maxTreeSize);
totalSize -= maxTreeSize;
}
else {
uint256 treeSize = _roundDownPowerOfTwo(totalSize);
treeSizes.push(treeSize);
totalSize -= treeSize;
}
}
return treeSizes;
}

function _createCommitment(bytes[] memory shares) pure returns (bytes32 commitment) {
uint256 subtreeWidth = _subtreeWidth(shares.length, SUBTREE_ROOT_THRESHOLD);
uint256[] treeSizes = _merkleMountainRangeSizes(shares.length, subtreeWidth);
bytes[][][] leafSets = new bytes[][][](treeSizes.length);
uint256 cursor = 0;
for (uint256 i = 0; i < treeSizes.length; i++) {
leafSets[i] = new bytes[][](treeSizes[i]);

// this is not it lol
return keccak256(abi.encode(shares));
}
}
6 changes: 3 additions & 3 deletions src/lib/commitment/test/Commitment.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.22;
import "ds-test/test.sol";
import "forge-std/Vm.sol";
import "forge-std/console.sol";
import {bytesToSharesV0, bytesToHexString} from "../Commitment.sol";
import {_bytesToSharesV0, _bytesToHexString} from "../Commitment.sol";
import {toNamespace, Namespace} from "../../tree/Types.sol";

contract CommitmentTest is DSTest {
Expand Down Expand Up @@ -54,10 +54,10 @@ contract CommitmentTest is DSTest {
bytes29 nsString = bytes29(fromHex(vecs[i].namespace));
Namespace memory ns = toNamespace(nsString);
bytes memory data = fromHex(vecs[i].data);
(bytes[] memory shares, bool err) = bytesToSharesV0(data, ns);
(bytes[] memory shares, bool err) = _bytesToSharesV0(data, ns);
string memory out = "";
for (uint j = 0; j < shares.length; j++) {
out = string.concat(out, bytesToHexString(shares[j]));
out = string.concat(out, _bytesToHexString(shares[j]));
}
// none of the test vectors should cause an error
assert(!err);
Expand Down

0 comments on commit 9ecf545

Please sign in to comment.