diff --git a/api/clients/accountant.go b/api/clients/accountant.go index bd8192b31..ef76eef1d 100644 --- a/api/clients/accountant.go +++ b/api/clients/accountant.go @@ -77,7 +77,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 @@ -166,7 +166,7 @@ func (a *Accountant) SetPaymentState(paymentState *disperser_rpc.GetPaymentState return fmt.Errorf("reservation cannot be nil") } else if paymentState.GetReservation().GetQuorumNumbers() == nil { return fmt.Errorf("reservation quorum numbers cannot be nil") - } else if paymentState.GetReservation().GetQuorumSplit() == nil { + } else if paymentState.GetReservation().GetQuorumSplits() == nil { return fmt.Errorf("reservation quorum split cannot be nil") } else if paymentState.GetBinRecords() == nil { return fmt.Errorf("bin records cannot be nil") @@ -177,7 +177,7 @@ func (a *Accountant) SetPaymentState(paymentState *disperser_rpc.GetPaymentState a.cumulativePayment = new(big.Int).SetBytes(paymentState.CumulativePayment) a.pricePerSymbol = uint32(paymentState.PaymentGlobalParams.PricePerSymbol) - a.reservation.SymbolsPerSec = uint64(paymentState.PaymentGlobalParams.GlobalSymbolsPerSecond) + a.reservation.SymbolsPerSecond = uint64(paymentState.PaymentGlobalParams.GlobalSymbolsPerSecond) a.reservation.StartTimestamp = uint64(paymentState.Reservation.StartTimestamp) a.reservation.EndTimestamp = uint64(paymentState.Reservation.EndTimestamp) a.reservationWindow = uint32(paymentState.PaymentGlobalParams.ReservationWindow) @@ -188,11 +188,11 @@ func (a *Accountant) SetPaymentState(paymentState *disperser_rpc.GetPaymentState } a.reservation.QuorumNumbers = quorumNumbers - quorumSplit := make([]uint8, len(paymentState.Reservation.QuorumSplit)) - for i, quorum := range paymentState.Reservation.QuorumSplit { - quorumSplit[i] = uint8(quorum) + quorumSplits := make([]uint8, len(paymentState.Reservation.QuorumSplits)) + for i, quorum := range paymentState.Reservation.QuorumSplits { + quorumSplits[i] = uint8(quorum) } - a.reservation.QuorumSplit = quorumSplit + a.reservation.QuorumSplits = quorumSplits binRecords := make([]BinRecord, len(paymentState.BinRecords)) for i, record := range paymentState.BinRecords { diff --git a/api/clients/accountant_test.go b/api/clients/accountant_test.go index 09b880664..5c19e1592 100644 --- a/api/clients/accountant_test.go +++ b/api/clients/accountant_test.go @@ -18,11 +18,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), @@ -48,11 +48,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), @@ -96,11 +96,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), @@ -152,11 +152,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), @@ -200,11 +200,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), @@ -242,11 +242,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), @@ -288,11 +288,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), @@ -333,11 +333,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), diff --git a/api/docs/disperser_v2.html b/api/docs/disperser_v2.html index 02c6ea22c..168ceeaf0 100644 --- a/api/docs/disperser_v2.html +++ b/api/docs/disperser_v2.html @@ -733,7 +733,7 @@

Reservation

- quorum_split + quorum_splits uint32 repeated

