Skip to content

Handle tss txp deletion; Add cli session restoration; Bug fixes & improvements - #4206

Open
kajoseph wants to merge 11 commits into
bitpay:masterfrom
kajoseph:bitcoreCli
Open

Handle tss txp deletion; Add cli session restoration; Bug fixes & improvements#4206
kajoseph wants to merge 11 commits into
bitpay:masterfrom
kajoseph:bitcoreCli

Conversation

@kajoseph

@kajoseph kajoseph commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Description

If walletA is in the process of signing a txp and walletB deletes the txp, then walletA will be spinning indefinitely. This PR deletes corresponding TSS signing sessions when deleting a txp. This will cause walletA's session to error with a "Session not found" error, leaving it up to the client to handle appropriately (as seen in CLI).

This PR adds support for TSS session restoration in case a session is interrupted.

This PR adds confirmation for password setting (would hate for someone to mistype their password only to find out later).

This PR makes the .toObj method make true copies of TssKey data. Without this, there was a race condition where exporting at the end of tss key creation may mean the unencrypted keyshare is saved to the wallet file. To that end, I also added a sanity check in the save method to ensure sensitive data does not get saved to disk.

This PR adds cleanup methods to the TSS keygen classes to zero out memory buffers that contain sensitive data.

This PR fixes a variety of CLI bugs.

Changelog

  • Deletes TSS signing sessions with txp removal.
  • Adds TSS signing session restoration.
    • TODO: would be prudent to add a cleanup function to CLI to remove any zombie state files
  • Adds confirmation prompts when setting passwords
  • Adds cleanup methods & makes true copies of data for TssKey's .toObj()
  • Adds prompt to encrypt wallet on load if not encrypted
  • BUG - Fixes tokens not being saved to persistent opts in EVM wallets
  • BUG - Fixes copayer0 of TSS wallets not getting other copayers. This would result in copayer0 being unable to verify txps created by other copayers.
  • BUG - Sorts txps by nonce/creation date

Testing Notes

Add any helpful notes for reviewers to test your code here.


Checklist

  • I have read CONTRIBUTING.md and verified that this PR follows the guidelines and requirements outlined in it.

@kajoseph kajoseph added BWC This pull request modifies the bitcore-wallet-client package bitcore-cli This pull request modifies the bitcore-cli package bitcore-tss This pull request modifies the bitcore-tss package labels Jul 28, 2026
@kajoseph kajoseph changed the title Handle tss txp deletion; Add cli session restoration; Bug fixes Handle tss txp deletion; Add cli session restoration; Bug fixes & imrovements Jul 28, 2026
@kajoseph kajoseph changed the title Handle tss txp deletion; Add cli session restoration; Bug fixes & imrovements Handle tss txp deletion; Add cli session restoration; Bug fixes & improvements Jul 28, 2026
Comment thread packages/bitcore-cli/src/filestorage.ts Outdated
Comment thread packages/bitcore-cli/src/prompts.ts Outdated
Comment thread packages/bitcore-cli/src/prompts.ts
Comment thread packages/bitcore-cli/src/tss.ts
Comment thread packages/bitcore-cli/src/wallet.ts
Comment thread packages/bitcore-cli/src/wallet.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR improves Threshold Signature Scheme (TSS) reliability and CLI UX/security by cleaning up server-side signing sessions when a tx proposal is deleted, adding CLI session restoration for interrupted TSS signing, and tightening wallet encryption/sensitive-data handling.

