Skip to content

Commit

Permalink
Merge pull request #89 from KPrasch/auth
Browse files Browse the repository at this point in the history
TACo Encryption Allow Logic Interfaces
  • Loading branch information
KPrasch authored Aug 18, 2023
2 parents 5251e07 + 0610332 commit 653b455
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 38 deletions.
2 changes: 0 additions & 2 deletions ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ deployments:
pre_base_penalty: 2
pre_penalty_history_coefficient: 0
pre_percentage_penalty_coefficient: 100000
pre_min_authorization: 40000000000000000000000
pre_min_operator_seconds: 86400 # one day in seconds
reward_duration: 604800 # one week in seconds
deauthorization_duration: 5184000 # 60 days in seconds
verify: False
Expand Down
47 changes: 35 additions & 12 deletions contracts/contracts/coordination/Coordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "./IFeeModel.sol";
import "./IReimbursementPool.sol";
import "../lib/BLS12381.sol";
import "../../threshold/IAccessControlApplication.sol";
import "./IEncryptionAuthorizer.sol";

/**
* @title Coordinator
Expand Down Expand Up @@ -58,6 +59,7 @@ contract Coordinator is AccessControlDefaultAdminRules {
address authority;
uint16 dkgSize;
bool aggregationMismatch;
IEncryptionAuthorizer accessController;
BLS12381.G1Point publicKey;
bytes aggregatedTranscript;
Participant[] participant;
Expand Down Expand Up @@ -100,11 +102,15 @@ contract Coordinator is AccessControlDefaultAdminRules {
feeModel = IFeeModel(_feeModel);
}

function getRitualState(uint256 ritualId) external view returns (RitualState){
// TODO: restrict to ritualID < rituals.length?
function getRitualState(uint32 ritualId) external view returns (RitualState){
// TODO: restrict to ritualId < rituals.length?
return getRitualState(rituals[ritualId]);
}

function isRitualFinalized(uint32 ritualId) external view returns (bool){
return getRitualState(rituals[ritualId]) == RitualState.FINALIZED;
}

function getRitualState(Ritual storage ritual) internal view returns (RitualState){
uint32 t0 = ritual.initTimestamp;
uint32 deadline = t0 + timeout;
Expand All @@ -125,6 +131,7 @@ contract Coordinator is AccessControlDefaultAdminRules {
// - No public key
// - All transcripts and all aggregations
// - Still within the deadline
revert("Invalid ritual state");
}
}

Expand Down Expand Up @@ -175,6 +182,13 @@ contract Coordinator is AccessControlDefaultAdminRules {
// TODO: Events
}

function setRitualAuthority(uint32 ritualId, address authority) external {
Ritual storage ritual = rituals[ritualId];
require(getRitualState(ritual) == RitualState.FINALIZED, "Ritual not finalized");
require(msg.sender == ritual.authority, "Sender not ritual authority");
ritual.authority = authority;
}

function numberOfRituals() external view returns (uint256) {
return rituals.length;
}
Expand All @@ -187,8 +201,12 @@ contract Coordinator is AccessControlDefaultAdminRules {
function initiateRitual(
address[] calldata providers,
address authority,
uint32 duration
uint32 duration,
IEncryptionAuthorizer accessController
) external returns (uint32) {

require(authority != address(0), "Invalid authority");

require(
isInitiationPublic || hasRole(INITIATOR_ROLE, msg.sender),
"Sender can't initiate ritual"
Expand All @@ -205,6 +223,7 @@ contract Coordinator is AccessControlDefaultAdminRules {
ritual.dkgSize = uint16(length);
ritual.initTimestamp = uint32(block.timestamp);
ritual.endTimestamp = ritual.initTimestamp + duration;
ritual.accessController = accessController;

address previous = address(0);
for (uint256 i = 0; i < length; i++) {
Expand Down Expand Up @@ -272,6 +291,10 @@ contract Coordinator is AccessControlDefaultAdminRules {
processReimbursement(initialGasLeft);
}

function getAuthority(uint32 ritualId) external view returns (address) {
return rituals[ritualId].authority;
}

function postAggregation(
uint32 ritualId,
bytes calldata aggregatedTranscript,
Expand Down Expand Up @@ -359,39 +382,39 @@ contract Coordinator is AccessControlDefaultAdminRules {
}

function getParticipantFromProvider(
uint256 ritualID,
uint32 ritualId,
address provider
) external view returns (Participant memory) {
return getParticipantFromProvider(rituals[ritualID], provider);
return getParticipantFromProvider(rituals[ritualId], provider);
}

function processRitualPayment(uint256 ritualID, address[] calldata providers, uint32 duration) internal {
function processRitualPayment(uint32 ritualId, address[] calldata providers, uint32 duration) internal {
uint256 ritualCost = feeModel.getRitualInitiationCost(providers, duration);
if (ritualCost > 0) {
totalPendingFees += ritualCost;
assert(pendingFees[ritualID] == 0); // TODO: This is an invariant, not sure if actually needed
pendingFees[ritualID] += ritualCost;
assert(pendingFees[ritualId] == 0); // TODO: This is an invariant, not sure if actually needed
pendingFees[ritualId] += ritualCost;
IERC20 currency = IERC20(feeModel.currency());
currency.safeTransferFrom(msg.sender, address(this), ritualCost);
// TODO: Define methods to manage these funds
}
}

function processPendingFee(uint256 ritualID) public {
Ritual storage ritual = rituals[ritualID];
function processPendingFee(uint32 ritualId) public {
Ritual storage ritual = rituals[ritualId];
RitualState state = getRitualState(ritual);
require(
state == RitualState.TIMEOUT ||
state == RitualState.INVALID ||
state == RitualState.FINALIZED,
"Ritual is not ended"
);
uint256 pending = pendingFees[ritualID];
uint256 pending = pendingFees[ritualId];
require(pending > 0, "No pending fees for this ritual");

// Finalize fees for this ritual
totalPendingFees -= pending;
delete pendingFees[ritualID];
delete pendingFees[ritualId];
// Transfer fees back to initiator if failed
if (state == RitualState.TIMEOUT || state == RitualState.INVALID) {
// Amount to refund depends on how much work nodes did for the ritual.
Expand Down
58 changes: 58 additions & 0 deletions contracts/contracts/coordination/GlobalAllowList.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControlDefaultAdminRules.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./IEncryptionAuthorizer.sol";
import "./Coordinator.sol";


contract GlobalAllowList is AccessControlDefaultAdminRules, IEncryptionAuthorizer {
using ECDSA for bytes32;

Coordinator public coordinator;
mapping(uint256 => mapping(address => bool)) public authorizations;

constructor(
Coordinator _coordinator,
address _admin
) AccessControlDefaultAdminRules(0, _admin) {
require(address(_coordinator) != address(0), "Coordinator cannot be zero address");
require(_coordinator.numberOfRituals() >= 0, "Invalid coordinator");
coordinator = _coordinator;
}

modifier onlyAuthority(uint32 ritualId) {
require(coordinator.getAuthority(ritualId) == msg.sender,
"Only ritual authority is permitted");
_;
}

function setCoordinator(Coordinator _coordinator) public {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Only admin can set coordinator");
coordinator = _coordinator;
}

function isAuthorized(
uint32 ritualId,
bytes memory evidence,
bytes32 digest
) public view override returns(bool) {
address recovered_address = digest.toEthSignedMessageHash().recover(evidence);
return authorizations[ritualId][recovered_address];
}

function authorize(uint32 ritualId, address[] calldata addresses) public onlyAuthority(ritualId) {
require(coordinator.isRitualFinalized(ritualId),
"Only active rituals can add authorizations");
for (uint256 i=0; i < addresses.length; i++) {
authorizations[ritualId][addresses[i]] = true;
}
}

function deauthorize(uint32 ritualId, address[] calldata addresses) public onlyAuthority(ritualId) {
require(coordinator.isRitualFinalized(ritualId),
"Only active rituals can add authorizations");
for (uint256 i=0; i < addresses.length; i++) {
authorizations[ritualId][addresses[i]] = false;
}
}
}
9 changes: 9 additions & 0 deletions contracts/contracts/coordination/IEncryptionAuthorizer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pragma solidity ^0.8.0;

interface IEncryptionAuthorizer {
function isAuthorized(
uint32 ritualID,
bytes memory evidence, // signature
bytes32 digest // signed message hash
) external view returns(bool);
}
Loading

0 comments on commit 653b455

Please sign in to comment.