Skip to content

Commit

Permalink
Fix "invalid signature" for paymentcode tx input (#333)
Browse files Browse the repository at this point in the history
* fix bug on paymentcode index derivation

* force _findLastUsedIndex to return -1 if no index is found

* fix bug in address calculation in paymentcode logic

* add testing script in examples folder

* change variable names within getChangeAddress function

* fix bug on getPrivateKeyForTxInput for paymentcodes

* modify testing script so Bob can afford Qi gas payment

---------

Co-authored-by: Riley Stephens <[email protected]>
  • Loading branch information
alejoacosta74 and rileystephens28 authored Oct 28, 2024
1 parent c6dc075 commit 3754361
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 21 deletions.
13 changes: 8 additions & 5 deletions examples/wallets/qi-wallet-alice-bob-send-receive.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ async function main() {
console.log('Bob Qi wallet scan complete');
printWalletInfo('Bob', bobQiWallet);

// Alice sends 50 Qi to Bob
console.log('\nAlice sends 50 Qi to Bob');
const tx = await aliceQiWallet.sendTransaction(bobPaymentCode, 50000n, quais.Zone.Cyprus1, quais.Zone.Cyprus1);
const aliceAmount = 5000000n;
// Alice sends 5000 Qi to Bob
console.log(`\nAlice sends ${quais.formatQi(aliceAmount)} Qi to Bob`);
const tx = await aliceQiWallet.sendTransaction(bobPaymentCode, aliceAmount, quais.Zone.Cyprus1, quais.Zone.Cyprus1);
// console.log('Transaction sent: ', tx);
console.log(`Transaction hash: ${tx.hash}`);
console.log(`Tx contains ${tx.txInputs?.length} inputs`);
Expand All @@ -56,8 +57,10 @@ async function main() {
console.log('Bob Qi wallet sync complete');
printWalletInfo('Bob', bobQiWallet);

console.log('\nBob sends back 25 Qi to Alice');
const tx2 = await bobQiWallet.sendTransaction(alicePaymentCode, 25000n, quais.Zone.Cyprus1, quais.Zone.Cyprus1);
const bobAmount = 5000n;
console.log(`\nBob sends back ${quais.formatQi(bobAmount)} Qi to Alice`);
const tx2 = await bobQiWallet.sendTransaction(alicePaymentCode, bobAmount, quais.Zone.Cyprus1, quais.Zone.Cyprus1);

console.log(`Transaction hash: ${tx2.hash}`);
console.log(`Tx contains ${tx2.txInputs?.length} inputs`);
console.log(`Tx inputs: ${JSON.stringify(tx2.txInputs)}`);
Expand Down
32 changes: 16 additions & 16 deletions src/wallet/qi-hdwallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,22 +504,22 @@ export class QiHDWallet extends AbstractHDWallet {
// 3. Generate as many unused addresses as required to populate the spend outputs
const sendAddresses = await getDestinationAddresses(selection.spendOutputs.length);

const getChangeAddresses = async (count: number): Promise<string[]> => {
const changeAddresses = this._addressesMap.get('BIP44:change') || [];
const addresses: QiAddressInfo[] = [];
const getChangeAddressesForOutputs = async (count: number): Promise<string[]> => {
const currentChangeAddresses = this._addressesMap.get('BIP44:change') || [];
const outpusChangeAddresses: QiAddressInfo[] = [];

for (let i = 0; i < changeAddresses.length; i++) {
if (changeAddresses[i].status === AddressStatus.UNUSED) {
addresses.push(changeAddresses[i]);
for (let i = 0; i < currentChangeAddresses.length; i++) {
if (currentChangeAddresses[i].status === AddressStatus.UNUSED) {
outpusChangeAddresses.push(currentChangeAddresses[i]);
}

if (addresses.length === count) break;
if (outpusChangeAddresses.length === count) break;
}

// Generate the remaining number of change addresses if needed
const remainingAddressesNeeded = count - addresses.length;
const remainingAddressesNeeded = count - outpusChangeAddresses.length;
if (remainingAddressesNeeded > 0) {
addresses.push(
outpusChangeAddresses.push(
...Array(remainingAddressesNeeded)
.fill(0)
.map(() => this.getNextChangeAddressSync(0, originZone)),
Expand All @@ -528,8 +528,8 @@ export class QiHDWallet extends AbstractHDWallet {

// Combine the existing change addresses with the newly generated addresses and ensure they are unique and sorted by index
const mergedChangeAddresses = [
...addresses.map((address) => ({ ...address, status: AddressStatus.ATTEMPTED_USE })),
...changeAddresses,
...outpusChangeAddresses.map((address) => ({ ...address, status: AddressStatus.ATTEMPTED_USE })),
...currentChangeAddresses,
];
const sortedAndFilteredChangeAddresses = mergedChangeAddresses
.filter((address, index, self) => self.findIndex((t) => t.address === address.address) === index)
Expand All @@ -538,11 +538,11 @@ export class QiHDWallet extends AbstractHDWallet {
// Update the _addressesMap with the modified change addresses and statuses
this._addressesMap.set('BIP44:change', sortedAndFilteredChangeAddresses);

return addresses.map((address) => address.address);
return outpusChangeAddresses.map((address) => address.address);
};

// 4. Get change addresses
const changeAddresses = await getChangeAddresses(selection.changeOutputs.length);
const changeAddresses = await getChangeAddressesForOutputs(selection.changeOutputs.length);

// 5. Create the transaction and sign it using the signTransaction method
let inputPubKeys = selection.inputs.map((input) => this.locateAddressInfo(input.address)?.pubKey);
Expand Down Expand Up @@ -574,8 +574,8 @@ export class QiHDWallet extends AbstractHDWallet {
// Determine if new addresses are needed for the change and spend outputs
const changeAddressesNeeded = selection.changeOutputs.length - changeAddresses.length;
if (changeAddressesNeeded > 0) {
const newChangeAddresses = await getChangeAddresses(changeAddressesNeeded);
changeAddresses.push(...newChangeAddresses);
const outpusChangeAddresses = await getChangeAddressesForOutputs(changeAddressesNeeded);
changeAddresses.push(...outpusChangeAddresses);
}

const spendAddressesNeeded = selection.spendOutputs.length - sendAddresses.length;
Expand Down Expand Up @@ -872,7 +872,7 @@ export class QiHDWallet extends AbstractHDWallet {
// (BIP47 addresses)
const pcAddressInfo = addressInfo;
const account = pcAddressInfo.account;
const index = pcAddressInfo.index - 1;
const index = pcAddressInfo.index;

const counterpartyPaymentCode = pcAddressInfo.derivationPath;
if (!counterpartyPaymentCode) {
Expand Down

0 comments on commit 3754361

Please sign in to comment.