nwaku/vendor/nim-dnsdisc/tests/test_builder.nim

127 lines
4.8 KiB
Nim

{.used.}
import
chronos,
std/[sequtils, strformat, tables],
testutils/unittests,
../discovery/dnsdisc/builder,
./test_utils
procSuite "Test DNS Discovery: Merkle Tree builder":
# Test tree entries:
asyncTest "Create TXT records":
check:
# Can convert (back) to TXT record
exampleRoot.toTXTRecord().get() == RootTxt
exampleEnr1.toTXTRecord().get() == Enr1Txt
exampleLink.toTXTRecord().get() == LinkTxt
exampleBranch.toTXTRecord().get() == BranchTxt
asyncTest "Determine subdomain":
check:
# Successfully compute subdomain hash for each entry
exampleEnr1.subdomain().get() == Enr1Subdomain
exampleLink.subdomain().get() == LinkSubdomain
exampleBranch.subdomain().get() == BranchSubdomain
asyncTest "Build TXT records":
check:
# Successfully build all TXT records from example tree
exampleTree.buildTXT("nodes.example.org").get() == exampleRecords
asyncTest "Build subtree entries":
# Test subtree from single leaf entry
let subtreeLeaf = buildSubtree(@[parseSubtreeEntry(Enr1Txt).get()])
check:
subtreeLeaf.isOk()
subtreeLeaf[].subtreeRoot.kind == Enr
subtreeLeaf[].subtreeEntries.len == 0
# Test subtree with single branch and leafs
let subtreeSingle = buildSubtree(@[parseSubtreeEntry(Enr1Txt).get(),
parseSubtreeEntry(Enr2Txt).get(),
parseSubtreeEntry(Enr3Txt).get()])
check:
# Successfully build ENR subtree
subtreeSingle.isOk()
subtreeSingle[].subtreeRoot.kind == Branch
subtreeSingle[].subtreeRoot.branchEntry.children == @[Enr1Subdomain, Enr2Subdomain, Enr3Subdomain]
subtreeSingle[].subtreeEntries.len == 3
# Test subtree with multiple branches-of-branches
var entries: seq[SubtreeEntry]
for i in 1..(MaxChildren*MaxChildren):
# We need at least MaxChildren branch entries holding MaxChildren leaf nodes
entries.add(parseSubtreeEntry(Enr1Txt).get())
let
subtreeMultiple = buildSubtree(entries)
expectedLeafCount = MaxChildren*MaxChildren
expectedBranchCount = MaxChildren # Excluding subtree root branch
check:
subtreeMultiple.isOk()
subtreeMultiple[].subtreeRoot.kind == Branch
subtreeMultiple[].subtreeEntries.len == expectedLeafCount + expectedBranchCount
subtreeMultiple[].subtreeEntries.filterIt(it.kind == Enr).len == expectedLeafCount
subtreeMultiple[].subtreeEntries.filterIt(it.kind == Branch).len == expectedBranchCount
asyncTest "Build complete tree":
var
enr1: Record
enr2: Record
enr3: Record
link = "enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org"
seqNo = 1.uint32
check:
enr1.fromBase64("-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA")
enr2.fromBase64("-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI")
enr3.fromBase64("-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o")
let tree = buildTree(seqNo, @[enr1, enr2, enr3], @[link])
check:
# Successfully build example tree
tree.isOk()
# Root entry
tree[].rootEntry.seqNo == 1
tree[].rootEntry.eroot == exampleRoot.eroot
tree[].rootEntry.lroot == exampleRoot.lroot
# Subtree entries
tree[].entries.len == 5
tree[].entries.filterIt(it.kind == Branch).len == 1
tree[].getNodes().len == 3
tree[].getLinks().len == 1
asyncTest "Sign tree":
let
secKeyHex = "58d23b55bc9cdce1f18c2500f40ff4ab7245df9a89505e9b1fa4851f623d241d"
expectedSig = "8BGq3_ZasQUPvDyU7cqBpsHVjn4CP5GsFf7Xf9M1bJARCXII3SrD7e_I8Q6qw9oLItHapevgFlfPfwhqPXFRrAA"
expectedTXT = fmt"{RootPrefix} e={exampleTree.rootEntry.eroot} l={exampleTree.rootEntry.lroot} seq={exampleTree.rootEntry.seqNo} sig={expectedSig}"
testSecKey = PrivateKey.fromHex(secKeyHex).get()
testPubKey = testSecKey.toPublicKey()
var tree = exampleTree
let
signRes = signTree(tree, testSecKey)
check:
signRes.isOk()
tree.rootEntry.signature.len == SkRawRecoverableSignatureSize # 65 bytes
# Verify signature
let
sigHash = hashableContent(tree.rootEntry)
sig = SignatureNR.fromRaw(tree.rootEntry.signature)
check:
sig.isOk()
verify(sig = sig[],
msg = sigHash,
key = testPubKey)
# Check TXT record
check:
tree.rootEntry.toTXTRecord().get() == expectedTXT