Changes:

  • Delete associated TSS signing sessions when removing a pending tx proposal; harden TSS auth public-key lookup.
  • Add CLI TSS session persistence/restoration and better cancellation handling; add password confirmation prompts across CLI flows.
  • Improve TSS key/keygen safety (true-copy serialization, buffer zeroing/cleanup), plus assorted CLI fixes and test additions.

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/bitcore-wallet-service/src/lib/storage.ts Adds storage helper to remove a TSS signing session document.
packages/bitcore-wallet-service/src/lib/server.ts Deletes TSS signing sessions when a tx proposal is removed.
packages/bitcore-wallet-service/src/lib/routes/middleware/authTssRequest.ts Prevents crashes when TSS sign session round/publicKey data is missing.
packages/bitcore-wallet-client/test/log.test.ts Adds expanded logger behavior tests (levels/format/filtering/trace).
packages/bitcore-wallet-client/test/index.test.ts Adds tests asserting expected public exports from the client index.
packages/bitcore-wallet-client/src/lib/tsssign.ts Adds restore-session password support; emits unsubscribe event on unsubscribe.
packages/bitcore-wallet-client/src/lib/tsskey.ts Ensures toObj() deep-copies buffers; zeroes keyshare buffers on encrypt; adds keygen cleanup hook.
packages/bitcore-wallet-client/src/lib/credentials.ts Tightens completeness check for TSS credentials (requires >1 participant).
packages/bitcore-wallet-client/src/lib/common/encryption.ts Adds explicit Buffer return types for decrypt methods.
packages/bitcore-tss/test/ecdsa.test.js Adds tests for keygen cleanup and minor formatting fixes.
packages/bitcore-tss/test/data/vectors.ecdsa.js Normalizes formatting/quoting in test vectors.
packages/bitcore-tss/ecdsa/keygen.js Returns copied keyshare buffers; adds cleanup API and post-cleanup guard.
packages/bitcore-cli/types/wallet.d.ts Renames password prompt method in wallet interface.
packages/bitcore-cli/test/wallets/btc-singlesig.json Updates fixture to store encrypted key material instead of plaintext.
packages/bitcore-cli/test/proposals.test.ts Updates CLI proposal flows for password prompts and prevents test exits.
packages/bitcore-cli/test/prompts.test.ts Adds coverage for password confirmation behavior.
packages/bitcore-cli/test/create.test.ts Updates create flows for password confirmation prompts.
packages/bitcore-cli/src/wallet.ts Adds “encrypt on load” prompt; prevents saving unencrypted sensitive data; adds state dir usage; renames password method.
packages/bitcore-cli/src/tss.ts Adds TSS session persistence/restoration to disk; handles session-not-found errors; improves cancel flow.
packages/bitcore-cli/src/prompts.ts Implements password confirmation and retry/back behavior.
packages/bitcore-cli/src/filestorage.ts Adds per-wallet .state/<walletName> directory helper for CLI state files.
packages/bitcore-cli/src/errors.ts Adds ProcessCancelled error type.
packages/bitcore-cli/src/commands/txproposals.ts Sorts txps by nonce/createdOn; normalizes gasLimit/nonce printing via BigInt.
packages/bitcore-cli/src/commands/join/joinThresholdSig.ts Adds password confirmation; cleans up TSS keygen memory buffers.
packages/bitcore-cli/src/commands/join/joinMultiSig.ts Adds password confirmation.
packages/bitcore-cli/src/commands/export.ts Adds password confirmation for export file encryption.
packages/bitcore-cli/src/commands/create/createThresholdSig.ts Adds password confirmation; uses spinner cancel hook; cleans up TSS keygen memory buffers.
packages/bitcore-cli/src/commands/create/createSingleSig.ts Adds password confirmation.
packages/bitcore-cli/src/commands/create/createMultiSig.ts Adds password confirmation.
packages/bitcore-cli/src/cli.ts Fixes token selection to update persistent opts correctly.
eslint.config.mjs Applies CommonJS linting mode to bitcore-tss package JS files.
Comments suppressed due to low confidence (3)

packages/bitcore-cli/src/tss.ts:51

  • Session restore currently assumes password is always provided and tries to decrypt unconditionally. If password is missing/empty, decryptWithPassword will throw and block signing (even though signing could proceed without persistence).
  // Restore a previously-interrupted TSS session if it exists
  if (fs.existsSync(storedSessionFile)) {
    const storedSession = Encryption.decryptWithPassword(fs.readFileSync(storedSessionFile, 'utf8'), password);
    await tssSign.restoreSession({ session: storedSession.toString(), password });
    storedSession.fill(0); // Clear sensitive data from memory

packages/bitcore-cli/src/tss.ts:61

  • After introducing sessionId for persistence, tssSign.start should use the same id; otherwise the state filename won’t correspond to the server session id (and restores won’t work reliably).
    try {
      await tssSign.start({
        id,
        messageHash,
        derivationPath,
        password
      });

packages/bitcore-cli/src/wallet.ts:596

  • getWalletPassword() only prompts when isWalletEncrypted() is true, but TSS signing/decryption requires a password whenever the TSS keychain is encrypted (even if the wallet’s xPriv/mnemonic are not). As-is, TSS signing can pass undefined into TssKey.get()/Encryption.decryptWithPassword() and fail.
  async getWalletPassword(): Promise<string> {
    let password;
    if (this.isWalletEncrypted()) {
      password = await getPassword('Wallet password:', {
        hidden: true,
        validate: (input) => {
          try {
            this.#walletData.key.get(input);
          } catch {
            return 'Invalid password. Please try again.';
          }
        }
      });
    }
    return password;
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3261 to +3266
try {
if (Array.isArray(txp.inputPaths)) {
const inputPaths = txp.inputPaths.length ? txp.inputPaths : ['m/0/0']; // doesn't actually matter what's in the array
await Promise.all(inputPaths.map((_, i) => this.storage.removeTssSigSession({ id: `${txp.id}:input${i}` })));
}
} catch (err) {
Comment on lines +29 to +39
const { host, chain, walletData, stateStoragePath, messageHash, derivationPath, password, id, logMessageWaiting, logMessageCompleted } = args;
const storedSessionFile = path.join(stateStoragePath, id);

const transformISignature = (signature: TssSign.ISignature): string => {
return Transactions.transformSignatureObject({ chain, obj: signature });
};

const storeSession = (session: string) => {
const encrypted = JSON.stringify(Encryption.encryptWithPassword(session, password));
fs.writeFileSync(storedSessionFile, encrypted, 'utf8');
};
Comment on lines 199 to +202
return {
privateKeyShare: keyShare,
reducedPrivateKeyShare: rKeyShare,
commonKeyChain: commonKeyChain
privateKeyShare: Buffer.copyBytesFrom(keyShare),
reducedPrivateKeyShare: Buffer.copyBytesFrom(rKeyShare),
commonKeyChain: commonKeyChain // string
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bitcore-cli This pull request modifies the bitcore-cli package bitcore-tss This pull request modifies the bitcore-tss package BWC This pull request modifies the bitcore-wallet-client package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants