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

web3.js: partialSign breaks deserialized transactions #20743

Closed
coffeemug opened this issue Oct 16, 2021 · 12 comments
Closed

web3.js: partialSign breaks deserialized transactions #20743

coffeemug opened this issue Oct 16, 2021 · 12 comments

Comments

@coffeemug
Copy link

Problem

Whenever partialSign is applied to a transaction that's been previously partially signed, serialized, and deserialized, it clears all existing signatures on the transaction:

const tx = new Transaction();
...
tx.partialSign(signer);

const deserializedTx = Transaction.from(tx.serialize({ requireAllSignatures: false }));
deserializedTx.partialSign(anotherSigner); // broken, clears `signer`

I tried various workarounds, for example taking signatures from tx and manually applying them to deserializedTx, but doing it that way causes validation of those signatures to fail. This means it's not possible to apply partialSign/addSignature to transactions that have been deserialized from the wire, which is a serious limitation.

Could someone recommend a workaround for this?

@MirekR
Copy link

MirekR commented Dec 15, 2021

We're having same issue, have you been able to get around it?

@MirekR
Copy link

MirekR commented Dec 16, 2021

For anyone who's interested in, we had some success with the below:

  const transactionHash = "YOUR_TRANSACTION_HASH";

  const rawTransaction = Buffer.from(transactionHash, 'base64');
  const newTrx = web3.Transaction.from(rawTransaction);

  console.log(`Transaction before partial sign ${JSON.stringify(newTrx)}`)

  // make sure we have immutable array
  const originalSignatures  = Object.assign([], newTrx.signatures) as web3.SignaturePubkeyPair[];
  const filteredSignatures = originalSignatures.filter(item => item.signature != null);

  console.log(`Original signatures are ${JSON.stringify(originalSignatures)}`);

  newTrx.partialSign(buyer);

  filteredSignatures.forEach(sign => {
      newTrx.addSignature(sign.publicKey, sign.signature as Buffer);
  });

  console.log("=============================================================");
  console.log(`After add ${JSON.stringify(newTrx.signatures)}`);
  
  const serialTx = newTrx.serialize(
    {
      requireAllSignatures: false,
      verifySignatures: false,
    }
  );
  
  console.log("=============================================================");
  console.log(`Full transaction ${JSON.stringify(web3.Transaction.from(serialTx))}`)

  const id = await web3.sendAndConfirmRawTransaction(connection, serialTx, {skipPreflight: true});
  

  console.log(`Complete transaction: ${id}`);

@bmeeder22
Copy link

We were having success with this code block as well and is no longer working ^

@bmeeder22
Copy link

This was working in @solana/web3.js version 1.31.0 and in all higher versions the workaround is broken. I believe this is due to this commit: solana-labs/solana-web3.js@410780a

@jordaaash
Copy link
Contributor

jordaaash commented Mar 30, 2022

This is caused by #21722. Closing as a duplicate (since there's more context on the more recent issue), but this should be fixed by #23720 soon.

@jordaaash
Copy link
Contributor

Actually, I'm going to reopen this until it's confirmed to be fixed by #23720 as well.

@jordaaash jordaaash reopened this Mar 31, 2022
@jordaaash
Copy link
Contributor

#23720 has been merged and published in @solana/[email protected]. Can you confirm if it fixes your issue?

@0xx400
Copy link

0xx400 commented Apr 18, 2022

This was working in @solana/web3.js version 1.31.0 and in all higher versions the workaround is broken. I believe this is due to this commit: solana-labs/solana-web3.js@410780a

Maybe just revert this commit? change order of account depending on it's base58 representation in transaction looks very odd.

e.g. it's very hard to sign offline transaction like here:
#21722 (comment)

As soon as serialize/deserialize problem was solved by #23720, we don't need to shuffle accounts by it's base58 names.

@rot0505
Copy link

rot0505 commented Jun 23, 2022

For anyone who's interested in, we had some success with the below:

  const transactionHash = "YOUR_TRANSACTION_HASH";

  const rawTransaction = Buffer.from(transactionHash, 'base64');
  const newTrx = web3.Transaction.from(rawTransaction);

  console.log(`Transaction before partial sign ${JSON.stringify(newTrx)}`)

  // make sure we have immutable array
  const originalSignatures  = Object.assign([], newTrx.signatures) as web3.SignaturePubkeyPair[];
  const filteredSignatures = originalSignatures.filter(item => item.signature != null);

  console.log(`Original signatures are ${JSON.stringify(originalSignatures)}`);

  newTrx.partialSign(buyer);

  filteredSignatures.forEach(sign => {
      newTrx.addSignature(sign.publicKey, sign.signature as Buffer);
  });

  console.log("=============================================================");
  console.log(`After add ${JSON.stringify(newTrx.signatures)}`);
  
  const serialTx = newTrx.serialize(
    {
      requireAllSignatures: false,
      verifySignatures: false,
    }
  );
  
  console.log("=============================================================");
  console.log(`Full transaction ${JSON.stringify(web3.Transaction.from(serialTx))}`)

  const id = await web3.sendAndConfirmRawTransaction(connection, serialTx, {skipPreflight: true});
  

  console.log(`Complete transaction: ${id}`);

Could you post the completed code here again?

@steveluscher
Copy link
Contributor

Closing this on the basis of #23720 having been merged; please reopen if there's more work to be done!

@shirecoding
Copy link

I have the opposite error. signTransactions removes the partialSigned. This is a problem because wallet adaptors can't partial sign, they can only sign, which removes any partial sign done in a backend server.

I had to do the opposite, sign using the wallet adapter, then serialize the transaction send it over to the backend, and then the backend partial signs using a private key and sends the transaction

I can't do it the other way around, eg. i always have to end with partial sign and not sign. Because sign removes partial sign, which means i want have the wallet adaptor which does not have partial sign be the last.

Am am i getting something wrong?

@CriesofCarrots
Copy link
Contributor

@shirecoding , please don't necropost. The web3.js code isn't in this repository anymore 😞
Also, developer questions should go to Solana Stack Exchange

@solana-labs solana-labs locked as resolved and limited conversation to collaborators Jan 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants