Skip to content
Merged
7 changes: 5 additions & 2 deletions modules/utxo-lib/src/bitgo/wallet/WalletOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ export function addWalletOutputToPsbt(
rootWalletKeys: RootWalletKeys,
chain: ChainCode,
index: number,
value: bigint
value: bigint,
{ addDerivationInfo = true }: { addDerivationInfo?: boolean } = {}
): void {
const walletKeys = rootWalletKeys.deriveForChainAndIndex(chain, index);
const scriptType = scriptTypeForChain(chain);
Expand All @@ -207,7 +208,9 @@ export function addWalletOutputToPsbt(
const { scriptPubKey: script } = createOutputScript2of3(walletKeys.publicKeys, scriptType);
psbt.addOutput({ script, value });
}
updateWalletOutputForPsbt(psbt, rootWalletKeys, psbt.data.outputs.length - 1, chain, index);
if (addDerivationInfo) {
updateWalletOutputForPsbt(psbt, rootWalletKeys, psbt.data.outputs.length - 1, chain, index);
}
}

/**
Expand Down
6 changes: 5 additions & 1 deletion modules/utxo-lib/src/testutil/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export function getDefaultCosigner<T>(keyset: Triple<T>, signer: T): T {
throw new Error(`signer not in pubkeys`);
}

export function getWalletKeysForSeed(seed: string): RootWalletKeys {
return new RootWalletKeys(getKeyTriple(seed));
}

export function getDefaultWalletKeys(): RootWalletKeys {
return new RootWalletKeys(getKeyTriple('default'));
return getWalletKeysForSeed('default');
}
30 changes: 24 additions & 6 deletions modules/utxo-lib/src/testutil/psbt.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as bitcoinjslib from 'bitcoinjs-lib';
import { ok as assert } from 'assert';

import {
Expand Down Expand Up @@ -31,9 +32,10 @@ import { mockReplayProtectionUnspent, mockWalletUnspent } from './mock';
import { toOutputScript } from '../address';

/**
* input script type and value.
* use p2trMusig2 for p2trMusig2 script path.
* use taprootKeyPathSpend for p2trMusig2 key path.
* This is a bit of a misnomer, as it actually specifies the spend type of the input.
* This makes a difference for p2trMusig2 inputs, as they can be spent either by key path or script path.
* The value p2trMusig2 is used for p2trMusig2 script path.
* The value taprootKeyPathSpend is used for p2trMusig2 key path.
*/
export type InputScriptType = ScriptType | 'taprootKeyPathSpend';
export type OutputScriptType = ScriptType2Of3;
Expand All @@ -52,8 +54,12 @@ export type Input = {
// Make script: string as instead of scriptType or address
export type Output = {
value: bigint;
// Determines chain code for the output
isInternalAddress?: boolean;
} & ({ scriptType: OutputScriptType } | { address: string } | { script: string });
// Determines the wallet keys to use for the output. By default use root wallet keys used for the inputs.
// When set to null, omits the derivation info and effectively makes the output non-wallet output.
walletKeys?: RootWalletKeys | null;
} & ({ scriptType: OutputScriptType } | { address: string } | { script: string } | { opReturn: string });

