Exercise 2: Hard

In this exercise, you will be working with a Bitcoin P2MS (Pay-to-Multisig) ScriptPubKey.

Your task is to complete the decompileP2MSScriptPubKey function, which decompiles a hex-encoded ScriptPubKey and extracts the number of required signatures and the associated public keys.

Follow the hints provided if you get stuck, and test your code by entering a ScriptPubKey hex string in the input field below.

Once you've completed the function, you can compare your solution with the provided answer.

// Complete the function to decompile a P2MS ScriptPubKey
export function decompileP2MSScriptPubKey(scriptPubKeyHex) {
const scriptPubKey = Buffer.from(scriptPubKeyHex, 'hex');
const script = [];
let i = 0;

while (i < scriptPubKey.length) {
const byte = scriptPubKey[i];

    // TODO: If the byte represents an opcode, handle the data extraction
    if (byte >= 0x01 && byte <= 0x4b) {
      const dataLength = byte;
      const data = scriptPubKey.slice(i + 1, i + 1 + dataLength);
      script.push(data);
      i += 1 + dataLength;
    } else {
      script.push(byte);
      i += 1;
    }

}

// TODO: Validate if it's a P2MS script and extract the number of required signatures and public keys

const opCheckMultiSig = 0xae;
if (script[script.length - 1] !== opCheckMultiSig) {
throw new Error('Invalid P2MS ScriptPubKey');
}

const m = script[0] - 0x50; // Number of required signatures (subtract 0x50 from the opcode value)
const publicKeys = script.slice(1, -2).map((key) => key.toString('hex'));

return {
requiredSignatures: m,
publicKeys: publicKeys,
};
}

Click to reveal next hint (0/6)
  • Start by iterating over each byte in the `scriptPubKeyHex` string. You’ll need to determine whether the byte represents an opcode or data.
  • For opcodes between 0x01 and 0x4b, you should treat the byte as the length of the data that follows.
  • Extract the data by slicing the scriptPubKey buffer and increment the index `i` appropriately.
  • Check if the last byte in the script is the `OP_CHECKMULTISIG` opcode (0xae). If it's not, throw an error.
  • Subtract 0x50 from the first byte to get the number of required signatures.
  • The remaining data elements between the first and last opcodes are the public keys. Convert them to hex strings.

Solution code

Suggest Edits