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

Restructured blinding + custom messages + keep vectors #218

Open
wants to merge 41 commits into
base: development
Choose a base branch
from

Conversation

Egge21M
Copy link
Collaborator

@Egge21M Egge21M commented Nov 30, 2024

Description

This PR addresses a couple of things that were discussed in the past: Sorted outputs when swapping, as well as custom outputs. I always felt like the old BlindingData type was not ergonomic enough, so I restructured some of the blinding types and logic, moved them to their own Class and Interface. These changes are so closely related, that they became a single PR (that got a little out of hand, sorry...).

Changes

  • BlindingData is now called OutputData. It holds all the data required to construct an Output from a BlindedMessage and a Signature
  • OutputData (form. BlindingData) is no longer an Array, but now represents a single encapsulated future Proof
  • Wallet methods now accept a new option outputData that implements the OutputDataLike Interface. Using this consumers of the library can opt out of the automatic creation of outputs and supply their own logic.
  • createSwapPayload now sorts the requested outputs by amount. It returns an additional keepVector (Array) that can be used to determine which outputs are meant to be kept. It also returns a sortedIndices array that can be used to reorder the sorted outputs in their original order.
  • Removed some of the old blinding code. Was internal code, so no breaking changes.

PR Tasks

  • Open PR
  • run npm run test --> no failing unit tests
  • run npm run format

@Egge21M Egge21M changed the title [WIP] Restructured bliding [WIP] Restructured blinding + custom messages + keep vectors Nov 30, 2024
more refactoring

more refactoring
@Egge21M Egge21M changed the title [WIP] Restructured blinding + custom messages + keep vectors Restructured blinding + custom messages + keep vectors Dec 4, 2024
@Egge21M Egge21M marked this pull request as ready for review December 4, 2024 12:58
@Egge21M Egge21M marked this pull request as draft December 9, 2024 15:36
@Egge21M
Copy link
Collaborator Author

Egge21M commented Dec 9, 2024

Converted back to draft because I came up with the idea to add factories and this needs some refactoring

@Egge21M Egge21M marked this pull request as ready for review December 19, 2024 13:18
@Egge21M
Copy link
Collaborator Author

Egge21M commented Dec 19, 2024

Edited the original PR message to reflect new changes. Review required and much appreciated!

src/model/OutputData.ts Outdated Show resolved Hide resolved
Copy link
Collaborator

@gudnuf gudnuf left a comment

Choose a reason for hiding this comment

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

Looks great! Just some minor nits and questions.

I don't fully understand the keepFactory and when it used. Can you elaborate a bit more on the logic behind that? My assumption is that this is used as a way to default how the user wants to store their proofs, but I think my confusion is related to my comment here

test/integration.test.ts Outdated Show resolved Hide resolved
test/integration.test.ts Outdated Show resolved Hide resolved
test/integration.test.ts Outdated Show resolved Hide resolved
const { send } = await wallet.send(32, testProofs, {
outputAmounts: {
sendAmounts: testOutputAmounts,
keepAmounts: [16, 8, ...Array(8 - fees).fill(1)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

can you explain the logic behind this keepAmounts. Is this something the users of cashu-ts will have to do whenever there are fees and they want change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

When you use outputAmounts you are required to specify amounts that match the keyset and also satisfy the amount constraints exactly. So yes, if your mint takes fees and you want to specify exact output amounts, you need to consider fees.

expectProofsSecretToEqual(key2Sends, 'key2');
});
});
describe('Keep Vector and Reordering', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

it doesn't seem like you are testing the "Keep Vector" here, just that send is properly created when keepAmounts is provided

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It does test the vector, but it is hidden behind the scenes. Any outputs in swap-payload ssend to the mint are now ordered by amount, to increase privacy. By testing that the output of receive is in the same order as the keepAmounts specified, we proof that the reordering of proofs works as expected. The code that does this can be found in CashuWallet.ts#305 (reordering) CashuWallet.ts#872 (sorting)

src/CashuWallet.ts Show resolved Hide resolved
privkey?: string,
customOutputData?: {
keep?: Array<OutputDataLike> | OutputDataFactory;
send?: Array<OutputDataLike> | OutputDataFactory;
Copy link
Collaborator

Choose a reason for hiding this comment

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

should there be a type for Array<OutputDataLike> | OutputDataFactory;? Seems to be repeated a lot, but maybe its more clear to write it out each time

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I decided to keep a union here, because IDEs will then show the union instead of the alias type. I think this is beneficial, because these two types are very different things that change the way the function behaves.

secretBytes = new TextEncoder().encode(secretHex);
pubkey?: string,
outputAmounts?: Array<number>,
p2pk?: { pubkey: string; locktime?: number; refundKeys?: Array<string> },
Copy link
Collaborator

Choose a reason for hiding this comment

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

are you keeping pubkey for backwards compatibility? Can we remove it to replace with p2pk?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes exactly. pubkey should be removed with a future major update.

src/CashuWallet.ts Outdated Show resolved Hide resolved
if (outputData) {
newOutputData = { send: outputData };
} else if (this._keepFactory) {
newOutputData = { send: this._keepFactory };
Copy link
Collaborator

Choose a reason for hiding this comment

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

why are you using the keepFactory for send?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch. Unfortunately there is a bug in the current version that requires this: #224

@Egge21M
Copy link
Collaborator Author

Egge21M commented Dec 30, 2024

Looks great! Just some minor nits and questions.

I don't fully understand the keepFactory and when it used. Can you elaborate a bit more on the logic behind that? My assumption is that this is used as a way to default how the user wants to store their proofs, but I think my confusion is related to my comment here

Thank you for taking the time to go through this!
The idea of the keepFactory is to provide a standard "fallback" factory to the CashuWallet instance that should be used whenever we create proofs that are supposed to be "kept" (e.g. mint, melt-change, send-change, receive, etc.).

Using this, you can create a factory that creates some sort of outputs (like deterministic ones) and make the library use is automatically. A simplistic example of a CashuWallet that creates auto-incrementing, deterministic secrets using a keepFactory can be seen here: https://njump.me/nevent1qqsvzxrfqyt5xk0s7f60mm9rlthkdtv70g3qsl8xykrgcvnfdrfpaecpzemhxue69uhhyetvv9ujumn0wd68ytnzv9hxgqg0waehxw309ahx7um5wghx6mmdqgsdmup6e2z6mcpeue6z6kl08he49hcen5xnrc3tnpvw0mdgtjemh0slwxw3x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants