rust-payjoin icon indicating copy to clipboard operation
rust-payjoin copied to clipboard

Duplicate proposals catch in ns1r

Open benalleng opened this issue 8 months ago • 10 comments

When building a multiparty proposal we did not have a catch to make sure that the proposals were all unique and as such a multiparty could be built by just adding the same proposal over and over. This creates a new error IdenticalProposals that checks to make sure the contexts are not matching when adding to a multiparty.

Closes #640

benalleng avatar Apr 10 '25 17:04 benalleng

Pull Request Test Coverage Report for Build 14669174853

Details

  • 116 of 136 (85.29%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.1%) to 82.057%

Changes Missing Coverage Covered Lines Changed/Added Lines %
payjoin/src/receive/multiparty/error.rs 13 14 92.86%
payjoin/src/receive/multiparty/mod.rs 89 108 82.41%
<!-- Total: 116 136
Totals Coverage Status
Change from base Build 14668777896: 0.1%
Covered Lines: 5433
Relevant Lines: 6621

💛 - Coveralls

coveralls avatar Apr 10 '25 20:04 coveralls

CI failures seems related to https://github.com/payjoin/rust-payjoin/pull/658 which just got merged. So this branch just needs a rebase

arminsabouri avatar Apr 17 '25 16:04 arminsabouri

Whoops, good catch.

As for the failing CI should we not display the session context in the error?

benalleng avatar Apr 18 '25 13:04 benalleng

Whoops, good catch.

As for the failing CI should we not display the session context in the error?

Perhaps just a top level identifier would work fine. The short id should work fine

arminsabouri avatar Apr 18 '25 13:04 arminsabouri

I kept the SessionContext as what is displayed, I just no longer leak it as accessible in the pub error interface and instead just stringify it

benalleng avatar Apr 18 '25 17:04 benalleng

I kept the SessionContext as what is displayed, I just no longer leak it as accessible in the pub error interface and instead just stringify it

The SessionContext does include the hpke keypair. Can you confirm that secret key material is redacted when its stringified.

arminsabouri avatar Apr 20 '25 13:04 arminsabouri

yes the hpke keypair is redacted in the stringify method. But the symmetric pk is not... I think I am just not going to expose the session context after all, what do you think?

More than one identical participant: Two sender contexts are identical
 left: SessionContext { address: tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4, directory: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("exampl
e.com")), port: None, path: "/", query: None, fragment: None }, subdirectory: None, ohttp_keys: OhttpKeys(KeyConfig { key_id: 1, kem: K256Sha256, symmetric: [SymmetricSuite { kdf: HkdfSha256,
 aead: ChaCha20Poly1305 }], sk: Some(PrivateKey 83862a342f732d7d1a97548f501ce02021fbbfdaf5af46ccd8e729d5b006bc90), pk: PublicKey 04d14d8a71d2109c7510063572f321772abb167be99e719628a3fe3250f460
6a8a86569320931680ef34506ddb9987c260c8bd9df5baff62bf5c52b60f4d93cf8e }), expiry: SystemTime { tv_sec: 1745181272, tv_nsec: 721110968 }, s: HpkeKeyPair(SecpHpkeSecretKey([REDACTED]), SecpHpkeP
ublicKey(PublicKey(PublicKey(b3934c5d680367a6e0b9d9b800f2d21b463414d63feca22a7613a8297d4ff2bbcf85ed1ceddf54a2e26257cbf54e03e1f3f2fe64bb6c085f9242c542b8213588)))), e: None }
 right: SessionContext { address: tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4, directory: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("examp
le.com")), port: None, path: "/", query: None, fragment: None }, subdirectory: None, ohttp_keys: OhttpKeys(KeyConfig { key_id: 1, kem: K256Sha256, symmetric: [SymmetricSuite { kdf: HkdfSha256
, aead: ChaCha20Poly1305 }], sk: Some(PrivateKey 83862a342f732d7d1a97548f501ce02021fbbfdaf5af46ccd8e729d5b006bc90), pk: PublicKey 04d14d8a71d2109c7510063572f321772abb167be99e719628a3fe3250f46
06a8a86569320931680ef34506ddb9987c260c8bd9df5baff62bf5c52b60f4d93cf8e }), expiry: SystemTime { tv_sec: 1745181272, tv_nsec: 721110968 }, s: HpkeKeyPair(SecpHpkeSecretKey([REDACTED]), SecpHpke
PublicKey(PublicKey(PublicKey(b3934c5d680367a6e0b9d9b800f2d21b463414d63feca22a7613a8297d4ff2bbcf85ed1ceddf54a2e26257cbf54e03e1f3f2fe64bb6c085f9242c542b8213588)))), e: None }

