From 091a897620e79aeabc1fd42ef1db6d56f0e1f167 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Tue, 5 Sep 2023 15:18:48 +0200
Subject: [PATCH] update coordinator contract
---
abi/Coordinator.json | 905 ++++++++++++++++++--
src/agents/coordinator.ts | 45 +-
src/conditions/condition-expr.ts | 6 +
src/dkg.ts | 21 +-
src/sdk/strategy/cbd-strategy.ts | 4 +-
src/taco.ts | 61 +-
test/unit/cbd-strategy.test.ts | 4 +-
test/unit/conditions/condition-expr.test.ts | 6 +
test/unit/taco.test.ts | 19 +-
test/utils.ts | 12 +-
10 files changed, 960 insertions(+), 123 deletions(-)
diff --git a/abi/Coordinator.json b/abi/Coordinator.json
index c572ea259..a9f0143da 100644
--- a/abi/Coordinator.json
+++ b/abi/Coordinator.json
@@ -3,7 +3,7 @@
"inputs": [
{
"internalType": "contract IAccessControlApplication",
- "name": "app",
+ "name": "_stakes",
"type": "address"
},
{
@@ -12,9 +12,24 @@
"type": "uint32"
},
{
- "internalType": "uint32",
+ "internalType": "uint16",
"name": "_maxDkgSize",
- "type": "uint32"
+ "type": "uint16"
+ },
+ {
+ "internalType": "address",
+ "name": "_admin",
+ "type": "address"
+ },
+ {
+ "internalType": "contract IERC20",
+ "name": "_currency",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_feeRatePerSecond",
+ "type": "uint256"
}
],
"stateMutability": "nonpayable",
@@ -45,21 +60,65 @@
"name": "AggregationPosted",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "DefaultAdminDelayChangeCanceled",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
{
- "indexed": true,
- "internalType": "uint32",
- "name": "ritualId",
- "type": "uint32"
+ "indexed": false,
+ "internalType": "uint48",
+ "name": "newDelay",
+ "type": "uint48"
},
+ {
+ "indexed": false,
+ "internalType": "uint48",
+ "name": "effectSchedule",
+ "type": "uint48"
+ }
+ ],
+ "name": "DefaultAdminDelayChangeScheduled",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "DefaultAdminTransferCanceled",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
{
"indexed": true,
"internalType": "address",
- "name": "initiator",
+ "name": "newAdmin",
"type": "address"
},
+ {
+ "indexed": false,
+ "internalType": "uint48",
+ "name": "acceptSchedule",
+ "type": "uint48"
+ }
+ ],
+ "name": "DefaultAdminTransferScheduled",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
{
"indexed": false,
"internalType": "bool",
@@ -75,15 +134,15 @@
"inputs": [
{
"indexed": false,
- "internalType": "uint32",
+ "internalType": "uint16",
"name": "oldSize",
- "type": "uint32"
+ "type": "uint16"
},
{
"indexed": false,
- "internalType": "uint32",
+ "internalType": "uint16",
"name": "newSize",
- "type": "uint32"
+ "type": "uint16"
}
],
"name": "MaxDkgSizeChanged",
@@ -92,20 +151,118 @@
{
"anonymous": false,
"inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "participant",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes32",
+ "name": "word0",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "word1",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "word2",
+ "type": "bytes32"
+ }
+ ],
+ "indexed": false,
+ "internalType": "struct BLS12381.G2Point",
+ "name": "publicKey",
+ "type": "tuple"
+ }
+ ],
+ "name": "ParticipantPublicKeySet",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "previousAdminRole",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "newAdminRole",
+ "type": "bytes32"
+ }
+ ],
+ "name": "RoleAdminChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "RoleGranted",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
{
"indexed": true,
"internalType": "address",
- "name": "previousOwner",
+ "name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
- "name": "newOwner",
+ "name": "sender",
"type": "address"
}
],
- "name": "OwnershipTransferred",
+ "name": "RoleRevoked",
"type": "event"
},
{
@@ -133,7 +290,7 @@
{
"indexed": true,
"internalType": "address",
- "name": "initiator",
+ "name": "authority",
"type": "address"
},
{
@@ -190,6 +347,52 @@
"name": "TranscriptPosted",
"type": "event"
},
+ {
+ "inputs": [],
+ "name": "DEFAULT_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "INITIATOR_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "TREASURY_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "acceptDefaultAdminTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [],
"name": "application",
@@ -203,6 +406,39 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newAdmin",
+ "type": "address"
+ }
+ ],
+ "name": "beginDefaultAdminTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "cancelDefaultAdminTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint48",
+ "name": "newDelay",
+ "type": "uint48"
+ }
+ ],
+ "name": "changeDefaultAdminDelay",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -223,11 +459,95 @@
"type": "function"
},
{
- "inputs": [
+ "inputs": [],
+ "name": "currency",
+ "outputs": [
+ {
+ "internalType": "contract IERC20",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "defaultAdmin",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "defaultAdminDelay",
+ "outputs": [
+ {
+ "internalType": "uint48",
+ "name": "",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "defaultAdminDelayIncreaseWait",
+ "outputs": [
+ {
+ "internalType": "uint48",
+ "name": "",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "feeRatePerSecond",
+ "outputs": [
{
"internalType": "uint256",
- "name": "ritualID",
+ "name": "",
"type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "name": "getAuthority",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
},
{
"internalType": "address",
@@ -312,17 +632,271 @@
{
"inputs": [
{
- "internalType": "uint256",
- "name": "ritualId",
- "type": "uint256"
+ "internalType": "address",
+ "name": "_provider",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_ritualId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getProviderPublicKey",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "bytes32",
+ "name": "word0",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "word1",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "word2",
+ "type": "bytes32"
+ }
+ ],
+ "internalType": "struct BLS12381.G2Point",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "name": "getPublicKeyFromRitualId",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "bytes32",
+ "name": "word0",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes16",
+ "name": "word1",
+ "type": "bytes16"
+ }
+ ],
+ "internalType": "struct BLS12381.G1Point",
+ "name": "dkgPublicKey",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "bytes32",
+ "name": "word0",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes16",
+ "name": "word1",
+ "type": "bytes16"
+ }
+ ],
+ "internalType": "struct BLS12381.G1Point",
+ "name": "dkgPublicKey",
+ "type": "tuple"
+ }
+ ],
+ "name": "getRitualIdFromPublicKey",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "providers",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint32",
+ "name": "duration",
+ "type": "uint32"
+ }
+ ],
+ "name": "getRitualInitiationCost",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "name": "getRitualState",
+ "outputs": [
+ {
+ "internalType": "enum Coordinator.RitualState",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getRoleAdmin",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint16",
+ "name": "size",
+ "type": "uint16"
+ }
+ ],
+ "name": "getThresholdForRitualSize",
+ "outputs": [
+ {
+ "internalType": "uint16",
+ "name": "",
+ "type": "uint16"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "grantRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "hasRole",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "providers",
+ "type": "address[]"
+ },
+ {
+ "internalType": "address",
+ "name": "authority",
+ "type": "address"
+ },
+ {
+ "internalType": "uint32",
+ "name": "duration",
+ "type": "uint32"
+ },
+ {
+ "internalType": "contract IEncryptionAuthorizer",
+ "name": "accessController",
+ "type": "address"
}
],
- "name": "getRitualState",
+ "name": "initiateRitual",
"outputs": [
{
- "internalType": "enum Coordinator.RitualState",
+ "internalType": "uint32",
"name": "",
- "type": "uint8"
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "isInitiationPublic",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
}
],
"stateMutability": "view",
@@ -331,19 +905,26 @@
{
"inputs": [
{
- "internalType": "address[]",
- "name": "providers",
- "type": "address[]"
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
}
],
- "name": "initiateRitual",
+ "name": "isRitualFinalized",
"outputs": [
{
- "internalType": "uint32",
+ "internalType": "bool",
"name": "",
- "type": "uint32"
+ "type": "bool"
}
],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "makeInitiationPublic",
+ "outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
@@ -352,9 +933,9 @@
"name": "maxDkgSize",
"outputs": [
{
- "internalType": "uint32",
+ "internalType": "uint16",
"name": "",
- "type": "uint32"
+ "type": "uint16"
}
],
"stateMutability": "view",
@@ -386,6 +967,61 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "pendingDefaultAdmin",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "newAdmin",
+ "type": "address"
+ },
+ {
+ "internalType": "uint48",
+ "name": "schedule",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "pendingDefaultAdminDelay",
+ "outputs": [
+ {
+ "internalType": "uint48",
+ "name": "newDelay",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "schedule",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "pendingFees",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -412,7 +1048,7 @@
}
],
"internalType": "struct BLS12381.G1Point",
- "name": "publicKey",
+ "name": "dkgPublicKey",
"type": "tuple"
},
{
@@ -445,8 +1081,50 @@
"type": "function"
},
{
- "inputs": [],
- "name": "renounceOwnership",
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "name": "processPendingFee",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "renounceRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "revokeRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
@@ -468,23 +1146,48 @@
},
{
"internalType": "uint32",
- "name": "dkgSize",
+ "name": "initTimestamp",
"type": "uint32"
},
{
"internalType": "uint32",
- "name": "initTimestamp",
+ "name": "endTimestamp",
"type": "uint32"
},
{
- "internalType": "uint32",
+ "internalType": "uint16",
"name": "totalTranscripts",
- "type": "uint32"
+ "type": "uint16"
},
{
- "internalType": "uint32",
+ "internalType": "uint16",
"name": "totalAggregations",
- "type": "uint32"
+ "type": "uint16"
+ },
+ {
+ "internalType": "address",
+ "name": "authority",
+ "type": "address"
+ },
+ {
+ "internalType": "uint16",
+ "name": "dkgSize",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint16",
+ "name": "threshold",
+ "type": "uint16"
+ },
+ {
+ "internalType": "bool",
+ "name": "aggregationMismatch",
+ "type": "bool"
+ },
+ {
+ "internalType": "contract IEncryptionAuthorizer",
+ "name": "accessController",
+ "type": "address"
},
{
"components": [
@@ -503,11 +1206,6 @@
"name": "publicKey",
"type": "tuple"
},
- {
- "internalType": "bool",
- "name": "aggregationMismatch",
- "type": "bool"
- },
{
"internalType": "bytes",
"name": "aggregatedTranscript",
@@ -517,12 +1215,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "rollbackDefaultAdminDelay",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
- "internalType": "uint32",
+ "internalType": "uint16",
"name": "newSize",
- "type": "uint32"
+ "type": "uint16"
}
],
"name": "setMaxDkgSize",
@@ -530,6 +1235,67 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "bytes32",
+ "name": "word0",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "word1",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "word2",
+ "type": "bytes32"
+ }
+ ],
+ "internalType": "struct BLS12381.G2Point",
+ "name": "_publicKey",
+ "type": "tuple"
+ }
+ ],
+ "name": "setProviderPublicKey",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "contract IReimbursementPool",
+ "name": "pool",
+ "type": "address"
+ }
+ ],
+ "name": "setReimbursementPool",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "internalType": "address",
+ "name": "authority",
+ "type": "address"
+ }
+ ],
+ "name": "setRitualAuthority",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -543,6 +1309,25 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [],
"name": "timeout",
@@ -556,15 +1341,33 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "totalPendingFees",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
- "internalType": "address",
- "name": "newOwner",
+ "internalType": "contract IERC20",
+ "name": "token",
"type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
}
],
- "name": "transferOwnership",
+ "name": "withdrawTokens",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
diff --git a/src/agents/coordinator.ts b/src/agents/coordinator.ts
index db8378d8d..28ed866cc 100644
--- a/src/agents/coordinator.ts
+++ b/src/agents/coordinator.ts
@@ -1,5 +1,5 @@
-import { SessionStaticKey } from '@nucypher/nucypher-core';
-import { ethers } from 'ethers';
+import { DkgPublicKey, SessionStaticKey } from '@nucypher/nucypher-core';
+import { BigNumberish, ethers } from 'ethers';
import {
Coordinator,
@@ -13,12 +13,16 @@ import { DEFAULT_WAIT_N_CONFIRMATIONS, getContract } from './contracts';
export interface CoordinatorRitual {
initiator: string;
- dkgSize: number;
initTimestamp: number;
+ endTimestamp: number;
totalTranscripts: number;
totalAggregations: number;
- publicKey: BLS12381.G1PointStructOutput;
+ authority: string;
+ dkgSize: number;
+ threshold: number;
aggregationMismatch: boolean;
+ accessController: string;
+ publicKey: BLS12381.G1PointStructOutput;
aggregatedTranscript: string;
}
@@ -59,10 +63,18 @@ export class DkgCoordinatorAgent {
public static async initializeRitual(
provider: ethers.providers.Provider,
signer: ethers.Signer,
- providers: ChecksumAddress[]
+ providers: ChecksumAddress[],
+ authority: string,
+ duration: BigNumberish,
+ accessController: string
): Promise {
const Coordinator = await this.connectReadWrite(provider, signer);
- const tx = await Coordinator.initiateRitual(providers);
+ const tx = await Coordinator.initiateRitual(
+ providers,
+ authority,
+ duration,
+ accessController
+ );
const txReceipt = await tx.wait(DEFAULT_WAIT_N_CONFIRMATIONS);
const [ritualStartEvent] = txReceipt.events ?? [];
if (!ritualStartEvent) {
@@ -95,16 +107,25 @@ export class DkgCoordinatorAgent {
const Coordinator = await this.connectReadOnly(provider);
// We leave `initiator` undefined because we don't care who the initiator is
// We leave `successful` undefined because we don't care if the ritual was successful
- const eventFilter = Coordinator.filters.EndRitual(
- ritualId,
- undefined,
- undefined
- );
- Coordinator.once(eventFilter, (_ritualId, _initiator, successful) => {
+ const eventFilter = Coordinator.filters.EndRitual(ritualId, undefined);
+ Coordinator.once(eventFilter, (_ritualId, successful) => {
callback(successful);
});
}
+ public static async getRitualIdFromPublicKey(
+ provider: ethers.providers.Provider,
+ dkgPublicKey: DkgPublicKey
+ ): Promise {
+ const Coordinator = await this.connectReadOnly(provider);
+ const dkgPublicKeyBytes = dkgPublicKey.toBytes();
+ const pointStruct: BLS12381.G1PointStruct = {
+ word0: dkgPublicKeyBytes.slice(0, 16),
+ word1: dkgPublicKeyBytes.slice(16, 32),
+ };
+ return await Coordinator.getRitualIdFromPublicKey(pointStruct);
+ }
+
private static async connectReadOnly(provider: ethers.providers.Provider) {
return await this.connect(provider);
}
diff --git a/src/conditions/condition-expr.ts b/src/conditions/condition-expr.ts
index d5e0d0e45..d7b0ce831 100644
--- a/src/conditions/condition-expr.ts
+++ b/src/conditions/condition-expr.ts
@@ -84,6 +84,12 @@ export class ConditionExpression {
return new WASMConditions(toJSON(this.toObj()));
}
+ public static fromWASMConditions(
+ wasmConditions: WASMConditions
+ ): ConditionExpression {
+ return ConditionExpression.fromObj(JSON.parse(wasmConditions.toString()));
+ }
+
public buildContext(
provider: ethers.providers.Provider,
customParameters: Record = {},
diff --git a/src/dkg.ts b/src/dkg.ts
index c5056c8f7..b907158ad 100644
--- a/src/dkg.ts
+++ b/src/dkg.ts
@@ -1,5 +1,5 @@
import { DkgPublicKey } from '@nucypher/nucypher-core';
-import { ethers } from 'ethers';
+import { BigNumberish, ethers } from 'ethers';
import { DkgCoordinatorAgent, DkgRitualState } from './agents/coordinator';
import { ChecksumAddress } from './types';
@@ -58,22 +58,23 @@ export class DkgRitual {
}
}
-// TODO: Currently, we're assuming that the threshold is always `floor(sharesNum / 2) + 1`.
-// https://github.com/nucypher/nucypher/issues/3095
-const assumedThreshold = (sharesNum: number): number =>
- Math.floor(sharesNum / 2) + 1;
-
export class DkgClient {
public static async initializeRitual(
provider: ethers.providers.Provider,
signer: ethers.Signer,
ursulas: ChecksumAddress[],
+ authority: string,
+ duration: BigNumberish,
+ accessController: string,
waitUntilEnd = false
): Promise {
const ritualId = await DkgCoordinatorAgent.initializeRitual(
provider,
signer,
- ursulas.sort()
+ ursulas.sort(),
+ authority,
+ duration,
+ accessController
);
if (waitUntilEnd) {
@@ -111,7 +112,7 @@ export class DkgClient {
});
};
- public static async getExistingRitual(
+ public static async getRitual(
provider: ethers.providers.Provider,
ritualId: number
): Promise {
@@ -129,7 +130,7 @@ export class DkgClient {
DkgPublicKey.fromBytes(dkgPkBytes),
{
sharesNum: ritual.dkgSize,
- threshold: assumedThreshold(ritual.dkgSize),
+ threshold: ritual.threshold,
},
ritualState
);
@@ -139,7 +140,7 @@ export class DkgClient {
provider: ethers.providers.Provider,
ritualId: number
): Promise {
- const ritual = await DkgClient.getExistingRitual(provider, ritualId);
+ const ritual = await DkgClient.getRitual(provider, ritualId);
if (ritual.state !== DkgRitualState.FINALIZED) {
throw new Error(
`Ritual ${ritualId} is not finalized. State: ${ritual.state}`
diff --git a/src/sdk/strategy/cbd-strategy.ts b/src/sdk/strategy/cbd-strategy.ts
index ed0a37d8f..ed27e24f7 100644
--- a/src/sdk/strategy/cbd-strategy.ts
+++ b/src/sdk/strategy/cbd-strategy.ts
@@ -44,7 +44,7 @@ export class CbdStrategy {
// // Given that we just initialized the ritual, this should never happen
// throw new Error('Ritual ID is undefined');
// }
- const dkgRitual = await DkgClient.getExistingRitual(provider, ritualId);
+ const dkgRitual = await DkgClient.getRitual(provider, ritualId);
return DeployedCbdStrategy.create(dkgRitual, this.cohort.porterUri);
}
@@ -92,7 +92,7 @@ export class DeployedCbdStrategy {
porterUri: string,
ritualId: number
): Promise {
- const dkgRitual = await DkgClient.getExistingRitual(provider, ritualId);
+ const dkgRitual = await DkgClient.getRitual(provider, ritualId);
return DeployedCbdStrategy.create(dkgRitual, porterUri);
}
diff --git a/src/taco.ts b/src/taco.ts
index ab68104b3..fad36b183 100644
--- a/src/taco.ts
+++ b/src/taco.ts
@@ -1,6 +1,7 @@
import { DkgPublicKey, ThresholdMessageKit } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
+import { DkgCoordinatorAgent } from './agents/coordinator';
import { ThresholdDecrypter } from './characters/cbd-recipient';
import { Enrico } from './characters/enrico';
import { Condition, ConditionExpression } from './conditions';
@@ -8,69 +9,53 @@ import { DkgClient } from './dkg';
import { getPorterUri } from './porter';
import { toBytes } from './utils';
-export interface TacoMessageKit {
- thresholdMessageKit: ThresholdMessageKit;
- conditionExpr: ConditionExpression;
- // TODO: How do we get rid of these two fields? We need them for decrypting
- // We ritualId in order to fetch the DKG participants and create DecryptionRequests for them
- ritualId: number;
- // We need to know the threshold in order to create DecryptionRequests
- threshold: number;
-}
-
export const encrypt = async (
provider: ethers.providers.Provider,
message: string,
condition: Condition,
ritualId: number
-): Promise => {
+): Promise => {
const dkgRitual = await DkgClient.getFinalizedRitual(provider, ritualId);
- return await encryptLight(
- message,
- condition,
- dkgRitual.dkgPublicKey,
- dkgRitual.dkgParams.threshold,
- ritualId
- );
+ return await encryptLight(message, condition, dkgRitual.dkgPublicKey);
};
export const encryptLight = async (
message: string,
condition: Condition,
- dkgPublicKey: DkgPublicKey,
- // TODO: Remove these parameters after fixing TacoMessageKit
- threshold: number,
- ritualId: number
-): Promise => {
+ dkgPublicKey: DkgPublicKey
+): Promise => {
const encrypter = new Enrico(dkgPublicKey);
const conditionExpr = new ConditionExpression(condition);
- const thresholdMessageKit = await encrypter.encryptMessageCbd(
- toBytes(message),
- conditionExpr
- );
- return {
- thresholdMessageKit,
- threshold,
- ritualId,
- conditionExpr,
- };
+ return encrypter.encryptMessageCbd(toBytes(message), conditionExpr);
};
export const decrypt = async (
provider: ethers.providers.Provider,
- messageKit: TacoMessageKit,
+ messageKit: ThresholdMessageKit,
signer?: ethers.Signer,
porterUri = getPorterUri('tapir')
): Promise => {
+ const ritualId = await DkgCoordinatorAgent.getRitualIdFromPublicKey(
+ provider,
+ messageKit.acp.publicKey
+ );
+ const ritual = await DkgClient.getFinalizedRitual(provider, ritualId);
const decrypter = ThresholdDecrypter.create(
porterUri,
- messageKit.ritualId,
- messageKit.threshold
+ ritualId,
+ ritual.dkgParams.threshold
+ );
+ // TODO: What do we do if there are no conditions?
+ if (!messageKit.acp.conditions) {
+ throw new Error('ThresholdMessageKit does not contain conditions');
+ }
+ const conditionExpr = ConditionExpression.fromWASMConditions(
+ messageKit.acp.conditions
);
return decrypter.retrieveAndDecrypt(
provider,
- messageKit.conditionExpr,
- messageKit.thresholdMessageKit,
+ conditionExpr,
+ messageKit,
signer
);
};
diff --git a/test/unit/cbd-strategy.test.ts b/test/unit/cbd-strategy.test.ts
index 8e1aabc21..64c01752d 100644
--- a/test/unit/cbd-strategy.test.ts
+++ b/test/unit/cbd-strategy.test.ts
@@ -15,8 +15,8 @@ import {
fakeUrsulas,
makeCohort,
mockCbdDecrypt,
- mockGetExistingRitual,
mockGetParticipants,
+ mockGetRitual,
mockGetUrsulas,
mockRandomSessionStaticSecret,
} from '../utils';
@@ -54,7 +54,7 @@ async function makeDeployedCbdStrategy() {
const mockedDkg = fakeDkgFlow(variant, 0, 4, 4);
const mockedDkgRitual = fakeDkgRitual(mockedDkg);
const getUrsulasSpy = mockGetUrsulas(ursulas);
- const getExistingRitualSpy = mockGetExistingRitual(mockedDkgRitual);
+ const getExistingRitualSpy = mockGetRitual(mockedDkgRitual);
const deployedStrategy = await strategy.deploy(provider, ritualId);
diff --git a/test/unit/conditions/condition-expr.test.ts b/test/unit/conditions/condition-expr.test.ts
index 238020313..9715d1eae 100644
--- a/test/unit/conditions/condition-expr.test.ts
+++ b/test/unit/conditions/condition-expr.test.ts
@@ -184,6 +184,12 @@ describe('condition set', () => {
ConditionExpression.fromJSON(conditionExprJson);
expect(conditionExprFromJson).toBeDefined();
expect(conditionExprFromJson.equals(conditionExprFromJson)).toBeTruthy();
+
+ const asWasmConditions = conditionExprFromJson.toWASMConditions();
+ const fromWasmConditions =
+ ConditionExpression.fromWASMConditions(asWasmConditions);
+ expect(fromWasmConditions).toBeDefined();
+ expect(fromWasmConditions.equals(conditionExprFromJson)).toBeTruthy();
});
it('incompatible version', () => {
diff --git a/test/unit/taco.test.ts b/test/unit/taco.test.ts
index bfe6ffc1f..8873f9b53 100644
--- a/test/unit/taco.test.ts
+++ b/test/unit/taco.test.ts
@@ -16,8 +16,9 @@ import {
fakeSigner,
fakeTDecFlow,
mockCbdDecrypt,
- mockGetExistingRitual,
mockGetParticipants,
+ mockGetRitual,
+ mockGetRitualIdFromPublicKey,
mockRandomSessionStaticSecret,
} from '../utils';
@@ -43,9 +44,9 @@ describe('taco', () => {
const mockedDkgRitual = fakeDkgRitual(mockedDkg);
const provider = fakeProvider(aliceSecretKey.toBEBytes());
const signer = fakeSigner(aliceSecretKey.toBEBytes());
- const getExistingRitualSpy = mockGetExistingRitual(mockedDkgRitual);
+ const getExistingRitualSpy = mockGetRitual(mockedDkgRitual);
- const tacoMk = await taco.encrypt(
+ const messageKit = await taco.encrypt(
provider,
message,
ownsNFT,
@@ -57,9 +58,9 @@ describe('taco', () => {
const { decryptionShares } = fakeTDecFlow({
...mockedDkg,
message: toBytes(message),
- conditionExpr: tacoMk.conditionExpr,
+ conditionExpr: new conditions.ConditionExpression(ownsNFT),
dkgPublicKey: mockedDkg.dkg.publicKey(),
- thresholdMessageKit: tacoMk.thresholdMessageKit,
+ thresholdMessageKit: messageKit,
});
const { participantSecrets, participants } = fakeDkgParticipants(
mockedDkg.ritualId
@@ -73,15 +74,21 @@ describe('taco', () => {
);
const getParticipantsSpy = mockGetParticipants(participants);
const sessionKeySpy = mockRandomSessionStaticSecret(requesterSessionKey);
+ const getRitualIdFromPublicKey = mockGetRitualIdFromPublicKey(
+ mockedDkg.ritualId
+ );
+ const getRitualSpy = mockGetRitual(mockedDkgRitual);
const decryptedMessage = await taco.decrypt(
provider,
- tacoMk,
+ messageKit,
signer,
fakePorterUri
);
expect(getParticipantsSpy).toHaveBeenCalled();
expect(sessionKeySpy).toHaveBeenCalled();
+ expect(getRitualIdFromPublicKey).toHaveBeenCalled();
+ expect(getRitualSpy).toHaveBeenCalled();
expect(decryptSpy).toHaveBeenCalled();
expect(decryptedMessage).toEqual(toBytes(message));
});
diff --git a/test/utils.ts b/test/utils.ts
index adb1cb2a9..a681fce99 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -537,12 +537,20 @@ export const fakeDkgRitual = (ritual: {
);
};
-export const mockGetExistingRitual = (dkgRitual: DkgRitual) => {
- return jest.spyOn(DkgClient, 'getExistingRitual').mockImplementation(() => {
+export const mockGetRitual = (dkgRitual: DkgRitual) => {
+ return jest.spyOn(DkgClient, 'getRitual').mockImplementation(() => {
return Promise.resolve(dkgRitual);
});
};
+export const mockGetRitualIdFromPublicKey = (ritualId: number) => {
+ return jest
+ .spyOn(DkgCoordinatorAgent, 'getRitualIdFromPublicKey')
+ .mockImplementation(() => {
+ return Promise.resolve(ritualId);
+ });
+};
+
export const makeCohort = async (ursulas: Ursula[]) => {
const getUrsulasSpy = mockGetUrsulas(ursulas);
const porterUri = 'https://_this.should.crash';