Skip to content

Commit

Permalink
Merge pull request #4397 from BitGo/EA-3408
Browse files Browse the repository at this point in the history
fix(sdk-coin-avaxp): update mapping of addresses
  • Loading branch information
noel-bitgo authored Apr 5, 2024
2 parents b103cc1 + 56e6f6c commit e54d913
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 46 deletions.
57 changes: 28 additions & 29 deletions modules/sdk-coin-avaxp/src/lib/permissionlessValidatorTxBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ export class PermissionlessValidatorTxBuilder extends TransactionBuilder {
this.transaction._fromAddresses = output.outputOwners.addrs.map((a) => a.toBytes());
this.transaction._stakeAmount = permissionlessValidatorTx.stake[0].output.amount();
this.transaction._utxos = recoverUtxos(permissionlessValidatorTx.getInputs());
// TODO(CR-1073): remove log
console.log('utxos: ', this.transaction._utxos);
console.log('fromAddresses: ', this.transaction.fromAddresses);
return this;
}

Expand Down Expand Up @@ -335,6 +338,8 @@ export class PermissionlessValidatorTxBuilder extends TransactionBuilder {
const bitgoAddresses = this.transaction._fromAddresses.map((b) =>
avaxUtils.format(this.transaction._network.alias, this.transaction._network.hrp, b)
);
// TODO(CR-1073): remove log
console.log(`bitgoAddress: ${bitgoAddresses}`);

// if we are in OVC, none of the utxos will have addresses since they come from
// deserialized inputs (which don't have addresses), not the IMS
Expand All @@ -347,74 +352,70 @@ export class PermissionlessValidatorTxBuilder extends TransactionBuilder {
if (!utxo) {
throw new BuildTransactionError('Utxo is undefined');
}
// addressesIndex should neve have a mismatch
// addressesIndex should never have a mismatch
if (utxo.addressesIndex?.includes(-1)) {
throw new BuildTransactionError('Addresses are inconsistent');
}
if (utxo.threshold < this.transaction._threshold) {
throw new BuildTransactionError('Threshold is inconsistent');
}

const bitGoAddressMapOnChain = new Map();
const onChainAddressMapBitgo = new Map();

const bitgoIndexToOnChainIndex = new Map();
// in WP, output.addressesIndex is empty, so fill it
if (!utxo.addressesIndex || utxo.addressesIndex.length === 0) {
utxo.addressesIndex = bitgoAddresses.map((a) => utxo.addresses.indexOf(a));
}
// utxo.addresses is null when build from raw
// but utxo.addressesIndex has only 2 elements when build from raw
// so the bitgoIndexToOnChainIndex map will be empty
utxo.addresses.forEach((a) => {
bitGoAddressMapOnChain.set(bitgoAddresses.indexOf(a), a);
onChainAddressMapBitgo.set(a, utxo.addresses.indexOf(a));
bitgoIndexToOnChainIndex.set(bitgoAddresses.indexOf(a), utxo.addresses.indexOf(a));
});
// TODO(CR-1073): remove log
console.log(`utxo.addresses: ${utxo.addresses}`);
console.log(`bitgoIndexToOnChainIndex: ${Array.from(bitgoIndexToOnChainIndex)}`);
// in OVC, output.addressesIndex is defined correctly from the previous iteration

if (utxo.outputID === SECP256K1_Transfer_Output) {
const utxoAmount = BigInt(utxo.amount);
// either user (0) or recovery (2)
// On regular mode: [user, bitgo] (i.e. [0, 1])
// On recovery mode: [backup, bitgo] (i.e. [2, 1])
const firstIndex = this.recoverSigner ? 2 : 0;
const userOrBackupIndex = this.recoverSigner ? 2 : 0;
const bitgoIndex = 1;

currentTotal = currentTotal + utxoAmount;

const utxoId = avaxSerial.UTXOID.fromNative(utxo.txid, Number(utxo.outputidx));

let addressesIndex: number[] = [];
if (utxo.addressesIndex && onChainAddressMapBitgo.size === 0) {
if (utxo.addressesIndex && bitgoIndexToOnChainIndex.size === 0) {
addressesIndex = [...utxo.addressesIndex];
} else {
addressesIndex.push(onChainAddressMapBitgo.get(bitGoAddressMapOnChain.get(bitgoIndex)));
addressesIndex.push(onChainAddressMapBitgo.get(bitGoAddressMapOnChain.get(firstIndex)));
addressesIndex.push(bitgoIndexToOnChainIndex.get(userOrBackupIndex));
addressesIndex.push(bitgoIndexToOnChainIndex.get(bitgoIndex));
}

const transferInputs = new TransferInput(
new BigIntPr(utxoAmount),
new Input([...addressesIndex].sort().map((num) => new Int(num)))
);
// TODO(CR-1073): remove log
console.log(`using addressesIndex sorted: ${[...addressesIndex].sort()}`);

const input = new avaxSerial.TransferableInput(utxoId, assetId, transferInputs);
utxos.push(new Utxo(utxoId, assetId, transferInputs));

inputs.push(input);
if (buildOutputs) {
// For the bitgo signature we create an empty signature
// For the user/backup signature we store the address that matches the key
// if user/backup > bitgo
if (utxo.addressesIndex[bitgoIndex] < utxo.addressesIndex[firstIndex]) {
credentials.push(
new Credential([
utils.createNewSig(BufferAvax.from('').toString('hex')),
utils.createNewSig(BufferAvax.from(this.transaction._fromAddresses[firstIndex]).toString('hex')),
])
);
} else {
credentials.push(
new Credential([
utils.createNewSig(BufferAvax.from(this.transaction._fromAddresses[firstIndex]).toString('hex')),
utils.createNewSig(BufferAvax.from('').toString('hex')),
])
);
}
credentials.push(
new Credential([
utils.createNewSig(BufferAvax.from(this.transaction._fromAddresses[userOrBackupIndex]).toString('hex')),
utils.createNewSig(BufferAvax.from('').toString('hex')),
])
);
} else {
// TODO(CR-1073): verify this else case for OVC
credentials.push(
Expand Down Expand Up @@ -468,9 +469,7 @@ export class PermissionlessValidatorTxBuilder extends TransactionBuilder {
}
}
const finalCredentials = this.transaction.credentials ?? credentials;
inputs.sort((a, b) =>
avaxUtils.bufferToHex(a.utxoID.txID.toBytes()).localeCompare(avaxUtils.bufferToHex(b.utxoID.txID.toBytes()))
);
inputs.sort((a, b) => avaxUtils.bytesCompare(a.utxoID.txID.toBytes(), b.utxoID.txID.toBytes()));
return { inputs, stakeOutputs, changeOutputs, utxos, credentials: finalCredentials };
}

Expand Down
6 changes: 5 additions & 1 deletion modules/sdk-coin-avaxp/src/lib/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,11 @@ export class Transaction extends BaseTransaction {
find = true;
}
});
if (!find) throw new SigningError('Private key cannot sign the transaction');
if (!find) {
throw new SigningError(
`Private key cannot sign the transaction, address hex ${addressHex}, public key: ${publicKey}`
);
}
});
}
}
Expand Down
14 changes: 7 additions & 7 deletions modules/sdk-coin-avaxp/test/resources/avaxp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,9 +571,9 @@ export const BUILD_AND_SIGN_ADD_PERMISSIONLESS_SAMPLE = {
halfSignedRawTxNonRecovery:
'0x00000000000c000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000baeb9000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd086001867012000000024f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000024f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000020000000094a8b8179f0b6e7e7ce55b4d6ec5ad56dae1de9f0000000062bb03e60000000062e32556000000003b9aca00000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9aca000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd086001867012000186a000000002000000090000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007cd1d8802e15894ee973ebba974d3965b3cc42d4963470d0b7fc7460d14aa5d97f567e4fe9ec2d1f80c9802ef0e37cbe216b09c6613991fe299954fe03702c5000000000090000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007cd1d8802e15894ee973ebba974d3965b3cc42d4963470d0b7fc7460d14aa5d97f567e4fe9ec2d1f80c9802ef0e37cbe216b09c6613991fe299954fe03702c5000f8dfbe9f',
unsignedRawtxRecovery:
'0x000000000019000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000baeb9000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd086001867012000000024f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000014f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000010000000094a8b8179f0b6e7e7ce55b4d6ec5ad56dae1de9f0000000062bb03e60000000062e32556000000003b9aca0000000000000000000000000000000000000000000000000000000000000000000000001c8f95423f7142d00a48e1014a3de8d28907d420dc33b3052a6dee03a3f2941a393c2351e354704ca66a3fc29870282e1586a3ab4c45cfe31cae34c1d06f212434ac71b1be6cfe046c80c162e057614a94a5bc9f1ded1a7029deb0ba4ca7c9b71411e293438691be79c2dbf19d1ca7c3eadb9c756246fc5de5b7b89511c7d7302ae051d9e03d7991138299b5ed6a570a98000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9aca000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd08600186701200030d4000000002000000090000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008be54f016ab748127ab1a184626cba44c748a1ee000000090000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008be54f016ab748127ab1a184626cba44c748a1ee2145400a',
'0x000000000019000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000baeb9000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd086001867012000000024f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000014f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000010000000094a8b8179f0b6e7e7ce55b4d6ec5ad56dae1de9f0000000062bb03e60000000062e32556000000003b9aca0000000000000000000000000000000000000000000000000000000000000000000000001c8f95423f7142d00a48e1014a3de8d28907d420dc33b3052a6dee03a3f2941a393c2351e354704ca66a3fc29870282e1586a3ab4c45cfe31cae34c1d06f212434ac71b1be6cfe046c80c162e057614a94a5bc9f1ded1a7029deb0ba4ca7c9b71411e293438691be79c2dbf19d1ca7c3eadb9c756246fc5de5b7b89511c7d7302ae051d9e03d7991138299b5ed6a570a98000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9aca000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd08600186701200030d400000000200000009000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008be54f016ab748127ab1a184626cba44c748a1ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008be54f016ab748127ab1a184626cba44c748a1ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003bbb49e',
halfSignedRawTxRecovery:
'0x000000000019000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000baeb9000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd086001867012000000024f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000014f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000010000000094a8b8179f0b6e7e7ce55b4d6ec5ad56dae1de9f0000000062bb03e60000000062e32556000000003b9aca0000000000000000000000000000000000000000000000000000000000000000000000001c8f95423f7142d00a48e1014a3de8d28907d420dc33b3052a6dee03a3f2941a393c2351e354704ca66a3fc29870282e1586a3ab4c45cfe31cae34c1d06f212434ac71b1be6cfe046c80c162e057614a94a5bc9f1ded1a7029deb0ba4ca7c9b71411e293438691be79c2dbf19d1ca7c3eadb9c756246fc5de5b7b89511c7d7302ae051d9e03d7991138299b5ed6a570a98000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9aca000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd08600186701200030d4000000002000000090000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008cfd7500ceacfcbae29e3f5e103ad932121a1e7f30f0c499faab1b721dc687424274ae4676e12edc7f90b2ba2d4722acfb8e13468e99fff2e3e4566fc9490edb01000000090000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008cfd7500ceacfcbae29e3f5e103ad932121a1e7f30f0c499faab1b721dc687424274ae4676e12edc7f90b2ba2d4722acfb8e13468e99fff2e3e4566fc9490edb01e3b1dcd9',
'0x000000000019000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000baeb9000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd086001867012000000024f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000014f194d8e066b11dfe92f593cfa5c2fa1ae450927ecd5b093952e61834f4d8aa4000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000023a4c1800000000200000000000000010000000094a8b8179f0b6e7e7ce55b4d6ec5ad56dae1de9f0000000062bb03e60000000062e32556000000003b9aca0000000000000000000000000000000000000000000000000000000000000000000000001c8f95423f7142d00a48e1014a3de8d28907d420dc33b3052a6dee03a3f2941a393c2351e354704ca66a3fc29870282e1586a3ab4c45cfe31cae34c1d06f212434ac71b1be6cfe046c80c162e057614a94a5bc9f1ded1a7029deb0ba4ca7c9b71411e293438691be79c2dbf19d1ca7c3eadb9c756246fc5de5b7b89511c7d7302ae051d9e03d7991138299b5ed6a570a98000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9aca000000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd0860018670120000000b0000000000000000000000020000000342e19ad9a617fb95dcf8843ade66e06e578f549a8be54f016ab748127ab1a184626cba44c748a1eeac03c0ca71a1dde84702d272fbdd08600186701200030d400000000200000009000000028cfd7500ceacfcbae29e3f5e103ad932121a1e7f30f0c499faab1b721dc687424274ae4676e12edc7f90b2ba2d4722acfb8e13468e99fff2e3e4566fc9490edb01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000028cfd7500ceacfcbae29e3f5e103ad932121a1e7f30f0c499faab1b721dc687424274ae4676e12edc7f90b2ba2d4722acfb8e13468e99fff2e3e4566fc9490edb010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fba08673',
userPrivateKey:
'xprv9xhdWP2xkT2o3vMjkWv1oxPUHvVLvSuGJYLA72MpuM5dBykYsBdzRB8uxcYiiLWvP8Z6Vjiq2wc4HfGtgedgNPSv85mebXPKHp7ov9eRzRK',
backupPrivateKey:
Expand Down Expand Up @@ -622,8 +622,8 @@ export const BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE = {
utxos: [
{
outputID: 7,
amount: '997000000',
txid: 'mR6AAgjorrUKWC4bnZi7SqbwcCAZ1TnBhQycMS6q19oH1s6az',
amount: '97000000',
txid: 's92SjoZQemgG97HocX9GgyFy6ZKmapgcgqQ3y5J2uwP3qWBUy',
threshold: 2,
addresses: [
'P-fuji1wzr0hsm8zlr6gpaakxvt67f999nj044ete07uw', // backup
Expand All @@ -635,15 +635,15 @@ export const BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE = {
},
{
outputID: 7,
amount: '485000000',
txid: 'puzEooM63MVKzPNLsu1DhocypVHjAjKuqZeEiHgMpYoy5Mmgk',
amount: '1000000000',
txid: 'WyjYJHa7Ye1KMsBZiQ8hQJzY7YYxTJTTyMkxcVrKRDiNytTY8',
threshold: 2,
addresses: [
'P-fuji1wzr0hsm8zlr6gpaakxvt67f999nj044ete07uw', // backup
'P-fuji1w4jjs4qfugq0m3nu0d3htx6662dlq87zq5nz33', // user
'P-fuji1k3ca2njcunzl4hhxy24avca7htf66cmjjukl0n', // bitgo
],
outputidx: '0',
outputidx: '1',
locktime: '0',
},
],
Expand Down
Loading

0 comments on commit e54d913

Please sign in to comment.