benalleng avatar Apr 20 '25 20:04 benalleng

yes the hpke keypair is redacted in the stringify method. But the symmetric pk is not... I think I am just not going to expose the session context after all, what do you think?

More than one identical participant: Two sender contexts are identical
 left: SessionContext { address: tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4, directory: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("exampl
e.com")), port: None, path: "/", query: None, fragment: None }, subdirectory: None, ohttp_keys: OhttpKeys(KeyConfig { key_id: 1, kem: K256Sha256, symmetric: [SymmetricSuite { kdf: HkdfSha256,
 aead: ChaCha20Poly1305 }], sk: Some(PrivateKey 83862a342f732d7d1a97548f501ce02021fbbfdaf5af46ccd8e729d5b006bc90), pk: PublicKey 04d14d8a71d2109c7510063572f321772abb167be99e719628a3fe3250f460
6a8a86569320931680ef34506ddb9987c260c8bd9df5baff62bf5c52b60f4d93cf8e }), expiry: SystemTime { tv_sec: 1745181272, tv_nsec: 721110968 }, s: HpkeKeyPair(SecpHpkeSecretKey([REDACTED]), SecpHpkeP
ublicKey(PublicKey(PublicKey(b3934c5d680367a6e0b9d9b800f2d21b463414d63feca22a7613a8297d4ff2bbcf85ed1ceddf54a2e26257cbf54e03e1f3f2fe64bb6c085f9242c542b8213588)))), e: None }
 right: SessionContext { address: tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4, directory: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("examp
le.com")), port: None, path: "/", query: None, fragment: None }, subdirectory: None, ohttp_keys: OhttpKeys(KeyConfig { key_id: 1, kem: K256Sha256, symmetric: [SymmetricSuite { kdf: HkdfSha256
, aead: ChaCha20Poly1305 }], sk: Some(PrivateKey 83862a342f732d7d1a97548f501ce02021fbbfdaf5af46ccd8e729d5b006bc90), pk: PublicKey 04d14d8a71d2109c7510063572f321772abb167be99e719628a3fe3250f46
06a8a86569320931680ef34506ddb9987c260c8bd9df5baff62bf5c52b60f4d93cf8e }), expiry: SystemTime { tv_sec: 1745181272, tv_nsec: 721110968 }, s: HpkeKeyPair(SecpHpkeSecretKey([REDACTED]), SecpHpke
PublicKey(PublicKey(PublicKey(b3934c5d680367a6e0b9d9b800f2d21b463414d63feca22a7613a8297d4ff2bbcf85ed1ceddf54a2e26257cbf54e03e1f3f2fe64bb6c085f9242c542b8213588)))), e: None }

I think short id is fine.

arminsabouri avatar Apr 22 '25 13:04 arminsabouri

Ended up adding a new id() method for UncheckedProposal similar to Receiver::id() so we don't have to worry about exposing anything we shouldn't.

benalleng avatar Apr 23 '25 16:04 benalleng

Lint is failing. Need https://github.com/payjoin/rust-payjoin/pull/667 to go in first

arminsabouri avatar Apr 24 '25 19:04 arminsabouri