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

fix(balance) #493

Open
wants to merge 2 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
69 changes: 40 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions src/middlewares/balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ class Balance {
return this.balance
}

getMinimum () {
return this.minimum
}

toJSON () {
return {
balance: this.balance.toString(),
Expand Down Expand Up @@ -174,23 +178,25 @@ export default class BalanceMiddleware implements Middleware {
return next(data)
}

// We do nothing here (i.e. unlike for incoming packets) and wait until the packet is fulfilled
// This means we always take the most conservative view of our balance with the upstream peer
let result
try {

balance.subtract(parsedPacket.amount)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we subtract on an outgoing packet and then add on a reject, it could put us above our maximum balance.

Imagine my max balance is 100, current balance is 80.

  1. I send out a packet for 30. Now my balance is 50 because outgoing packet was subtracted on prepare.
  2. I get an incoming packet for 40. Now my balance is 90 because incoming packets are added.
  3. Outgoing packet for 30 is rejected, meaning that it's added back to the balance. Now our balance is 120 which is greater than our maximum.

The only correct way I can think of is to track two balances, one that represents your minimum balance possible and one that represents your maximum balance possible. Outgoing packets are counted against min-possible but incoming packets are not added. Incoming packets are counted against max-possible but outgoing packets are not subtracted. min-possible can never exceed min balance and max-possible can never exceed max balance.


result = await next(data)
} catch (err) {
log.debug('outgoing packet not applied due to error. accountId=%s amount=%s newBalance=%s', accountId, parsedPacket.amount, balance.getValue())
this.stats.outgoingDataPacketValue.increment(account, { result : 'failed' }, +parsedPacket.amount)
balance.add(parsedPacket.amount)
throw err
}

if (result[0] === IlpPacket.Type.TYPE_ILP_REJECT) {
balance.add(parsedPacket.amount)
log.debug('outgoing packet not applied due to ilp reject. accountId=%s amount=%s newBalance=%s', accountId, parsedPacket.amount, balance.getValue())
this.stats.outgoingDataPacketValue.increment(account, { result : 'rejected' }, +parsedPacket.amount)
} else if (result[0] === IlpPacket.Type.TYPE_ILP_FULFILL) {
// Decrease balance on prepare
balance.subtract(parsedPacket.amount)
this.maybeSettle(accountId).catch(log.error)
log.trace('balance decreased due to outgoing ilp fulfill. accountId=%s amount=%s newBalance=%s', accountId, parsedPacket.amount, balance.getValue())
this.stats.balance.setValue(account, {}, balance.getValue().toNumber())
Expand Down
7 changes: 1 addition & 6 deletions test/middleware.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,13 +335,8 @@ describe('Middleware Manager', function () {
destination: 'mock.test3.bob',
data: Buffer.alloc(0)
})
const fulfillPacket = IlpPacket.serializeIlpFulfill({
fulfillment: Buffer.from('HS8e5Ew02XKAglyus2dh2Ohabuqmy3HDM8EXMLz22ok', 'base64'),
data: Buffer.alloc(0)
})

sinon.stub(this.mockPlugin3Wrapped, 'sendData')
.resolves(fulfillPacket)
sinon.stub(this.mockPlugin3Wrapped, 'sendData').throws()

await this.middlewareManager.setup()
const result = await this.mockPlugin1Wrapped._dataHandler(preparePacket)
Expand Down