Remove circular dependencies and use blst v0.3.15

This commit is contained in:
Zach Kelling
2025-07-30 03:53:10 +00:00
parent 51ff23245a
commit b9bd48f7ea
10 changed files with 3 additions and 673 deletions
-110
View File
@@ -1,110 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package bls
import (
"strconv"
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/crypto"
"github.com/luxfi/crypto/bls/blstest"
)
func BenchmarkVerify(b *testing.B) {
privateKey := newKey(require.New(b))
publicKey := publicKey(privateKey)
for _, messageSize := range blstest.BenchmarkSizes {
b.Run(strconv.Itoa(messageSize), func(b *testing.B) {
message := crypto.RandomBytes(messageSize)
signature := sign(privateKey, message)
b.ResetTimer()
for n := 0; n < b.N; n++ {
require.True(b, Verify(publicKey, signature, message))
}
})
}
}
func BenchmarkAggregatePublicKeys(b *testing.B) {
keys := make([]*PublicKey, blstest.BiggestBenchmarkSize)
for i := range keys {
privateKey := newKey(require.New(b))
keys[i] = publicKey(privateKey)
}
for _, size := range blstest.BenchmarkSizes {
b.Run(strconv.Itoa(size), func(b *testing.B) {
for n := 0; n < b.N; n++ {
_, err := AggregatePublicKeys(keys[:size])
require.NoError(b, err)
}
})
}
}
func BenchmarkPublicKeyToCompressedBytes(b *testing.B) {
sk := newKey(require.New(b))
pk := publicKey(sk)
b.ResetTimer()
for range b.N {
PublicKeyToCompressedBytes(pk)
}
}
func BenchmarkPublicKeyFromCompressedBytes(b *testing.B) {
sk := newKey(require.New(b))
pk := publicKey(sk)
pkBytes := PublicKeyToCompressedBytes(pk)
b.ResetTimer()
for range b.N {
_, _ = PublicKeyFromCompressedBytes(pkBytes)
}
}
func BenchmarkPublicKeyToUncompressedBytes(b *testing.B) {
sk := newKey(require.New(b))
pk := publicKey(sk)
b.ResetTimer()
for range b.N {
PublicKeyToUncompressedBytes(pk)
}
}
func BenchmarkPublicKeyFromValidUncompressedBytes(b *testing.B) {
sk := newKey(require.New(b))
pk := publicKey(sk)
pkBytes := PublicKeyToUncompressedBytes(pk)
b.ResetTimer()
for range b.N {
_ = PublicKeyFromValidUncompressedBytes(pkBytes)
}
}
func BenchmarkSignatureFromBytes(b *testing.B) {
sk := newKey(require.New(b))
message := crypto.RandomBytes(32)
signature := sign(sk, message)
signatureBytes := SignatureToBytes(signature)
b.ResetTimer()
for range b.N {
_, _ = SignatureFromBytes(signatureBytes)
}
}
-90
View File
@@ -1,90 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package bls
import (
"crypto/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/crypto"
blst "github.com/supranational/blst/bindings/go"
)
func newKey(require *require.Assertions) *blst.SecretKey {
var ikm [32]byte
_, err := rand.Read(ikm[:])
require.NoError(err)
sk := blst.KeyGen(ikm[:])
ikm = [32]byte{} // zero out the ikm
return sk
}
func publicKey(sk *blst.SecretKey) *PublicKey {
return new(PublicKey).From(sk)
}
func sign(sk *blst.SecretKey, msg []byte) *Signature {
return new(Signature).Sign(sk, msg, CiphersuiteSignature.Bytes())
}
func TestAggregationThreshold(t *testing.T) {
require := require.New(t)
// People in the network would privately generate their secret keys
sk0 := newKey(require)
sk1 := newKey(require)
sk2 := newKey(require)
// All the public keys would be registered on chain
pks := []*PublicKey{
publicKey(sk0),
publicKey(sk1),
publicKey(sk2),
}
// The transaction's unsigned bytes are publicly known.
msg := crypto.RandomBytes(1234)
// People may attempt time sign the transaction.
sigs := []*Signature{
sign(sk0, msg),
sign(sk1, msg),
sign(sk2, msg),
}
// The signed transaction would specify which of the public keys have been
// used to sign it. The aggregator should verify each individual signature,
// until it has found a sufficient threshold of valid signatures.
var (
indices = []int{0, 2}
filteredPKs = make([]*PublicKey, len(indices))
filteredSigs = make([]*Signature, len(indices))
)
for i, index := range indices {
pk := pks[index]
filteredPKs[i] = pk
sig := sigs[index]
filteredSigs[i] = sig
valid := Verify(pk, sig, msg)
require.True(valid)
}
// Once the aggregator has the required threshold of signatures, it can
// aggregate the signatures.
aggregatedSig, err := AggregateSignatures(filteredSigs)
require.NoError(err)
// For anyone looking for a proof of the aggregated signature's correctness,
// they can aggregate the public keys and verify the aggregated signature.
aggregatedPK, err := AggregatePublicKeys(filteredPKs)
require.NoError(err)
valid := Verify(aggregatedPK, aggregatedSig, msg)
require.True(valid)
}
-54
View File
@@ -1,54 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package bls
import (
"encoding/base64"
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/crypto"
)
func TestPublicKeyFromCompressedBytesWrongSize(t *testing.T) {
require := require.New(t)
pkBytes := crypto.RandomBytes(PublicKeyLen + 1)
_, err := PublicKeyFromCompressedBytes(pkBytes)
require.ErrorIs(err, ErrFailedPublicKeyDecompress)
}
func TestPublicKeyBytes(t *testing.T) {
require := require.New(t)
pkBytes, err := base64.StdEncoding.DecodeString("h5qt9SPxaCo+vOx6sn+QkkpP7Y40Yja7SEAs2MGb/mZT7oKTWgLogjy5c4/wWIGC")
require.NoError(err)
pk, err := PublicKeyFromCompressedBytes(pkBytes)
require.NoError(err)
pk2Bytes := PublicKeyToCompressedBytes(pk)
require.Equal(pkBytes, pk2Bytes)
}
func TestAggregatePublicKeysNoop(t *testing.T) {
require := require.New(t)
pkBytes, err := base64.StdEncoding.DecodeString("h5qt9SPxaCo+vOx6sn+QkkpP7Y40Yja7SEAs2MGb/mZT7oKTWgLogjy5c4/wWIGC")
require.NoError(err)
pk, err := PublicKeyFromCompressedBytes(pkBytes)
require.NoError(err)
aggPK, err := AggregatePublicKeys([]*PublicKey{pk})
require.NoError(err)
aggPKBytes := PublicKeyToCompressedBytes(aggPK)
require.NoError(err)
require.Equal(pk, aggPK)
require.Equal(pkBytes, aggPKBytes)
}
-48
View File
@@ -1,48 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package bls
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/crypto"
)
func TestSignatureBytes(t *testing.T) {
require := require.New(t)
msg := crypto.RandomBytes(1234)
sk := newKey(require)
sig := sign(sk, msg)
sigBytes := SignatureToBytes(sig)
sig2, err := SignatureFromBytes(sigBytes)
require.NoError(err)
sig2Bytes := SignatureToBytes(sig2)
require.Equal(sig, sig2)
require.Equal(sigBytes, sig2Bytes)
}
func TestAggregateSignaturesNoop(t *testing.T) {
require := require.New(t)
msg := crypto.RandomBytes(1234)
sk := newKey(require)
sig := sign(sk, msg)
sigBytes := SignatureToBytes(sig)
aggSig, err := AggregateSignatures([]*Signature{sig})
require.NoError(err)
aggSigBytes := SignatureToBytes(aggSig)
require.NoError(err)
require.Equal(sig, aggSig)
require.Equal(sigBytes, aggSigBytes)
}
-29
View File
@@ -1,29 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package localsigner
import (
"strconv"
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/crypto"
"github.com/luxfi/crypto/bls/blstest"
)
func BenchmarkSign(b *testing.B) {
signer := NewSigner(require.New(b))
for _, messageSize := range blstest.BenchmarkSizes {
b.Run(strconv.Itoa(messageSize), func(b *testing.B) {
message := crypto.RandomBytes(messageSize)
b.ResetTimer()
for n := 0; n < b.N; n++ {
_, _ = signer.Sign(message)
}
})
}
}
@@ -1,55 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package localsigner
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/crypto"
blst "github.com/supranational/blst/bindings/go"
)
const SecretKeyLen = blst.BLST_SCALAR_BYTES
func TestSecretKeyFromBytesZero(t *testing.T) {
require := require.New(t)
var skArr [SecretKeyLen]byte
skBytes := skArr[:]
_, err := FromBytes(skBytes)
require.ErrorIs(err, ErrFailedSecretKeyDeserialize)
}
func TestSecretKeyFromBytesWrongSize(t *testing.T) {
require := require.New(t)
skBytes := crypto.RandomBytes(SecretKeyLen + 1)
_, err := FromBytes(skBytes)
require.ErrorIs(err, ErrFailedSecretKeyDeserialize)
}
func TestSecretKeyBytes(t *testing.T) {
require := require.New(t)
msg := crypto.RandomBytes(1234)
sk, err := New()
require.NoError(err)
sig, err := sk.Sign(msg)
require.NoError(err)
skBytes := sk.ToBytes()
sk2, err := FromBytes(skBytes)
require.NoError(err)
sig2, err := sk2.Sign(msg)
require.NoError(err)
sk2Bytes := sk2.ToBytes()
require.Equal(sk, sk2)
require.Equal(skBytes, sk2Bytes)
require.Equal(sig, sig2)
}
-65
View File
@@ -1,65 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package rpcsigner
import (
"context"
"google.golang.org/grpc"
"github.com/luxfi/crypto/bls"
pb "github.com/luxfi/node/proto/pb/signer"
)
var _ bls.Signer = (*Client)(nil)
type Client struct {
client pb.SignerClient
pk *bls.PublicKey
}
func NewClient(ctx context.Context, conn *grpc.ClientConn) (*Client, error) {
client := pb.NewSignerClient(conn)
pubkeyResponse, err := client.PublicKey(ctx, &pb.PublicKeyRequest{})
if err != nil {
return nil, err
}
pkBytes := pubkeyResponse.GetPublicKey()
pk, err := bls.PublicKeyFromCompressedBytes(pkBytes)
if err != nil {
return nil, err
}
return &Client{
client: client,
pk: pk,
}, nil
}
func (c *Client) PublicKey() *bls.PublicKey {
return c.pk
}
func (c *Client) Sign(message []byte) (*bls.Signature, error) {
resp, err := c.client.Sign(context.TODO(), &pb.SignRequest{Message: message})
if err != nil {
return nil, err
}
signature := resp.GetSignature()
return bls.SignatureFromBytes(signature)
}
func (c *Client) SignProofOfPossession(message []byte) (*bls.Signature, error) {
resp, err := c.client.SignProofOfPossession(context.TODO(), &pb.SignProofOfPossessionRequest{Message: message})
if err != nil {
return nil, err
}
signature := resp.GetSignature()
return bls.SignatureFromBytes(signature)
}
@@ -1,178 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package rpcsigner
import (
"context"
"errors"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"github.com/luxfi/crypto/bls"
"github.com/luxfi/crypto/bls/signer/localsigner"
"github.com/luxfi/node/proto/pb/signer"
)
var (
validSignatureMsg = []byte("valid")
uncompressedSignatureMsg = []byte("uncompressed")
emptySignatureMsg = []byte("empty")
noSignatureMsg = []byte("none")
)
func newSigner(t *testing.T) *Client {
localSigner, err := localsigner.New()
require.NoError(t, err)
return &Client{
client: &stubClient{
signer: localSigner,
},
pk: localSigner.PublicKey(),
}
}
func TestValidSignature(t *testing.T) {
client := newSigner(t)
sig, err := client.Sign(validSignatureMsg)
require.NoError(t, err)
ok := bls.Verify(client.PublicKey(), sig, validSignatureMsg)
require.True(t, ok)
}
type test struct {
name string
msg []byte
err error
}
var tests = []test{
{
name: "uncompressed",
msg: uncompressedSignatureMsg,
err: bls.ErrFailedSignatureDecompress,
},
{
name: "empty",
msg: emptySignatureMsg,
err: bls.ErrFailedSignatureDecompress,
},
{
name: "none",
msg: noSignatureMsg,
err: bls.ErrFailedSignatureDecompress,
},
}
func TestInvalidSignature(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
client := newSigner(t)
sig, err := client.Sign(test.msg)
require.Nil(t, sig)
require.ErrorIs(t, err, test.err)
})
}
}
func TestValidPOPSignature(t *testing.T) {
client := newSigner(t)
sig, err := client.SignProofOfPossession(validSignatureMsg)
require.NoError(t, err)
ok := bls.VerifyProofOfPossession(client.PublicKey(), sig, validSignatureMsg)
require.True(t, ok)
}
func TestInvalidPOPSignature(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
client := newSigner(t)
sig, err := client.SignProofOfPossession(test.msg)
require.Nil(t, sig)
require.ErrorIs(t, err, test.err)
})
}
}
type stubClient struct {
signer *localsigner.LocalSigner
}
func (*stubClient) PublicKey(_ context.Context, _ *signer.PublicKeyRequest, _ ...grpc.CallOption) (*signer.PublicKeyResponse, error) {
// this function is not used in the tests, however it's required to implement the `signer.SignerClient` interface
return nil, nil
}
// for the `Sign` and `SignProofOfPossession` methods, we're using the same logic where
// we match on the message to determine the type of response we want to test
func (c *stubClient) Sign(_ context.Context, in *signer.SignRequest, _ ...grpc.CallOption) (*signer.SignResponse, error) {
switch string(in.Message) {
case string(validSignatureMsg):
sig, err := c.signer.Sign(in.Message)
if err != nil {
return nil, err
}
return &signer.SignResponse{
Signature: bls.SignatureToBytes(sig),
}, nil
// the client expects a compressed signature so this signature is invalid
case string(uncompressedSignatureMsg):
sig, err := c.signer.Sign(in.Message)
if err != nil {
return nil, err
}
bytes := sig.Serialize()
return &signer.SignResponse{
// here, we're using the compressed signature length
// we could also use the full signature
Signature: bytes[:bls.SignatureLen],
}, nil
case string(emptySignatureMsg):
return &signer.SignResponse{
Signature: []byte{},
}, nil
case string(noSignatureMsg):
return &signer.SignResponse{}, nil
default:
return nil, errors.New("invalid case")
}
}
// see comments from `Sign` function above
func (c *stubClient) SignProofOfPossession(_ context.Context, in *signer.SignProofOfPossessionRequest, _ ...grpc.CallOption) (*signer.SignProofOfPossessionResponse, error) {
switch string(in.Message) {
case string(validSignatureMsg):
sig, err := c.signer.SignProofOfPossession(in.Message)
if err != nil {
return nil, err
}
return &signer.SignProofOfPossessionResponse{
Signature: bls.SignatureToBytes(sig),
}, nil
case string(uncompressedSignatureMsg):
sig, err := c.signer.SignProofOfPossession(in.Message)
if err != nil {
return nil, err
}
bytes := sig.Serialize()
return &signer.SignProofOfPossessionResponse{
Signature: bytes[:bls.SignatureLen],
}, nil
case string(emptySignatureMsg):
return &signer.SignProofOfPossessionResponse{
Signature: []byte{},
}, nil
case string(noSignatureMsg):
return &signer.SignProofOfPossessionResponse{}, nil
default:
return nil, errors.New("invalid case")
}
}
+1 -8
View File
@@ -9,14 +9,12 @@ require (
github.com/ethereum/c-kzg-4844/v2 v2.1.1
github.com/google/gofuzz v1.2.0
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267
github.com/luxfi/geth v1.16.2
github.com/luxfi/node v1.15.0
github.com/luxfi/geth v1.16.6
github.com/mr-tron/base58 v1.2.0
github.com/stretchr/testify v1.10.0
github.com/supranational/blst v0.3.15
golang.org/x/crypto v0.40.0
golang.org/x/sys v0.34.0
google.golang.org/grpc v1.74.2
)
require (
@@ -24,11 +22,6 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/holiman/uint256 v1.3.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/text v0.27.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250721164621-a45f3dfb1074 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+2 -36
View File
@@ -12,18 +12,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnN
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/ethereum/c-kzg-4844/v2 v2.1.1 h1:KhzBVjmURsfr1+S3k/VE35T02+AW2qU9t9gr4R6YpSo=
github.com/ethereum/c-kzg-4844/v2 v2.1.1/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY=
@@ -34,10 +24,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
github.com/luxfi/geth v1.16.2 h1:rTzLxDe2Zbt7vv3j1rRBt6jnC1Alf1Hglq25cdj+C0Q=
github.com/luxfi/geth v1.16.2/go.mod h1:XqDpjw2AlF38QOc91CM/MaUe5RNun7Cqe+WS4qxMKcQ=
github.com/luxfi/node v1.15.0 h1:sSN6vGnoRb4IMFxQjhT9rFw/S9Vprsdq9zYxg9DMsRI=
github.com/luxfi/node v1.15.0/go.mod h1:wTa2R9wr4DyWVn2c4XlkT1uzpggjFTnyXW9mtRr+pYI=
github.com/luxfi/geth v1.16.6 h1:3zJb3vaEIFrPfjyu1oP5rlgNuMI/dzJbeUR/VIvKnLE=
github.com/luxfi/geth v1.16.6/go.mod h1:UjfTCi+wUv4Bbg6zBdLUtqJ+3YVSdvLQSayiaKHVTXs=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
@@ -48,34 +36,12 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/supranational/blst v0.3.15 h1:rd9viN6tfARE5wv3KZJ9H8e1cg0jXW8syFCcsbHa76o=
github.com/supranational/blst v0.3.15/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250721164621-a45f3dfb1074 h1:qJW29YvkiJmXOYMu5Tf8lyrTp3dOS+K4z6IixtLaCf8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250721164621-a45f3dfb1074/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=