diff --git a/api/docs/disperser_v2.md b/api/docs/disperser_v2.md index 5b987d96f..7c02307bc 100644 --- a/api/docs/disperser_v2.md +++ b/api/docs/disperser_v2.md @@ -248,7 +248,7 @@ GetPaymentStateRequest contains parameters to query the payment state of an acco | start_timestamp | [uint32](#uint32) | | | | end_timestamp | [uint32](#uint32) | | | | quorum_numbers | [uint32](#uint32) | repeated | | -| quorum_split | [uint32](#uint32) | repeated | | +| quorum_splits | [uint32](#uint32) | repeated | | diff --git a/api/docs/eigenda-protos.html b/api/docs/eigenda-protos.html index 9f1c0c1c9..7ffceec02 100644 --- a/api/docs/eigenda-protos.html +++ b/api/docs/eigenda-protos.html @@ -2396,7 +2396,7 @@

Reservation

- quorum_split + quorum_splits uint32 repeated

diff --git a/api/docs/eigenda-protos.md b/api/docs/eigenda-protos.md index 8b4992a42..fa357e9df 100644 --- a/api/docs/eigenda-protos.md +++ b/api/docs/eigenda-protos.md @@ -949,7 +949,7 @@ GetPaymentStateRequest contains parameters to query the payment state of an acco | start_timestamp | [uint32](#uint32) | | | | end_timestamp | [uint32](#uint32) | | | | quorum_numbers | [uint32](#uint32) | repeated | | -| quorum_split | [uint32](#uint32) | repeated | | +| quorum_splits | [uint32](#uint32) | repeated | | diff --git a/api/grpc/disperser/v2/disperser_v2.pb.go b/api/grpc/disperser/v2/disperser_v2.pb.go index 6e1db037b..cca3e75de 100644 --- a/api/grpc/disperser/v2/disperser_v2.pb.go +++ b/api/grpc/disperser/v2/disperser_v2.pb.go @@ -862,7 +862,7 @@ type Reservation struct { StartTimestamp uint32 `protobuf:"varint,2,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"` EndTimestamp uint32 `protobuf:"varint,3,opt,name=end_timestamp,json=endTimestamp,proto3" json:"end_timestamp,omitempty"` QuorumNumbers []uint32 `protobuf:"varint,4,rep,packed,name=quorum_numbers,json=quorumNumbers,proto3" json:"quorum_numbers,omitempty"` - QuorumSplit []uint32 `protobuf:"varint,5,rep,packed,name=quorum_split,json=quorumSplit,proto3" json:"quorum_split,omitempty"` + QuorumSplits []uint32 `protobuf:"varint,5,rep,packed,name=quorum_splits,json=quorumSplits,proto3" json:"quorum_splits,omitempty"` } func (x *Reservation) Reset() { @@ -925,9 +925,9 @@ func (x *Reservation) GetQuorumNumbers() []uint32 { return nil } -func (x *Reservation) GetQuorumSplit() []uint32 { +func (x *Reservation) GetQuorumSplits() []uint32 { if x != nil { - return x.QuorumSplit + return x.QuorumSplits } return nil } @@ -1108,7 +1108,7 @@ var file_disperser_v2_disperser_v2_proto_rawDesc = []byte{ 0x5f, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x71, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x15, 0x6f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x51, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x4e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x22, 0xd3, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, + 0x65, 0x72, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, @@ -1119,47 +1119,47 @@ var file_disperser_v2_disperser_v2_proto_rawDesc = []byte{ 0x0d, 0x52, 0x0c, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x71, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0d, 0x71, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x4e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x71, 0x75, 0x6f, 0x72, 0x75, 0x6d, - 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0b, 0x71, 0x75, - 0x6f, 0x72, 0x75, 0x6d, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x22, 0x37, 0x0a, 0x09, 0x42, 0x69, 0x6e, - 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x14, 0x0a, 0x05, - 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x75, 0x73, 0x61, - 0x67, 0x65, 0x2a, 0x6a, 0x0a, 0x0a, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, - 0x06, 0x51, 0x55, 0x45, 0x55, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x43, - 0x4f, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, - 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, - 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x10, 0x05, 0x32, 0xf2, - 0x02, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x0c, - 0x44, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x21, 0x2e, 0x64, - 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x44, 0x69, 0x73, 0x70, - 0x65, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x44, - 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x70, 0x6c, 0x79, - 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x64, 0x69, 0x73, - 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x42, - 0x6c, 0x6f, 0x62, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, - 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, - 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x22, 0x00, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x4c, 0x61, 0x79, 0x72, 0x2d, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x65, 0x69, 0x67, 0x65, - 0x6e, 0x64, 0x61, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x64, 0x69, 0x73, - 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x71, 0x75, 0x6f, 0x72, 0x75, 0x6d, + 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x71, + 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x73, 0x22, 0x37, 0x0a, 0x09, 0x42, + 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x14, + 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x75, + 0x73, 0x61, 0x67, 0x65, 0x2a, 0x6a, 0x0a, 0x0a, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, + 0x0a, 0x0a, 0x06, 0x51, 0x55, 0x45, 0x55, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x45, + 0x4e, 0x43, 0x4f, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x45, 0x52, 0x54, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, + 0x44, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, + 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x10, 0x05, + 0x32, 0xf2, 0x02, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x12, 0x54, + 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x21, + 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x44, 0x69, + 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, + 0x2e, 0x44, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x6c, + 0x6f, 0x62, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x64, + 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, + 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x64, 0x69, 0x73, 0x70, + 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x22, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x47, + 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x4c, 0x61, 0x79, 0x72, 0x2d, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x65, 0x69, + 0x67, 0x65, 0x6e, 0x64, 0x61, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x64, + 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/api/proto/disperser/v2/disperser_v2.proto b/api/proto/disperser/v2/disperser_v2.proto index 4107023bc..a9425249d 100644 --- a/api/proto/disperser/v2/disperser_v2.proto +++ b/api/proto/disperser/v2/disperser_v2.proto @@ -164,7 +164,7 @@ message Reservation { uint32 start_timestamp = 2; uint32 end_timestamp = 3; repeated uint32 quorum_numbers = 4; - repeated uint32 quorum_split = 5; + repeated uint32 quorum_splits = 5; } // BinRecord is the usage record of an account in a bin. The API should return the active bin diff --git a/core/chainio.go b/core/chainio.go index b5b587c8d..f9bf66081 100644 --- a/core/chainio.go +++ b/core/chainio.go @@ -110,16 +110,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 []gethcommon.Address) (map[gethcommon.Address]*ActiveReservation, error) // GetActiveReservationByAccount returns active reservation by account ID - GetActiveReservationByAccount(ctx context.Context, blockNumber uint32, accountID string) (ActiveReservation, error) + GetActiveReservationByAccount(ctx context.Context, accountID gethcommon.Address) (*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 []gethcommon.Address) (map[gethcommon.Address]*OnDemandPayment, error) // GetOnDemandPaymentByAccount returns on-demand payment of an account - GetOnDemandPaymentByAccount(ctx context.Context, blockNumber uint32, accountID string) (OnDemandPayment, error) + GetOnDemandPaymentByAccount(ctx context.Context, accountID gethcommon.Address) (*OnDemandPayment, error) // GetRelayURL returns the relay URL address for the given key. GetRelayURL(ctx context.Context, key uint32) (string, error) diff --git a/core/data.go b/core/data.go index 1a3b5218a..256f6f70e 100644 --- a/core/data.go +++ b/core/data.go @@ -601,13 +601,13 @@ 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 + SymbolsPerSecond uint64 // reserve number of symbols per second //TODO: we are not using start and end timestamp, add check or remove 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 + QuorumSplits []byte // ordered mapping of quorum number to payment split; on-chain validation should ensure split <= 100 } type OnDemandPayment struct { diff --git a/core/eth/reader.go b/core/eth/reader.go index 8e231f867..b87724244 100644 --- a/core/eth/reader.go +++ b/core/eth/reader.go @@ -15,6 +15,7 @@ import ( relayreg "github.com/Layr-Labs/eigenda/contracts/bindings/IEigenDARelayRegistry" 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" socketreg "github.com/Layr-Labs/eigenda/contracts/bindings/SocketRegistry" stakereg "github.com/Layr-Labs/eigenda/contracts/bindings/StakeRegistry" @@ -41,6 +42,7 @@ type ContractBindings struct { AVSDirectory *avsdir.ContractAVSDirectory SocketRegistry *socketreg.ContractSocketRegistry RelayRegistry *relayreg.ContractIEigenDARelayRegistry + PaymentVault *paymentvault.ContractPaymentVault } type Reader struct { @@ -208,6 +210,7 @@ func (t *Reader) updateContractBindings(blsOperatorStateRetrieverAddr, eigenDASe EigenDAServiceManager: contractEigenDAServiceManager, DelegationManager: contractDelegationManager, RelayRegistry: contractRelayRegistry, + // PaymentVault: contractPaymentVault, } return nil } @@ -654,44 +657,152 @@ 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 []gethcommon.Address) (map[gethcommon.Address]*core.ActiveReservation, error) { + if t.bindings.PaymentVault == nil { + return nil, errors.New("payment vault not deployed") + } + reservationsMap := make(map[gethcommon.Address]*core.ActiveReservation) + reservations, err := t.bindings.PaymentVault.GetReservations(&bind.CallOpts{ + Context: ctx, + }, accountIDs) + 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 { + res, err := ConvertToActiveReservation(reservation) + if err != nil { + t.logger.Warn("failed to get active reservation", "account", accountIDs[i], "err", err) + continue + } + + reservationsMap[accountIDs[i]] = res + } + + return reservationsMap, 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 gethcommon.Address) (*core.ActiveReservation, error) { + if t.bindings.PaymentVault == nil { + return nil, errors.New("payment vault not deployed") + } + reservation, err := t.bindings.PaymentVault.GetReservation(&bind.CallOpts{ + Context: ctx, + }, accountID) + if err != nil { + return nil, err + } + return ConvertToActiveReservation(reservation) } -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 []gethcommon.Address) (map[gethcommon.Address]*core.OnDemandPayment, error) { + if t.bindings.PaymentVault == nil { + return nil, errors.New("payment vault not deployed") + } + paymentsMap := make(map[gethcommon.Address]*core.OnDemandPayment) + payments, err := t.bindings.PaymentVault.GetOnDemandAmounts(&bind.CallOpts{ + Context: ctx, + }, accountIDs) + 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 { + if payment.Cmp(big.NewInt(0)) == 0 { + t.logger.Warn("failed to get on demand payment for account", "account", accountIDs[i]) + continue + } + paymentsMap[accountIDs[i]] = &core.OnDemandPayment{ + CumulativePayment: payment, + } + } + + return paymentsMap, 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 gethcommon.Address) (*core.OnDemandPayment, error) { + if t.bindings.PaymentVault == nil { + return nil, errors.New("payment vault not deployed") + } + onDemandPayment, err := t.bindings.PaymentVault.GetOnDemandAmount(&bind.CallOpts{ + Context: ctx, + }, accountID) + if err != nil { + return nil, err + } + if onDemandPayment.Cmp(big.NewInt(0)) == 0 { + return nil, errors.New("ondemand payment does not exist for given account") + } + return &core.OnDemandPayment{ + CumulativePayment: onDemandPayment, + }, nil } func (t *Reader) GetGlobalSymbolsPerSecond(ctx context.Context) (uint64, error) { - // contract is not implemented yet - return 0, nil + if t.bindings.PaymentVault == nil { + return 0, errors.New("payment vault not deployed") + } + 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) { + if t.bindings.PaymentVault == nil { + return 0, errors.New("payment vault not deployed") + } + 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 + if t.bindings.PaymentVault == nil { + return 0, errors.New("payment vault not deployed") + } + 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 + if t.bindings.PaymentVault == nil { + return 0, errors.New("payment vault not deployed") + } + 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 + if t.bindings.PaymentVault == nil { + return 0, errors.New("payment vault not deployed") + } + reservationWindow, err := t.bindings.PaymentVault.ReservationBinInterval(&bind.CallOpts{ + Context: ctx, + }) + if err != nil { + return 0, err + } + return uint32(reservationWindow.Uint64()), nil } func (t *Reader) GetOperatorSocket(ctx context.Context, operatorId core.OperatorID) (string, error) { diff --git a/core/eth/utils.go b/core/eth/utils.go index 8556fa82d..d98b6def2 100644 --- a/core/eth/utils.go +++ b/core/eth/utils.go @@ -1,12 +1,14 @@ package eth import ( + "fmt" "math/big" "slices" "github.com/Layr-Labs/eigenda/core" eigendasrvmg "github.com/Layr-Labs/eigenda/contracts/bindings/EigenDAServiceManager" + paymentvault "github.com/Layr-Labs/eigenda/contracts/bindings/PaymentVault" "github.com/ethereum/go-ethereum/crypto" ) @@ -126,3 +128,27 @@ func bitmapToBytesArray(bitmap *big.Int) []byte { } return bytesArray } + +func isZeroValuedReservation(reservation paymentvault.IPaymentVaultReservation) bool { + return reservation.SymbolsPerSecond == 0 && + reservation.StartTimestamp == 0 && + reservation.EndTimestamp == 0 && + len(reservation.QuorumNumbers) == 0 && + len(reservation.QuorumSplits) == 0 +} + +// ConvertToActiveReservation converts a upstream binding data structure to local definition. +// Returns an error if the input reservation is zero-valued. +func ConvertToActiveReservation(reservation paymentvault.IPaymentVaultReservation) (*core.ActiveReservation, error) { + if isZeroValuedReservation(reservation) { + return nil, fmt.Errorf("reservation is not a valid active reservation") + } + + return &core.ActiveReservation{ + SymbolsPerSecond: reservation.SymbolsPerSecond, + StartTimestamp: reservation.StartTimestamp, + EndTimestamp: reservation.EndTimestamp, + QuorumNumbers: reservation.QuorumNumbers, + QuorumSplits: reservation.QuorumSplits, + }, nil +} diff --git a/core/meterer/meterer.go b/core/meterer/meterer.go index ba1f2cfc6..f8d46d0b7 100644 --- a/core/meterer/meterer.go +++ b/core/meterer/meterer.go @@ -8,6 +8,7 @@ import ( "github.com/Layr-Labs/eigenda/core" "github.com/Layr-Labs/eigensdk-go/logging" + gethcommon "github.com/ethereum/go-ethereum/common" ) // Config contains network parameters that should be published on-chain. We currently configure these params through disperser env vars. @@ -71,21 +72,22 @@ func (m *Meterer) Start(ctx context.Context) { // MeterRequest validates a blob header and adds it to the meterer's state // TODO: return error if there's a rejection (with reasoning) or internal error (should be very rare) func (m *Meterer) MeterRequest(ctx context.Context, header core.PaymentMetadata, numSymbols uint, quorumNumbers []uint8) error { + accountID := gethcommon.HexToAddress(header.AccountID) // Validate against the payment method if header.CumulativePayment.Sign() == 0 { - reservation, err := m.ChainPaymentState.GetActiveReservationByAccount(ctx, header.AccountID) + reservation, err := m.ChainPaymentState.GetActiveReservationByAccount(ctx, accountID) if err != nil { return fmt.Errorf("failed to get active reservation by account: %w", err) } - if err := m.ServeReservationRequest(ctx, header, &reservation, numSymbols, quorumNumbers); err != nil { + if err := m.ServeReservationRequest(ctx, header, reservation, numSymbols, quorumNumbers); err != nil { return fmt.Errorf("invalid reservation: %w", err) } } else { - onDemandPayment, err := m.ChainPaymentState.GetOnDemandPaymentByAccount(ctx, header.AccountID) + onDemandPayment, err := m.ChainPaymentState.GetOnDemandPaymentByAccount(ctx, accountID) if err != nil { return fmt.Errorf("failed to get on-demand payment by account: %w", err) } - if err := m.ServeOnDemandRequest(ctx, header, &onDemandPayment, numSymbols, quorumNumbers); err != nil { + if err := m.ServeOnDemandRequest(ctx, header, onDemandPayment, numSymbols, quorumNumbers); err != nil { return fmt.Errorf("invalid on-demand request: %w", err) } } @@ -268,6 +270,7 @@ func (m *Meterer) ValidateGlobalBinIndex(header core.PaymentMetadata) (uint32, e // IncrementBinUsage increments the bin usage atomically and checks for overflow func (m *Meterer) IncrementGlobalBinUsage(ctx context.Context, symbolsCharged uint64) error { + //TODO: edit globalIndex based on bin interval in a subsequent PR globalIndex := uint64(time.Now().Unix()) newUsage, err := m.OffchainStore.UpdateGlobalBin(ctx, globalIndex, symbolsCharged) if err != nil { @@ -281,5 +284,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()) } diff --git a/core/meterer/meterer_test.go b/core/meterer/meterer_test.go index d4298d601..dfc4b5f6b 100644 --- a/core/meterer/meterer_test.go +++ b/core/meterer/meterer_test.go @@ -17,6 +17,7 @@ import ( "github.com/Layr-Labs/eigenda/core/mock" "github.com/Layr-Labs/eigenda/inabox/deploy" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ory/dockertest/v3" "github.com/stretchr/testify/assert" @@ -30,12 +31,12 @@ var ( dockertestResource *dockertest.Resource dynamoClient commondynamodb.Client clientConfig commonaws.ClientConfig - accountID1 string - account1Reservations core.ActiveReservation - account1OnDemandPayments core.OnDemandPayment - accountID2 string - account2Reservations core.ActiveReservation - account2OnDemandPayments core.OnDemandPayment + accountID1 gethcommon.Address + account1Reservations *core.ActiveReservation + account1OnDemandPayments *core.OnDemandPayment + accountID2 gethcommon.Address + account2Reservations *core.ActiveReservation + account2OnDemandPayments *core.OnDemandPayment mt *meterer.Meterer deployLocalStack bool @@ -123,12 +124,12 @@ 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}} - account1OnDemandPayments = core.OnDemandPayment{CumulativePayment: big.NewInt(3864)} - account2OnDemandPayments = core.OnDemandPayment{CumulativePayment: big.NewInt(2000)} + accountID1 = crypto.PubkeyToAddress(privateKey1.PublicKey) + accountID2 = crypto.PubkeyToAddress(privateKey2.PublicKey) + 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)} store, err := meterer.NewOffchainStore( clientConfig, @@ -170,18 +171,19 @@ func TestMetererReservations(t *testing.T) { ctx := context.Background() paymentChainState.On("GetReservationWindow", testifymock.Anything).Return(uint32(1), nil) paymentChainState.On("GetGlobalSymbolsPerSecond", testifymock.Anything).Return(uint64(1009), nil) + paymentChainState.On("GetGlobalRateBinInterval", testifymock.Anything).Return(uint64(1), nil) paymentChainState.On("GetMinNumSymbols", testifymock.Anything).Return(uint32(3), nil) binIndex := meterer.GetBinIndex(uint64(time.Now().Unix()), mt.ChainPaymentState.GetReservationWindow()) quoromNumbers := []uint8{0, 1} - paymentChainState.On("GetActiveReservationByAccount", testifymock.Anything, testifymock.MatchedBy(func(account string) bool { + paymentChainState.On("GetActiveReservationByAccount", testifymock.Anything, testifymock.MatchedBy(func(account gethcommon.Address) bool { return account == accountID1 })).Return(account1Reservations, nil) - paymentChainState.On("GetActiveReservationByAccount", testifymock.Anything, testifymock.MatchedBy(func(account string) bool { + paymentChainState.On("GetActiveReservationByAccount", testifymock.Anything, testifymock.MatchedBy(func(account gethcommon.Address) bool { return account == accountID2 })).Return(account2Reservations, nil) - paymentChainState.On("GetActiveReservationByAccount", testifymock.Anything, testifymock.Anything).Return(core.ActiveReservation{}, fmt.Errorf("reservation not found")) + paymentChainState.On("GetActiveReservationByAccount", testifymock.Anything, testifymock.Anything).Return(&core.ActiveReservation{}, fmt.Errorf("reservation not found")) // test invalid quorom ID header := createPaymentHeader(1, 0, accountID1) @@ -202,7 +204,7 @@ func TestMetererReservations(t *testing.T) { if err != nil { t.Fatalf("Failed to generate key: %v", err) } - header = createPaymentHeader(1, 0, crypto.PubkeyToAddress(unregisteredUser.PublicKey).Hex()) + header = createPaymentHeader(1, 0, crypto.PubkeyToAddress(unregisteredUser.PublicKey)) assert.NoError(t, err) err = mt.MeterRequest(ctx, *header, 1000, []uint8{0, 1, 2}) assert.ErrorContains(t, err, "failed to get active reservation by account: reservation not found") @@ -220,11 +222,11 @@ func TestMetererReservations(t *testing.T) { err = mt.MeterRequest(ctx, *header, symbolLength, quoromNumbers) assert.NoError(t, err) item, err := dynamoClient.GetItem(ctx, reservationTableName, commondynamodb.Key{ - "AccountID": &types.AttributeValueMemberS{Value: accountID2}, + "AccountID": &types.AttributeValueMemberS{Value: accountID2.Hex()}, "BinIndex": &types.AttributeValueMemberN{Value: strconv.Itoa(int(binIndex))}, }) assert.NoError(t, err) - assert.Equal(t, accountID2, item["AccountID"].(*types.AttributeValueMemberS).Value) + assert.Equal(t, accountID2.Hex(), item["AccountID"].(*types.AttributeValueMemberS).Value) assert.Equal(t, strconv.Itoa(int(binIndex)), item["BinIndex"].(*types.AttributeValueMemberN).Value) assert.Equal(t, strconv.Itoa((i+1)*int(requiredLength)), item["BinUsage"].(*types.AttributeValueMemberN).Value) @@ -236,11 +238,11 @@ func TestMetererReservations(t *testing.T) { assert.NoError(t, err) overflowedBinIndex := binIndex + 2 item, err := dynamoClient.GetItem(ctx, reservationTableName, commondynamodb.Key{ - "AccountID": &types.AttributeValueMemberS{Value: accountID2}, + "AccountID": &types.AttributeValueMemberS{Value: accountID2.Hex()}, "BinIndex": &types.AttributeValueMemberN{Value: strconv.Itoa(int(overflowedBinIndex))}, }) assert.NoError(t, err) - assert.Equal(t, accountID2, item["AccountID"].(*types.AttributeValueMemberS).Value) + assert.Equal(t, accountID2.Hex(), item["AccountID"].(*types.AttributeValueMemberS).Value) assert.Equal(t, strconv.Itoa(int(overflowedBinIndex)), item["BinIndex"].(*types.AttributeValueMemberN).Value) // 25 rounded up to the nearest multiple of minNumSymbols - (200-21*9) = 16 assert.Equal(t, strconv.Itoa(int(16)), item["BinUsage"].(*types.AttributeValueMemberN).Value) @@ -259,13 +261,13 @@ func TestMetererOnDemand(t *testing.T) { paymentChainState.On("GetMinNumSymbols", testifymock.Anything).Return(uint32(3), nil) binIndex := uint32(0) // this field doesn't matter for on-demand payments wrt global rate limit - paymentChainState.On("GetOnDemandPaymentByAccount", testifymock.Anything, testifymock.MatchedBy(func(account string) bool { + paymentChainState.On("GetOnDemandPaymentByAccount", testifymock.Anything, testifymock.MatchedBy(func(account gethcommon.Address) bool { return account == accountID1 })).Return(account1OnDemandPayments, nil) - paymentChainState.On("GetOnDemandPaymentByAccount", testifymock.Anything, testifymock.MatchedBy(func(account string) bool { + paymentChainState.On("GetOnDemandPaymentByAccount", testifymock.Anything, testifymock.MatchedBy(func(account gethcommon.Address) bool { return account == accountID2 })).Return(account2OnDemandPayments, nil) - paymentChainState.On("GetOnDemandPaymentByAccount", testifymock.Anything, testifymock.Anything).Return(core.OnDemandPayment{}, fmt.Errorf("payment not found")) + paymentChainState.On("GetOnDemandPaymentByAccount", testifymock.Anything, testifymock.Anything).Return(&core.OnDemandPayment{}, fmt.Errorf("payment not found")) paymentChainState.On("GetOnDemandQuorumNumbers", testifymock.Anything).Return(quorumNumbers, nil) // test unregistered account @@ -273,7 +275,7 @@ func TestMetererOnDemand(t *testing.T) { if err != nil { t.Fatalf("Failed to generate key: %v", err) } - header := createPaymentHeader(binIndex, 2, crypto.PubkeyToAddress(unregisteredUser.PublicKey).Hex()) + header := createPaymentHeader(binIndex, 2, crypto.PubkeyToAddress(unregisteredUser.PublicKey)) assert.NoError(t, err) err = mt.MeterRequest(ctx, *header, 1000, quorumNumbers) assert.ErrorContains(t, err, "failed to get on-demand payment by account: payment not found") @@ -290,7 +292,7 @@ func TestMetererOnDemand(t *testing.T) { // No rollback after meter request result, err := dynamoClient.Query(ctx, ondemandTableName, "AccountID = :account", commondynamodb.ExpressionValues{ ":account": &types.AttributeValueMemberS{ - Value: accountID1, + Value: accountID1.Hex(), }}) assert.NoError(t, err) assert.Equal(t, 1, len(result)) @@ -335,7 +337,7 @@ func TestMetererOnDemand(t *testing.T) { numPrevRecords := 12 result, err = dynamoClient.Query(ctx, ondemandTableName, "AccountID = :account", commondynamodb.ExpressionValues{ ":account": &types.AttributeValueMemberS{ - Value: accountID2, + Value: accountID2.Hex(), }}) assert.NoError(t, err) assert.Equal(t, numPrevRecords, len(result)) @@ -346,7 +348,7 @@ func TestMetererOnDemand(t *testing.T) { // Correct rollback result, err = dynamoClient.Query(ctx, ondemandTableName, "AccountID = :account", commondynamodb.ExpressionValues{ ":account": &types.AttributeValueMemberS{ - Value: accountID2, + Value: accountID2.Hex(), }}) assert.NoError(t, err) assert.Equal(t, numPrevRecords, len(result)) @@ -463,9 +465,9 @@ func TestMeterer_symbolsCharged(t *testing.T) { } } -func createPaymentHeader(binIndex uint32, cumulativePayment uint64, accountID string) *core.PaymentMetadata { +func createPaymentHeader(binIndex uint32, cumulativePayment uint64, accountID gethcommon.Address) *core.PaymentMetadata { return &core.PaymentMetadata{ - AccountID: accountID, + AccountID: accountID.Hex(), BinIndex: binIndex, CumulativePayment: big.NewInt(int64(cumulativePayment)), } diff --git a/core/meterer/onchain_state.go b/core/meterer/onchain_state.go index 2725ef765..cdfaef457 100644 --- a/core/meterer/onchain_state.go +++ b/core/meterer/onchain_state.go @@ -4,9 +4,11 @@ import ( "context" "fmt" "sync" + "sync/atomic" "github.com/Layr-Labs/eigenda/core" "github.com/Layr-Labs/eigenda/core/eth" + gethcommon "github.com/ethereum/go-ethereum/common" ) // PaymentAccounts (For reservations and on-demand payments) @@ -14,10 +16,11 @@ import ( // OnchainPaymentState is an interface for getting information about the current chain state for payments. type OnchainPayment interface { RefreshOnchainPaymentState(ctx context.Context, tx *eth.Reader) error - GetActiveReservationByAccount(ctx context.Context, accountID string) (core.ActiveReservation, error) - GetOnDemandPaymentByAccount(ctx context.Context, accountID string) (core.OnDemandPayment, error) + GetActiveReservationByAccount(ctx context.Context, accountID gethcommon.Address) (*core.ActiveReservation, error) + GetOnDemandPaymentByAccount(ctx context.Context, accountID gethcommon.Address) (*core.OnDemandPayment, error) GetOnDemandQuorumNumbers(ctx context.Context) ([]uint8, error) GetGlobalSymbolsPerSecond() uint64 + GetGlobalRateBinInterval() uint64 GetMinNumSymbols() uint32 GetPricePerSymbol() uint32 GetReservationWindow() uint32 @@ -28,69 +31,73 @@ var _ OnchainPayment = (*OnchainPaymentState)(nil) type OnchainPaymentState struct { tx *eth.Reader - ActiveReservations map[string]core.ActiveReservation - OnDemandPayments map[string]core.OnDemandPayment + ActiveReservations map[gethcommon.Address]*core.ActiveReservation + OnDemandPayments map[gethcommon.Address]*core.OnDemandPayment ReservationsLock sync.RWMutex OnDemandLocks sync.RWMutex - PaymentVaultParams PaymentVaultParams + PaymentVaultParams atomic.Pointer[PaymentVaultParams] } type PaymentVaultParams struct { GlobalSymbolsPerSecond uint64 + GlobalRateBinInterval uint64 MinNumSymbols uint32 PricePerSymbol uint32 ReservationWindow uint32 OnDemandQuorumNumbers []uint8 } -func NewOnchainPaymentState(ctx context.Context, tx *eth.Reader) (OnchainPaymentState, error) { +func NewOnchainPaymentState(ctx context.Context, tx *eth.Reader) (*OnchainPaymentState, error) { paymentVaultParams, err := GetPaymentVaultParams(ctx, tx) if err != nil { - return OnchainPaymentState{}, err + return nil, err } - return OnchainPaymentState{ + state := OnchainPaymentState{ tx: tx, - ActiveReservations: make(map[string]core.ActiveReservation), - OnDemandPayments: make(map[string]core.OnDemandPayment), - PaymentVaultParams: paymentVaultParams, - }, nil + ActiveReservations: make(map[gethcommon.Address]*core.ActiveReservation), + OnDemandPayments: make(map[gethcommon.Address]*core.OnDemandPayment), + PaymentVaultParams: atomic.Pointer[PaymentVaultParams]{}, + } + state.PaymentVaultParams.Store(paymentVaultParams) + + return &state, nil } -func GetPaymentVaultParams(ctx context.Context, tx *eth.Reader) (PaymentVaultParams, error) { +func GetPaymentVaultParams(ctx context.Context, tx *eth.Reader) (*PaymentVaultParams, error) { blockNumber, err := tx.GetCurrentBlockNumber(ctx) if err != nil { - return PaymentVaultParams{}, err + return nil, err } quorumNumbers, err := tx.GetRequiredQuorumNumbers(ctx, blockNumber) if err != nil { - return PaymentVaultParams{}, err + return nil, err } globalSymbolsPerSecond, err := tx.GetGlobalSymbolsPerSecond(ctx) if err != nil { - return PaymentVaultParams{}, err + return nil, err } minNumSymbols, err := tx.GetMinNumSymbols(ctx) if err != nil { - return PaymentVaultParams{}, err + return nil, err } pricePerSymbol, err := tx.GetPricePerSymbol(ctx) if err != nil { - return PaymentVaultParams{}, err + return nil, err } reservationWindow, err := tx.GetReservationWindow(ctx) if err != nil { - return PaymentVaultParams{}, err + return nil, err } - return PaymentVaultParams{ + return &PaymentVaultParams{ OnDemandQuorumNumbers: quorumNumbers, GlobalSymbolsPerSecond: globalSymbolsPerSecond, MinNumSymbols: minNumSymbols, @@ -106,63 +113,88 @@ func (pcs *OnchainPaymentState) RefreshOnchainPaymentState(ctx context.Context, return err } // These parameters should be rarely updated, but we refresh them anyway - pcs.PaymentVaultParams = paymentVaultParams + pcs.PaymentVaultParams.Store(paymentVaultParams) + + pcs.ReservationsLock.Lock() + accountIDs := make([]gethcommon.Address, 0, len(pcs.ActiveReservations)) + for accountID := range pcs.ActiveReservations { + accountIDs = append(accountIDs, accountID) + } + + activeReservations, err := tx.GetActiveReservations(ctx, accountIDs) + if err != nil { + return err + } + pcs.ActiveReservations = activeReservations + pcs.ReservationsLock.Unlock() + + pcs.OnDemandLocks.Lock() + accountIDs = make([]gethcommon.Address, 0, len(pcs.OnDemandPayments)) + for accountID := range pcs.OnDemandPayments { + accountIDs = append(accountIDs, accountID) + } + + onDemandPayments, err := tx.GetOnDemandPayments(ctx, accountIDs) + if err != nil { + return err + } + pcs.OnDemandPayments = onDemandPayments + pcs.OnDemandLocks.Unlock() + return nil } // GetActiveReservationByAccount returns a pointer to the active reservation for the given account ID; no writes will be made to the reservation -func (pcs *OnchainPaymentState) GetActiveReservationByAccount(ctx context.Context, accountID string) (core.ActiveReservation, error) { - if reservation, ok := pcs.ActiveReservations[accountID]; ok { +func (pcs *OnchainPaymentState) GetActiveReservationByAccount(ctx context.Context, accountID gethcommon.Address) (*core.ActiveReservation, error) { + pcs.ReservationsLock.RLock() + defer pcs.ReservationsLock.RUnlock() + if reservation, ok := (pcs.ActiveReservations)[accountID]; ok { return reservation, nil } - res, err := pcs.GetActiveReservationByAccountOnChain(ctx, accountID) + + // pulls the chain state + res, err := pcs.tx.GetActiveReservationByAccount(ctx, accountID) if err != nil { - return core.ActiveReservation{}, err + return nil, err } - pcs.ReservationsLock.Lock() - pcs.ActiveReservations[accountID] = res + (pcs.ActiveReservations)[accountID] = res pcs.ReservationsLock.Unlock() return res, nil } // GetActiveReservationByAccountOnChain returns on-chain reservation for the given account ID -func (pcs *OnchainPaymentState) GetActiveReservationByAccountOnChain(ctx context.Context, accountID string) (core.ActiveReservation, error) { - blockNumber, err := pcs.tx.GetCurrentBlockNumber(ctx) - if err != nil { - return core.ActiveReservation{}, err - } - res, err := pcs.tx.GetActiveReservationByAccount(ctx, blockNumber, accountID) +func (pcs *OnchainPaymentState) GetActiveReservationByAccountOnChain(ctx context.Context, accountID gethcommon.Address) (*core.ActiveReservation, error) { + res, err := pcs.tx.GetActiveReservationByAccount(ctx, accountID) if err != nil { - return core.ActiveReservation{}, fmt.Errorf("reservation account not found on-chain: %w", err) + return nil, fmt.Errorf("reservation account not found on-chain: %w", err) } return res, nil } // GetOnDemandPaymentByAccount returns a pointer to the on-demand payment for the given account ID; no writes will be made to the payment -func (pcs *OnchainPaymentState) GetOnDemandPaymentByAccount(ctx context.Context, accountID string) (core.OnDemandPayment, error) { - if payment, ok := pcs.OnDemandPayments[accountID]; ok { +func (pcs *OnchainPaymentState) GetOnDemandPaymentByAccount(ctx context.Context, accountID gethcommon.Address) (*core.OnDemandPayment, error) { + pcs.OnDemandLocks.RLock() + defer pcs.OnDemandLocks.RUnlock() + if payment, ok := (pcs.OnDemandPayments)[accountID]; ok { return payment, nil } - res, err := pcs.GetOnDemandPaymentByAccountOnChain(ctx, accountID) + // pulls the chain state + res, err := pcs.tx.GetOnDemandPaymentByAccount(ctx, accountID) if err != nil { - return core.OnDemandPayment{}, err + return nil, err } pcs.OnDemandLocks.Lock() - pcs.OnDemandPayments[accountID] = res + (pcs.OnDemandPayments)[accountID] = res pcs.OnDemandLocks.Unlock() return res, nil } -func (pcs *OnchainPaymentState) GetOnDemandPaymentByAccountOnChain(ctx context.Context, accountID string) (core.OnDemandPayment, error) { - blockNumber, err := pcs.tx.GetCurrentBlockNumber(ctx) +func (pcs *OnchainPaymentState) GetOnDemandPaymentByAccountOnChain(ctx context.Context, accountID gethcommon.Address) (*core.OnDemandPayment, error) { + res, err := pcs.tx.GetOnDemandPaymentByAccount(ctx, accountID) if err != nil { - return core.OnDemandPayment{}, err - } - res, err := pcs.tx.GetOnDemandPaymentByAccount(ctx, blockNumber, accountID) - if err != nil { - return core.OnDemandPayment{}, fmt.Errorf("on-demand not found on-chain: %w", err) + return nil, fmt.Errorf("on-demand not found on-chain: %w", err) } return res, nil } @@ -176,17 +208,21 @@ func (pcs *OnchainPaymentState) GetOnDemandQuorumNumbers(ctx context.Context) ([ } func (pcs *OnchainPaymentState) GetGlobalSymbolsPerSecond() uint64 { - return pcs.PaymentVaultParams.GlobalSymbolsPerSecond + return pcs.PaymentVaultParams.Load().GlobalSymbolsPerSecond +} + +func (pcs *OnchainPaymentState) GetGlobalRateBinInterval() uint64 { + return pcs.PaymentVaultParams.Load().GlobalRateBinInterval } func (pcs *OnchainPaymentState) GetMinNumSymbols() uint32 { - return pcs.PaymentVaultParams.MinNumSymbols + return pcs.PaymentVaultParams.Load().MinNumSymbols } func (pcs *OnchainPaymentState) GetPricePerSymbol() uint32 { - return pcs.PaymentVaultParams.PricePerSymbol + return pcs.PaymentVaultParams.Load().PricePerSymbol } func (pcs *OnchainPaymentState) GetReservationWindow() uint32 { - return pcs.PaymentVaultParams.ReservationWindow + return pcs.PaymentVaultParams.Load().ReservationWindow } diff --git a/core/meterer/onchain_state_test.go b/core/meterer/onchain_state_test.go index efd7149a6..d7fca8484 100644 --- a/core/meterer/onchain_state_test.go +++ b/core/meterer/onchain_state_test.go @@ -8,18 +8,19 @@ import ( "github.com/Layr-Labs/eigenda/core" "github.com/Layr-Labs/eigenda/core/eth" "github.com/Layr-Labs/eigenda/core/mock" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" testifymock "github.com/stretchr/testify/mock" ) var ( - dummyActiveReservation = core.ActiveReservation{ - SymbolsPerSec: 100, - StartTimestamp: 1000, - EndTimestamp: 2000, - QuorumSplit: []byte{50, 50}, + dummyActiveReservation = &core.ActiveReservation{ + SymbolsPerSecond: 100, + StartTimestamp: 1000, + EndTimestamp: 2000, + QuorumSplits: []byte{50, 50}, } - dummyOnDemandPayment = core.OnDemandPayment{ + dummyOnDemandPayment = &core.OnDemandPayment{ CumulativePayment: big.NewInt(1000), } ) @@ -47,7 +48,7 @@ func TestGetActiveReservationByAccount(t *testing.T) { ctx := context.Background() mockState.On("GetActiveReservationByAccount", testifymock.Anything, testifymock.Anything).Return(dummyActiveReservation, nil) - reservation, err := mockState.GetActiveReservationByAccount(ctx, "account1") + reservation, err := mockState.GetActiveReservationByAccount(ctx, gethcommon.Address{}) assert.NoError(t, err) assert.Equal(t, dummyActiveReservation, reservation) } @@ -55,10 +56,9 @@ func TestGetActiveReservationByAccount(t *testing.T) { func TestGetOnDemandPaymentByAccount(t *testing.T) { mockState := &mock.MockOnchainPaymentState{} ctx := context.Background() - accountID := "account1" mockState.On("GetOnDemandPaymentByAccount", testifymock.Anything, testifymock.Anything, testifymock.Anything).Return(dummyOnDemandPayment, nil) - payment, err := mockState.GetOnDemandPaymentByAccount(ctx, accountID) + payment, err := mockState.GetOnDemandPaymentByAccount(ctx, gethcommon.Address{}) assert.NoError(t, err) assert.Equal(t, dummyOnDemandPayment, payment) } diff --git a/core/mock/payment_state.go b/core/mock/payment_state.go index c5e788510..e4c89784d 100644 --- a/core/mock/payment_state.go +++ b/core/mock/payment_state.go @@ -6,6 +6,7 @@ import ( "github.com/Layr-Labs/eigenda/core" "github.com/Layr-Labs/eigenda/core/eth" "github.com/Layr-Labs/eigenda/core/meterer" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/mock" ) @@ -29,20 +30,20 @@ func (m *MockOnchainPaymentState) RefreshOnchainPaymentState(ctx context.Context return args.Error(0) } -func (m *MockOnchainPaymentState) GetActiveReservationByAccount(ctx context.Context, accountID string) (core.ActiveReservation, error) { +func (m *MockOnchainPaymentState) GetActiveReservationByAccount(ctx context.Context, accountID gethcommon.Address) (*core.ActiveReservation, error) { args := m.Called(ctx, accountID) - var value core.ActiveReservation + var value *core.ActiveReservation if args.Get(0) != nil { - value = args.Get(0).(core.ActiveReservation) + value = args.Get(0).(*core.ActiveReservation) } return value, args.Error(1) } -func (m *MockOnchainPaymentState) GetOnDemandPaymentByAccount(ctx context.Context, accountID string) (core.OnDemandPayment, error) { +func (m *MockOnchainPaymentState) GetOnDemandPaymentByAccount(ctx context.Context, accountID gethcommon.Address) (*core.OnDemandPayment, error) { args := m.Called(ctx, accountID) - var value core.OnDemandPayment + var value *core.OnDemandPayment if args.Get(0) != nil { - value = args.Get(0).(core.OnDemandPayment) + value = args.Get(0).(*core.OnDemandPayment) } return value, args.Error(1) } @@ -61,6 +62,11 @@ func (m *MockOnchainPaymentState) GetGlobalSymbolsPerSecond() uint64 { return args.Get(0).(uint64) } +func (m *MockOnchainPaymentState) GetGlobalRateBinInterval() uint64 { + args := m.Called() + return args.Get(0).(uint64) +} + func (m *MockOnchainPaymentState) GetMinNumSymbols() uint32 { args := m.Called() return args.Get(0).(uint32) diff --git a/core/mock/writer.go b/core/mock/writer.go index 7e56e64cc..0f1dcee9e 100644 --- a/core/mock/writer.go +++ b/core/mock/writer.go @@ -221,28 +221,28 @@ func (t *MockWriter) PubkeyHashToOperator(ctx context.Context, operatorId core.O return result.(gethcommon.Address), args.Error(1) } -func (t *MockWriter) GetActiveReservations(ctx context.Context, blockNumber uint32, accountIDs []string) (map[string]core.ActiveReservation, error) { +func (t *MockWriter) GetActiveReservations(ctx context.Context, accountIDs []gethcommon.Address) (map[gethcommon.Address]*core.ActiveReservation, error) { args := t.Called() result := args.Get(0) - return result.(map[string]core.ActiveReservation), args.Error(1) + return result.(map[gethcommon.Address]*core.ActiveReservation), args.Error(1) } -func (t *MockWriter) GetActiveReservationByAccount(ctx context.Context, blockNumber uint32, accountID string) (core.ActiveReservation, error) { +func (t *MockWriter) GetActiveReservationByAccount(ctx context.Context, accountID gethcommon.Address) (*core.ActiveReservation, error) { args := t.Called() result := args.Get(0) - return result.(core.ActiveReservation), args.Error(1) + return result.(*core.ActiveReservation), args.Error(1) } -func (t *MockWriter) GetOnDemandPayments(ctx context.Context, blockNumber uint32, accountIDs []string) (map[string]core.OnDemandPayment, error) { +func (t *MockWriter) GetOnDemandPayments(ctx context.Context, accountIDs []gethcommon.Address) (map[gethcommon.Address]*core.OnDemandPayment, error) { args := t.Called() result := args.Get(0) - return result.(map[string]core.OnDemandPayment), args.Error(1) + return result.(map[gethcommon.Address]*core.OnDemandPayment), args.Error(1) } -func (t *MockWriter) GetOnDemandPaymentByAccount(ctx context.Context, blockNumber uint32, accountID string) (core.OnDemandPayment, error) { +func (t *MockWriter) GetOnDemandPaymentByAccount(ctx context.Context, accountID gethcommon.Address) (*core.OnDemandPayment, error) { args := t.Called() result := args.Get(0) - return result.(core.OnDemandPayment), args.Error(1) + return result.(*core.OnDemandPayment), args.Error(1) } func (t *MockWriter) GetOperatorSocket(ctx context.Context, operatorID core.OperatorID) (string, error) { diff --git a/disperser/apiserver/server_test.go b/disperser/apiserver/server_test.go index 43a5b0333..29f4f74a9 100644 --- a/disperser/apiserver/server_test.go +++ b/disperser/apiserver/server_test.go @@ -758,15 +758,15 @@ func newTestServer(transactor core.Writer, testName string) *apiserver.Dispersal mockState.On("GetRequiredQuorumNumbers").Return([]uint8{0, 1}, nil) mockState.On("GetOnDemandQuorumNumbers").Return([]uint8{0, 1}, nil) mockState.On("GetReservationWindow").Return(uint32(1), nil) - mockState.On("GetOnDemandPaymentByAccount", tmock.Anything, tmock.Anything).Return(core.OnDemandPayment{ + mockState.On("GetOnDemandPaymentByAccount", tmock.Anything, tmock.Anything).Return(&core.OnDemandPayment{ CumulativePayment: big.NewInt(3000), }, nil) - mockState.On("GetActiveReservationByAccount", tmock.Anything, tmock.Anything).Return(core.ActiveReservation{ - SymbolsPerSec: 2048, - StartTimestamp: 0, - EndTimestamp: math.MaxUint32, - QuorumNumbers: []uint8{0, 1}, - QuorumSplit: []byte{50, 50}, + mockState.On("GetActiveReservationByAccount", tmock.Anything, tmock.Anything).Return(&core.ActiveReservation{ + SymbolsPerSecond: 2048, + StartTimestamp: 0, + EndTimestamp: math.MaxUint32, + QuorumNumbers: []uint8{0, 1}, + QuorumSplits: []byte{50, 50}, }, nil) // append test name to each table name for an unique store table_names := []string{"reservations_server_" + testName, "ondemand_server_" + testName, "global_server_" + testName} diff --git a/disperser/apiserver/server_v2.go b/disperser/apiserver/server_v2.go index e8dece0b3..cb96f8b40 100644 --- a/disperser/apiserver/server_v2.go +++ b/disperser/apiserver/server_v2.go @@ -22,6 +22,7 @@ import ( "github.com/Layr-Labs/eigenda/disperser/common/v2/blobstore" "github.com/Layr-Labs/eigenda/encoding" "github.com/Layr-Labs/eigensdk-go/logging" + gethcommon "github.com/ethereum/go-ethereum/common" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) @@ -222,6 +223,7 @@ func (s *DispersalServerV2) RefreshOnchainState(ctx context.Context) error { } func (s *DispersalServerV2) GetPaymentState(ctx context.Context, req *pb.GetPaymentStateRequest) (*pb.GetPaymentStateReply, error) { + accountID := gethcommon.HexToAddress(req.AccountId) // validate the signature if err := s.authenticator.AuthenticatePaymentStateRequest(req.GetSignature(), req.GetAccountId()); err != nil { return nil, api.NewErrorInvalidArg(fmt.Sprintf("authentication failed: %s", err.Error())) @@ -244,11 +246,11 @@ func (s *DispersalServerV2) GetPaymentState(ctx context.Context, req *pb.GetPaym return nil, api.NewErrorNotFound("failed to get largest cumulative payment") } // on-Chain account state - reservation, err := s.meterer.ChainPaymentState.GetActiveReservationByAccount(ctx, req.AccountId) + reservation, err := s.meterer.ChainPaymentState.GetActiveReservationByAccount(ctx, accountID) if err != nil { return nil, api.NewErrorNotFound("failed to get active reservation") } - onDemandPayment, err := s.meterer.ChainPaymentState.GetOnDemandPaymentByAccount(ctx, req.AccountId) + onDemandPayment, err := s.meterer.ChainPaymentState.GetOnDemandPaymentByAccount(ctx, accountID) if err != nil { return nil, api.NewErrorNotFound("failed to get on-demand payment") } @@ -264,20 +266,21 @@ func (s *DispersalServerV2) GetPaymentState(ctx context.Context, req *pb.GetPaym for i, v := range reservation.QuorumNumbers { quorumNumbers[i] = uint32(v) } - quorumSplit := make([]uint32, len(reservation.QuorumSplit)) - for i, v := range reservation.QuorumSplit { - quorumSplit[i] = uint32(v) + + quorumSplits := make([]uint32, len(reservation.QuorumSplits)) + for i, v := range reservation.QuorumSplits { + quorumSplits[i] = uint32(v) } // build reply reply := &pb.GetPaymentStateReply{ PaymentGlobalParams: &paymentGlobalParams, BinRecords: binRecords[:], Reservation: &pb.Reservation{ - SymbolsPerSecond: reservation.SymbolsPerSec, + SymbolsPerSecond: reservation.SymbolsPerSecond, StartTimestamp: uint32(reservation.StartTimestamp), EndTimestamp: uint32(reservation.EndTimestamp), QuorumNumbers: quorumNumbers, - QuorumSplit: quorumSplit, + QuorumSplits: quorumSplits, }, CumulativePayment: largestCumulativePayment.Bytes(), OnchainCumulativePayment: onDemandPayment.CumulativePayment.Bytes(), diff --git a/disperser/apiserver/server_v2_test.go b/disperser/apiserver/server_v2_test.go index 17f84f510..d5f826287 100644 --- a/disperser/apiserver/server_v2_test.go +++ b/disperser/apiserver/server_v2_test.go @@ -441,8 +441,8 @@ func newTestServerV2(t *testing.T) *testComponents { mockState.On("GetMinNumSymbols", tmock.Anything).Return(uint32(3), nil) now := uint64(time.Now().Unix()) - mockState.On("GetActiveReservationByAccount", tmock.Anything, tmock.Anything).Return(core.ActiveReservation{SymbolsPerSec: 100, StartTimestamp: now + 1200, EndTimestamp: now + 1800, QuorumSplit: []byte{50, 50}, QuorumNumbers: []uint8{0, 1}}, nil) - mockState.On("GetOnDemandPaymentByAccount", tmock.Anything, tmock.Anything).Return(core.OnDemandPayment{CumulativePayment: big.NewInt(3864)}, nil) + mockState.On("GetActiveReservationByAccount", tmock.Anything, tmock.Anything).Return(&core.ActiveReservation{SymbolsPerSecond: 100, StartTimestamp: now + 1200, EndTimestamp: now + 1800, QuorumSplits: []byte{50, 50}, QuorumNumbers: []uint8{0, 1}}, nil) + mockState.On("GetOnDemandPaymentByAccount", tmock.Anything, tmock.Anything).Return(&core.OnDemandPayment{CumulativePayment: big.NewInt(3864)}, nil) mockState.On("GetOnDemandQuorumNumbers", tmock.Anything).Return([]uint8{0, 1}, nil) if err := mockState.RefreshOnchainPaymentState(context.Background(), nil); err != nil { diff --git a/disperser/cmd/apiserver/main.go b/disperser/cmd/apiserver/main.go index bebdc1812..9a5752b6a 100644 --- a/disperser/cmd/apiserver/main.go +++ b/disperser/cmd/apiserver/main.go @@ -124,7 +124,7 @@ func RunDisperserServer(ctx *cli.Context) error { // add some default sensible configs meterer = mt.NewMeterer( mtConfig, - &paymentChainState, + paymentChainState, offchainStore, logger, // metrics.NewNoopMetrics(), diff --git a/test/integration_test.go b/test/integration_test.go index b3efdc25f..5016f3598 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -216,20 +216,20 @@ func mustMakeDisperser(t *testing.T, cst core.IndexedChainState, store disperser if err != nil { panic("failed to convert hex to ECDSA") } - publicKey := crypto.PubkeyToAddress(privateKey.PublicKey).Hex() + publicKey := crypto.PubkeyToAddress(privateKey.PublicKey) mockState := &coremock.MockOnchainPaymentState{} reservationLimit := uint64(1024) paymentLimit := big.NewInt(512) - mockState.On("GetActiveReservationByAccount", mock.Anything, mock.MatchedBy(func(account string) bool { + mockState.On("GetActiveReservationByAccount", mock.Anything, mock.MatchedBy(func(account gethcommon.Address) bool { return account == publicKey - })).Return(core.ActiveReservation{SymbolsPerSec: reservationLimit, StartTimestamp: 0, EndTimestamp: math.MaxUint32, QuorumSplit: []byte{50, 50}, QuorumNumbers: []uint8{0, 1}}, nil) - mockState.On("GetActiveReservationByAccount", mock.Anything, mock.Anything).Return(core.ActiveReservation{}, errors.New("reservation not found")) + })).Return(&core.ActiveReservation{SymbolsPerSecond: reservationLimit, StartTimestamp: 0, EndTimestamp: math.MaxUint32, QuorumSplits: []byte{50, 50}, QuorumNumbers: []uint8{0, 1}}, nil) + mockState.On("GetActiveReservationByAccount", mock.Anything, mock.Anything).Return(&core.ActiveReservation{}, errors.New("reservation not found")) - mockState.On("GetOnDemandPaymentByAccount", mock.Anything, mock.MatchedBy(func(account string) bool { + mockState.On("GetOnDemandPaymentByAccount", mock.Anything, mock.MatchedBy(func(account gethcommon.Address) bool { return account == publicKey - })).Return(core.OnDemandPayment{CumulativePayment: paymentLimit}, nil) - mockState.On("GetOnDemandPaymentByAccount", mock.Anything, mock.Anything).Return(core.OnDemandPayment{}, errors.New("payment not found")) + })).Return(&core.OnDemandPayment{CumulativePayment: paymentLimit}, nil) + mockState.On("GetOnDemandPaymentByAccount", mock.Anything, mock.Anything).Return(&core.OnDemandPayment{}, errors.New("payment not found")) mockState.On("GetOnDemandQuorumNumbers", mock.Anything).Return([]uint8{0, 1}, nil) mockState.On("GetGlobalSymbolsPerSecond", mock.Anything).Return(uint64(1024), nil) mockState.On("GetPricePerSymbol", mock.Anything).Return(uint32(1), nil)