Skip to content
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

[payment] transactor ping payment vault contract #827

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/clients/accountant.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (a *accountant) BlobPaymentInfo(ctx context.Context, numSymbols uint64, quo
relativeBinRecord.Usage += numSymbols

// first attempt to use the active reservation
binLimit := a.reservation.SymbolsPerSec * uint64(a.reservationWindow)
binLimit := a.reservation.SymbolsPerSecond * uint64(a.reservationWindow)
if relativeBinRecord.Usage <= binLimit {
if err := QuorumCheck(quorumNumbers, a.reservation.QuorumNumbers); err != nil {
return 0, big.NewInt(0), err
Expand Down
80 changes: 40 additions & 40 deletions api/clients/accountant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ const numBins = uint32(3)

func TestNewAccountant(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 100,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 100,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(500),
Expand All @@ -50,11 +50,11 @@ func TestNewAccountant(t *testing.T) {

func TestAccountBlob_Reservation(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(500),
Expand Down Expand Up @@ -102,11 +102,11 @@ func TestAccountBlob_Reservation(t *testing.T) {

func TestAccountBlob_OnDemand(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(1500),
Expand Down Expand Up @@ -161,11 +161,11 @@ func TestAccountBlob_InsufficientOnDemand(t *testing.T) {

func TestAccountBlobCallSeries(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(1000),
Expand Down Expand Up @@ -213,11 +213,11 @@ func TestAccountBlobCallSeries(t *testing.T) {

func TestAccountBlob_BinRotation(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 1000,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 1000,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(1000),
Expand Down Expand Up @@ -255,11 +255,11 @@ func TestAccountBlob_BinRotation(t *testing.T) {

func TestConcurrentBinRotationAndAccountBlob(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 1000,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 1000,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(1000),
Expand Down Expand Up @@ -302,11 +302,11 @@ func TestConcurrentBinRotationAndAccountBlob(t *testing.T) {

func TestAccountBlob_ReservationWithOneOverflow(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 200,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(1000),
Expand Down Expand Up @@ -350,11 +350,11 @@ func TestAccountBlob_ReservationWithOneOverflow(t *testing.T) {

func TestAccountBlob_ReservationOverflowReset(t *testing.T) {
reservation := &core.ActiveReservation{
SymbolsPerSec: 1000,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplit: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
SymbolsPerSecond: 1000,
StartTimestamp: 100,
EndTimestamp: 200,
QuorumSplits: []byte{50, 50},
QuorumNumbers: []uint8{0, 1},
}
onDemand := &core.OnDemandPayment{
CumulativePayment: big.NewInt(1000),
Expand Down
12 changes: 6 additions & 6 deletions core/chainio.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,16 @@ type Reader interface {
GetAllVersionedBlobParams(ctx context.Context) (map[uint8]*BlobVersionParameters, error)

// GetActiveReservations returns active reservations (end timestamp > current timestamp)
GetActiveReservations(ctx context.Context, blockNumber uint32, accountIDs []string) (map[string]ActiveReservation, error)
GetActiveReservations(ctx context.Context, accountIDs []string) (map[string]ActiveReservation, error)

// GetActiveReservationByAccount returns active reservation by account ID
GetActiveReservationByAccount(ctx context.Context, blockNumber uint32, accountID string) (ActiveReservation, error)
// GetActiveReservations returns active reservations (end timestamp > current timestamp)
GetActiveReservationByAccount(ctx context.Context, accountID string) (ActiveReservation, error)

// GetOnDemandPayments returns all on-demand payments
GetOnDemandPayments(ctx context.Context, blockNumber uint32, accountIDs []string) (map[string]OnDemandPayment, error)
GetOnDemandPayments(ctx context.Context, accountIDs []string) (map[string]OnDemandPayment, error)

// GetOnDemandPaymentByAccount returns on-demand payment of an account
GetOnDemandPaymentByAccount(ctx context.Context, blockNumber uint32, accountID string) (OnDemandPayment, error)
// GetOnDemandPayments returns all on-demand payments
GetOnDemandPaymentByAccount(ctx context.Context, accountID string) (OnDemandPayment, error)
}

type Writer interface {
Expand Down
10 changes: 2 additions & 8 deletions core/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

commonpb "github.com/Layr-Labs/eigenda/api/grpc/common"
"github.com/Layr-Labs/eigenda/common"
paymentvault "github.com/Layr-Labs/eigenda/contracts/bindings/PaymentVault"
"github.com/Layr-Labs/eigenda/encoding"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/consensys/gnark-crypto/ecc/bn254"
Expand Down Expand Up @@ -600,14 +601,7 @@ func ConvertToPaymentMetadata(ph *commonpb.PaymentHeader) *PaymentMetadata {

// OperatorInfo contains information about an operator which is stored on the blockchain state,
// corresponding to a particular quorum
type ActiveReservation struct {
SymbolsPerSec uint64 // reserve number of symbols per second
StartTimestamp uint64 // Unix timestamp that's valid for basically eternity
EndTimestamp uint64

QuorumNumbers []uint8 // allowed quorums
QuorumSplit []byte // ordered mapping of quorum number to payment split; on-chain validation should ensure split <= 100
}
type ActiveReservation = paymentvault.IPaymentVaultReservation

type OnDemandPayment struct {
CumulativePayment *big.Int // Total amount deposited by the user
Expand Down
119 changes: 99 additions & 20 deletions core/eth/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
ejectionmg "github.com/Layr-Labs/eigenda/contracts/bindings/EjectionManager"
indexreg "github.com/Layr-Labs/eigenda/contracts/bindings/IIndexRegistry"
opstateretriever "github.com/Layr-Labs/eigenda/contracts/bindings/OperatorStateRetriever"
paymentvault "github.com/Layr-Labs/eigenda/contracts/bindings/PaymentVault"
regcoordinator "github.com/Layr-Labs/eigenda/contracts/bindings/RegistryCoordinator"
stakereg "github.com/Layr-Labs/eigenda/contracts/bindings/StakeRegistry"
"github.com/Layr-Labs/eigenda/core"
Expand All @@ -37,6 +38,7 @@ type ContractBindings struct {
EigenDAServiceManager *eigendasrvmg.ContractEigenDAServiceManager
EjectionManager *ejectionmg.ContractEjectionManager
AVSDirectory *avsdir.ContractAVSDirectory
PaymentVault *paymentvault.ContractPaymentVault
}

type Reader struct {
Expand Down Expand Up @@ -616,42 +618,119 @@ func (t *Reader) GetAllVersionedBlobParams(ctx context.Context) (map[uint8]*core
return res, nil
}

func (t *Reader) GetActiveReservations(ctx context.Context, blockNumber uint32, accountIDs []string) (map[string]core.ActiveReservation, error) {
// contract is not implemented yet
return map[string]core.ActiveReservation{}, nil
func (t *Reader) GetActiveReservations(ctx context.Context, accountIDs []string) (map[string]core.ActiveReservation, error) {
// map accountIDs to addresses
accountAddresses := make([]gethcommon.Address, len(accountIDs))
for i, accountID := range accountIDs {
accountAddresses[i] = gethcommon.HexToAddress(accountID)
}

reservations_map := make(map[string]core.ActiveReservation)
reservations, err := t.bindings.PaymentVault.GetReservations(&bind.CallOpts{
Context: ctx,
}, accountAddresses)
if err != nil {
return nil, err
}

// since reservations are returned in the same order as the accountIDs, we can directly map them
for i, reservation := range reservations {
reservations_map[accountIDs[i]] = reservation
}
return reservations_map, nil
}

func (t *Reader) GetActiveReservationByAccount(ctx context.Context, blockNumber uint32, accountID string) (core.ActiveReservation, error) {
// contract is not implemented yet
return core.ActiveReservation{}, nil
func (t *Reader) GetActiveReservationByAccount(ctx context.Context, accountID string) (core.ActiveReservation, error) {
reservation, err := t.bindings.PaymentVault.GetReservation(&bind.CallOpts{
Context: ctx,
}, gethcommon.HexToAddress(accountID))
if err != nil {
return core.ActiveReservation{}, err
}
return reservation, nil
}

func (t *Reader) GetOnDemandPayments(ctx context.Context, blockNumber uint32, accountIDs []string) (map[string]core.OnDemandPayment, error) {
// contract is not implemented yet
return map[string]core.OnDemandPayment{}, nil
func (t *Reader) GetOnDemandPayments(ctx context.Context, accountIDs []string) (map[string]core.OnDemandPayment, error) {
// map accountIDs to addresses
accountAddresses := make([]gethcommon.Address, len(accountIDs))
for i, accountID := range accountIDs {
accountAddresses[i] = gethcommon.HexToAddress(accountID)
}
payments_map := make(map[string]core.OnDemandPayment)
payments, err := t.bindings.PaymentVault.GetOnDemandAmounts(&bind.CallOpts{
Context: ctx,
}, accountAddresses)
if err != nil {
return nil, err
}

// since payments are returned in the same order as the accountIDs, we can directly map them
for i, payment := range payments {
payments_map[accountIDs[i]] = core.OnDemandPayment{
CumulativePayment: payment,
}
}
return payments_map, nil
}

func (t *Reader) GetOnDemandPaymentByAccount(ctx context.Context, blockNumber uint32, accountID string) (core.OnDemandPayment, error) {
// contract is not implemented yet
return core.OnDemandPayment{}, nil
func (t *Reader) GetOnDemandPaymentByAccount(ctx context.Context, accountID string) (core.OnDemandPayment, error) {
onDemandPayment, err := t.bindings.PaymentVault.GetOnDemandAmount(&bind.CallOpts{
Context: ctx,
}, gethcommon.HexToAddress(accountID))
if err != nil {
return core.OnDemandPayment{}, err
}
return core.OnDemandPayment{
CumulativePayment: onDemandPayment,
}, nil
}

func (t *Reader) GetGlobalSymbolsPerSecond(ctx context.Context) (uint64, error) {
// contract is not implemented yet
return 0, nil
globalSymbolsPerSecond, err := t.bindings.PaymentVault.GlobalRateBinInterval(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return 0, err
}
return globalSymbolsPerSecond.Uint64(), nil
}

func (t *Reader) GetGlobalRateBinInterval(ctx context.Context) (uint64, error) {
globalRateBinInterval, err := t.bindings.PaymentVault.GlobalRateBinInterval(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return 0, err
}
return globalRateBinInterval.Uint64(), nil
}

func (t *Reader) GetMinNumSymbols(ctx context.Context) (uint32, error) {
// contract is not implemented yet
return 0, nil
minNumSymbols, err := t.bindings.PaymentVault.MinNumSymbols(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return 0, err
}
return uint32(minNumSymbols.Uint64()), nil
}

func (t *Reader) GetPricePerSymbol(ctx context.Context) (uint32, error) {
// contract is not implemented yet
return 0, nil
pricePerSymbol, err := t.bindings.PaymentVault.PricePerSymbol(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return 0, err
}
return uint32(pricePerSymbol.Uint64()), nil
}

func (t *Reader) GetReservationWindow(ctx context.Context) (uint32, error) {
// contract is not implemented yet
return 0, nil
reservationWindow, err := t.bindings.PaymentVault.ReservationBinInterval(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return 0, err
}
return uint32(reservationWindow.Uint64()), nil
}
2 changes: 1 addition & 1 deletion core/meterer/meterer.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,5 +281,5 @@ func (m *Meterer) IncrementGlobalBinUsage(ctx context.Context, symbolsCharged ui

// GetReservationBinLimit returns the bin limit for a given reservation
func (m *Meterer) GetReservationBinLimit(reservation *core.ActiveReservation) uint64 {
return reservation.SymbolsPerSec * uint64(m.ChainPaymentState.GetReservationWindow())
return reservation.SymbolsPerSecond * uint64(m.ChainPaymentState.GetReservationWindow())
}
4 changes: 2 additions & 2 deletions core/meterer/meterer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ func setup(_ *testing.M) {
now := uint64(time.Now().Unix())
accountID1 = crypto.PubkeyToAddress(privateKey1.PublicKey).Hex()
accountID2 = crypto.PubkeyToAddress(privateKey2.PublicKey).Hex()
account1Reservations = core.ActiveReservation{SymbolsPerSec: 100, StartTimestamp: now + 1200, EndTimestamp: now + 1800, QuorumSplit: []byte{50, 50}, QuorumNumbers: []uint8{0, 1}}
account2Reservations = core.ActiveReservation{SymbolsPerSec: 200, StartTimestamp: now - 120, EndTimestamp: now + 180, QuorumSplit: []byte{30, 70}, QuorumNumbers: []uint8{0, 1}}
account1Reservations = core.ActiveReservation{SymbolsPerSecond: 100, StartTimestamp: now + 1200, EndTimestamp: now + 1800, QuorumSplits: []byte{50, 50}, QuorumNumbers: []uint8{0, 1}}
account2Reservations = core.ActiveReservation{SymbolsPerSecond: 200, StartTimestamp: now - 120, EndTimestamp: now + 180, QuorumSplits: []byte{30, 70}, QuorumNumbers: []uint8{0, 1}}
account1OnDemandPayments = core.OnDemandPayment{CumulativePayment: big.NewInt(3864)}
account2OnDemandPayments = core.OnDemandPayment{CumulativePayment: big.NewInt(2000)}

Expand Down
Loading
Loading