/**
* array of supported input script types.
Expand Down Expand Up @@ -194,18 +200,30 @@ export function constructPsbt(
if ('scriptType' in output) {
addWalletOutputToPsbt(
psbt,
rootWalletKeys,
output.walletKeys ?? rootWalletKeys,
output.isInternalAddress ? getInternalChainCode(output.scriptType) : getExternalChainCode(output.scriptType),
i,
output.value
output.value,
{ addDerivationInfo: output.walletKeys !== null }
);
return;
} else if ('address' in output) {
const { address, value } = output;
psbt.addOutput({ script: toOutputScript(address, network), value });
return;
} else if ('opReturn' in output) {
const { opReturn, value } = output;
const script = bitcoinjslib.payments.embed({ data: [Buffer.from(opReturn, 'ascii')] }).output;
assert(script, 'script is required');
psbt.addOutput({ script, value });
return;
} else if ('script' in output) {
const { script, value } = output;
psbt.addOutput({ script: Buffer.from(script, 'hex'), value });
return;
}

throw new Error('invalid output');
});

if (sign === 'unsigned') {
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
{
"walletKeys": [
"xprv9s21ZrQH143K45bDYc9c3aEaGiTK9aPtjgtHg6wBdkryBjix1KKXRCszxPcFPejLT9tdLgNe8E8AuQXK2fy8KhNPeLAZsGoX8w9KS2PkacL",
"xprv9s21ZrQH143K2eBLSVNk4zhjDzqzqM29aS9cjr4CcoNrKLYwLHtwgTURSk7RPV3cH9zNZQeR1zGw3MEwSjvARSfWEGpxfaBmduhW3TKsH5g",
"xprv9s21ZrQH143K39N9shF9hAsTwh1FvQuBk8UVsZVwr4XtpqF7stCu2LH358NLuqkkK6pu1Af7TJHr5FZERQoLLtnC7wkoM9sdFo1HuP7dWuv"
],
"psbtBase64": "cHNidP8BANYCAAAAAtXfdTBXaO3hAaMVPLavKMxhzcqBZRvfo2qnxEBDSeXtAAAAAAD/////AWwmXH9/BmqsmzByVuaOTbCQFWkakkLlHO5gfQAfp/MBAAAAAP////8EhAMAAAAAAAAXqRTZCUdEBMEko9BMP7/2H6pJz0PFi4eEAwAAAAAAABepFE79dh6b5hyqQhyKrEqQKtbypUvPh4QDAAAAAAAAF6kU0k04Fr6KJQy93n6qZ0+AFwzalE6HhAMAAAAAAAARag9zZXRlYyBhc3Ryb25vbXkAAAAATwEEiLIeAAAAAAAAAAAAOpIuKfDI6w2ypgSEy9y2MfaxB8nKrj/9zz59LsH2vNADEhSHFfNh2raFpmnUJDHl1tP5c0BNq5yf0blQsnmtdjQEzBiuCE8BBIiyHgAAAAAAAAAAAG0dZW093ZHBlMBFZaNgNwKiEBbO0UomXziYLWJ15ntkA9O6wjE6fGshy7EbFLDRA0H5IsCkA6i9jIfw3IIPNa9uBPZc2GlPAQSIsh4AAAAAAAAAAADLBP1jqzTZD+ZGa4gOKgLM+KhjN0MSmRr4kRsaqrRDNAM27yKP/puO//ugUsMtM0Zg3R+DZs+P5Erlqmcra2KQlQTy7wOJAAEBINAHAAAAAAAAF6kUVnzXtE+fOgfDE483v5hLYPu68kOHIgID4VJNf2/FerPqy7ZZt4cQZ4CkddHbSDlSwjELfpo4l1tHMEQCIHx8FMHuRp436O94yr4Jy5FCN1fCdXn6QPS6uER7NnPOAiA/b3nRLhMOejAXm1WMySFo+hMXiW1P7VdAnKE66lUr7kEiAgP29AdkvV1j8gCid4iDrPdelvFQlcmYJjwIcnDQyX5+f0cwRAIgRnE/5xcnJ3snIaHplFxYTgb6Nk4tEl+VW47krOGgN14CICBeVli3kPKrCNz3zz9ncwr9mN0Kgs4wYS1JEQQwkX4kQQEDBEEAAAABBGlSIQP29AdkvV1j8gCid4iDrPdelvFQlcmYJjwIcnDQyX5+fyEDX/t6vHAVngRp9LmJptXheFopBBaf8FCy9Gj+XT1du/IhA+FSTX9vxXqz6su2WbeHEGeApHXR20g5UsIxC36aOJdbU64iBgNf+3q8cBWeBGn0uYmm1eF4WikEFp/wULL0aP5dPV278hTMGK4IAAAAAAAAAAABAAAAAAAAACIGA+FSTX9vxXqz6su2WbeHEGeApHXR20g5UsIxC36aOJdbFPZc2GkAAAAAAAAAAAEAAAAAAAAAIgYD9vQHZL1dY/IAoneIg6z3XpbxUJXJmCY8CHJw0Ml+fn8U8u8DiQAAAAAAAAAAAQAAAAAAAAAAAQEg0AcAAAAAAAAXqRQgs3CU2CpRNFH/DM2dsjq6Bbxe84ciAgM27yKP/puO//ugUsMtM0Zg3R+DZs+P5Erlqmcra2KQlUcwRAIgHhJfj5FRT4qdeiAUK1YD6Ze6wfOK602Sr0vAcMbtEU4CICCvQsG9s0n8SOciyg1ew28eLeuv5yJCjvXraTqowIcXQQEDBEEAAAABBCMhAzbvIo/+m47/+6BSwy0zRmDdH4Nmz4/kSuWqZytrYpCVrAABAGlSIQLMTQ+kEcrCREhvjrLAjgNf90EPRgo1nKf4gQmRvTtCCSEC1y/Q0NkCk0NK1fyhYPJ44DxhRJeqTkJc9FTiwTMPlqshA0TYhBNt9VAgKGX/vGIYx/nIj+bOOclFeYGQuts4p1LxU64iAgLMTQ+kEcrCREhvjrLAjgNf90EPRgo1nKf4gQmRvTtCCRTy7wOJAAAAAAAAAAAAAAAAAAAAACICAtcv0NDZApNDStX8oWDyeOA8YUSXqk5CXPRU4sEzD5arFMwYrggAAAAAAAAAAAAAAAAAAAAAIgIDRNiEE231UCAoZf+8YhjH+ciP5s45yUV5gZC62zinUvEU9lzYaQAAAAAAAAAAAAAAAAAAAAAAAQBpUiEDa3kQtZHTp1bV7nWl6MwOJ+dF6FUw/qvSfU9YR6UPMIYhAq/hLVd9GiCj7a/C/T0lWs59G4sYPQr53T++W/VUOrx9IQNKJrA23w9fA99EdNB5JKmKBeEbolhEduGt20SCrOpAEVOuIgICr+EtV30aIKPtr8L9PSVazn0bixg9CvndP75b9VQ6vH0U1K2DcgAAAAAAAAAAAAAAAAEAAAAiAgNKJrA23w9fA99EdNB5JKmKBeEbolhEduGt20SCrOpAERRAXGW9AAAAAAAAAAAAAAAAAQAAACICA2t5ELWR06dW1e51pejMDifnRehVMP6r0n1PWEelDzCGFFR/RXYAAAAAAAAAAAAAAAABAAAAAAAA",
"psbtBase64Finalized": "cHNidP8BANYCAAAAAtXfdTBXaO3hAaMVPLavKMxhzcqBZRvfo2qnxEBDSeXtAAAAAAD/////AWwmXH9/BmqsmzByVuaOTbCQFWkakkLlHO5gfQAfp/MBAAAAAP////8EhAMAAAAAAAAXqRTZCUdEBMEko9BMP7/2H6pJz0PFi4eEAwAAAAAAABepFE79dh6b5hyqQhyKrEqQKtbypUvPh4QDAAAAAAAAF6kU0k04Fr6KJQy93n6qZ0+AFwzalE6HhAMAAAAAAAARag9zZXRlYyBhc3Ryb25vbXkAAAAATwEEiLIeAAAAAAAAAAAAOpIuKfDI6w2ypgSEy9y2MfaxB8nKrj/9zz59LsH2vNADEhSHFfNh2raFpmnUJDHl1tP5c0BNq5yf0blQsnmtdjQEzBiuCE8BBIiyHgAAAAAAAAAAAG0dZW093ZHBlMBFZaNgNwKiEBbO0UomXziYLWJ15ntkA9O6wjE6fGshy7EbFLDRA0H5IsCkA6i9jIfw3IIPNa9uBPZc2GlPAQSIsh4AAAAAAAAAAADLBP1jqzTZD+ZGa4gOKgLM+KhjN0MSmRr4kRsaqrRDNAM27yKP/puO//ugUsMtM0Zg3R+DZs+P5Erlqmcra2KQlQTy7wOJAAEBINAHAAAAAAAAF6kUVnzXtE+fOgfDE483v5hLYPu68kOHAQf8AEcwRAIgRnE/5xcnJ3snIaHplFxYTgb6Nk4tEl+VW47krOGgN14CICBeVli3kPKrCNz3zz9ncwr9mN0Kgs4wYS1JEQQwkX4kQUcwRAIgfHwUwe5Gnjfo73jKvgnLkUI3V8J1efpA9Lq4RHs2c84CID9vedEuEw56MBebVYzJIWj6ExeJbU/tV0CcoTrqVSvuQUxpUiED9vQHZL1dY/IAoneIg6z3XpbxUJXJmCY8CHJw0Ml+fn8hA1/7erxwFZ4EafS5iabV4XhaKQQWn/BQsvRo/l09XbvyIQPhUk1/b8V6s+rLtlm3hxBngKR10dtIOVLCMQt+mjiXW1OuAAEBINAHAAAAAAAAF6kUILNwlNgqUTRR/wzNnbI6ugW8XvOHAQdsRzBEAiAeEl+PkVFPip16IBQrVgPpl7rB84rrTZKvS8Bwxu0RTgIgIK9Cwb2zSfxI5yLKDV7Dbx4t66/nIkKO9etpOqjAhxdBIyEDNu8ij/6bjv/7oFLDLTNGYN0fg2bPj+RK5apnK2tikJWsAAEAaVIhAsxND6QRysJESG+OssCOA1/3QQ9GCjWcp/iBCZG9O0IJIQLXL9DQ2QKTQ0rV/KFg8njgPGFEl6pOQlz0VOLBMw+WqyEDRNiEE231UCAoZf+8YhjH+ciP5s45yUV5gZC62zinUvFTriICAsxND6QRysJESG+OssCOA1/3QQ9GCjWcp/iBCZG9O0IJFPLvA4kAAAAAAAAAAAAAAAAAAAAAIgIC1y/Q0NkCk0NK1fyhYPJ44DxhRJeqTkJc9FTiwTMPlqsUzBiuCAAAAAAAAAAAAAAAAAAAAAAiAgNE2IQTbfVQIChl/7xiGMf5yI/mzjnJRXmBkLrbOKdS8RT2XNhpAAAAAAAAAAAAAAAAAAAAAAABAGlSIQNreRC1kdOnVtXudaXozA4n50XoVTD+q9J9T1hHpQ8whiECr+EtV30aIKPtr8L9PSVazn0bixg9CvndP75b9VQ6vH0hA0omsDbfD18D30R00HkkqYoF4RuiWER24a3bRIKs6kARU64iAgKv4S1XfRogo+2vwv09JVrOfRuLGD0K+d0/vlv1VDq8fRTUrYNyAAAAAAAAAAAAAAAAAQAAACICA0omsDbfD18D30R00HkkqYoF4RuiWER24a3bRIKs6kARFEBcZb0AAAAAAAAAAAAAAAABAAAAIgIDa3kQtZHTp1bV7nWl6MwOJ+dF6FUw/qvSfU9YR6UPMIYUVH9FdgAAAAAAAAAAAAAAAAEAAAAAAAA=",
"inputs": [
{
"hash": "d5df75305768ede101a3153cb6af28cc61cdca81651bdfa36aa7c4404349e5ed",
"index": 0,
"sequence": 4294967295
},
{
"hash": "016c265c7f7f066aac9b307256e68e4db09015691a9242e51cee607d001fa7f3",
"index": 1,
"sequence": 4294967295
}
],
"psbtInputs": [
{
"type": "p2sh",
"partialSig": [
{
"pubkey": "03e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b",
"signature": "304402207c7c14c1ee469e37e8ef78cabe09cb91423757c27579fa40f4bab8447b3673ce02203f6f79d12e130e7a30179b558cc92168fa1317896d4fed57409ca13aea552bee41"
},
{
"pubkey": "03f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f",
"signature": "3044022046713fe71727277b2721a1e9945c584e06fa364e2d125f955b8ee4ace1a0375e0220205e5658b790f2ab08dcf7cf3f67730afd98dd0a82ce30612d49110430917e2441"
}
],
"sighashType": 65,
"redeemScript": "522103f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f21035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf22103e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b53ae",
"bip32Derivation": [
{
"masterFingerprint": "cc18ae08",
"pubkey": "035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf2",
"path": "0/0/1/0"
},
{
"masterFingerprint": "f65cd869",
"pubkey": "03e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b",
"path": "0/0/1/0"
},
{
"masterFingerprint": "f2ef0389",
"pubkey": "03f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f",
"path": "0/0/1/0"
}
],
"witnessUtxo": {
"value": "2000",
"script": "a914567cd7b44f9f3a07c3138f37bf984b60fbbaf24387"
}
},
{
"type": "p2shP2pk",
"partialSig": [
{
"pubkey": "0336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095",
"signature": "304402201e125f8f91514f8a9d7a20142b5603e997bac1f38aeb4d92af4bc070c6ed114e022020af42c1bdb349fc48e722ca0d5ec36f1e2debafe722428ef5eb693aa8c0871741"
}
],
"sighashType": 65,
"redeemScript": "210336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095ac",
"witnessUtxo": {
"value": "2000",
"script": "a91420b37094d82a513451ff0ccd9db23aba05bc5ef387"
}
}
],
"psbtInputsFinalized": [
{
"type": "p2sh",
"witnessUtxo": {
"script": "a914567cd7b44f9f3a07c3138f37bf984b60fbbaf24387",
"value": "2000"
},
"finalScriptSig": "00473044022046713fe71727277b2721a1e9945c584e06fa364e2d125f955b8ee4ace1a0375e0220205e5658b790f2ab08dcf7cf3f67730afd98dd0a82ce30612d49110430917e244147304402207c7c14c1ee469e37e8ef78cabe09cb91423757c27579fa40f4bab8447b3673ce02203f6f79d12e130e7a30179b558cc92168fa1317896d4fed57409ca13aea552bee414c69522103f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f21035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf22103e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b53ae"
},
{
"type": "p2shP2pk",
"witnessUtxo": {
"script": "a91420b37094d82a513451ff0ccd9db23aba05bc5ef387",
"value": "2000"
},
"finalScriptSig": "47304402201e125f8f91514f8a9d7a20142b5603e997bac1f38aeb4d92af4bc070c6ed114e022020af42c1bdb349fc48e722ca0d5ec36f1e2debafe722428ef5eb693aa8c087174123210336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095ac"
}
],
"outputs": [
{
"script": "a914d909474404c124a3d04c3fbff61faa49cf43c58b87",
"value": "900",
"address": "3MUbfqvBeD7g1R3b9g8ZQxDwjR7SjQWciv"
},
{
"script": "a9144efd761e9be61caa421c8aac4a902ad6f2a54bcf87",
"value": "900",
"address": "38tgGK9PBA4aV6wWA7yf3D9xjAdNNKpu3D"
},
{
"script": "a914d24d3816be8a250cbdde7eaa674f80170cda944e87",
"value": "900",
"address": "3LrzL73h2RSmuGnSF5YsvuVZ4J8nr5sUwu"
},
{
"script": "6a0f736574656320617374726f6e6f6d79",
"value": "900"
}
],
"psbtOutputs": [
{
"redeemScript": "522102cc4d0fa411cac244486f8eb2c08e035ff7410f460a359ca7f8810991bd3b42092102d72fd0d0d90293434ad5fca160f278e03c614497aa4e425cf454e2c1330f96ab210344d884136df550202865ffbc6218c7f9c88fe6ce39c945798190badb38a752f153ae",
"bip32Derivation": [
{
"masterFingerprint": "f2ef0389",
"pubkey": "02cc4d0fa411cac244486f8eb2c08e035ff7410f460a359ca7f8810991bd3b4209",
"path": "0/0/0/0"
},
{
"masterFingerprint": "cc18ae08",
"pubkey": "02d72fd0d0d90293434ad5fca160f278e03c614497aa4e425cf454e2c1330f96ab",
"path": "0/0/0/0"
},
{
"masterFingerprint": "f65cd869",
"pubkey": "0344d884136df550202865ffbc6218c7f9c88fe6ce39c945798190badb38a752f1",
"path": "0/0/0/0"
}
]
},
{
"redeemScript": "5221036b7910b591d3a756d5ee75a5e8cc0e27e745e85530feabd27d4f5847a50f30862102afe12d577d1a20a3edafc2fd3d255ace7d1b8b183d0af9dd3fbe5bf5543abc7d21034a26b036df0f5f03df4474d07924a98a05e11ba2584476e1addb4482acea401153ae",
"bip32Derivation": [
{
"masterFingerprint": "d4ad8372",
"pubkey": "02afe12d577d1a20a3edafc2fd3d255ace7d1b8b183d0af9dd3fbe5bf5543abc7d",
"path": "0/0/0/1"
},
{
"masterFingerprint": "405c65bd",
"pubkey": "034a26b036df0f5f03df4474d07924a98a05e11ba2584476e1addb4482acea4011",
"path": "0/0/0/1"
},
{
"masterFingerprint": "547f4576",
"pubkey": "036b7910b591d3a756d5ee75a5e8cc0e27e745e85530feabd27d4f5847a50f3086",
"path": "0/0/0/1"
}
]
},
{},
{}
],
"extractedTransaction": "0200000002d5df75305768ede101a3153cb6af28cc61cdca81651bdfa36aa7c4404349e5ed00000000fc00473044022046713fe71727277b2721a1e9945c584e06fa364e2d125f955b8ee4ace1a0375e0220205e5658b790f2ab08dcf7cf3f67730afd98dd0a82ce30612d49110430917e244147304402207c7c14c1ee469e37e8ef78cabe09cb91423757c27579fa40f4bab8447b3673ce02203f6f79d12e130e7a30179b558cc92168fa1317896d4fed57409ca13aea552bee414c69522103f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f21035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf22103e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b53aeffffffff016c265c7f7f066aac9b307256e68e4db09015691a9242e51cee607d001fa7f3010000006c47304402201e125f8f91514f8a9d7a20142b5603e997bac1f38aeb4d92af4bc070c6ed114e022020af42c1bdb349fc48e722ca0d5ec36f1e2debafe722428ef5eb693aa8c087174123210336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095acffffffff04840300000000000017a914d909474404c124a3d04c3fbff61faa49cf43c58b87840300000000000017a9144efd761e9be61caa421c8aac4a902ad6f2a54bcf87840300000000000017a914d24d3816be8a250cbdde7eaa674f80170cda944e878403000000000000116a0f736574656320617374726f6e6f6d7900000000"
}
Loading