-
Notifications
You must be signed in to change notification settings - Fork 175
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
[payments] meterer core logic #790
Conversation
f553c37
to
6ae70ef
Compare
6092848
to
2211a82
Compare
core/meterer/meterer.go
Outdated
if err := m.ValidateQuorum(blobHeader, reservation.QuorumNumbers); err != nil { | ||
return fmt.Errorf("invalid quorum for reservation: %w", err) | ||
} | ||
if !m.ValidateBinIndex(blobHeader, reservation) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of the idea of adding a ReceiptTime
field to the context when we receive the message and then using these field when we validate the bin index?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this idea is similar to having disperser set the bin index of a message. The main trade-off was client cannot easily predict the ReceiptTime
and the behavior of the message in the local accounting. I think this is a good idea with tolerance, something like MaxDelayReceiveTime
?
core/meterer/meterer.go
Outdated
return nil | ||
} | ||
|
||
func (m *Meterer) ValidateQuorum(blobHeader BlobHeader, allowedQuoroms []uint8) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment: ValidateQuorums
ensures that the quorums listed in the blobHeader
are present within allowedQuorums
core/meterer/meterer.go
Outdated
type Config struct { | ||
GlobalBytesPerSecond uint64 // 2^64 bytes ~= 18 exabytes per second; if we use uint32, that's ~4GB/s | ||
PricePerChargeable uint32 // 2^64 gwei ~= 18M Eth; uint32 => ~4ETH | ||
MinChargeableSize uint32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: In current implementation, this should be in units of Symbols
since DataLength
is also in symbols. As we've discussed, this parametrization is subject to change.
core/meterer/meterer_test.go
Outdated
assert.Error(t, err, "invalid bin index for reservation") | ||
|
||
// test bin usage | ||
accountID := crypto.PubkeyToAddress(privateKey2.PublicKey).Hex() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this bin index pass?
core/meterer/meterer_test.go
Outdated
header, err = meterer.ConstructPaymentMetadata(signer, binIndex, 0, 50, quorumNumbers, privateKey2) | ||
assert.NoError(t, err) | ||
err = mt.MeterRequest(ctx, *header) | ||
assert.Error(t, err, "cannot insert cumulative payment in out of order") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't completely understand how this is different from the previous check...
60d7524
to
0323624
Compare
31932db
to
f43e6cf
Compare
ec28469
to
50c7f63
Compare
ac0c882
to
fab84e3
Compare
1bd1029
to
d402849
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good! A few more comments
return nil | ||
} | ||
|
||
// ValidateQuorums ensures that the quorums listed in the blobHeader are present within allowedQuorums |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: A reservation that does not utilize all of the allowed quorums will be accepted. However, it will still charge against all of the allowed quorums. We should make sure this is the desired UX.
core/meterer/meterer_test.go
Outdated
assert.Equal(t, strconv.Itoa(int((i+1)*dataLength)), item["BinUsage"].(*types.AttributeValueMemberN).Value) | ||
|
||
} | ||
// frist over flow is allowed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: first
core/meterer/meterer_test.go
Outdated
assert.ErrorContains(t, err, "bin has already been filled") | ||
|
||
// overwhelming bin overflow for empty bins (assuming all previous requests happened within 1 reservation window) | ||
header, err = auth.ConstructPaymentMetadata(&signer, binIndex-1, 0, 1000, quoromNumbers, privateKey2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shoud we also have a passing test for binIndex-1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep! added it and ready for review
core/meterer/meterer_test.go
Outdated
GlobalBytesPerSecond: 1000, | ||
ReservationWindow: 60, | ||
ChainReadTimeout: 3 * time.Second, | ||
PricePerSymbol: 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be worth using some unique prime values here for different parameters (e.g. 2,3,5,7) to give better confidence that the calcualtions are being done correctly?
aae5395
to
4a50bf6
Compare
d402849
to
d86aab9
Compare
0d0dabf
to
9d5663a
Compare
ea5bc3b
to
a1e4589
Compare
core/data.go
Outdated
@@ -490,22 +490,24 @@ type PaymentMetadata struct { | |||
BinIndex uint32 | |||
// TODO: we are thinking the contract can use uint128 for cumulative payment, | |||
// but the definition on v2 uses uint64. Double check with team. | |||
CumulativePayment uint64 | |||
CumulativePayment big.Int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's common practice to use a pointer for big.Int, i.e. CumulativePayment *big.Int, as most methods consume the pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sg, updated
2f44b2f
to
b956ae0
Compare
b72877e
to
b085195
Compare
462f216
to
0aaa646
Compare
} | ||
pcs.ActiveReservations = activeReservations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should lock this method unless there is a strong reason not to, as i don't think it will cause any performance issues but there is a chance ActiveReservations
and OnDemandPayments
are accessed in parallel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just one comment around locking
cc53fab
to
05f9379
Compare
05f9379
to
3521295
Compare
pcs.OnDemandPayments = onDemandPayments | ||
pcs.OnDemandLocks.Unlock() | ||
|
||
return nil | ||
} | ||
|
||
func (pcs *OnchainPaymentState) GetActiveReservations(ctx context.Context, blockNumber uint) (map[string]core.ActiveReservation, error) { | ||
return pcs.ActiveReservations, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it needs to get RLock here
pcs.ReservationsLock.Lock() | ||
pcs.ActiveReservations[accountID] = res | ||
pcs.ReservationsLock.Unlock() | ||
return res, nil | ||
} | ||
|
||
func (pcs *OnchainPaymentState) GetOnDemandPayments(ctx context.Context, blockNumber uint) (map[string]core.OnDemandPayment, error) { | ||
return pcs.OnDemandPayments, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
Why are these changes needed?
Core logic of payments metering
Checks