Implement custom distance function (#827)

* Implement custom distance function

* More docs about function equivalence
This commit is contained in:
KonradStaniec 2021-09-14 13:36:55 +02:00 committed by GitHub
parent 749069da5c
commit 58b11e683d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 1 deletions

View File

@ -0,0 +1,32 @@
import stint
const MID* = u256(2).pow(u256(255))
const MAX* = high(Uint256)
# Custom distance function described in: https://notes.ethereum.org/h58LZcqqRRuarxx4etOnGQ#Storage-Layout
# The implementation looks different than in spec, due to the fact that in practice
# we are operating on unsigned 256bit integers instead of signed big ints.
# Thanks to this we do not need to use:
# - modulo operations
# - abs operation
# and the results are eqivalent to function described in spec.
#
# The way it works is as follows. Let say we have integers modulo 8:
# [0, 1, 2, 3, 4, 5, 6, 7]
# and we want to calculate minimal distance between 0 and 5.
# Raw difference is: 5 - 0 = 5, which is larger than mid point which is equal to 4.
# From this we know that the shorter distance is the one wraping around 0, which
# is equal to 3
proc distance*(node_id: UInt256, content_id: UInt256): UInt256 =
let rawDiff =
if node_id > content_id:
node_id - content_id
else:
content_id - node_id
if rawDiff > MID:
# If rawDiff is larger than mid this means that distance between node_id and
# content_id is smaller when going from max side.
MAX - rawDiff + UInt256.one
else:
rawDiff

View File

@ -13,7 +13,8 @@ import
./test_portal_encoding,
./test_portal,
./test_content_network,
./test_discovery_rpc
./test_discovery_rpc,
./test_custom_distance
cliBuilder:
import

View File

@ -0,0 +1,30 @@
# Nimbus - Portal Network
# Copyright (c) 2021 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.used.}
import
std/unittest,
stint,
../network/state/custom_distance
suite "State network custom distance function":
test "Calculate distance according to spec":
check:
# Test cases from spec
distance(u256(10), u256(10)) == 0
distance(u256(5), high(UInt256)) == 6
distance(high(UInt256), u256(6)) == 7
distance(u256(5), u256(1)) == 4
distance(u256(1), u256(5)) == 4
distance(UInt256.zero, MID) == MID
distance(UInt256.zero, MID + UInt256.one) == MID - UInt256.one
# Additional test cases to check some basic properties
distance(UInt256.zero, MID + MID) == UInt256.zero
distance(UInt256.zero, UInt256.one) == distance(UInt256.zero, high(UInt256))