Skip to content

Commit

Permalink
Implemented distance/score calculation for LinearSum, adapted Scoring…
Browse files Browse the repository at this point in the history
…Proxy to work with both old and new proximity-score function pairs
  • Loading branch information
u-hubar committed Jan 24, 2024
1 parent 122b318 commit 7a86352
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {ContentAssetErrors} from "./errors/assets/ContentAssetErrors.sol";
import {GeneralErrors} from "../v1/errors/GeneralErrors.sol";
import {ServiceAgreementErrorsV1} from "../v1/errors/ServiceAgreementErrorsV1.sol";
import {ServiceAgreementErrorsV2} from "./errors/ServiceAgreementErrorsV2.sol";
import {ServiceAgreementStructsV1} from "../v1/structs/ServiceAgreementStructsV1.sol";
import {ServiceAgreementStructsV2} from "./structs/ServiceAgreementStructsV2.sol";
import {ShardingTableStructsV2} from "../v2/structs/ShardingTableStructsV2.sol";
import {CommitManagerErrorsV2} from "./errors/CommitManagerErrorsV2.sol";
Expand Down Expand Up @@ -109,7 +110,7 @@ contract CommitManagerV2 is Named, Versioned, ContractStatus, Initializable {
function getTopCommitSubmissions(
bytes32 agreementId,
uint16 epoch
) external view returns (ServiceAgreementStructsV2.CommitSubmission[] memory) {
) external view returns (ServiceAgreementStructsV1.CommitSubmission[] memory) {
ServiceAgreementStorageProxy sasProxy = serviceAgreementStorageProxy;

if (!sasProxy.agreementV1Exists(agreementId))
Expand All @@ -124,8 +125,8 @@ contract CommitManagerV2 is Named, Versioned, ContractStatus, Initializable {

uint32 r0 = parametersStorage.r0();

ServiceAgreementStructsV2.CommitSubmission[]
memory epochCommits = new ServiceAgreementStructsV2.CommitSubmission[](r0);
ServiceAgreementStructsV1.CommitSubmission[]
memory epochCommits = new ServiceAgreementStructsV1.CommitSubmission[](r0);

bytes32 epochSubmissionsHead = sasProxy.getV1AgreementEpochSubmissionHead(agreementId, epoch);

Expand Down Expand Up @@ -231,9 +232,11 @@ contract CommitManagerV2 is Named, Versioned, ContractStatus, Initializable {
);
}

ShardingTableStructs.Node memory closestNode = shardingTableStorage.getNode(args.closestNode);
ShardingTableStructs.Node memory leftNeighborhoodEdge = shardingTableStorage.getNode(args.leftNeighborhoodEdge);
ShardingTableStructs.Node memory rightNeighborhoodEdge = shardingTableStorage.getNode(
ShardingTableStructsV2.Node memory closestNode = shardingTableStorage.getNode(args.closestNode);
ShardingTableStructsV2.Node memory leftNeighborhoodEdge = shardingTableStorage.getNode(
args.leftNeighborhoodEdge
);
ShardingTableStructsV2.Node memory rightNeighborhoodEdge = shardingTableStorage.getNode(
args.rightNeighborhoodEdge
);

Expand Down Expand Up @@ -358,7 +361,7 @@ contract CommitManagerV2 is Named, Versioned, ContractStatus, Initializable {

sasProxy.createV1CommitSubmissionObject(commitId, identityId, prevIdentityId, nextIdentityId, score);

ServiceAgreementStructsV2.CommitSubmission memory refCommit = sasProxy.getCommitSubmission(refCommitId);
ServiceAgreementStructsV1.CommitSubmission memory refCommit = sasProxy.getCommitSubmission(refCommitId);

if ((i == 0) && (refCommit.identityId == 0)) {
// No head -> Setting new head
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
pragma solidity ^0.8.16;

import {ContractStatus} from "../v1/abstract/ContractStatus.sol";
import {IProximityScoreFunctionsPair} from "./interface/IProximityScoreFunctionsPair.sol";
import {IScoreFunction} from "../v1/interface/IScoreFunction.sol";
import {Named} from "../v1/interface/Named.sol";
import {Versioned} from "../v1/interface/Versioned.sol";
import {UnorderedIndexableContractDynamicSetLib} from "../v1/utils/UnorderedIndexableContractDynamicSet.sol";

contract ScoringProxyV2 is Named, Versioned, ContractStatus {
contract ProximityScoringProxy is Named, Versioned, ContractStatus {
using UnorderedIndexableContractDynamicSetLib for UnorderedIndexableContractDynamicSetLib.Set;

event NewScoringFunctionContract(uint8 indexed scoreFunctionId, address newContractAddress);
Expand Down Expand Up @@ -44,15 +45,36 @@ contract ScoringProxyV2 is Named, Versioned, ContractStatus {
scoreFunctionSet.remove(scoreFunctionId);
}

//remove everthring except id, noramlised distance, normalized stake
function callScoreFunction(uint8 scoreFunctionId, uint256 distance, uint96 stake) external view returns (uint40) {
IScoreFunction scoreFunction = IScoreFunction(scoreFunctionSet.get(scoreFunctionId).addr);
return scoreFunction.calculateScore(distance, stake);
}

function callScoreFunction(
uint8 scoreFunctionId,
uint256 mappedDistance,
uint256 mappedStake
) external view returns (uint40) {
IScoreFunction scoringFunction = IScoreFunction(scoreFunctionSet.get(scoreFunctionId).addr);
uint256 distance,
uint256 maxDistance,
uint72 maxNodesNumber,
uint96 stake
) external view returns (uint64) {
IProximityScoreFunctionsPair proximityScoreFunctionsPair = IProximityScoreFunctionsPair(
scoreFunctionSet.get(scoreFunctionId).addr
);

return proximityScoreFunctionsPair.calculateScore(distance, maxDistance, maxNodesNumber, stake);
}

return scoringFunction.calculateScore(mappedDistance, mappedStake);
function callProximityFunction(
uint8 proximityFunctionId,
uint8 hashFunctionId,
bytes memory nodeId,
bytes memory keyword
) external view returns (uint256) {
IProximityScoreFunctionsPair proximityScoreFunctionsPair = IProximityScoreFunctionsPair(
scoreFunctionSet.get(proximityFunctionId).addr
);

return proximityScoreFunctionsPair.calculateDistance(hashFunctionId, nodeId, keyword);
}

function getScoreFunctionName(uint8 scoreFunctionId) external view returns (string memory) {
Expand Down
18 changes: 18 additions & 0 deletions contracts/v2/interface/IProximityScoreFunctionsPair.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.16;

interface IProximityScoreFunctionsPair {
function calculateScore(
uint256 distance,
uint256 maxDistance,
uint72 maxNodesNumber,
uint96 stake
) external view returns (uint64);

function calculateDistance(
uint8 hashFunctionId,
bytes calldata nodeId,
bytes calldata keyword
) external view returns (uint256);
}
106 changes: 67 additions & 39 deletions contracts/v2/scoring/LinearSum.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,27 @@ import {ParametersStorage} from "../../v1/storage/ParametersStorage.sol";
import {HubDependent} from "../../v1/abstract/HubDependent.sol";
import {Indexable} from "../../v1/interface/Indexable.sol";
import {Initializable} from "../../v1/interface/Initializable.sol";
import {IScoreFunction} from "../../v1/interface/IScoreFunction.sol";
import {IProximityScoreFunctionsPair} from "../interface/IProximityScoreFunctionsPair.sol";
import {Named} from "../../v1/interface/Named.sol";
import {PRBMathUD60x18} from "@prb/math/contracts/PRBMathUD60x18.sol";

contract LinearSum is IScoreFunction, Indexable, Named, HubDependent, Initializable {
using PRBMathUD60x18 for uint256;

contract LinearSum is IProximityScoreFunctionsPair, Indexable, Named, HubDependent, Initializable {
event ParameterChanged(string parameterName, uint256 parameterValue);

uint8 private constant _ID = 2;
string private constant _NAME = "LinearSum";

HashingProxy public hashingProxy;
ParametersStorage public parametersStorage;

uint256 constant HASH_RING_SIZE = type(uint256).max;

uint256 public distanceScaleFactor;
HashingProxy public hashingProxy;
ParametersStorage public parametersStorage;

uint96 public distanceScaleFactor;
uint96 public stakeScaleFactor;
uint32 public w1;
uint32 public w2;

constructor(address hubAddress) HubDependent(hubAddress) {
distanceScaleFactor = 1000000000000000000;
distanceScaleFactor = 1e18;
w1 = 1;
w2 = 1;
}
Expand All @@ -48,52 +45,85 @@ contract LinearSum is IScoreFunction, Indexable, Named, HubDependent, Initializa
return _NAME;
}

// TODO: Implement scoring function
function calculateScore(
uint8 hashFunctionId,
bytes calldata nodeId,
bytes calldata keyword
) external view returns (uint40) {
return 1;
uint256 distance,
uint256 maxDistance,
uint72 maxNodesNumber,
uint96 stake
) external view returns (uint64) {
return ((1e18 - normalizeDistance(distance, maxDistance, maxNodesNumber)) * w1 + normalizeStake(stake) * w2);
}

// TODO: Change this
function calculateDistance(
uint8 hashFunctionId,
bytes calldata nodeId,
bytes calldata keyword
) external view returns (uint256) {
HashingProxy hp = hashingProxy;
bytes32 nodeIdHash = hp.callHashFunction(hashFunctionId, nodeId);
bytes32 keywordHash = hp.callHashFunction(hashFunctionId, keyword);
uint256 nodePositionOnHashRing = uint256(hashingProxy.callHashFunction(hashFunctionId, nodeId));
uint256 keywordPositionOnHashRing = uint256(hashingProxy.callHashFunction(hashFunctionId, keyword));

return uint256(nodeIdHash ^ keywordHash);
uint256 directDistance = (
(nodePositionOnHashRing > keywordPositionOnHashRing)
? nodePositionOnHashRing - keywordPositionOnHashRing
: keywordPositionOnHashRing - nodePositionOnHashRing
);

return (directDistance < HASH_RING_SIZE - directDistance) ? directDistance : HASH_RING_SIZE - directDistance;
}

function calculateBidirectionalProximityOnHashRing(
uint8 hashFunctionId,
bytes calldata peerHash,
bytes calldata keyHash
) external view returns (uint256) {
uint256 peerPositionOnHashRing = uint256(hashingProxy.callHashFunction(hashFunctionId, peerHash));
uint256 keyPositionOnHashRing = uint256(hashingProxy.callHashFunction(hashFunctionId, keyHash));

uint256 directDistance;
if (peerPositionOnHashRing > keyPositionOnHashRing) {
directDistance = peerPositionOnHashRing - keyPositionOnHashRing;
} else {
directDistance = keyPositionOnHashRing - peerPositionOnHashRing;
function normalizeDistance(
uint256 distance,
uint256 maxDistance,
uint72 maxNodesNumber
) public view returns (uint64) {
if (distance == 0) {
return 0;
}

uint256 idealMaxDistance = (HASH_RING_SIZE / maxNodesNumber) * (parametersStorage.r2() / 2);
uint256 divisor = (maxDistance <= idealMaxDistance) ? maxDistance : idealMaxDistance;

uint256 maxMultiplier = type(uint256).max / distance;

uint256 scaledDistanceScaleFactor = distanceScaleFactor;
uint256 compensationFactor = 1;

if (scaledDistanceScaleFactor > maxMultiplier) {
compensationFactor = scaledDistanceScaleFactor / maxMultiplier;
scaledDistanceScaleFactor = maxMultiplier;
}

uint256 wraparoundDistance = HASH_RING_SIZE - directDistance;
uint256 scaledDistance = distance * scaledDistanceScaleFactor;
uint256 adjustedDivisor = divisor / compensationFactor;

return uint64(scaledDistance / adjustedDivisor);
}

function normalizeStake(uint96 stake) public view returns (uint64) {
ParametersStorage ps = parametersStorage;

uint96 minStake = ps.minimumStake();
uint96 maxStake = ps.maximumStake();

return (directDistance < wraparoundDistance) ? directDistance : wraparoundDistance;
return uint64((uint256(distanceScaleFactor) * (stake - minStake)) / (maxStake - minStake));
}

function getParameters() external view returns (uint256, uint32, uint32) {
function getParameters() external view returns (uint192, uint32, uint32) {
return (distanceScaleFactor, w1, w2);
}

function setDistanceScaleFactor(uint96 distanceScaleFactor_) external onlyHubOwner {
distanceScaleFactor = distanceScaleFactor_;

emit ParameterChanged("distanceScaleFactor", distanceScaleFactor);
}

function setStakeScaleFactor(uint96 stakeScaleFactor_) external onlyHubOwner {
stakeScaleFactor = stakeScaleFactor_;

emit ParameterChanged("stakeScaleFactor", stakeScaleFactor);
}

function setW1(uint32 w1_) external onlyHubOwner {
w1 = w1_;

Expand All @@ -105,6 +135,4 @@ contract LinearSum is IScoreFunction, Indexable, Named, HubDependent, Initializa

emit ParameterChanged("w2", w2);
}

function calculateScore(uint256 distance, uint96 stake) external view override returns (uint40) {}
}
55 changes: 0 additions & 55 deletions contracts/v2/structs/ServiceAgreementStructsV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,6 @@
pragma solidity ^0.8.16;

library ServiceAgreementStructsV2 {
struct CommitSubmission {
uint72 identityId;
uint72 prevIdentityId;
uint72 nextIdentityId;
uint40 score;
}

struct ServiceAgreementInputArgs {
address assetCreator;
address assetContract;
uint256 tokenId;
bytes keyword;
uint8 hashFunctionId;
uint16 epochsNumber;
uint96 tokenAmount;
uint8 scoreFunctionId;
}

struct ServiceAgreement {
uint256 startTime;
uint16 epochsNumber;
uint128 epochLength;
uint96 tokenAmount;
uint8 scoreFunctionId;
uint8 proofWindowOffsetPerc;
// epoch => headCommitId
mapping(uint16 => bytes32) epochSubmissionHeads;
// epoch => number of nodes received rewards
mapping(uint16 => uint32) rewardedNodesNumber;
}

struct ExtendedServiceAgreement {
uint256 startTime;
uint16 epochsNumber;
uint128 epochLength;
uint96 tokenAmount;
uint96 updateTokenAmount;
uint8 scoreFunctionId;
uint8 proofWindowOffsetPerc;
// keccak256(epoch + stateIndex) => headCommitId
mapping(bytes32 => bytes32) epochSubmissionHeads;
// epoch => number of nodes received rewards
mapping(uint16 => uint32) rewardedNodesNumber;
}

struct CommitInputArgs {
address assetContract;
uint256 tokenId;
Expand All @@ -58,14 +13,4 @@ library ServiceAgreementStructsV2 {
uint72 leftNeighborhoodEdge;
uint72 rightNeighborhoodEdge;
}

struct ProofInputArgs {
address assetContract;
uint256 tokenId;
bytes keyword;
uint8 hashFunctionId;
uint16 epoch;
bytes32[] proof;
bytes32 chunkHash;
}
}

0 comments on commit 7a86352

Please sign in to comment.