feat: cryptography integration trail 1

This commit is contained in:
Advaita Saha 2024-01-08 13:11:11 +05:30 committed by Daniel Lamberger
parent 95ff0ca332
commit f2fa2075c9
6 changed files with 115 additions and 89 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ htmldocs/
bin/*
testResults/*
build/
.DS_Store

@ -1 +1 @@
Subproject commit 3e27f1e831700139bf659ca8f46a2816d2a852dc
Subproject commit 077cfb2ab6abf584cb57f25b4425397c71bb4ccc

View File

@ -12,54 +12,80 @@
import
std/[tables, sequtils],
elvis,
./tree
./tree,
../../constantine/constantine/hashes,
../../constantine/constantine/serialization/[io_limbs, codecs_banderwagon, codecs],
../../constantine/constantine/platforms/primitives,
../../constantine/constantine/curves_primitives,
../../constantine/constantine/math/elliptic/ec_twistededwards_projective,
../../constantine/constantine/math/arithmetic,
../../constantine/constantine/math/config/[type_ff, curves],
../../constantine/constantine/math/io/[io_bigints, io_fields, io_ec, io_extfields],
../../constantine/constantine/math/extension_fields,
../../constantine/constantine/ethereum_verkle_primitives,
../../constantine/constantine/ethereum_verkle_trees
{.push warning[DotLikeOps]: off.}
# Todo: Initialize to montgomery X=0, Y=1, Z=1
const IdentityPoint = Point()
var IdentityPoint: Point
IdentityPoint.x.setZero()
IdentityPoint.y.setOne()
IdentityPoint.z.setOne()
var ipaConfig: IPASettings
var ipaTranscript: IpaTranscript[sha256, 32]
discard ipaConfig.genIPAConfig(ipaTranscript)
var testGeneratedPoints: array[256, EC_P]
testGeneratedPoints.generate_random_points(ipaTranscript, 256)
# Todo: implement; this is a mock
proc banderwagonMultiMapToScalarField(fields: var openArray[Field], points: openArray[Point]) =
for i in 0..<points.len:
fields[i] = points[i].X
fields.batchMapToScalarField(points)
# Todo: implement; this is a mock
proc banderwagonMultiMapToScalarField2(fields: openArray[ptr Field], points: openArray[Point]) =
for i in 0..<points.len:
fields[i][] = points[i].X
var correctFields: seq[Fr[Banderwagon]] = @[]
for field in fields:
correctFields.add(Fr[Banderwagon](field[])) # Assuming Fr[Banderwagon] can be initialized from a Field
correctFields.batchMapToScalarField(points)
# Todo: implement; this is a mock
proc banderwagonAddPoint(dst: var Point, src: Point) =
dst.X[0] += src.X[0]
dst.sum(dst, src)
# Todo: implement; this is a mock
proc bandesnatchSubtract(x, y: Field): Field =
[x[0] - y[0], 0, 0, 0]
result.diff(x, y)
# Todo: implement
# SetUint64 z = v, sets z LSB to v (non-Montgomery form) and convert z to Montgomery form
proc bandesnatchSetUint64(z: Field, v: uint64) =
discard
proc bandesnatchSetUint64(z: var Field, v: uint64) =
z.fromInt(int(v))
# Todo: implement; this is a mock
proc ipaCommitToPoly(poly: array[256, Field]): Point =
var x,y,z: Field
for field in poly:
x[0] += field[0]
Point(X:x, Y:y, Z:z)
var comm: Point
comm.pedersen_commit_varbasis(testGeneratedPoints, testGeneratedPoints.len, poly, poly.len)
return comm
# Todo: implement
proc fromLEBytes(field: var Field, data: openArray[byte]) =
discard
var temp{.noinit.}: matchingOrderBigInt(Banderwagon)
temp.unmarshal(data, littleEndian)
field.fromBig(temp)
# leafToComms turns a leaf into two commitments of the suffix
@ -105,8 +131,8 @@ proc initializeCommitment*(vn: ValuesNode) =
var count = fillSuffixTreePoly(c1poly, vn.values[0..<128])
let containsEmptyCodeHash =
len(c1poly) >= EmptyCodeHashSecondHalfIdx and
c1poly[EmptyCodeHashFirstHalfIdx] == EmptyCodeHashFirstHalfValue and
c1poly[EmptyCodeHashSecondHalfIdx] == EmptyCodeHashSecondHalfValue
(c1poly[EmptyCodeHashFirstHalfIdx] == EmptyCodeHashFirstHalfValue).bool() and
(c1poly[EmptyCodeHashSecondHalfIdx] == EmptyCodeHashSecondHalfValue).bool()
if containsEmptyCodeHash:
# Clear out values of the cached point.
c1poly[EmptyCodeHashFirstHalfIdx] = FrZero
@ -207,7 +233,7 @@ proc snapshotChildCommitment*(node: BranchesNode, childIndex: byte) =
## This is done so that we can later compute the delta between the child's
## current commitment and updated commitment. That delta will be used to
## update the parent `node`'s own commitment.
if node.commitmentsSnapshot == nil:
if node.commitmentsSnapshot.isNil:
node.commitmentsSnapshot = new Table[byte, Point]
let childCommitment = node.branches[childIndex].?commitment ?: IdentityPoint
discard node.commitmentsSnapshot.hasKeyOrPut(childIndex, childCommitment)
@ -217,13 +243,13 @@ proc snapshotChildCommitment*(node: BranchesNode, childIndex: byte) =
proc updateAllCommitments*(tree: BranchesNode) =
## Updates the commitments of all modified nodes in the tree, bottom-up.
if tree.commitmentsSnapshot == nil:
if tree.commitmentsSnapshot.isNil:
return
var levels: array[31, seq[BranchesNode]]
levels[0].add(tree)
for node, depth, _ in tree.enumerateModifiedTree():
if node of BranchesNode and node.BranchesNode.commitmentsSnapshot != nil:
if node of BranchesNode and (not node.BranchesNode.commitmentsSnapshot.isNil):
levels[depth].add(node.BranchesNode)
for depth in countdown(30, 0):
@ -233,6 +259,7 @@ proc updateAllCommitments*(tree: BranchesNode) =
var points: seq[Point]
var childIndexes: seq[byte]
echo nodes
for node in nodes:
for index, commitment in node.commitmentsSnapshot:
@ -255,7 +282,9 @@ proc updateAllCommitments*(tree: BranchesNode) =
inc(childIndexesIdx)
inc(deltasIdx)
node.commitmentsSnapshot = nil
node.commitment.banderwagonAddPoint(ipaCommitToPoly(poly))
let diff = ipaCommitToPoly(poly)
echo diff.toHex()
node.commitment.banderwagonAddPoint(diff)
#[

View File

@ -10,7 +10,10 @@
import
std/[streams, tables, strformat],
../utils
../utils,
../verkle_types/types,
../../constantine/constantine/math/io/[io_bigints, io_fields, ],
../../constantine/constantine/serialization/[codecs_banderwagon, codecs]
# TODO: make sizes configurable
@ -19,10 +22,9 @@ type
Bytes32* = array[32, byte]
## A 32-bytes blob that can represent a verkle key or value
Field* = array[4, uint64]
Field* = EC_P_Fr
Point* = object
X*, Y*, Z*: Field
Point* = EC_P
Node* = ref object of RootObj
## Base node type
@ -78,7 +80,7 @@ iterator enumerateModifiedTree*(node: BranchesNode, depth: uint8 = 1):
tuple[node: Node, depth: uint8, index: uint8] {.closure.} =
## Iterates over all the nodes in the tree which were modified, or had one of
## their descendants modified
if node.commitmentsSnapshot != nil:
if node.commitmentsSnapshot.len == 0:
for index in node.commitmentsSnapshot.keys:
let child = node.branches[index]
yield (child, depth, index)
@ -135,7 +137,9 @@ proc printTree*(node: BranchesNode, stream: Stream) =
## Writes all the nodes and values into the given `stream`.
## Outputs a line for each branch, stem and value in the tree, indented by
## depth, along with their commitment.
stream.writeLine(&"<Tree root> Branch. Commitment: {node.commitment.X[0].byte.toHex}")
var arr: array[32, byte]
discard arr.serialize(node.commitment)
stream.writeLine(&"<Tree root> Branch. Commitment: {arr.toHex()}")
for n, depth, parentIndex in node.enumerateTree():
for _ in 0 ..< depth.int:
stream.write(" ")
@ -143,12 +147,16 @@ proc printTree*(node: BranchesNode, stream: Stream) =
if n of BranchesNode:
for _ in depth.int .. 68:
stream.write(" ")
stream.writeLine(&"Branch. Commitment: {n.commitment.X[0].byte.toHex}")
var arr2: array[32, byte]
discard arr2.serialize(n.commitment)
stream.writeLine(&"Branch. Commitment: {arr2.toHex()}")
elif n of ValuesNode:
stream.writeAsHex(n.ValuesNode.stem[depth..^1])
for _ in 0 .. 37:
stream.write(" ")
stream.writeLine(&"Leaves. Commitment: {n.commitment.X[0].byte.toHex}")
var arr3: array[32, byte]
discard arr3.serialize(n.commitment)
stream.writeLine(&"Leaves. Commitment: {arr3.toHex()}")
for valueIndex, value in n.ValuesNode.values.pairs:
if value != nil:
stream.write(" ")

View File

@ -66,19 +66,6 @@ proc writeAsHex*(stream: Stream, bytes: openArray[byte]) =
stream.writeAsHex(b)
proc toHex*(b: byte): string =
## Converts a byte to a two-characters hex string
result.add(bitsToHex(b shr 4))
result.add(bitsToHex(b and 0x0f))
proc toHex*(bytes: openArray[byte]): string =
## Converts a bytes array to a hex string
for b in bytes:
result.add(bitsToHex(b shr 4))
result.add(bitsToHex(b and 0x0f))
proc fromHex*(s: string): seq[byte] =
## Converts a hex string into a bytes sequence
if s.len mod 2 == 1:

View File

@ -11,6 +11,7 @@ import
std/[random, streams, os, sequtils],
unittest2,
../eth_verkle/utils,
../constantine/constantine/serialization/[codecs, codecs_banderwagon],
../eth_verkle/tree/[tree, operations, commitment]
createDir "testResults"
@ -35,7 +36,7 @@ suite "main":
let sampleKvps = @[
("0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000001"),
("0000000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000123456789abcdef0123456789abcdef"),
("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f", "0000000000000000000000000000000000000000000000000000000000000002"),
("1100000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000003"),
("2200000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000004"),
@ -76,56 +77,56 @@ suite "main":
tree.setValue(key, value)
tree.printAndTestCommitments()
echo "\n\nUpdating tree...\n\n"
for (key, value) in updateKvps.hexKvpsToBlob32():
tree.setValue(key, value)
tree.printAndTestCommitments()
# echo "\n\nUpdating tree...\n\n"
# for (key, value) in updateKvps.hexKvpsToBlob32():
# tree.setValue(key, value)
# tree.printAndTestCommitments()
echo "\n\nDeleting nodes:"
echo deleteKvps.foldl(a & " " & b & "\n", "")
for key in deleteKvps:
discard tree.deleteValue(key.toBlob32)
tree.printAndTestCommitments()
# echo "\n\nDeleting nodes:"
# echo deleteKvps.foldl(a & " " & b & "\n", "")
# for key in deleteKvps:
# discard tree.deleteValue(key.toBlob32)
# tree.printAndTestCommitments()
test "testDelValues":
## Makes a small sample tree
var tree = new BranchesNode
var key, value: Bytes32
for (keyHex, valueHex) in sampleKvps:
key[0..^1] = keyHex.fromHex
value[0..^1] = valueHex.fromHex
tree.setValue(key, value)
# test "testDelValues":
# ## Makes a small sample tree
# var tree = new BranchesNode
# var key, value: Bytes32
# for (keyHex, valueHex) in sampleKvps:
# key[0..^1] = keyHex.fromHex
# value[0..^1] = valueHex.fromHex
# tree.setValue(key, value)
## Deletes some values
key[0..^1] = sampleKvps[6][0].fromHex
check tree.deleteValue(key) == true
key[0..^1] = sampleKvps[7][0].fromHex
check tree.deleteValue(key) == true
key[0..^1] = sampleKvps[8][0].fromHex
check tree.deleteValue(key) == true
tree.printTree(newFileStream(stdout)) # prints full tree
# ## Deletes some values
# key[0..^1] = sampleKvps[6][0].fromHex
# check tree.deleteValue(key) == true
# key[0..^1] = sampleKvps[7][0].fromHex
# check tree.deleteValue(key) == true
# key[0..^1] = sampleKvps[8][0].fromHex
# check tree.deleteValue(key) == true
# tree.printTree(newFileStream(stdout)) # prints full tree
test "testDelNonExistingValues":
var key1, key2, key3, value: Bytes32
key1[0..^1] = "2200000000000000000000000000000000000000000000000000000000000000".fromHex
key2[0..^1] = "2211000000000000000000000000000000000000000000000000000000000000".fromHex
key3[0..^1] = "3300000000000000000000000000000000000000000000000000000000000000".fromHex
value[0..^1] = "0000000000000000000000000000000000000000000000000000000000000000".fromHex
# test "testDelNonExistingValues":
# var key1, key2, key3, value: Bytes32
# key1[0..^1] = "2200000000000000000000000000000000000000000000000000000000000000".fromHex
# key2[0..^1] = "2211000000000000000000000000000000000000000000000000000000000000".fromHex
# key3[0..^1] = "3300000000000000000000000000000000000000000000000000000000000000".fromHex
# value[0..^1] = "0000000000000000000000000000000000000000000000000000000000000000".fromHex
var tree = new BranchesNode
tree.setValue(key1, value)
tree.setValue(key2, value)
# var tree = new BranchesNode
# tree.setValue(key1, value)
# tree.setValue(key2, value)
check tree.deleteValue(key3) == false
# check tree.deleteValue(key3) == false
test "randomValues_10000":
## Writes a larger tree with random nodes to a file
var tree = new BranchesNode
for i in 0..10000:
tree.setValue(key = makeRandomBlob32(), value = makeRandomBlob32())
tree.updateAllCommitments()
var file = open("testResults/randomValues_10000", fmWrite)
defer: close(file)
tree.printTree(newFileStream(file))
echo "Tree dumped to 'testResults/randomValues_10000'"
# test "randomValues_10000":
# ## Writes a larger tree with random nodes to a file
# var tree = new BranchesNode
# for i in 0..10000:
# tree.setValue(key = makeRandomBlob32(), value = makeRandomBlob32())
# tree.updateAllCommitments()
# var file = open("testResults/randomValues_10000", fmWrite)
# defer: close(file)
# tree.printTree(newFileStream(file))
# echo "Tree dumped to 'testResults/randomValues_10000'"