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

faulty amountShape param in interface guard #9407

Open
turadg opened this issue May 23, 2024 · 5 comments · May be fixed by #9863
Open

faulty amountShape param in interface guard #9407

turadg opened this issue May 23, 2024 · 5 comments · May be fixed by #9863
Labels
bug Something isn't working

Comments

@turadg
Copy link
Member

turadg commented May 23, 2024

Describe the bug

Some ERTP methods have an optAmountShape param that ends up here

/**
* @param {Payment} payment awaited by callWhen
* @param {Pattern} optAmountShape
*/
burn(payment, optAmountShape = undefined) {
// IssuerI delays calling this method until `payment` is a Remotable
assertLivePayment(payment);
const paymentBalance = paymentLedger.get(payment);
assertAmountConsistent(paymentBalance, optAmountShape);

That confirms that the amount matches the shape.

Some interface guards use that shape object directly, but they are shape specifiers themselves so it has to be something like AmountShapeShape. (or simply M.pattern())

What happens now when using that is an error

To Reproduce

Steps to reproduce the behavior:

  1. Deposit to a VirtualPurse with an amountShape param
  2. Get this error:
In "retain" method of (VirtualPurseKit utils): arg 1?: value: "[match:recordOf]" - Must match one of ["[match:nat]","[match:setOf]","[match:arrayOf]","[match:bagOf]"]

Expected behavior

No error.

Additional context

#9402 has a fix in 0ce647f but it requires a change to vat-bank which is in production.

Some options:

  1. document the frailty and recommend not using it, but leave the production behavior
  2. upgrade vat-bank with the fix
  3. fix it in master but leave production alone
  4. update master to remove the option so that it's an error to try to use it (because it will fail in production anyway)
@turadg turadg added the bug Something isn't working label May 23, 2024
@Chris-Hibbert
Copy link
Contributor

I don't get some of the details.

  • Is anything wrong with non-virtual purses? Are they incompatible with virtual purses?
  • does "recommend not using it" apply to some parameters of non-virtual purse (or other objects)?
  • are you recommending any changes in /packages/ERTP/?
  • How hard would it be to upgrade vat-bank? I see that it's not a contract. Is it durable? It makes use of baggage. Has upgrade been tested?

@turadg turadg mentioned this issue May 24, 2024
@turadg
Copy link
Member Author

turadg commented May 24, 2024

Is anything wrong with non-virtual purses?

No, it uses M.pattern() for the optAmountShape param.

Are they incompatible with virtual purses?

They have different uses. If you are asking whether their interfaces differ, vpurses have more methods and guards.

does "recommend not using it" apply to some parameters of non-virtual purse (or other objects)?

I'm only talking about virtual purses. The idea is to add a JSDoc to the param explaining that it's broken and not to pass it in. The TypeScript could type the param as never to raise an error if it's tried.

are you recommending any changes in /packages/ERTP/?

The fix would go in virtual-purse.js which is in vats package. One idea is to use an AmountShapeShape which I propose would live in ERTP's typeGuards.js

/** For parameters that are themselves an AmountShape pattern. */
export const AmountShapeShape = harden({
  brand: M.pattern(),
  value: M.pattern(),
});

How hard would it be to upgrade vat-bank? I see that it's not a contract. Is it durable? It makes use of baggage. Has upgrade been tested?

Here is a test of upgrade:

test('upgrade vat-bank', async t => {

@dckc
Copy link
Member

dckc commented May 24, 2024

To Reproduce

Steps to reproduce the behavior:

  1. Deposit to a VirtualPurse with an amountShape param

not just any amountShape, right? an exact amount such as AmountMath.make(brand1, 123n) would not trigger the bug, would it? only something like harden({ brand1, M.gte(10n)}) that doesn't match AmountShape would trigger it, right?

@turadg
Copy link
Member Author

turadg commented May 24, 2024

Correct, if you give a concrete value with no matchers, it will work. That's not what the API describes though.

@erights
Copy link
Member

erights commented Aug 7, 2024

Originally #9410 was supposed to fix #9407 , by relaxing an incorrect rejection into a correct acceptance. But we are not yet ready to deploy such a fix on-chain, due to upgrade constraints, so fixing it in agoric-sdk master would be misleading. It might lead people to write other code that depends on this bug being fixed when tested against agoric-sdk master, only to have that code fail later on-chain when invoking the non-upgraded buggy code.

So we unfixed #9410 to restore the buggy behavior, but with a better error message, and refactored to make fixing it again easier. #9863 is that fix. #9863 will remain draft until we are confident we can upgrade the relevant on-chain vat (the vbank) in a timely manner. Nevertheless, though we'll keep #9863 in draft until then as a safety measure.

mergify bot pushed a commit that referenced this issue Aug 8, 2024
closes: XXX
refs: #9402 (comment) #9402 (comment)  #9407

## Description

#9407 explains that sometimes we used a `.optional(AmountShape)` guard to describe an `optAmountShape` argument.

#9402 (comment) #9402 (comment) discussed ways to fix this that were ultimately omitted from #9402 . This PR provides a form of the fix discussed in those comments. Three remaining controversies I'd like my reviewers to comment on:
- Whether the name of the exported pattern should be `AmountShapeShape` or `AmountPatternShape`. See my doc-comment on `AmountPatternShape` for my weak reasoning about why I chose this name.
- If we do go with `AmountPatternShape` for the stated reasons, should the corresponding parameter variables be changed from `optAmountShape` to `optAmountPattern`.
- Whatever the name of the exported pattern, should it be defined as 
   - `M.pattern()`
   - `harden({ brand: M.pattern(), value: M.pattern() })`
   - `harden({ brand: BrandShape, value: M.pattern() })`
   - something else

### Security Considerations

For almost all of the choices of resolving the above controversies, this PR remains a pure bug fix. All correct code that used to work will continue working the same way, and some correct code that used to incorrectly fail due to this bug will now start working correctly.

The exception would be if we both accepting the renaming of some existing occurrences of `M.pattern()` to `AmountPatternShape`/`AmountShapeShape`, and define this name as a pattern narrower than `M.pattern()`. In that case, existing (hypothetical) code that, for example, used `M.any()` in such an argument position would start failing.

### Scaling Considerations

None
### Documentation Considerations

None
### Testing Considerations

#9407 mentions how to reproduce the bug it reports. This PR should add that as a test, to verify that this PR fixes that bug.
### Upgrade Considerations

#9402 (comment) and #9402 (comment) explain the upgrade concern that was likely the cause for omitting this fix from #9042
kriskowal pushed a commit that referenced this issue Aug 27, 2024
closes: XXX
refs: #9402 (comment) #9402 (comment)  #9407

## Description

#9407 explains that sometimes we used a `.optional(AmountShape)` guard to describe an `optAmountShape` argument.

#9402 (comment) #9402 (comment) discussed ways to fix this that were ultimately omitted from #9402 . This PR provides a form of the fix discussed in those comments. Three remaining controversies I'd like my reviewers to comment on:
- Whether the name of the exported pattern should be `AmountShapeShape` or `AmountPatternShape`. See my doc-comment on `AmountPatternShape` for my weak reasoning about why I chose this name.
- If we do go with `AmountPatternShape` for the stated reasons, should the corresponding parameter variables be changed from `optAmountShape` to `optAmountPattern`.
- Whatever the name of the exported pattern, should it be defined as 
   - `M.pattern()`
   - `harden({ brand: M.pattern(), value: M.pattern() })`
   - `harden({ brand: BrandShape, value: M.pattern() })`
   - something else

### Security Considerations

For almost all of the choices of resolving the above controversies, this PR remains a pure bug fix. All correct code that used to work will continue working the same way, and some correct code that used to incorrectly fail due to this bug will now start working correctly.

The exception would be if we both accepting the renaming of some existing occurrences of `M.pattern()` to `AmountPatternShape`/`AmountShapeShape`, and define this name as a pattern narrower than `M.pattern()`. In that case, existing (hypothetical) code that, for example, used `M.any()` in such an argument position would start failing.

### Scaling Considerations

None
### Documentation Considerations

None
### Testing Considerations

#9407 mentions how to reproduce the bug it reports. This PR should add that as a test, to verify that this PR fixes that bug.
### Upgrade Considerations

#9402 (comment) and #9402 (comment) explain the upgrade concern that was likely the cause for omitting this fix from #9042
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants