-
Notifications
You must be signed in to change notification settings - Fork 240
feat: v3 cert type with new interaction patterns with onchain Router
&& CertVerifier
interfaces
#1532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: v3 cert type with new interaction patterns with onchain Router
&& CertVerifier
interfaces
#1532
Changes from 81 commits
d93e21e
7ce68c3
4d17389
7757b99
b3fe8c1
52d12dc
0985b47
5be5313
2957935
f451cb7
0dd14a2
5ef491b
b964301
f597d07
8f59b00
7e26828
c1b9fdb
c2db1b4
d4d304f
c9a5699
35cd63f
887ffae
6cbf4be
515ef68
b72abad
191ed61
cfba65a
4e394f9
1058ea0
b9745fc
d7dc0e1
f6384f3
9fed5c6
b4ede42
79dd5e8
cd33eb8
84b2bed
a4374d6
f0d58d9
072c3ad
8dcadff
a4369fe
b60dcff
3982d5f
159c8d0
03050a0
8a2956e
69b8a00
f1ee309
3419421
ce6fd1c
4635dba
ca824be
463e78a
6fda146
b14769f
fdcc4a9
e3fac51
1980319
4b046f2
f989da6
3e39303
59db366
8bf0a01
0d0f7bb
0a0588a
08b6343
31177e6
4afbd8d
61ce636
296f23c
92ab00c
41a28c4
e3aa022
88c2cc5
13d650c
2a23dcb
8357550
037a5f4
d3ab9f6
ca29316
611662c
0129bfe
01be9bb
941c350
276fafc
407bb0d
e4f2697
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
package clients | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math/big" | ||
"time" | ||
|
||
"github.com/Layr-Labs/eigenda/api/clients/v2/coretypes" | ||
coreEth "github.com/Layr-Labs/eigenda/core/eth" | ||
|
||
disperser "github.com/Layr-Labs/eigenda/api/grpc/disperser/v2" | ||
"github.com/Layr-Labs/eigenda/common" | ||
certTypesBinding "github.com/Layr-Labs/eigenda/contracts/bindings/IEigenDACertTypeBindings" | ||
opsrbinding "github.com/Layr-Labs/eigenda/contracts/bindings/OperatorStateRetriever" | ||
"github.com/Layr-Labs/eigenda/core" | ||
coreV2 "github.com/Layr-Labs/eigenda/core/v2" | ||
"github.com/Layr-Labs/eigensdk-go/logging" | ||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
gethcommon "github.com/ethereum/go-ethereum/common" | ||
) | ||
|
||
|
||
type CertBuilder struct { | ||
logger logging.Logger | ||
opsrCaller *opsrbinding.ContractOperatorStateRetrieverCaller | ||
registryCoordinatorAddr gethcommon.Address | ||
} | ||
|
||
// NewCertBuilder constructs a new CertBuilder instance used to build EigenDA certificates | ||
// across different versions. | ||
func NewCertBuilder( | ||
logger logging.Logger, | ||
opsrAddr gethcommon.Address, | ||
registryCoordinatorAddr gethcommon.Address, | ||
ethClient common.EthClient, | ||
) (*CertBuilder, error) { | ||
if logger == nil { | ||
return nil, fmt.Errorf("logger cannot be nil") | ||
} | ||
// Create the Operator State Retriever caller | ||
opsrCaller, err := opsrbinding.NewContractOperatorStateRetrieverCaller(opsrAddr, ethClient) | ||
if err != nil { | ||
return nil, fmt.Errorf("create operator state retriever caller: %w", err) | ||
} | ||
|
||
|
||
return &CertBuilder{ | ||
logger: logger, | ||
opsrCaller: opsrCaller, | ||
registryCoordinatorAddr: registryCoordinatorAddr, | ||
}, nil | ||
} | ||
|
||
// BuildCert builds an EigenDA certificate of the specified version using the provided blob key and blob status reply. | ||
func (cb *CertBuilder) BuildCert( | ||
ctx context.Context, | ||
certVersion coretypes.CertificateVersion, | ||
blobKey coreV2.BlobKey, | ||
blobStatusReply *disperser.BlobStatusReply, | ||
) (coretypes.EigenDACert, error) { | ||
switch certVersion { | ||
case coretypes.VersionThreeCert: | ||
return cb.buildEigenDAV3Cert(ctx, blobKey, blobStatusReply) | ||
default: | ||
return nil, fmt.Errorf("unsupported EigenDA cert version: %d", certVersion) | ||
} | ||
} | ||
|
||
// buildEigenDAV3Cert builds an EigenDA certificate of version 3 using the provided blob key and blob status reply. | ||
func (cb *CertBuilder) buildEigenDAV3Cert( | ||
ctx context.Context, | ||
blobKey coreV2.BlobKey, | ||
blobStatusReply *disperser.BlobStatusReply, | ||
) (*coretypes.EigenDACertV3, error) { | ||
// TODO: configurable timeout | ||
timeoutCtx, cancel := context.WithTimeout(ctx, time.Second) | ||
litt3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer cancel() | ||
nonSignerStakesAndSignature, err := cb.getNonSignerStakesAndSignature( | ||
timeoutCtx, blobStatusReply.GetSignedBatch()) | ||
if err != nil { | ||
return nil, fmt.Errorf("get non signer stake and signature: %w", err) | ||
} | ||
cb.logger.Debug("Retrieved NonSignerStakesAndSignature", "blobKey", blobKey.Hex()) | ||
|
||
eigenDACert, err := coretypes.BuildEigenDACertV3(blobStatusReply, nonSignerStakesAndSignature) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. still think the name warrants changing to make them both have the same name. Actually maybe make the coretype use NewEigenDACertV3. I like the separation between New and Build, and imo Build should be the external layer doing IO that can return errors, and the New constructors should be purely stateless with dependency injection and are just doing stateless data manipulation (which I think is what's happening here..) |
||
if err != nil { | ||
return nil, fmt.Errorf("build eigenda v3 cert: %w", err) | ||
} | ||
cb.logger.Debug("Constructed EigenDACertV3", "blobKey", blobKey.Hex()) | ||
|
||
return eigenDACert, nil | ||
} | ||
|
||
// GetNonSignerStakesAndSignature constructs a NonSignerStakesAndSignature object by calling an | ||
// onchain OperatorStateRetriever retriever to fetch necessary non-signer metadata | ||
func (cb *CertBuilder) getNonSignerStakesAndSignature( | ||
ctx context.Context, | ||
signedBatch *disperser.SignedBatch, | ||
) (*certTypesBinding.EigenDATypesV1NonSignerStakesAndSignature, error) { | ||
// 1 - Pre-process inputs for operator state retriever call | ||
signedBatchBinding, err := coretypes.SignedBatchProtoToV2CertBinding(signedBatch) | ||
litt3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
return nil, fmt.Errorf("convert signed batch: %w", err) | ||
} | ||
|
||
nonSignerPubKeys := signedBatchBinding.Attestation.NonSignerPubkeys | ||
|
||
// 2a - create operator IDs by hashing non-signer public keys | ||
nonSignerOperatorIDs := make([][32]byte, len(nonSignerPubKeys)) | ||
for i, pubKeySet := range nonSignerPubKeys { | ||
g1Point := core.NewG1Point(pubKeySet.X, pubKeySet.Y) | ||
nonSignerOperatorIDs[i] = coreEth.HashPubKeyG1(g1Point) | ||
} | ||
|
||
// 2b - cast []uint32 to []byte for quorum numbers | ||
quorumNumbers := make([]byte, len(signedBatch.GetAttestation().GetQuorumNumbers())) | ||
litt3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for i, qn := range signedBatch.GetAttestation().GetQuorumNumbers() { | ||
quorumNumbers[i] = byte(qn) | ||
} | ||
|
||
// use the reference block # from the disperser generated signed batch header | ||
// for referencing operator states at a specific block checkpoint | ||
rbn := signedBatch.GetHeader().GetReferenceBlockNumber() | ||
|
||
// 3 - call operator state retriever to fetch signature indices | ||
checkSigIndices, err := cb.opsrCaller.GetCheckSignaturesIndices(&bind.CallOpts{Context: ctx, BlockNumber: big.NewInt(int64(rbn))}, | ||
cb.registryCoordinatorAddr, uint32(rbn), quorumNumbers, nonSignerOperatorIDs) | ||
|
||
if err != nil { | ||
return nil, fmt.Errorf("check sig indices call: %w", err) | ||
} | ||
|
||
// 4 - translate from CertVerifier binding types to cert type | ||
// TODO: Should probably put SignedBatch into the types directly to avoid this downstream conversion | ||
nonSignerPubKeysBN254 := make([]certTypesBinding.BN254G1Point, len(signedBatchBinding.Attestation.NonSignerPubkeys)) | ||
for i, pubKeySet := range signedBatchBinding.Attestation.NonSignerPubkeys { | ||
nonSignerPubKeysBN254[i] = certTypesBinding.BN254G1Point{ | ||
X: pubKeySet.X, | ||
Y: pubKeySet.Y, | ||
} | ||
} | ||
|
||
quorumApksBN254 := make([]certTypesBinding.BN254G1Point, len(signedBatchBinding.Attestation.QuorumApks)) | ||
for i, apkSet := range signedBatchBinding.Attestation.QuorumApks { | ||
quorumApksBN254[i] = certTypesBinding.BN254G1Point{ | ||
X: apkSet.X, | ||
Y: apkSet.Y, | ||
} | ||
} | ||
|
||
apkG2BN254 := certTypesBinding.BN254G2Point{ | ||
X: signedBatchBinding.Attestation.ApkG2.X, | ||
Y: signedBatchBinding.Attestation.ApkG2.Y, | ||
} | ||
|
||
sigmaBN254 := certTypesBinding.BN254G1Point{ | ||
X: signedBatchBinding.Attestation.Sigma.X, | ||
Y: signedBatchBinding.Attestation.Sigma.Y, | ||
} | ||
|
||
|
||
// 5 - construct non signer stakes and signature | ||
return &certTypesBinding.EigenDATypesV1NonSignerStakesAndSignature{ | ||
NonSignerQuorumBitmapIndices: checkSigIndices.NonSignerQuorumBitmapIndices, | ||
NonSignerPubkeys: nonSignerPubKeysBN254, | ||
QuorumApks: quorumApksBN254, | ||
ApkG2: apkG2BN254, | ||
Sigma: sigmaBN254, | ||
QuorumApkIndices: checkSigIndices.QuorumApkIndices, | ||
TotalStakeIndices: checkSigIndices.TotalStakeIndices, | ||
NonSignerStakeIndices: checkSigIndices.NonSignerStakeIndices, | ||
}, nil | ||
} |
samlaf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.