Skip to content

Commit

Permalink
fix: use existing signaturemethod
Browse files Browse the repository at this point in the history
  • Loading branch information
hopeyen committed Nov 22, 2024
1 parent 06999f3 commit cfc0477
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 273 deletions.
24 changes: 9 additions & 15 deletions api/clients/accountant.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -36,16 +37,15 @@ type accountant struct {
usageLock sync.Mutex
cumulativePayment *big.Int

paymentSigner core.PaymentSigner
numBins uint32
numBins uint32
}

type BinRecord struct {
Index uint32
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
Expand All @@ -54,14 +54,14 @@ 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,
pricePerSymbol: pricePerSymbol,
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?
Expand Down Expand Up @@ -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
Expand Down
86 changes: 39 additions & 47 deletions api/clients/accountant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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")
}

Expand All @@ -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")
}
Expand All @@ -225,30 +219,30 @@ 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)

// next reservation duration
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)
}
Expand All @@ -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}
Expand All @@ -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)
// }
Expand Down Expand Up @@ -317,30 +310,30 @@ 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)
assert.Equal(t, big.NewInt(0), metadata.CumulativePayment)
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)
Expand All @@ -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)
Expand All @@ -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)
}
Expand Down
1 change: 1 addition & 0 deletions api/clients/mock/disperser_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit cfc0477

Please sign in to comment.