diff --git a/api/clients/accountant.go b/api/clients/accountant.go index 122ec3eea..08d714703 100644 --- a/api/clients/accountant.go +++ b/api/clients/accountant.go @@ -17,13 +17,14 @@ var minNumBins uint32 = 3 var requiredQuorums = []uint8{0, 1} type Accountant interface { - AccountBlob(ctx context.Context, numSymbols uint64, quorums []uint8) (*commonpb.PaymentHeader, []byte, error) + AccountBlob(ctx context.Context, numSymbols uint64, quorums []uint8) (*commonpb.PaymentHeader, error) } var _ Accountant = &accountant{} type accountant struct { // on-chain states + accountID string reservation *core.ActiveReservation onDemand *core.OnDemandPayment reservationWindow uint32 @@ -36,8 +37,7 @@ type accountant struct { usageLock sync.Mutex cumulativePayment *big.Int - paymentSigner core.PaymentSigner - numBins uint32 + numBins uint32 } type BinRecord struct { @@ -45,7 +45,7 @@ type BinRecord struct { Usage uint64 } -func NewAccountant(reservation *core.ActiveReservation, onDemand *core.OnDemandPayment, reservationWindow uint32, pricePerSymbol uint32, minNumSymbols uint32, paymentSigner core.PaymentSigner, numBins uint32) *accountant { +func NewAccountant(accountID string, reservation *core.ActiveReservation, onDemand *core.OnDemandPayment, reservationWindow uint32, pricePerSymbol uint32, minNumSymbols uint32, numBins uint32) *accountant { //TODO: client storage; currently every instance starts fresh but on-chain or a small store makes more sense // Also client is currently responsible for supplying network params, we need to add RPC in order to be automatic // There's a subsequent PR that handles populating the accountant with on-chain state from the disperser @@ -54,6 +54,7 @@ func NewAccountant(reservation *core.ActiveReservation, onDemand *core.OnDemandP binRecords[i] = BinRecord{Index: uint32(i), Usage: 0} } a := accountant{ + accountID: accountID, reservation: reservation, onDemand: onDemand, reservationWindow: reservationWindow, @@ -61,7 +62,6 @@ func NewAccountant(reservation *core.ActiveReservation, onDemand *core.OnDemandP minNumSymbols: minNumSymbols, binRecords: binRecords, cumulativePayment: big.NewInt(0), - paymentSigner: paymentSigner, numBins: max(numBins, minNumBins), } // TODO: add a routine to refresh the on-chain state occasionally? @@ -116,26 +116,20 @@ func (a *accountant) BlobPaymentInfo(ctx context.Context, numSymbols uint64, quo } // AccountBlob accountant provides and records payment information -func (a *accountant) AccountBlob(ctx context.Context, numSymbols uint64, quorums []uint8) (*commonpb.PaymentHeader, []byte, error) { +func (a *accountant) AccountBlob(ctx context.Context, numSymbols uint64, quorums []uint8) (*commonpb.PaymentHeader, error) { binIndex, cumulativePayment, err := a.BlobPaymentInfo(ctx, numSymbols, quorums) if err != nil { - return nil, nil, err + return nil, err } - accountID := a.paymentSigner.GetAccountID() pm := &core.PaymentMetadata{ - AccountID: accountID, + AccountID: a.accountID, BinIndex: binIndex, CumulativePayment: cumulativePayment, } protoPaymentHeader := pm.ConvertToProtoPaymentHeader() - signature, err := a.paymentSigner.SignBlobPayment(pm) - if err != nil { - return nil, nil, err - } - - return protoPaymentHeader, signature, nil + return protoPaymentHeader, nil } // TODO: PaymentCharged and SymbolsCharged copied from meterer, should be refactored diff --git a/api/clients/accountant_test.go b/api/clients/accountant_test.go index d40f75550..979c08792 100644 --- a/api/clients/accountant_test.go +++ b/api/clients/accountant_test.go @@ -9,7 +9,6 @@ import ( "time" "github.com/Layr-Labs/eigenda/core" - "github.com/Layr-Labs/eigenda/core/auth" "github.com/Layr-Labs/eigenda/core/meterer" "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" @@ -34,9 +33,8 @@ func TestNewAccountant(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) assert.NotNil(t, accountant) assert.Equal(t, reservation, accountant.reservation) @@ -65,15 +63,14 @@ func TestAccountBlob_Reservation(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) ctx := context.Background() symbolLength := uint64(500) quorums := []uint8{0, 1} - header, _, err := accountant.AccountBlob(ctx, symbolLength, quorums) + header, err := accountant.AccountBlob(ctx, symbolLength, quorums) metadata := core.ConvertPaymentHeader(header) assert.NoError(t, err) @@ -83,7 +80,7 @@ func TestAccountBlob_Reservation(t *testing.T) { symbolLength = uint64(700) - header, _, err = accountant.AccountBlob(ctx, symbolLength, quorums) + header, err = accountant.AccountBlob(ctx, symbolLength, quorums) metadata = core.ConvertPaymentHeader(header) assert.NoError(t, err) @@ -92,7 +89,7 @@ func TestAccountBlob_Reservation(t *testing.T) { assert.Equal(t, isRotation([]uint64{1200, 0, 200}, mapRecordUsage(accountant.binRecords)), true) // Second call should use on-demand payment - header, _, err = accountant.AccountBlob(ctx, 300, quorums) + header, err = accountant.AccountBlob(ctx, 300, quorums) metadata = core.ConvertPaymentHeader(header) assert.NoError(t, err) @@ -117,15 +114,14 @@ func TestAccountBlob_OnDemand(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) ctx := context.Background() numSymbols := uint64(1500) quorums := []uint8{0, 1} - header, _, err := accountant.AccountBlob(ctx, numSymbols, quorums) + header, err := accountant.AccountBlob(ctx, numSymbols, quorums) assert.NoError(t, err) metadata := core.ConvertPaymentHeader(header) @@ -147,15 +143,14 @@ func TestAccountBlob_InsufficientOnDemand(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) ctx := context.Background() numSymbols := uint64(2000) quorums := []uint8{0, 1} - _, _, err = accountant.AccountBlob(ctx, numSymbols, quorums) + _, err = accountant.AccountBlob(ctx, numSymbols, quorums) assert.Contains(t, err.Error(), "neither reservation nor on-demand payment is available") } @@ -176,37 +171,36 @@ func TestAccountBlobCallSeries(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) ctx := context.Background() quorums := []uint8{0, 1} now := time.Now().Unix() // First call: Use reservation - header, _, err := accountant.AccountBlob(ctx, 800, quorums) + header, err := accountant.AccountBlob(ctx, 800, quorums) metadata := core.ConvertPaymentHeader(header) assert.NoError(t, err) assert.Equal(t, meterer.GetBinIndex(uint64(now), reservationWindow), header.BinIndex) assert.Equal(t, big.NewInt(0), metadata.CumulativePayment) // Second call: Use remaining reservation + overflow - header, _, err = accountant.AccountBlob(ctx, 300, quorums) + header, err = accountant.AccountBlob(ctx, 300, quorums) metadata = core.ConvertPaymentHeader(header) assert.NoError(t, err) assert.Equal(t, meterer.GetBinIndex(uint64(now), reservationWindow), header.BinIndex) assert.Equal(t, big.NewInt(0), metadata.CumulativePayment) // Third call: Use on-demand - header, _, err = accountant.AccountBlob(ctx, 500, quorums) + header, err = accountant.AccountBlob(ctx, 500, quorums) metadata = core.ConvertPaymentHeader(header) assert.NoError(t, err) assert.Equal(t, uint32(0), header.BinIndex) assert.Equal(t, big.NewInt(500), metadata.CumulativePayment) // Fourth call: Insufficient on-demand - _, _, err = accountant.AccountBlob(ctx, 600, quorums) + _, err = accountant.AccountBlob(ctx, 600, quorums) assert.Error(t, err) assert.Contains(t, err.Error(), "neither reservation nor on-demand payment is available") } @@ -225,17 +219,17 @@ func TestAccountBlob_BinRotation(t *testing.T) { reservationWindow := uint32(1) // Set to 1 second for testing pricePerSymbol := uint32(1) minNumSymbols := uint32(100) + privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) ctx := context.Background() quorums := []uint8{0, 1} // First call - _, _, err = accountant.AccountBlob(ctx, 800, quorums) + _, err = accountant.AccountBlob(ctx, 800, quorums) assert.NoError(t, err) assert.Equal(t, isRotation([]uint64{800, 0, 0}, mapRecordUsage(accountant.binRecords)), true) @@ -243,12 +237,12 @@ func TestAccountBlob_BinRotation(t *testing.T) { time.Sleep(1000 * time.Millisecond) // Second call - _, _, err = accountant.AccountBlob(ctx, 300, quorums) + _, err = accountant.AccountBlob(ctx, 300, quorums) assert.NoError(t, err) assert.Equal(t, isRotation([]uint64{800, 300, 0}, mapRecordUsage(accountant.binRecords)), true) // Third call - _, _, err = accountant.AccountBlob(ctx, 500, quorums) + _, err = accountant.AccountBlob(ctx, 500, quorums) assert.NoError(t, err) assert.Equal(t, isRotation([]uint64{800, 800, 0}, mapRecordUsage(accountant.binRecords)), true) } @@ -270,9 +264,8 @@ func TestConcurrentBinRotationAndAccountBlob(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) ctx := context.Background() quorums := []uint8{0, 1} @@ -285,7 +278,7 @@ func TestConcurrentBinRotationAndAccountBlob(t *testing.T) { defer wg.Done() // for j := 0; j < 5; j++ { // fmt.Println("request ", i) - _, _, err := accountant.AccountBlob(ctx, 100, quorums) + _, err := accountant.AccountBlob(ctx, 100, quorums) assert.NoError(t, err) time.Sleep(500 * time.Millisecond) // } @@ -317,15 +310,15 @@ func TestAccountBlob_ReservationWithOneOverflow(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) + ctx := context.Background() quorums := []uint8{0, 1} now := time.Now().Unix() // Okay reservation - header, _, err := accountant.AccountBlob(ctx, 800, quorums) + header, err := accountant.AccountBlob(ctx, 800, quorums) assert.NoError(t, err) assert.Equal(t, meterer.GetBinIndex(uint64(now), reservationWindow), header.BinIndex) metadata := core.ConvertPaymentHeader(header) @@ -333,14 +326,14 @@ func TestAccountBlob_ReservationWithOneOverflow(t *testing.T) { assert.Equal(t, isRotation([]uint64{800, 0, 0}, mapRecordUsage(accountant.binRecords)), true) // Second call: Allow one overflow - header, _, err = accountant.AccountBlob(ctx, 500, quorums) + header, err = accountant.AccountBlob(ctx, 500, quorums) assert.NoError(t, err) metadata = core.ConvertPaymentHeader(header) assert.Equal(t, big.NewInt(0), metadata.CumulativePayment) assert.Equal(t, isRotation([]uint64{1300, 0, 300}, mapRecordUsage(accountant.binRecords)), true) // Third call: Should use on-demand payment - header, _, err = accountant.AccountBlob(ctx, 200, quorums) + header, err = accountant.AccountBlob(ctx, 200, quorums) assert.NoError(t, err) assert.Equal(t, uint32(0), header.BinIndex) metadata = core.ConvertPaymentHeader(header) @@ -365,20 +358,19 @@ func TestAccountBlob_ReservationOverflowReset(t *testing.T) { privateKey1, err := crypto.GenerateKey() assert.NoError(t, err) - paymentSigner, err := auth.NewPaymentSigner(hex.EncodeToString(privateKey1.D.Bytes())) - assert.NoError(t, err) - accountant := NewAccountant(reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, paymentSigner, numBins) + accountId := hex.EncodeToString(privateKey1.D.Bytes()) + accountant := NewAccountant(accountId, reservation, onDemand, reservationWindow, pricePerSymbol, minNumSymbols, numBins) ctx := context.Background() quorums := []uint8{0, 1} // full reservation - _, _, err = accountant.AccountBlob(ctx, 1000, quorums) + _, err = accountant.AccountBlob(ctx, 1000, quorums) assert.NoError(t, err) assert.Equal(t, isRotation([]uint64{1000, 0, 0}, mapRecordUsage(accountant.binRecords)), true) // no overflow - header, _, err := accountant.AccountBlob(ctx, 500, quorums) + header, err := accountant.AccountBlob(ctx, 500, quorums) assert.NoError(t, err) assert.Equal(t, isRotation([]uint64{1000, 0, 0}, mapRecordUsage(accountant.binRecords)), true) metadata := core.ConvertPaymentHeader(header) @@ -388,7 +380,7 @@ func TestAccountBlob_ReservationOverflowReset(t *testing.T) { time.Sleep(time.Duration(reservationWindow) * time.Second) // Third call: Should use new bin and allow overflow again - _, _, err = accountant.AccountBlob(ctx, 500, quorums) + _, err = accountant.AccountBlob(ctx, 500, quorums) assert.NoError(t, err) assert.Equal(t, isRotation([]uint64{1000, 500, 0}, mapRecordUsage(accountant.binRecords)), true) } diff --git a/api/clients/mock/disperser_client.go b/api/clients/mock/disperser_client.go index ffdb0b4b9..3763e8130 100644 --- a/api/clients/mock/disperser_client.go +++ b/api/clients/mock/disperser_client.go @@ -80,6 +80,7 @@ func (c *MockDisperserClient) DisperseBlob(ctx context.Context, data []byte, quo return status, key, err } + func (c *MockDisperserClient) GetBlobStatus(ctx context.Context, key []byte) (*disperser_rpc.BlobStatusReply, error) { args := c.Called(key) var reply *disperser_rpc.BlobStatusReply diff --git a/core/auth/payment_signer.go b/core/auth/payment_signer.go deleted file mode 100644 index a6f11c28a..000000000 --- a/core/auth/payment_signer.go +++ /dev/null @@ -1,121 +0,0 @@ -package auth - -import ( - "crypto/ecdsa" - "encoding/hex" - "fmt" - "log" - - "github.com/Layr-Labs/eigenda/core" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -type paymentSigner struct { - PrivateKey *ecdsa.PrivateKey -} - -var _ core.PaymentSigner = &paymentSigner{} - -func NewPaymentSigner(privateKeyHex string) (*paymentSigner, error) { - if len(privateKeyHex) == 0 { - return nil, fmt.Errorf("private key cannot be empty") - } - privateKeyBytes := common.FromHex(privateKeyHex) - privateKey, err := crypto.ToECDSA(privateKeyBytes) - if err != nil { - return nil, fmt.Errorf("failed to convert hex to ECDSA private key: %w", err) - } - - return &paymentSigner{ - PrivateKey: privateKey, - }, nil -} - -// SignBlobPayment signs the payment header and returns the signature -func (s *paymentSigner) SignBlobPayment(pm *core.PaymentMetadata) ([]byte, error) { - hash, err := pm.Hash() - if err != nil { - return nil, fmt.Errorf("failed to hash payment header: %w", err) - } - - sig, err := crypto.Sign(hash[:], s.PrivateKey) - if err != nil { - return nil, fmt.Errorf("failed to sign hash: %w", err) - } - - return sig, nil -} - -type NoopPaymentSigner struct{} - -func NewNoopPaymentSigner() *NoopPaymentSigner { - return &NoopPaymentSigner{} -} - -func (s *NoopPaymentSigner) SignBlobPayment(header *core.PaymentMetadata) ([]byte, error) { - return nil, fmt.Errorf("noop signer cannot sign blob payment header") -} - -func (s *NoopPaymentSigner) GetAccountID() string { - return "" -} - -// VerifyPaymentSignature verifies the signature against the payment metadata -func VerifyPaymentSignature(paymentHeader *core.PaymentMetadata, paymentSignature []byte) error { - hash, err := paymentHeader.Hash() - if err != nil { - return fmt.Errorf("failed to hash payment header: %w", err) - } - - recoveredPubKey, err := crypto.SigToPub(hash[:], paymentSignature) - if err != nil { - return fmt.Errorf("failed to recover public key from signature: %w", err) - } - - recoveredAddress := crypto.PubkeyToAddress(*recoveredPubKey) - accountId := common.HexToAddress(paymentHeader.AccountID) - if recoveredAddress != accountId { - return fmt.Errorf("signature address %s does not match account id %s", recoveredAddress.Hex(), accountId.Hex()) - } - - ok := crypto.VerifySignature( - crypto.FromECDSAPub(recoveredPubKey), - hash[:], - paymentSignature[:len(paymentSignature)-1], // Remove recovery ID - ) - - if !ok { - return fmt.Errorf("invalid signature") - } - - return nil -} - -// VerifyAccountSignature verifies the signature against an account ID -func VerifyAccountSignature(accountID string, paymentSignature []byte) bool { - pubKeyBytes, err := hex.DecodeString(accountID) - if err != nil { - log.Printf("Failed to decode AccountId: %v\n", err) - return false - } - accountPubKey, err := crypto.UnmarshalPubkey(pubKeyBytes) - if err != nil { - log.Printf("Failed to unmarshal public key: %v\n", err) - return false - } - - return crypto.VerifySignature( - crypto.FromECDSAPub(accountPubKey), - []byte(accountID), - paymentSignature[:len(paymentSignature)-1], // Remove recovery ID - ) -} - -// GetAccountID returns the Ethereum address of the signer -func (s *paymentSigner) GetAccountID() string { - publicKey := crypto.FromECDSAPub(&s.PrivateKey.PublicKey) - hash := crypto.Keccak256(publicKey[1:]) - - return common.BytesToAddress(hash[12:]).Hex() -} diff --git a/core/auth/payment_signer_test.go b/core/auth/payment_signer_test.go deleted file mode 100644 index e2c1a172a..000000000 --- a/core/auth/payment_signer_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package auth_test - -import ( - "encoding/hex" - "math/big" - "testing" - - "github.com/Layr-Labs/eigenda/core" - "github.com/Layr-Labs/eigenda/core/auth" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestPaymentSigner(t *testing.T) { - privateKey, err := crypto.GenerateKey() - require.NoError(t, err) - - privateKeyHex := hex.EncodeToString(crypto.FromECDSA(privateKey)) - signer, err := auth.NewPaymentSigner(privateKeyHex) - require.NoError(t, err) - - t.Run("SignBlobPayment", func(t *testing.T) { - header := &core.PaymentMetadata{ - AccountID: signer.GetAccountID(), - BinIndex: 1, - CumulativePayment: big.NewInt(1), - } - - signature, err := signer.SignBlobPayment(header) - require.NoError(t, err) - assert.NotEmpty(t, signature) - - // Verify the signature - err = auth.VerifyPaymentSignature(header, signature) - assert.NoError(t, err) - }) - - t.Run("VerifyPaymentSignature_InvalidSignature", func(t *testing.T) { - header := &core.PaymentMetadata{ - BinIndex: 1, - CumulativePayment: big.NewInt(1), - AccountID: signer.GetAccountID(), - } - - // Create an invalid signature - invalidSignature := make([]byte, 65) - err = auth.VerifyPaymentSignature(header, invalidSignature) - assert.Error(t, err) - }) - - t.Run("VerifyPaymentSignature_ModifiedHeader", func(t *testing.T) { - header := &core.PaymentMetadata{ - BinIndex: 1, - CumulativePayment: big.NewInt(1), - AccountID: signer.GetAccountID(), - } - - signature, err := signer.SignBlobPayment(header) - require.NoError(t, err) - - // Modify the header after signing - header.BinIndex = 2 - - err = auth.VerifyPaymentSignature(header, signature) - assert.Error(t, err) - }) -} - -func TestNoopPaymentSigner(t *testing.T) { - signer := auth.NewNoopPaymentSigner() - - t.Run("SignBlobRequest", func(t *testing.T) { - _, err := signer.SignBlobPayment(nil) - assert.Error(t, err) - assert.Contains(t, err.Error(), "noop signer cannot sign blob payment header") - }) -} diff --git a/disperser/apiserver/disperse_blob_v2.go b/disperser/apiserver/disperse_blob_v2.go index fbee06e4c..d8af9f3b4 100644 --- a/disperser/apiserver/disperse_blob_v2.go +++ b/disperser/apiserver/disperse_blob_v2.go @@ -9,7 +9,6 @@ import ( "github.com/Layr-Labs/eigenda/api" pb "github.com/Layr-Labs/eigenda/api/grpc/disperser/v2" "github.com/Layr-Labs/eigenda/core" - "github.com/Layr-Labs/eigenda/core/auth" corev2 "github.com/Layr-Labs/eigenda/core/v2" dispv2 "github.com/Layr-Labs/eigenda/disperser/common/v2" "github.com/Layr-Labs/eigenda/encoding" @@ -32,10 +31,6 @@ func (s *DispersalServerV2) DisperseBlob(ctx context.Context, req *pb.DisperseBl if req.GetBlobHeader().GetPaymentHeader() != nil { binIndex := req.GetBlobHeader().GetPaymentHeader().GetBinIndex() cumulativePayment := new(big.Int).SetBytes(req.GetBlobHeader().GetPaymentHeader().GetCumulativePayment()) - signature := req.GetBlobHeader().GetSignature() - if err := auth.VerifyPaymentSignature(core.ConvertToPaymentMetadata(req.GetBlobHeader().GetPaymentHeader()), signature); err != nil { - return nil, api.NewErrorInvalidArg("payment signature is invalid") - } paymentHeader := core.PaymentMetadata{ AccountID: req.GetBlobHeader().GetPaymentHeader().GetAccountId(), @@ -49,7 +44,6 @@ func (s *DispersalServerV2) DisperseBlob(ctx context.Context, req *pb.DisperseBl return nil, api.NewErrorResourceExhausted(err.Error()) } } else { - // Q: do we want a seprate check to use original rate limiter if there's no payment attached? return nil, api.NewErrorInvalidArg("payment header is required") } diff --git a/disperser/apiserver/server_v2_test.go b/disperser/apiserver/server_v2_test.go index e70fb3c82..e2cbb3f16 100644 --- a/disperser/apiserver/server_v2_test.go +++ b/disperser/apiserver/server_v2_test.go @@ -57,20 +57,28 @@ func TestV2DisperseBlob(t *testing.T) { assert.NoError(t, err) commitmentProto, err := commitments.ToProtobuf() assert.NoError(t, err) + paymentMetadata := core.PaymentMetadata{ + AccountID: accountID, + BinIndex: 5, + CumulativePayment: big.NewInt(100), + } + pk := "2d23e142a9e86a9175b9dfa213f20ea01f6c1731e09fa6edf895f70fe279cbb1" + paymentSigner, err := auth.NewPaymentSigner(pk) + assert.NoError(t, err) + sig, err := paymentSigner.SignBlobPayment(&paymentMetadata) + assert.NoError(t, err) + blobHeaderProto := &pbcommonv2.BlobHeader{ Version: 0, QuorumNumbers: []uint32{0, 1}, Commitment: commitmentProto, - PaymentHeader: &pbcommon.PaymentHeader{ - AccountId: accountID, - BinIndex: 5, - CumulativePayment: big.NewInt(100).Bytes(), - }, + PaymentHeader: paymentMetadata.ToProtobuf(), + Signature: sig, } blobHeader, err := corev2.BlobHeaderFromProtobuf(blobHeaderProto) assert.NoError(t, err) signer := auth.NewLocalBlobRequestSigner(privateKeyHex) - sig, err := signer.SignBlobRequest(blobHeader) + sig, err = signer.SignBlobRequest(blobHeader) assert.NoError(t, err) blobHeader.Signature = sig blobHeaderProto.Signature = sig