diff --git a/.github/actions/nimbus-build-system/action.yml b/.github/actions/nimbus-build-system/action.yml index 590c5571..f074830d 100644 --- a/.github/actions/nimbus-build-system/action.yml +++ b/.github/actions/nimbus-build-system/action.yml @@ -147,7 +147,7 @@ runs: - name: Restore Nim toolchain binaries from cache id: nim-cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: NimBinaries key: ${{ inputs.os }}-${{ inputs.cpu }}-cache-${{ env.cache_nonce }}-${{ github.run_id }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 152c13da..675f770d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: timeout-minutes: 80 steps: - name: Checkout sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive @@ -64,9 +64,9 @@ jobs: # workaround for https://github.com/NomicFoundation/hardhat/issues/3877 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18.15 + node-version: 18.15 - name: Start Ethereum node with Codex contracts if: matrix.tests == 'contract' || matrix.tests == 'integration' || matrix.tests == 'all' @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/docker-reusable.yml b/.github/workflows/docker-reusable.yml index 2ebb53a8..816b0791 100644 --- a/.github/workflows/docker-reusable.yml +++ b/.github/workflows/docker-reusable.yml @@ -101,26 +101,26 @@ jobs: PLATFORM: ${{ format('{0}/{1}', 'linux', matrix.target.arch) }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Docker - Meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.DOCKER_REPO }} - name: Docker - Set up Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Docker - Login to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Docker - Build and Push by digest id: build - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ${{ env.DOCKER_FILE }} @@ -140,9 +140,9 @@ jobs: touch "/tmp/digests/${digest#sha256:}" - name: Docker - Upload digest - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: digests + name: digests-${{ matrix.target.arch }} path: /tmp/digests/* if-no-files-found: error retention-days: 1 @@ -180,17 +180,18 @@ jobs: fi - name: Docker - Download digests - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: digests + pattern: digests-* + merge-multiple: true path: /tmp/digests - name: Docker - Set up Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Docker - Meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.DOCKER_REPO }} flavor: | @@ -202,7 +203,7 @@ jobs: type=sha,enable=${{ env.TAG_SHA }} - name: Docker - Login to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 1ffcef8a..6ec42ebe 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -26,11 +26,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: '0' - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 @@ -44,11 +44,11 @@ jobs: if: github.ref == 'refs/heads/master' steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: '0' - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 @@ -57,9 +57,9 @@ jobs: run: npx @redocly/cli build-docs openapi.yaml --output "openapi/index.html" --title "Codex API" - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 with: path: './openapi' - name: Deploy to GitHub Pages - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v4 diff --git a/codex/slots/builder/builder.nim b/codex/slots/builder/builder.nim index 6bfabc4b..0de1aca1 100644 --- a/codex/slots/builder/builder.nim +++ b/codex/slots/builder/builder.nim @@ -129,6 +129,12 @@ func numBlockCells*(self: SlotsBuilder): Natural = (self.manifest.blockSize div self.cellSize).Natural +func numBlockCellsPadded*(self: SlotsBuilder): Natural = + ## Number of cells per block including padding. + ## + + nextPowerOfTwo(self.numBlockCells.int).Natural + func cellSize*(self: SlotsBuilder): NBytes = ## Cell size. ## @@ -141,6 +147,18 @@ func numSlotCells*(self: SlotsBuilder): Natural = self.numBlockCells * self.numSlotBlocks +func numSlotCellsPadded*(self: SlotsBuilder): Natural = + ## Number of cells per slot including padding. + ## + + nextPowerOfTwo(self.numBlockCellsPadded.int * self.numSlotBlocks.int).Natural + +func emptyDigestTree*(self: SlotsBuilder): Poseidon2Tree {.inline.} = + ## Returns the tree of a padding block. + ## + + self.emptyDigestTree + func slotIndicesIter*(self: SlotsBuilder, slot: Natural): ?!Iter[int] = ## Returns the slot indices. ## @@ -180,7 +198,7 @@ proc buildBlockTree*( success (blk.data, tree) -proc getCellHashes*( +proc getBlockHashes*( self: SlotsBuilder, slotIndex: Natural): Future[?!seq[Poseidon2Hash]] {.async.} = @@ -201,9 +219,9 @@ proc getCellHashes*( for blkIdx in self.strategy.getIndices(slotIndex): trace "Getting block CID for tree at index" - without (_, tree) =? (await self.buildBlockTree(blkIdx)) and - digest =? tree.root, err: - error "Failed to get block CID for tree at index", err = err.msg + without (_, blockTree) =? (await self.buildBlockTree(blkIdx)) and + digest =? blockTree.root, err: + error "Failed to get block CID for block tree at index", err = err.msg return failure(err) digest @@ -213,11 +231,11 @@ proc getCellHashes*( proc buildSlotTree*( self: SlotsBuilder, slotIndex: Natural): Future[?!Poseidon2Tree] {.async.} = - without cellHashes =? (await self.getCellHashes(slotIndex)), err: + without blockHashes =? (await self.getBlockHashes(slotIndex)), err: error "Failed to select slot blocks", err = err.msg return failure(err) - Poseidon2Tree.init(cellHashes & self.slotsPadLeafs) + Poseidon2Tree.init(blockHashes & self.slotsPadLeafs) proc buildSlot*( self: SlotsBuilder, @@ -331,8 +349,8 @@ proc new*( # all trees have to be padded to power of two numBlockCells = (manifest.blockSize div cellSize).int # number of cells per block blockPadBytes = newSeq[byte](numBlockCells.nextPowerOfTwoPad * cellSize.int) # power of two padding for blocks - numSlotLeafs = (manifest.blocksCount div manifest.numSlots) - slotsPadLeafs = newSeqWith(numSlotLeafs.nextPowerOfTwoPad, Poseidon2Zero) # power of two padding for block roots + numSlotBlocks = (manifest.blocksCount div manifest.numSlots) + slotsPadLeafs = newSeqWith(numSlotBlocks.nextPowerOfTwoPad, Poseidon2Zero) # power of two padding for block roots rootsPadLeafs = newSeqWith(manifest.numSlots.nextPowerOfTwoPad, Poseidon2Zero) emptyDigestTree = ? Poseidon2Tree.digestTree(DefaultEmptyBlock & blockPadBytes, DefaultCellSize.int) diff --git a/codex/slots/sampler/sampler.nim b/codex/slots/sampler/sampler.nim index a8376eed..802ebdf1 100644 --- a/codex/slots/sampler/sampler.nim +++ b/codex/slots/sampler/sampler.nim @@ -80,6 +80,66 @@ proc getCell*(self: DataSampler, blkBytes: seq[byte], blkCellIdx: Natural): Cell dataEnd = dataStart + cellSize return blkBytes[dataStart ..< dataEnd] +proc createProofSample(self: DataSampler, slotTreeCid: Cid, cellIdx: Natural): Future[?!Sample] {.async.} = + let + cellsPerBlock = self.builder.numBlockCells + blkCellIdx = cellIdx.toBlockCellIdx(cellsPerBlock) + slotBlkIdx = cellIdx.toBlockIdx(cellsPerBlock) + + logScope: + cellIdx = cellIdx + slotBlkIdx = slotBlkIdx + blkCellIdx = blkCellIdx + + without (cid, proof) =? await self.blockStore.getCidAndProof( + slotTreeCid, + slotBlkIdx.Natural), err: + error "Failed to get block from block store", err = err.msg + return failure(err) + + without slotProof =? proof.toVerifiableProof(), err: + error "Unable to convert slot proof to poseidon proof", error = err.msg + return failure(err) + + # If the cell index is greater than or equal to the UNPADDED number of slot cells, + # Then we're sampling inside a padded block. + # In this case, we use the pre-generated zero-data and pre-generated padding-proof for this cell index. + if cellIdx >= self.builder.numSlotCells: + trace "Sampling a padded block" + + without blockProof =? self.builder.emptyDigestTree.getProof(blkCellIdx), err: + error "Failed to get proof from empty block tree", err = err.msg + return failure(err) + + success(Sample( + data: newSeq[byte](self.builder.cellSize.int), + slotProof: slotProof, + cellProof: blockProof, + slotBlockIdx: slotBlkIdx.Natural, + blockCellIdx: blkCellIdx.Natural)) + + else: + trace "Sampling a dataset block" + # This converts our slotBlockIndex to a datasetBlockIndex using the + # indexing-strategy used by the builder. + # We need this to fetch the block data. We can't do it by slotTree + slotBlkIdx. + let datasetBlockIndex = self.builder.slotIndicies(self.index)[slotBlkIdx] + + without (bytes, blkTree) =? await self.builder.buildBlockTree(datasetBlockIndex), err: + error "Failed to build block tree", err = err.msg + return failure(err) + + without blockProof =? blkTree.getProof(blkCellIdx), err: + error "Failed to get proof from block tree", err = err.msg + return failure(err) + + success(Sample( + data: self.getCell(bytes, blkCellIdx), + slotProof: slotProof, + cellProof: blockProof, + slotBlockIdx: slotBlkIdx.Natural, + blockCellIdx: blkCellIdx.Natural)) + proc getProofInput*( self: DataSampler, entropy: ProofChallenge, @@ -97,61 +157,27 @@ proc getProofInput*( error "Failed to get slot proof from verify tree", err = err.msg return failure(err) - let - slotTreeCid = self.builder.manifest.slotRoots[self.index] - cellsPerBlock = self.builder.numBlockCells - cellIdxs = entropy.cellIndices( - self.builder.slotRoots[self.index], - self.builder.numSlotCells, - nSamples) + let slotTreeCid = self.builder.manifest.slotRoots[self.index] logScope: index = self.index samples = nSamples - cells = cellIdxs slotTreeCid = slotTreeCid trace "Collecting input for proof" + + let cellIdxs = entropy.cellIndices( + self.builder.slotRoots[self.index], + self.builder.numSlotCellsPadded, + nSamples) + + trace "Found cell indices", cellIdxs let samples = collect(newSeq): for cellIdx in cellIdxs: - let - blkCellIdx = cellIdx.toBlockCellIdx(cellsPerBlock) # block cell index - slotCellIdx = cellIdx.toBlockIdx(cellsPerBlock) # slot tree index - - logScope: - cellIdx = cellIdx - slotCellIdx = slotCellIdx - blkCellIdx = blkCellIdx - - without (cid, proof) =? await self.blockStore.getCidAndProof( - slotTreeCid, - slotCellIdx.Natural), err: - error "Failed to get block from block store", err = err.msg + without sample =? (await self.createProofSample(slotTreeCid, cellIdx)), err: + error "Failed to create proof sample", error = err.msg return failure(err) - - without slotProof =? proof.toVerifiableProof(), err: - error "Unable to convert slot proof to poseidon proof", error = err.msg - return failure(err) - - # This converts our slotBlockIndex to a datasetBlockIndex using the - # indexing-strategy used by the builder. - # We need this to fetch the block data. We can't do it by slotTree + slotBlkIdx. - let datasetBlockIndex = self.builder.slotIndices(self.index)[slotCellIdx] - - without (bytes, blkTree) =? await self.builder.buildBlockTree(datasetBlockIndex), err: - error "Failed to build block tree", err = err.msg - return failure(err) - - without blockProof =? blkTree.getProof(blkCellIdx), err: - error "Failed to get proof from block tree", err = err.msg - return failure(err) - - Sample( - data: self.getCell(bytes, blkCellIdx), - slotProof: slotProof, - cellProof: blockProof, - slotBlockIdx: slotCellIdx.Natural, - blockCellIdx: blkCellIdx.Natural) + sample success ProofInput( entropy: entropy, diff --git a/codex/slots/sampler/utils.nim b/codex/slots/sampler/utils.nim index c73f7b95..0379fb07 100644 --- a/codex/slots/sampler/utils.nim +++ b/codex/slots/sampler/utils.nim @@ -10,6 +10,7 @@ import std/sugar import std/bitops +import pkg/chronicles import pkg/poseidon2 import pkg/poseidon2/io @@ -67,7 +68,6 @@ func cellIndex*( doAssert( 1 shl log2 == numCells , "`numCells` is assumed to be a power of two" ) let hash = Sponge.digest( @[ slotRoot, entropy, counter.toF ], rate = 2 ) - return int( extractLowBits(hash, log2) ) func cellIndices*( @@ -75,6 +75,8 @@ func cellIndices*( slotRoot: Poseidon2Hash, numCells: Natural, nSamples: Natural): seq[Natural] = + trace "Calculating cell indices", numCells, nSamples + var indices: seq[Natural] while (indices.len < nSamples): let idx = cellIndex(entropy, slotRoot, numCells, indices.len + 1) diff --git a/tests/codex/slots/provingtestenv.nim b/tests/codex/slots/provingtestenv.nim index 9b7e6d83..6214ca59 100644 --- a/tests/codex/slots/provingtestenv.nim +++ b/tests/codex/slots/provingtestenv.nim @@ -1,4 +1,5 @@ import std/sequtils +import std/math import pkg/questionable/results import pkg/poseidon2/io @@ -28,7 +29,8 @@ const # in the dataset. bytesPerBlock* = 64 * 1024 cellsPerBlock* = bytesPerBlock div DefaultCellSize.int - numberOfSlotBlocks* = 4 + numberOfSlotBlocks* = 3 + numberOfSlotBlocksPadded* = numberOfSlotBlocks.nextPowerOfTwo totalNumberOfSlots* = 2 datasetSlotIndex* = 1 cellsPerSlot* = (bytesPerBlock * numberOfSlotBlocks) div DefaultCellSize.int @@ -37,7 +39,14 @@ const type ProvingTestEnvironment* = ref object # Invariant: - challenge*: Poseidon2Hash + # These challenges are chosen such that with the testenv default values + # and nSamples=3, they will land on [3x data cells + 0x padded cell], + # and [2x data cells + 1x padded cell] respectively: + challengeNoPad*: Poseidon2Hash + challengeOnePad*: Poseidon2Hash + blockPadBytes*: seq[byte] + emptyBlockTree*: Poseidon2Tree + emptyBlockCid*: Cid # Variant: localStore*: CacheStore manifest*: Manifest @@ -79,17 +88,19 @@ proc createSlotTree(self: ProvingTestEnvironment, dSlotIndex: uint64): Future[Po let slotBlocks = datasetBlockIndices.mapIt(self.datasetBlocks[it]) - numBlockCells = bytesPerBlock.int div DefaultCellSize.int - blockPadBytes = newSeq[byte](numBlockCells.nextPowerOfTwoPad * DefaultCellSize.int) - slotBlockRoots = slotBlocks.mapIt(Poseidon2Tree.digest(it.data & blockPadBytes, DefaultCellSize.int).tryGet()) - tree = Poseidon2Tree.init(slotBlockRoots).tryGet() + slotBlockRoots = slotBlocks.mapIt(Poseidon2Tree.digest(it.data & self.blockPadBytes, DefaultCellSize.int).tryGet()) + slotBlockRootPads = newSeqWith((slotBlockRoots.len).nextPowerOfTwoPad, Poseidon2Zero) + tree = Poseidon2Tree.init(slotBlockRoots & slotBlockRootPads).tryGet() treeCid = tree.root().tryGet().toSlotCid().tryGet() - for i in 0 ..< numberOfSlotBlocks: - let + for i in 0 ..< numberOfSlotBlocksPadded: + var blkCid: Cid + if i < slotBlockRoots.len: blkCid = slotBlockRoots[i].toCellCid().tryGet() - proof = tree.getProof(i).tryGet().toEncodableProof().tryGet() + else: + blkCid = self.emptyBlockCid + let proof = tree.getProof(i).tryGet().toEncodableProof().tryGet() discard await self.localStore.putCidAndProof(treeCid, i, blkCid, proof) return tree @@ -159,8 +170,18 @@ proc createSlot(self: ProvingTestEnvironment): void = ) proc createProvingTestEnvironment*(): Future[ProvingTestEnvironment] {.async.} = + let + numBlockCells = bytesPerBlock.int div DefaultCellSize.int + blockPadBytes = newSeq[byte](numBlockCells.nextPowerOfTwoPad * DefaultCellSize.int) + emptyBlockTree = Poseidon2Tree.digestTree(DefaultEmptyBlock & blockPadBytes, DefaultCellSize.int).tryGet() + emptyBlockCid = emptyBlockTree.root.tryGet().toCellCid().tryGet() + var testEnv = ProvingTestEnvironment( - challenge: toF(12345) + challengeNoPad: toF(6), + challengeOnePad: toF(9), + blockPadBytes: blockPadBytes, + emptyBlockTree: emptyBlockTree, + emptyBlockCid: emptyBlockCid ) testEnv.localStore = CacheStore.new() diff --git a/tests/codex/slots/testsampler.nim b/tests/codex/slots/testsampler.nim index 79fdc24f..8956a131 100644 --- a/tests/codex/slots/testsampler.nim +++ b/tests/codex/slots/testsampler.nim @@ -73,7 +73,7 @@ asyncchecksuite "Test DataSampler": test "Can gather proof input": let nSamples = 3 - challengeBytes = env.challenge.toBytes() + challengeBytes = env.challengeNoPad.toBytes() input = (await dataSampler.getProofInput(challengeBytes, nSamples)).tryget() proc equal(a: Poseidon2Hash, b: Poseidon2Hash): bool = @@ -91,29 +91,65 @@ asyncchecksuite "Test DataSampler": check: equal(input.verifyRoot, env.datasetRootHash) - equal(input.entropy, env.challenge) + equal(input.entropy, env.challengeNoPad) input.numCells == ((bytesPerBlock * numberOfSlotBlocks) div DefaultCellSize.int).Natural input.numSlots == totalNumberOfSlots.Natural input.slotIndex == env.slot.slotIndex.truncate(Natural) input.verifyProof == expectedProof # block-slot proofs - input.samples[0].slotBlockIdx == 2 + input.samples[0].slotBlockIdx == 1 input.samples[1].slotBlockIdx == 2 - input.samples[2].slotBlockIdx == 0 + input.samples[2].slotBlockIdx == 1 toStr(input.samples[0].slotProof) == expectedBlockSlotProofs[0] toStr(input.samples[1].slotProof) == expectedBlockSlotProofs[1] toStr(input.samples[2].slotProof) == expectedBlockSlotProofs[2] # cell-block proofs - input.samples[0].blockCellIdx == 26 - input.samples[1].blockCellIdx == 29 - input.samples[2].blockCellIdx == 29 + input.samples[0].blockCellIdx == 25 + input.samples[1].blockCellIdx == 18 + input.samples[2].blockCellIdx == 17 toStr(input.samples[0].cellProof) == expectedCellBlockProofs[0] toStr(input.samples[1].cellProof) == expectedCellBlockProofs[1] toStr(input.samples[2].cellProof) == expectedCellBlockProofs[2] - # # cell data + # cell data nimcrypto.toHex(input.samples[0].data) == expectedCellData[0] nimcrypto.toHex(input.samples[1].data) == expectedCellData[1] nimcrypto.toHex(input.samples[2].data) == expectedCellData[2] + + test "Can select samples in padded cells": + let + nSamples = 3 + challengeBytes = env.challengeOnePad.toBytes() + input = (await dataSampler.getProofInput(challengeBytes, nSamples)).tryget() + + proc equal(a: Poseidon2Hash, b: Poseidon2Hash): bool = + a.toDecimal() == b.toDecimal() + + proc toStr(proof: Poseidon2Proof): string = + let a = proof.path.mapIt(toHex(it)) + join(a) + + let expectedProof = env.datasetToSlotTree.getProof(datasetSlotIndex).tryGet() + + check: + equal(input.verifyRoot, env.datasetRootHash) + equal(input.entropy, env.challengeOnePad) + input.numCells == ((bytesPerBlock * numberOfSlotBlocks) div DefaultCellSize.int).Natural + input.numSlots == totalNumberOfSlots.Natural + input.slotIndex == env.slot.slotIndex.truncate(Natural) + input.verifyProof == expectedProof + + input.samples[0].slotBlockIdx == 2 + input.samples[1].slotBlockIdx == 2 + input.samples[2].slotBlockIdx == 3 + # The third sample is a padded sample + toStr(input.samples[2].slotProof) == toStr(env.slotTree.getProof(3).tryGet()) + + input.samples[0].blockCellIdx == 29 + input.samples[1].blockCellIdx == 26 + input.samples[2].blockCellIdx == 30 + toStr(input.samples[2].cellProof) == toStr(env.emptyBlockTree.getProof(30).tryGet()) + + input.samples[2].data == newSeq[byte](DefaultCellSize.int) diff --git a/tests/codex/slots/testsampler_expected.nim b/tests/codex/slots/testsampler_expected.nim index 7d041f86..7be9b129 100644 --- a/tests/codex/slots/testsampler_expected.nim +++ b/tests/codex/slots/testsampler_expected.nim @@ -5,21 +5,21 @@ import pkg/codex/codextypes proc getExpectedCellBlockProofs*(): seq[string] = @[ - "0x189890bedf2a40f2757554c5f089811e07601543a576e2d40d68a1bd295adbee0x059f227fe687a7abd9c3d9878c0b812aa7829c85d30c23154b8824a907909b060x2c685fc951f1684fd3979f7e3a558fa6aeed3f960ef0a9e2ba51cc62cff7de0e0x10ebae3fb12d502044216e40319726ed36308b9ae4ab3fb0a36c77e5614c6fbd0x1decd3fb7ff458261149731115657cecd7eb2fe4a6cf84f3c6761aa8b0dd6b9a", - "0x2567cd93b3fe058b31908656c05d3a09fd33cc0d7df3c7c005d991a8cda60ba80x16e4788105082295706c49c604216518f16ca9dd106012c7c98e6ee138893f6e0x1c258af996aecf9bba249130182ccfe44a9090bc58fe59063a06db67efb7b5240x10ebae3fb12d502044216e40319726ed36308b9ae4ab3fb0a36c77e5614c6fbd0x1decd3fb7ff458261149731115657cecd7eb2fe4a6cf84f3c6761aa8b0dd6b9a", - "0x0568735989a51526104eddbcf386b8aaef186a2d31afce0c2671c8ce8dd8cd1a0x20d06082668338924981a9e0e4f18e7ec6e2b7912e7fb74c1b6dc921b824def60x2fd45662152ae87192971a0e9b7d50de48d7bc8ab22e5711680173a302120bf00x0f528a58c839889e4bb9195e2bcbc2addb7022e47c8fb11bbdeba0a0e9c6f4cb0x0edf43ec0f277500371537a4d566f3f352d0c49bfa9d4659e07d776ffe119437" + "0x13935d7f73028fd425e557b8e0b737fcba3f8bcda0e07a9047868bc7c5a2519e0x17d36c9bcef9febb77b129e8bbe971b754d7b3e1df8c7d881b64bf0aa055f5570x02610a45fa39d4859e5c0c53bda9cc6bd627ae4b5aa462f9e86f47f3db96b2700x27a362c0f92c887d74ee77df2df5e51f0f66b0564a2af8b1c11b02dab0a34f780x095eb3c0d166c19f9cac8ea0e6ba274dfeef802cf7d01c90378585fd4d788e56", + "0x128b43cb1f87736d5b826c5a440d373c0e4c147a81a0edc40b106abd2c10af960x2160ba1c1ed893685b849a8f1be6d32bb11a6ebb8690c5af95e0ce0e9d72b6580x1332185d0ef7b76e55c7464f37df96d41f256249d74678d8191030912036b7aa0x0522383db3f9cb9c75d5b209bd795566e9cffa632819628194416a479998a4270x1decd3fb7ff458261149731115657cecd7eb2fe4a6cf84f3c6761aa8b0dd6b9a", + "0x2a2c8663e354dbc1857a654134de3b690d73ffedcc7c0ba770a39f3e48675ee10x01914d98d4103889ea59ce6e970dae95f7e463350184c5f7f3806997e10748520x10e8f6235ac7e95af5aea6fc77ebe60e1028b48eb84027ea46d403d809852b6b0x04bd51be7ff42db27a7605124d3d2d1c4cbca43f93d1997060ac8a1009fa48b40x095eb3c0d166c19f9cac8ea0e6ba274dfeef802cf7d01c90378585fd4d788e56" ] proc getExpectedBlockSlotProofs*(): seq[string] = @[ - "0x0684458ea77eca59be05e368bb26b7ca318b8e836100c415e60136876c01ba170x2a66917fa49371e835376fcece0d854c77008ac1195740963b1ac4491ee1aaf1", - "0x0684458ea77eca59be05e368bb26b7ca318b8e836100c415e60136876c01ba170x2a66917fa49371e835376fcece0d854c77008ac1195740963b1ac4491ee1aaf1", - "0x03883ad2637a4c68f29bc0910400259291d9c3d730de7e3925adbf26c80b7f440x2d6a888f50b14b0c686f64c4bd0d8389cd555cdf0e3d6f387682c4722ac2a674" + "0x008fccffc5d2e5010a44bc718fed80d4d891e6517c022ba1bff65763dd79dbb90x117662f365386ee6784274dfa3a3b35126291cdf013c5e90d07bee79f32b2f40", + "0x00000000000000000000000000000000000000000000000000000000000000000x2a66917fa49371e835376fcece0d854c77008ac1195740963b1ac4491ee1aaf1", + "0x008fccffc5d2e5010a44bc718fed80d4d891e6517c022ba1bff65763dd79dbb90x117662f365386ee6784274dfa3a3b35126291cdf013c5e90d07bee79f32b2f40" ] proc getExpectedCellData*(): seq[string] = @[ - "BA".repeat(DefaultCellSize.int), - "BD".repeat(DefaultCellSize.int), - "3D".repeat(DefaultCellSize.int) + "79".repeat(DefaultCellSize.int), + "B2".repeat(DefaultCellSize.int), + "71".repeat(DefaultCellSize.int) ] diff --git a/tests/codex/slots/testslotbuilder.nim b/tests/codex/slots/testslotbuilder.nim index 96e5d61b..5c8a8b48 100644 --- a/tests/codex/slots/testslotbuilder.nim +++ b/tests/codex/slots/testslotbuilder.nim @@ -217,7 +217,7 @@ suite "Slot builder": for blk in expectedBlock: SpongeMerkle.digest(blk.data & blockPadBytes, cellSize.int) - cellHashes = (await slotBuilder.getCellHashes(i)).tryGet() + cellHashes = (await slotBuilder.getBlockHashes(i)).tryGet() check: expectedHashes == cellHashes diff --git a/tests/codex/slots/testutils.nim b/tests/codex/slots/testutils.nim index 49e9e639..736d4a9f 100644 --- a/tests/codex/slots/testutils.nim +++ b/tests/codex/slots/testutils.nim @@ -2,6 +2,7 @@ import std/sequtils import std/sugar import std/random import std/strutils +import std/math import pkg/questionable/results import pkg/constantine/math/arithmetic @@ -27,17 +28,19 @@ import ../merkletree/helpers import ./provingtestenv asyncchecksuite "Test proof sampler utils": - let knownIndices: seq[Natural] = @[90, 93, 29] + let knownIndices: seq[Natural] = @[57, 82, 49] var env: ProvingTestEnvironment slotRoot: Poseidon2Hash numCells: Natural + numCellsPadded: Natural setup: env = await createProvingTestEnvironment() slotRoot = env.slotRoots[datasetSlotIndex] numCells = cellsPerSlot + numCellsPadded = numCells.nextPowerOfTwo teardown: reset(env) @@ -61,14 +64,15 @@ asyncchecksuite "Test proof sampler utils": test "Can find single slot-cell index": proc slotCellIndex(i: Natural): Natural = - return cellIndex(env.challenge, slotRoot, numCells, i) + return cellIndex(env.challengeNoPad, slotRoot, numCellsPadded, i) proc getExpectedIndex(i: int): Natural = let numberOfCellsInSlot = (bytesPerBlock * numberOfSlotBlocks) div DefaultCellSize.uint64.int - hash = Sponge.digest(@[slotRoot, env.challenge, toF(i)], rate = 2) + numberOfCellsInSlotPadded = numberOfCellsInSlot.nextPowerOfTwo + hash = Sponge.digest(@[slotRoot, env.challengeNoPad, toF(i)], rate = 2) - return int(extractLowBits(hash.toBig(), ceilingLog2(numberOfCellsInSlot))) + return int(extractLowBits(hash.toBig(), ceilingLog2(numberOfCellsInSlotPadded))) check: slotCellIndex(1) == getExpectedIndex(1) @@ -80,10 +84,10 @@ asyncchecksuite "Test proof sampler utils": test "Can find sequence of slot-cell indices": proc slotCellIndices(n: int): seq[Natural] = - cellIndices(env.challenge, slotRoot, numCells, n) + cellIndices(env.challengeNoPad, slotRoot, numCellsPadded, n) proc getExpectedIndices(n: int): seq[Natural] = - return collect(newSeq, (for i in 1..n: cellIndex(env.challenge, slotRoot, numCells, i))) + return collect(newSeq, (for i in 1..n: cellIndex(env.challengeNoPad, slotRoot, numCellsPadded, i))) check: slotCellIndices(3) == getExpectedIndices(3)