Skip to content

Commit aea686a

Browse files
committed
feat: support multiple quorums in Aggregator and AlignedLayerServiceManager
1 parent 124eba8 commit aea686a

File tree

9 files changed

+94
-93
lines changed

9 files changed

+94
-93
lines changed

aggregator/pkg/aggregator.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,14 @@ import (
2828
)
2929

3030
// FIXME(marian): Read this from Aligned contract directly
31-
const QUORUM_NUMBER = byte(0)
32-
const QUORUM_THRESHOLD = byte(67)
31+
const QuorumThreshold = byte(67)
32+
33+
var QuorumNums = eigentypes.QuorumNums{eigentypes.QuorumNum(0)}
34+
var QuorumThresholdPercentages = eigentypes.QuorumThresholdPercentages{eigentypes.QuorumThresholdPercentage(QuorumThreshold)}
35+
36+
// TODO: Use these once we have two quorums deployed
37+
//var QuorumNums = eigentypes.QuorumNums{eigentypes.QuorumNum(0), eigentypes.QuorumNum(1)}
38+
//var QuorumThresholdPercentages = eigentypes.QuorumThresholdPercentages{eigentypes.QuorumThresholdPercentage(QUORUM_THRESHOLD), eigentypes.QuorumThresholdPercentage(QUORUM_THRESHOLD)}
3339

3440
// Aggregator stores TaskResponse for a task here
3541
type TaskResponses = []types.SignedTaskResponse
@@ -337,6 +343,7 @@ func (agg *Aggregator) sendAggregatedResponse(batchIdentifierHash [32]byte, batc
337343
batchIdentifierHash,
338344
batchMerkleRoot,
339345
senderAddress,
346+
QuorumNums,
340347
nonSignerStakesAndSignature,
341348
agg.AggregatorConfig.Aggregator.GasBaseBumpPercentage,
342349
agg.AggregatorConfig.Aggregator.GasBumpIncrementalPercentage,
@@ -407,10 +414,7 @@ func (agg *Aggregator) AddNewTask(batchMerkleRoot [32]byte, senderAddress [20]by
407414
)
408415
agg.nextBatchIndex += 1
409416

410-
quorumNums := eigentypes.QuorumNums{eigentypes.QuorumNum(QUORUM_NUMBER)}
411-
quorumThresholdPercentages := eigentypes.QuorumThresholdPercentages{eigentypes.QuorumThresholdPercentage(QUORUM_THRESHOLD)}
412-
413-
err := agg.blsAggregationService.InitializeNewTaskWithWindow(batchIndex, taskCreatedBlock, quorumNums, quorumThresholdPercentages, agg.AggregatorConfig.Aggregator.BlsServiceTaskTimeout, 15*time.Second)
417+
err := agg.blsAggregationService.InitializeNewTaskWithWindow(batchIndex, taskCreatedBlock, QuorumNums, QuorumThresholdPercentages, agg.AggregatorConfig.Aggregator.BlsServiceTaskTimeout, 15*time.Second)
414418
if err != nil {
415419
agg.logger.Fatalf("BLS aggregation service error when initializing new task: %s", err)
416420
}

contracts/bindings/AlignedLayerServiceManager/binding.go

Lines changed: 57 additions & 68 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contracts/bindings/ERC20Mock/binding.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contracts/scripts/anvil/state/alignedlayer-deployed-anvil-state.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

contracts/src/core/AlignedLayerServiceManager.sol

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ contract AlignedLayerServiceManager is
156156
// (batchMerkleRoot,senderAddress) is signed as a way to verify the batch was right
157157
bytes32 batchMerkleRoot,
158158
address senderAddress,
159+
bytes calldata quorumNumbers,
159160
NonSignerStakesAndSignature memory nonSignerStakesAndSignature
160161
) external onlyAggregator onlyWhenNotPaused(1) {
161162
uint256 initialGasLeft = gasleft();
@@ -194,22 +195,26 @@ contract AlignedLayerServiceManager is
194195
// check that aggregated BLS signature is valid
195196
(QuorumStakeTotals memory quorumStakeTotals, ) = checkSignatures(
196197
batchIdentifierHash,
198+
quorumNumbers,
197199
currentBatch.taskCreatedBlock,
198200
nonSignerStakesAndSignature
199201
);
200202

201203
// check that signatories own at least a threshold percentage of each quourm
202-
if (
203-
quorumStakeTotals.signedStakeForQuorum[0] * THRESHOLD_DENOMINATOR <
204-
quorumStakeTotals.totalStakeForQuorum[0] *
205-
QUORUM_THRESHOLD_PERCENTAGE
206-
) {
207-
revert InvalidQuorumThreshold(
208-
quorumStakeTotals.signedStakeForQuorum[0] *
209-
THRESHOLD_DENOMINATOR,
210-
quorumStakeTotals.totalStakeForQuorum[0] *
204+
for (uint256 i = 0; i < quorumStakeTotals.signedStakeForQuorum.length; i++) {
205+
if (
206+
quorumStakeTotals.signedStakeForQuorum[i] *
207+
THRESHOLD_DENOMINATOR <
208+
quorumStakeTotals.totalStakeForQuorum[i] *
211209
QUORUM_THRESHOLD_PERCENTAGE
212-
);
210+
) {
211+
revert InvalidQuorumThreshold(
212+
quorumStakeTotals.signedStakeForQuorum[i] *
213+
THRESHOLD_DENOMINATOR,
214+
quorumStakeTotals.totalStakeForQuorum[i] *
215+
QUORUM_THRESHOLD_PERCENTAGE
216+
);
217+
}
213218
}
214219

215220
emit BatchVerified(batchMerkleRoot, senderAddress);

contracts/src/core/IAlignedLayerServiceManager.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ interface IAlignedLayerServiceManager {
4646
function respondToTaskV2(
4747
bytes32 batchMerkleRoot,
4848
address senderAddress,
49+
bytes calldata quorumNumbers,
4950
IBLSSignatureChecker.NonSignerStakesAndSignature
5051
memory nonSignerStakesAndSignature
5152
) external;

core/chainio/avs_writer.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/hex"
66
"fmt"
7+
eigentypes "github.com/Layr-Labs/eigensdk-go/types"
78
"math/big"
89
"time"
910

@@ -89,10 +90,10 @@ func NewAvsWriterFromConfig(baseConfig *config.BaseConfig, ecdsaConfig *config.E
8990
// - If no receipt is found, but the batch state indicates the response has already been processed, it exits
9091
// without an error (returning `nil, nil`).
9192
// - An error if the process encounters a fatal issue (e.g., permanent failure in verifying balances or state).
92-
func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMerkleRoot [32]byte, senderAddress [20]byte, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature, gasBumpPercentage uint, gasBumpIncrementalPercentage uint, gasBumpPercentageLimit uint, timeToWaitBeforeBump time.Duration, metrics *metrics.Metrics, onSetGasPrice func(*big.Int)) (*types.Receipt, error) {
93+
func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMerkleRoot [32]byte, senderAddress [20]byte, quorumNums eigentypes.QuorumNums, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature, gasBumpPercentage uint, gasBumpIncrementalPercentage uint, gasBumpPercentageLimit uint, timeToWaitBeforeBump time.Duration, metrics *metrics.Metrics, onSetGasPrice func(*big.Int)) (*types.Receipt, error) {
9394
txOpts := *w.Signer.GetTxOpts()
9495
txOpts.NoSend = true // simulate the transaction
95-
simTx, err := w.RespondToTaskV2Retryable(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature, retry.SendToChainRetryParams())
96+
simTx, err := w.RespondToTaskV2Retryable(&txOpts, batchMerkleRoot, senderAddress, quorumNums, nonSignerStakesAndSignature, retry.SendToChainRetryParams())
9697
if err != nil {
9798
return nil, err
9899
}
@@ -175,7 +176,7 @@ func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMe
175176
}
176177

177178
w.logger.Infof("Sending RespondToTask transaction with a gas price of %v", txOpts.GasPrice, "merkle root", batchMerkleRootHashString)
178-
realTx, err := w.RespondToTaskV2Retryable(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature, retry.SendToChainRetryParams())
179+
realTx, err := w.RespondToTaskV2Retryable(&txOpts, batchMerkleRoot, senderAddress, quorumNums, nonSignerStakesAndSignature, retry.SendToChainRetryParams())
179180
if err != nil {
180181
w.logger.Errorf("Respond to task transaction err, %v", err, "merkle root", batchMerkleRootHashString)
181182
return nil, err

core/chainio/retryable.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"math/big"
66

7+
eigentypes "github.com/Layr-Labs/eigensdk-go/types"
78
"github.com/ethereum/go-ethereum"
89
"github.com/ethereum/go-ethereum/accounts/abi/bind"
910
"github.com/ethereum/go-ethereum/common"
@@ -22,13 +23,13 @@ Send a transaction to the AVS contract to respond to a task.
2223
- Retry times (3 retries): 12 sec (1 Blocks), 24 sec (2 Blocks), 48 sec (4 Blocks)
2324
- NOTE: Contract call reverts are not considered `PermanentError`'s as block reorg's may lead to contract call revert in which case the aggregator should retry.
2425
*/
25-
func (w *AvsWriter) RespondToTaskV2Retryable(opts *bind.TransactOpts, batchMerkleRoot [32]byte, senderAddress common.Address, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature, config *retry.RetryParams) (*types.Transaction, error) {
26+
func (w *AvsWriter) RespondToTaskV2Retryable(opts *bind.TransactOpts, batchMerkleRoot [32]byte, senderAddress common.Address, quorumNums eigentypes.QuorumNums, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature, config *retry.RetryParams) (*types.Transaction, error) {
2627
respondToTaskV2_func := func() (*types.Transaction, error) {
2728
// Try with main connection
28-
tx, err := w.AvsContractBindings.ServiceManager.RespondToTaskV2(opts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
29+
tx, err := w.AvsContractBindings.ServiceManager.RespondToTaskV2(opts, batchMerkleRoot, senderAddress, quorumNums.UnderlyingType(), nonSignerStakesAndSignature)
2930
if err != nil {
3031
// If error try with fallback
31-
tx, err = w.AvsContractBindings.ServiceManagerFallback.RespondToTaskV2(opts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
32+
tx, err = w.AvsContractBindings.ServiceManagerFallback.RespondToTaskV2(opts, batchMerkleRoot, senderAddress, quorumNums.UnderlyingType(), nonSignerStakesAndSignature)
3233
}
3334

3435
return tx, err

0 commit comments

Comments
 (0)