commit
aca976689f
19 changed files with 4441 additions and 0 deletions
|
@ -85,6 +85,14 @@ The below examples are implemented as integration tests, they should be very eas
|
|||
Otherwise, pull requests are appreciated.
|
||||
Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
|
||||
|
||||
### Warning: Currently the tests use TransactionBuilder, which will be removed in the future (v6.x.x or higher)
|
||||
We will move towards replacing all instances of TransactionBuilder in the tests with the new Psbt.
|
||||
|
||||
Currently we have a few examples on how to use the newer Psbt class at the following link:
|
||||
- [Psbt examples](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions-psbt.js)
|
||||
|
||||
The rest of the examples are below (using TransactionBuilder for Transaction creation)
|
||||
|
||||
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js)
|
||||
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js)
|
||||
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js)
|
||||
|
|
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -199,6 +199,11 @@
|
|||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bip174": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bip174/-/bip174-1.0.0.tgz",
|
||||
"integrity": "sha512-AaoWrkYtv6A2y8H+qzs6NvRWypzNbADT8PQGpM9rnP+jLzeol+uzhe3Myeuq/dwrHYtmsW8V71HmX2oXhQGagw=="
|
||||
},
|
||||
"bip32": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.3.tgz",
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"dependencies": {
|
||||
"@types/node": "10.12.18",
|
||||
"bech32": "^1.1.2",
|
||||
"bip174": "^1.0.0",
|
||||
"bip32": "^2.0.3",
|
||||
"bip66": "^1.1.0",
|
||||
"bitcoin-ops": "^1.4.0",
|
||||
|
|
|
@ -16,6 +16,8 @@ const script = require('./script');
|
|||
exports.script = script;
|
||||
var block_1 = require('./block');
|
||||
exports.Block = block_1.Block;
|
||||
var psbt_1 = require('./psbt');
|
||||
exports.Psbt = psbt_1.Psbt;
|
||||
var script_1 = require('./script');
|
||||
exports.opcodes = script_1.OPS;
|
||||
var transaction_1 = require('./transaction');
|
||||
|
|
1114
src/psbt.js
Normal file
1114
src/psbt.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -57,6 +57,13 @@ class TransactionBuilder {
|
|||
this.__TX = new transaction_1.Transaction();
|
||||
this.__TX.version = 2;
|
||||
this.__USE_LOW_R = false;
|
||||
console.warn(
|
||||
'Deprecation Warning: TransactionBuilder will be removed in the future. ' +
|
||||
'(v6.x.x or later) Please use the Psbt class instead. Examples of usage ' +
|
||||
'are available in the transactions-psbt.js integration test file on our ' +
|
||||
'Github. A high level explanation is available in the psbt.ts and psbt.js ' +
|
||||
'files as well.',
|
||||
);
|
||||
}
|
||||
static fromTransaction(transaction, network) {
|
||||
const txb = new TransactionBuilder(network);
|
||||
|
|
550
test/fixtures/psbt.json
vendored
Normal file
550
test/fixtures/psbt.json
vendored
Normal file
|
@ -0,0 +1,550 @@
|
|||
{
|
||||
"bip174": {
|
||||
"invalid": [
|
||||
{
|
||||
"description": "Network transaction, not PSBT format",
|
||||
"errorMessage": "Format Error: Invalid Magic Number",
|
||||
"psbt": "AgAAAAEmgXE3Ht/yhek3re6ks3t4AAwFZsuzrWRkFxPKQhcb9gAAAABqRzBEAiBwsiRRI+a/R01gxbUMBD1MaRpdJDXwmjSnZiqdwlF5CgIgATKcqdrPKAvfMHQOwDkEIkIsgctFg5RXrrdvwS7dlbMBIQJlfRGNM1e44PTCzUbbezn22cONmnCry5st5dyNv+TOMf7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHsy4TAA=="
|
||||
},
|
||||
{
|
||||
"description": "PSBT missing outputs",
|
||||
"errorMessage": "Format Error: Unexpected End of PSBT",
|
||||
"psbt": "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA=="
|
||||
},
|
||||
{
|
||||
"description": "PSBT where one input has a filled scriptSig in the unsigned tx",
|
||||
"errorMessage": "Format Error: Transaction ScriptSigs are not empty",
|
||||
"psbt": "cHNidP8BAP0KAQIAAAACqwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QAAAAAakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpL+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAABASAA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHhwEEFgAUhdE1N/LiZUBaNNuvqePdoB+4IwgAAAA="
|
||||
},
|
||||
{
|
||||
"description": "PSBT where inputs and outputs are provided but without an unsigned tx",
|
||||
"errorMessage": "Format Error: Only one UNSIGNED_TX allowed",
|
||||
"psbt": "cHNidP8AAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA=="
|
||||
},
|
||||
{
|
||||
"description": "PSBT with duplicate keys in an input",
|
||||
"errorMessage": "Format Error: Keys must be unique for each input: input index 0 key 00",
|
||||
"psbt": "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQA/AgAAAAH//////////////////////////////////////////wAAAAAA/////wEAAAAAAAAAAANqAQAAAAAAAAAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid global transaction typed key",
|
||||
"errorMessage": "Format Error: Invalid global key: 0001",
|
||||
"psbt": "cHNidP8CAAFVAgAAAAEnmiMjpd+1H8RfIg+liw/BPh4zQnkqhdfjbNYzO1y8OQAAAAAA/////wGgWuoLAAAAABl2qRT/6cAGEJfMO2NvLLBGD6T8Qn0rRYisAAAAAAABASCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid input witness utxo typed key",
|
||||
"errorMessage": "Format Error: Invalid input key: 0100",
|
||||
"psbt": "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAIBACCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid pubkey length for input partial signature typed key",
|
||||
"errorMessage": "Format Error: invalid pubkey in key 0x0203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd",
|
||||
"psbt": "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIQIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYwQwIgBCS1jv+qppThVZ6lyTu/1KiQZCJAVc3wcLZ3FGlELQcCH1yOsP6mUW1guKyzOtZO3mDoeFv7OqlLmb34YVHbmpoBAQQiACB3H9GK1FlmbdSfPVZOPbxC9MhHdONgraFoFqjtSI1WgQEFR1IhA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GIQPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvVKuIgYDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYQtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA=="
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid redeemscript typed key",
|
||||
"errorMessage": "Format Error: Invalid input key: 0400",
|
||||
"psbt": "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQIEACIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid witnessscript typed key",
|
||||
"errorMessage": "Format Error: Invalid input key: 0500",
|
||||
"psbt": "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoECBQBHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid bip32 typed key",
|
||||
"errorMessage": "Format Error: invalid pubkey in key 0x0603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd",
|
||||
"psbt": "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriEGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb0QtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA=="
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid non-witness utxo typed key",
|
||||
"errorMessage": "Format Error: Invalid input key: 0000",
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAIAALsCAAAAAarXOTEBi9JfhK5AC2iEi+CdtwbqwqwYKYur7nGrZW+LAAAAAEhHMEQCIFj2/HxqM+GzFUjUgcgmwBW9MBNarULNZ3kNq2bSrSQ7AiBKHO0mBMZzW2OT5bQWkd14sA8MWUL7n3UYVvqpOBV9ugH+////AoDw+gIAAAAAF6kUD7lGNCFpa4LIM68kHHjBfdveSTSH0PIKJwEAAAAXqRQpynT4oI+BmZQoGFyXtdhS5AY/YYdlAAAAAQfaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA="
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid final scriptsig typed key",
|
||||
"errorMessage": "Format Error: Invalid input key: 0700",
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAACBwDaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA="
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid final script witness typed key",
|
||||
"errorMessage": "Format Error: Invalid input key: 0800",
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAggA2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA="
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid pubkey in output BIP 32 derivation paths typed key",
|
||||
"errorMessage": "Format Error: invalid pubkey in key 0x0203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca587",
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIQIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1PtnuylhxDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid input sighash type typed key",
|
||||
"errorMessage": "Format Error: Invalid input key: 0300",
|
||||
"psbt": "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid output redeemScript typed key",
|
||||
"errorMessage": "Format Error: Invalid output key: 0000",
|
||||
"psbt": "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A"
|
||||
},
|
||||
{
|
||||
"description": "PSBT With invalid output witnessScript typed key",
|
||||
"errorMessage": "Format Error: Unexpected End of PSBT",
|
||||
"psbt": "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A"
|
||||
}
|
||||
],
|
||||
"valid": [
|
||||
{
|
||||
"description": "PSBT with one P2PKH input. Outputs are empty",
|
||||
"psbt": "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT with one P2PKH input and one P2SH-P2WPKH input. First input is signed and finalized. Outputs are empty",
|
||||
"psbt": "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA"
|
||||
},
|
||||
{
|
||||
"description": "PSBT with one P2PKH input which has a non-final scriptSig and has a sighash type specified. Outputs are empty",
|
||||
"psbt": "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQMEAQAAAAAAAA=="
|
||||
},
|
||||
{
|
||||
"description": "PSBT with one P2PKH input and one P2SH-P2WPKH input both with non-final scriptSigs. P2SH-P2WPKH input's redeemScript is available. Outputs filled.",
|
||||
"psbt": "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEA3wIAAAABJoFxNx7f8oXpN63upLN7eAAMBWbLs61kZBcTykIXG/YAAAAAakcwRAIgcLIkUSPmv0dNYMW1DAQ9TGkaXSQ18Jo0p2YqncJReQoCIAEynKnazygL3zB0DsA5BCJCLIHLRYOUV663b8Eu3ZWzASECZX0RjTNXuOD0ws1G23s59tnDjZpwq8ubLeXcjb/kzjH+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA="
|
||||
},
|
||||
{
|
||||
"description": "PSBT with one P2SH-P2WSH input of a 2-of-2 multisig, redeemScript, witnessScript, and keypaths are available. Contains one signature.",
|
||||
"psbt": "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriIGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GELSmumcAAACAAAAAgAQAAIAiBgPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvRC0prpnAAAAgAAAAIAFAACAAAA="
|
||||
},
|
||||
{
|
||||
"description": "PSBT with unknown types in the inputs.",
|
||||
"psbt": "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAA="
|
||||
}
|
||||
],
|
||||
"failSignChecks": [
|
||||
{
|
||||
"description": "A Witness UTXO is provided for a non-witness input",
|
||||
"errorMessage": "Input #0 has witnessUtxo but non-segwit script",
|
||||
"psbt": "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEBItPf9QUAAAAAGXapFNSO0xELlAFMsRS9Mtb00GbcdCVriKwAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=",
|
||||
"inputToCheck": 0
|
||||
},
|
||||
{
|
||||
"description": "redeemScript with non-witness UTXO does not match the scriptPubKey",
|
||||
"errorMessage": "Redeem script for input #0 doesn't match the scriptPubKey in the prevout",
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq8iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=",
|
||||
"inputToCheck": 0
|
||||
},
|
||||
{
|
||||
"description": "redeemScript with witness UTXO does not match the scriptPubKey",
|
||||
"errorMessage": "Redeem script for input #1 doesn't match the scriptPubKey in the prevout",
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQABBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=",
|
||||
"inputToCheck": 1
|
||||
},
|
||||
{
|
||||
"description": "witnessScript with witness UTXO does not match the redeemScript",
|
||||
"errorMessage": "Witness script for input #1 doesn't match the scriptPubKey in the prevout",
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSrSIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=",
|
||||
"inputToCheck": 1
|
||||
}
|
||||
],
|
||||
"creator": [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"hash": "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"hash": "1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83",
|
||||
"index": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"script": "0014d85c2b71d0060b09c9886aeb815e50991dda124d",
|
||||
"value": 149990000
|
||||
},
|
||||
{
|
||||
"script": "001400aea9a2e5f0f876a588df5546e8742d1d87008f",
|
||||
"value": 100000000
|
||||
}
|
||||
],
|
||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA="
|
||||
}
|
||||
],
|
||||
"updater": [
|
||||
{
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA=",
|
||||
"inputData": [
|
||||
{
|
||||
"nonWitnessUtxo": "Buffer.from('0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000', 'hex')",
|
||||
"redeemScript": "Buffer.from('5221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae', 'hex')",
|
||||
"bip32Derivation": [
|
||||
{
|
||||
"masterFingerprint": "Buffer.from('d90c6a4f', 'hex')",
|
||||
"pubkey": "Buffer.from('029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f', 'hex')",
|
||||
"path": "m/0'/0'/0'"
|
||||
},
|
||||
{
|
||||
"masterFingerprint": "Buffer.from('d90c6a4f', 'hex')",
|
||||
"pubkey": "Buffer.from('02dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7', 'hex')",
|
||||
"path": "m/0'/0'/1'"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"witnessUtxo": {
|
||||
"script": "Buffer.from('a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887', 'hex')",
|
||||
"value": 200000000
|
||||
},
|
||||
"redeemScript": "Buffer.from('00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903', 'hex')",
|
||||
"witnessScript": "Buffer.from('522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae', 'hex')",
|
||||
"bip32Derivation": [
|
||||
{
|
||||
"masterFingerprint": "Buffer.from('d90c6a4f', 'hex')",
|
||||
"pubkey": "Buffer.from('023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73', 'hex')",
|
||||
"path": "m/0'/0'/3'"
|
||||
},
|
||||
{
|
||||
"masterFingerprint": "Buffer.from('d90c6a4f', 'hex')",
|
||||
"pubkey": "Buffer.from('03089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc', 'hex')",
|
||||
"path": "m/0'/0'/2'"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputData": [
|
||||
{
|
||||
"bip32Derivation": [
|
||||
{
|
||||
"masterFingerprint": "Buffer.from('d90c6a4f', 'hex')",
|
||||
"pubkey": "Buffer.from('03a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca58771', 'hex')",
|
||||
"path": "m/0'/0'/4'"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"bip32Derivation": [
|
||||
{
|
||||
"masterFingerprint": "Buffer.from('d90c6a4f', 'hex')",
|
||||
"pubkey": "Buffer.from('027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b50051096', 'hex')",
|
||||
"path": "m/0'/0'/5'"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA=="
|
||||
},
|
||||
{
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==",
|
||||
"inputData": [
|
||||
{
|
||||
"sighashType": 1
|
||||
},
|
||||
{
|
||||
"sighashType": 1
|
||||
}
|
||||
],
|
||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA"
|
||||
}
|
||||
],
|
||||
"signer": [
|
||||
{
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||
"keys": [
|
||||
{
|
||||
"inputToSign": 0,
|
||||
"WIF": "cP53pDbR5WtAD8dYAW9hhTjuvvTVaEiQBdrz9XPrgLBeRFiyCbQr"
|
||||
},
|
||||
{
|
||||
"inputToSign": 1,
|
||||
"WIF": "cR6SXDoyfQrcp4piaiHE97Rsgta9mNhGTen9XeonVgwsh4iSgw6d"
|
||||
}
|
||||
],
|
||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA=="
|
||||
},
|
||||
{
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||
"keys": [
|
||||
{
|
||||
"inputToSign": 0,
|
||||
"WIF": "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au"
|
||||
},
|
||||
{
|
||||
"inputToSign": 1,
|
||||
"WIF": "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE"
|
||||
}
|
||||
],
|
||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA="
|
||||
}
|
||||
],
|
||||
"combiner": [
|
||||
{
|
||||
"psbts": [
|
||||
"cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==",
|
||||
"cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA="
|
||||
],
|
||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA"
|
||||
},
|
||||
{
|
||||
"psbts": [
|
||||
"cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwA=",
|
||||
"cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA="
|
||||
],
|
||||
"result": "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8KDwECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PCg8BAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwoPAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA="
|
||||
}
|
||||
],
|
||||
"finalizer": [
|
||||
{
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA=="
|
||||
}
|
||||
],
|
||||
"extractor": [
|
||||
{
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==",
|
||||
"transaction": "0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
"addInput": {
|
||||
"checks": [
|
||||
{
|
||||
"description": "checks for hash and index",
|
||||
"inputData": {
|
||||
"hash": 42
|
||||
},
|
||||
"exception": "Error adding input."
|
||||
},
|
||||
{
|
||||
"description": "should be equal",
|
||||
"inputData": {
|
||||
"hash": "Buffer.from('000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f', 'hex')",
|
||||
"index": 2
|
||||
},
|
||||
"equals": "cHNidP8BADMCAAAAAQABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4PAgAAAAD/////AAAAAAAAAAA="
|
||||
}
|
||||
]
|
||||
},
|
||||
"addOutput": {
|
||||
"checks": [
|
||||
{
|
||||
"description": "Checks value is number",
|
||||
"outputData": {
|
||||
"address": "1P2NFEBp32V2arRwZNww6tgXEV58FG94mr",
|
||||
"value": "xyz"
|
||||
},
|
||||
"exception": "Error adding output."
|
||||
},
|
||||
{
|
||||
"description": "Adds output normally",
|
||||
"outputData": {
|
||||
"address": "1P2NFEBp32V2arRwZNww6tgXEV58FG94mr",
|
||||
"value": 42
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"signInput": {
|
||||
"checks": [
|
||||
{
|
||||
"description": "checks the input exists",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFC8spHIOpiw9giaEPd5RGkMYvXRHiKwAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "No input #1",
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFC8spHIOpiw9giaEPd5RGkMYvXRHiKwAAAAAAAA=",
|
||||
"inputToCheck": 1,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks a UTXO value exists for the input",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFC8spHIOpiw9giaEPd5RGkMYvXRHiKwAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Need a Utxo input item for signing",
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks privkey matches the input it's signing",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFC8spHIOpiw9giaEPd5RGkMYvXRHiKwAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Can not sign for this input with the key 02e717fee6be913148f9fd676c0876b7e4574118542c6758b4a9fb9f38f171842b",
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFC8spHIOpiw9giaEPd5RGkMYvXRHiKwAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "Kz4mjzErKCH5eQ97RXNQd3Wv7WsLA83BjynfQk4N7BB8J5xuUjAv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks non-witness UTXO matches the hash specified in the prevout",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFC8spHIOpiw9giaEPd5RGkMYvXRHiKwAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Non-witness UTXO hash for input #0 doesn't match the hash specified in the prevout",
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQD4AQAAAAABAbD7u8z1SxTjfvhwmkQQvdbbWA+n3GKBBmGecSIAaM5jBQAAABcWABS0SqIhdn2LbW4TAJc3GVh7SnD/eP////8CNg8AAAAAAAAWABSmNm8WWVF+wq+QAeRo9d763jEXhRAnAAAAAAAAGXapFNpkc+03Pgj0bdgAP8p7py++nFVeiKwCRzBEAiB/u0BLwdeerqWf0JH33wwMv8Nn3sKblFvj+CntdC4B9gIgKVVHBH1c9ewnzkuyW6dnz1YARujBJnle1eBNSBAJD9IBIQOmYxHmd2Yz53FpC9+nv+pKdM+5OyEAW3BAN2cccQ0LkgAAAAAAAA==",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks redeem script matches the scriptPubKey in a non-witness prevout",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAAR2dq8JwBaxnbWHZGw0HdxuUGFcg6dvx3pgjWMm+Pzf2AAAAAAD/////AAAAAAAAAQC9AgAAAAH//////////////////////////////////////////wAAAABqRzBEAiAf7N+IK1uuxTxvEOoVGabNsiT7jMlfSDCd0VYxv+sQTQIgQVYM7ig9TIx1LzrX2RXgw2zW2fMKuRs/bT9eZx6jmYwBIQJpKKFOB6PrPJhRAtaQ+cHHryY5QYIi5dxZtkMwCtuFYf////8BAOH1BQAAAAAXqRRdh8wk5NRiF7VGQ4Zb4i8Vl1YFMocAAAAAAQRpUiECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWEhAgHGF3SgP82qhvqMptNluTLHhLtzDsmc0pNWEDETNj/rIQIFIl+T3Z90vBFGN8uYJHCrUO4DvrOGVWkVDsBeEzBUi1OuAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Redeem script for input #0 doesn't match the scriptPubKey in the prevout",
|
||||
"psbt": "cHNidP8BADMBAAAAAR2dq8JwBaxnbWHZGw0HdxuUGFcg6dvx3pgjWMm+Pzf2AAAAAAD/////AAAAAAAAAQC9AgAAAAH//////////////////////////////////////////wAAAABqRzBEAiAf7N+IK1uuxTxvEOoVGabNsiT7jMlfSDCd0VYxv+sQTQIgQVYM7ig9TIx1LzrX2RXgw2zW2fMKuRs/bT9eZx6jmYwBIQJpKKFOB6PrPJhRAtaQ+cHHryY5QYIi5dxZtkMwCtuFYf////8BAOH1BQAAAAAXqRRdh8wk5NRiF7VGQ4Zb4i8Vl1YFMocAAAAAAQRpUiEDGMZFrWWJBIIu33FdV9Q+Zit0fcoBOdgS7ooA2h2QlbAhAuAzQeDZh730hBbfTPzlaXJgCh2Jyui/ufS0k8wqJ55FIQKMg6lgEnyRnGIZ90eP4MmuRdT3EcO4+irJEm5yTCiko1OuAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks redeem script matches the scriptPubKey in a witness prevout",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAAYaq+PdOUY2PnV9kZKa82XlqrPByOqwH2TRg2+LQdqs2AAAAAAD/////AAAAAAAAAQEgAOH1BQAAAAAXqRSTNeWHqa9INvSnQ120SZeJc+6JSocBBBYAFC8spHIOpiw9giaEPd5RGkMYvXRHAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Redeem script for input #0 doesn't match the scriptPubKey in the prevout",
|
||||
"psbt": "cHNidP8BADMBAAAAAYaq+PdOUY2PnV9kZKa82XlqrPByOqwH2TRg2+LQdqs2AAAAAAD/////AAAAAAAAAQEgAOH1BQAAAAAXqRSTNeWHqa9INvSnQ120SZeJc+6JSocBBBYAFA3zpl6FMnlgCviVJgbcnBj01iLgAAA=",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks the sighash type",
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Sighash type is not allowed. Retry the sign method passing the sighashTypes array of whitelisted types. Sighash type: SIGHASH_ANYONECANPAY | SIGHASH_ALL",
|
||||
"psbt": "cHNidP8BADMBAAAAAYaq+PdOUY2PnV9kZKa82XlqrPByOqwH2TRg2+LQdqs2AAAAAAD/////AAAAAAAAAQEgAOH1BQAAAAAXqRSTNeWHqa9INvSnQ120SZeJc+6JSocBAwSBAAAAAQQWABQvLKRyDqYsPYImhD3eURpDGL10RwAA",
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "allows signing non-whitelisted sighashtype when explicitly passed in",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAAYaq+PdOUY2PnV9kZKa82XlqrPByOqwH2TRg2+LQdqs2AAAAAAD/////AAAAAAAAAQEgAOH1BQAAAAAXqRSTNeWHqa9INvSnQ120SZeJc+6JSocBAwSBAAAAAQQWABQvLKRyDqYsPYImhD3eURpDGL10RwAA",
|
||||
"sighashTypes": [129],
|
||||
"inputToCheck": 0,
|
||||
"WIF": "KxnAnQh6UJBxLF8Weup77yn8tWhLHhDhnXeyJuzmmcZA5aRdMJni"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"signInputHD": {
|
||||
"checks": [
|
||||
{
|
||||
"description": "checks the bip32Derivation exists",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAARtEptsZNydT9Bh9A5ptwIZz87yH8NXwzr1bjJorAZEAAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFJWXNY2Vp7E5pNOey64rnhhgUlohiKwAAAAAIgYDn85vSg5rlR25fd4MOU2ANsFoO+q828zuOI/5b8tj89kYBCppsiwAAIAAAACAAAAAgAAAAAAAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"xprv": "xprv9s21ZrQH143K2XNCa3o3tii6nbyJAET6GjTfzcF6roTjAMzLUBe8nt7QHNYqKah8JBv8V67MTWBCqPptRr6khjTSvCUVru78KHW13Viwnev"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Need bip32Derivation to sign with HD",
|
||||
"psbt": "cHNidP8BADMBAAAAAXVa+rWvBGNyifYXEMlTten9+qC0xuHcAMxQYrQTwX1dAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFC8spHIOpiw9giaEPd5RGkMYvXRHiKwAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"xprv": "xprv9s21ZrQH143K2XNCa3o3tii6nbyJAET6GjTfzcF6roTjAMzLUBe8nt7QHNYqKah8JBv8V67MTWBCqPptRr6khjTSvCUVru78KHW13Viwnev"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks the bip32Derivation exists",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAARtEptsZNydT9Bh9A5ptwIZz87yH8NXwzr1bjJorAZEAAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFJWXNY2Vp7E5pNOey64rnhhgUlohiKwAAAAAIgYDn85vSg5rlR25fd4MOU2ANsFoO+q828zuOI/5b8tj89kYBCppsiwAAIAAAACAAAAAgAAAAAAAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"xprv": "xprv9s21ZrQH143K2XNCa3o3tii6nbyJAET6GjTfzcF6roTjAMzLUBe8nt7QHNYqKah8JBv8V67MTWBCqPptRr6khjTSvCUVru78KHW13Viwnev"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "Need one bip32Derivation masterFingerprint to match the HDSigner fingerprint",
|
||||
"psbt": "cHNidP8BADMBAAAAARtEptsZNydT9Bh9A5ptwIZz87yH8NXwzr1bjJorAZEAAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFJWXNY2Vp7E5pNOey64rnhhgUlohiKwAAAAAIgYD/85vSg5rlR25fd4MOU2ANsFoO+q828zuOI/5b8tj89kY/////ywAAIAAAACAAAAAgAAAAAAAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"xprv": "xprv9s21ZrQH143K2XNCa3o3tii6nbyJAET6GjTfzcF6roTjAMzLUBe8nt7QHNYqKah8JBv8V67MTWBCqPptRr6khjTSvCUVru78KHW13Viwnev"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "checks the bip32Derivation exists",
|
||||
"shouldSign": {
|
||||
"psbt": "cHNidP8BADMBAAAAARtEptsZNydT9Bh9A5ptwIZz87yH8NXwzr1bjJorAZEAAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFJWXNY2Vp7E5pNOey64rnhhgUlohiKwAAAAAIgYDn85vSg5rlR25fd4MOU2ANsFoO+q828zuOI/5b8tj89kYBCppsiwAAIAAAACAAAAAgAAAAAAAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"xprv": "xprv9s21ZrQH143K2XNCa3o3tii6nbyJAET6GjTfzcF6roTjAMzLUBe8nt7QHNYqKah8JBv8V67MTWBCqPptRr6khjTSvCUVru78KHW13Viwnev"
|
||||
},
|
||||
"shouldThrow": {
|
||||
"errorMessage": "pubkey did not match bip32Derivation",
|
||||
"psbt": "cHNidP8BADMBAAAAARtEptsZNydT9Bh9A5ptwIZz87yH8NXwzr1bjJorAZEAAAAAAAD/////AAAAAAAAAQDAAgAAAAH//////////////////////////////////////////wAAAABrSDBFAiEAjtCPUj0vx3I5HFQKAUWHN0vCnT17jd41/omb4nobq/sCIAilSeQVi4mqykgBbs+Wz6PyqdMThi2gT463v4kPWk6cASECaSihTgej6zyYUQLWkPnBx68mOUGCIuXcWbZDMArbhWH/////AQDh9QUAAAAAGXapFJWXNY2Vp7E5pNOey64rnhhgUlohiKwAAAAAIgYD/85vSg5rlR25fd4MOU2ANsFoO+q828zuOI/5b8tj89kYBCppsiwAAIAAAACAAAAAgAAAAAAAAAAAAAA=",
|
||||
"inputToCheck": 0,
|
||||
"xprv": "xprv9s21ZrQH143K2XNCa3o3tii6nbyJAET6GjTfzcF6roTjAMzLUBe8nt7QHNYqKah8JBv8V67MTWBCqPptRr6khjTSvCUVru78KHW13Viwnev"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"finalizeAllInputs": [
|
||||
{
|
||||
"type": "P2PK",
|
||||
"psbt": "cHNidP8BAFUCAAAAAZfdvR7JvbVsuXunG1P19tTYi8Z0l6WHiz+0jpzTNTt+AAAAAAD/////AYA4AQAAAAAAGXapFMjtQ0xCK7OPd32ZJTY2UcdpFIaJiKwAAAAAAAEAygIAAAABb7TMmNs5UwEEpccLHlaaM0w3HEHhh85NjrUObLDMuZsBAAAAa0gwRQIhANWUevBBcqfRpH67rDuFqI+KHqxViKXxmSM+6/jE5ZHjAiBgO/vQg2EsYhaOD5lQbmZYaymRLukA6SCoXhkN21hiOwEhAoKzWGkj1LJ2iOt5wj6jMOtAMGJH50ZjAYZU81uUu6y+/////wGQXwEAAAAAACMhAzpK4NeYX+xyBOKynjD3BEPDq7EN8brZXje488gxshXwrAAAAAAiAgM6SuDXmF/scgTisp4w9wRDw6uxDfG62V43uPPIMbIV8EgwRQIhAL3H/XEPRAZEbpjBwkuLqUKBSu1Inpb2rganXNFcY2JsAiASrXTM2xODEKp7m7RTzYqBchqlvbl88zO/CGW9SePj2gEAAA==",
|
||||
"result": "cHNidP8BAFUCAAAAAZfdvR7JvbVsuXunG1P19tTYi8Z0l6WHiz+0jpzTNTt+AAAAAAD/////AYA4AQAAAAAAGXapFMjtQ0xCK7OPd32ZJTY2UcdpFIaJiKwAAAAAAAEAygIAAAABb7TMmNs5UwEEpccLHlaaM0w3HEHhh85NjrUObLDMuZsBAAAAa0gwRQIhANWUevBBcqfRpH67rDuFqI+KHqxViKXxmSM+6/jE5ZHjAiBgO/vQg2EsYhaOD5lQbmZYaymRLukA6SCoXhkN21hiOwEhAoKzWGkj1LJ2iOt5wj6jMOtAMGJH50ZjAYZU81uUu6y+/////wGQXwEAAAAAACMhAzpK4NeYX+xyBOKynjD3BEPDq7EN8brZXje488gxshXwrAAAAAABB0lIMEUCIQC9x/1xD0QGRG6YwcJLi6lCgUrtSJ6W9q4Gp1zRXGNibAIgEq10zNsTgxCqe5u0U82KgXIapb25fPMzvwhlvUnj49oBAAA="
|
||||
},
|
||||
{
|
||||
"type": "P2PKH",
|
||||
"psbt": "cHNidP8BAFUCAAAAAaTbj9mE+B5Z8PLsuGUNGOzDqrtwdB08vvSccSCrezh+AAAAAAD/////AYA4AQAAAAAAGXapFDuK+0mR+qtL9tyadI72bKMwH+vuiKwAAAAAAAEAwAIAAAABks7XL87tkSusFA3L2u2CdJeNkqTMobehPNm/wkGQUzoBAAAAa0gwRQIhAMtzqC7axSA7/7nbio9NKQZz2ePuKeaF5T4c8JSXWEdgAiAID39I05hbJMNGSomrF7XVWEsEEHHzX/lkL3vnOOu4cAEhAvu+bfurbDCzxfOLxEhvz9ZyxPLdI1h9wMT8gl2nyLYV/////wGQXwEAAAAAABl2qRTH5239BfS9zrbwUtvpATwjua4LGYisAAAAACICA1oNX0U/6GwAuVI7JHhneD94sm/o+YrfTnRAhdRUMjoISDBFAiEAhk+HbvY6YShBCUmBVCk42sFWH9LTwUv2wbRC/tIuEAwCIED/UkklY3fpdDBN7qSBHFDyEOeHMUzXD0bvtFTAiKP7AQAA",
|
||||
"result": "cHNidP8BAFUCAAAAAaTbj9mE+B5Z8PLsuGUNGOzDqrtwdB08vvSccSCrezh+AAAAAAD/////AYA4AQAAAAAAGXapFDuK+0mR+qtL9tyadI72bKMwH+vuiKwAAAAAAAEAwAIAAAABks7XL87tkSusFA3L2u2CdJeNkqTMobehPNm/wkGQUzoBAAAAa0gwRQIhAMtzqC7axSA7/7nbio9NKQZz2ePuKeaF5T4c8JSXWEdgAiAID39I05hbJMNGSomrF7XVWEsEEHHzX/lkL3vnOOu4cAEhAvu+bfurbDCzxfOLxEhvz9ZyxPLdI1h9wMT8gl2nyLYV/////wGQXwEAAAAAABl2qRTH5239BfS9zrbwUtvpATwjua4LGYisAAAAAAEHa0gwRQIhAIZPh272OmEoQQlJgVQpONrBVh/S08FL9sG0Qv7SLhAMAiBA/1JJJWN36XQwTe6kgRxQ8hDnhzFM1w9G77RUwIij+wEhA1oNX0U/6GwAuVI7JHhneD94sm/o+YrfTnRAhdRUMjoIAAA="
|
||||
},
|
||||
{
|
||||
"type": "P2MS",
|
||||
"psbt": "cHNidP8BAFUCAAAAAbmLTo7GeyF7IT5PJznDiTVjhv5pQKcKe8Qa+8rqUpXuAAAAAAD/////AYA4AQAAAAAAGXapFF2G82oAzUpx/kcDUPy58goX16gkiKwAAAAAAAEAvgIAAAABMBwIKVKOFbas6tBD24LPchtrweE2jiXkPgSHdJndEfoAAAAAa0gwRQIhAJNchwx4je/ZqtZXSCD6BKJBQkpkTBGGdLoFZTcPKlDtAiAZefY/giaVw5rcEoJk4TRnFCyMG0dYLV5IVnFWkR38fQEhAi5yX8RMW6plVrMY26hithJ6j1w2mgqh/bOCAEVnbn/Z/////wGQXwEAAAAAABepFIoQ3seh+nGYzkI7MDw5zuSCIxEyhwAAAAAiAgLFmuo7gG8OjgmaO5AHuC/1OvDarQt16R7VEKU8dkRRCEgwRQIhAOqqlnUwmc+PqKZVwAAMLPNCKskHhVgk1pXR9d7nmB6SAiA0C24idVdtgl9+sIBR8A3Za5WcswNJ3i8PWTMWR10C4QEiAgPnartRgvSQnSJ2ydRuwSPXDdU3P1YQwhYsK7XzfGuUREgwRQIhANnDBUQWjS8hDTPidRZ95rGZK3LWCLIZB1NYx9++eBT8AiASupLR+KNa1Se7eoBkWQcDny+BaBfMQ+p1RTCAXd7/GAEBBItSIQLFmuo7gG8OjgmaO5AHuC/1OvDarQt16R7VEKU8dkRRCCEC4X74b+vRF3XLgyXyGejmE5VB1f3RY/IReUggyNHgdLYhA+dqu1GC9JCdInbJ1G7BI9cN1Tc/VhDCFiwrtfN8a5REIQO94OZv6yPD4kEZSZBquYA7FPsABZZ6UAteVuEw7fVxzlSuAAA=",
|
||||
"result": "cHNidP8BAFUCAAAAAbmLTo7GeyF7IT5PJznDiTVjhv5pQKcKe8Qa+8rqUpXuAAAAAAD/////AYA4AQAAAAAAGXapFF2G82oAzUpx/kcDUPy58goX16gkiKwAAAAAAAEAvgIAAAABMBwIKVKOFbas6tBD24LPchtrweE2jiXkPgSHdJndEfoAAAAAa0gwRQIhAJNchwx4je/ZqtZXSCD6BKJBQkpkTBGGdLoFZTcPKlDtAiAZefY/giaVw5rcEoJk4TRnFCyMG0dYLV5IVnFWkR38fQEhAi5yX8RMW6plVrMY26hithJ6j1w2mgqh/bOCAEVnbn/Z/////wGQXwEAAAAAABepFIoQ3seh+nGYzkI7MDw5zuSCIxEyhwAAAAABB/0gAQBIMEUCIQDqqpZ1MJnPj6imVcAADCzzQirJB4VYJNaV0fXe55gekgIgNAtuInVXbYJffrCAUfAN2WuVnLMDSd4vD1kzFkddAuEBSDBFAiEA2cMFRBaNLyENM+J1Fn3msZkrctYIshkHU1jH3754FPwCIBK6ktH4o1rVJ7t6gGRZBwOfL4FoF8xD6nVFMIBd3v8YAUyLUiECxZrqO4BvDo4JmjuQB7gv9Trw2q0Ldeke1RClPHZEUQghAuF++G/r0Rd1y4Ml8hno5hOVQdX90WPyEXlIIMjR4HS2IQPnartRgvSQnSJ2ydRuwSPXDdU3P1YQwhYsK7XzfGuURCEDveDmb+sjw+JBGUmQarmAOxT7AAWWelALXlbhMO31cc5UrgAA"
|
||||
},
|
||||
{
|
||||
"type": "P2SH-P2WPKH",
|
||||
"psbt": "cHNidP8BAFUCAAAAATIK6DMTn8bbrG7ZdiiVU3/YAgzyk3dwa56En58YfXbDAAAAAAD/////AYA4AQAAAAAAGXapFNU4SHWUW9ZNz+BcxCiuU/7UtJoMiKwAAAAAAAEAvgIAAAABly2BCiYZ3slqurlLwE7b8UXINYKfrJ9sQlBovzBAwFsBAAAAa0gwRQIhAJJ+Hyniw+KneWomeQYrP1duH7cfQ3j8GN6/RshZCfuvAiBux7Uu/5QqmSmL+LjoWZY2b9TWdluY6zLTkQWIornmYwEhAvUo9Sy7Pu44z84ZZPrQMQxBPpDJyy9WlLQMGdGIuUy7/////wGQXwEAAAAAABepFPwojcWCH2oE9dUjMmLC3bdK/xeWhwAAAAAiAgKj88rhJwk3Zxm0p0Rp+xC/6cxmj+I741DHPWPWN7iA+0cwRAIgTRhd9WUpoHYl9tUVmoJ336fJAJInIjdYsoatvRiW8hgCIGOYMlpKRHiHA428Sfa2CdAIIGGQCGhuIgIzj2FN6USnAQEEFgAU4sZupXPxqhcsOB1ghJxBvH4XcesAAA==",
|
||||
"result": "cHNidP8BAFUCAAAAATIK6DMTn8bbrG7ZdiiVU3/YAgzyk3dwa56En58YfXbDAAAAAAD/////AYA4AQAAAAAAGXapFNU4SHWUW9ZNz+BcxCiuU/7UtJoMiKwAAAAAAAEAvgIAAAABly2BCiYZ3slqurlLwE7b8UXINYKfrJ9sQlBovzBAwFsBAAAAa0gwRQIhAJJ+Hyniw+KneWomeQYrP1duH7cfQ3j8GN6/RshZCfuvAiBux7Uu/5QqmSmL+LjoWZY2b9TWdluY6zLTkQWIornmYwEhAvUo9Sy7Pu44z84ZZPrQMQxBPpDJyy9WlLQMGdGIuUy7/////wGQXwEAAAAAABepFPwojcWCH2oE9dUjMmLC3bdK/xeWhwAAAAABBxcWABTixm6lc/GqFyw4HWCEnEG8fhdx6wAA"
|
||||
},
|
||||
{
|
||||
"type": "P2WPKH",
|
||||
"psbt": "cHNidP8BAFICAAAAAb5UIQFSoXPjqxSmuiSZkM5PjaycnrXQ6VB+u2+MzbSGAAAAAAD/////ASBOAAAAAAAAFgAUXsVBEaHSlhycDORbHHtBKwDo4zIAAAAAAAEBHzB1AAAAAAAAFgAUvIgag7HZu7Rjd/ugmJC/MHlZmAYiAgLN1zezMD4c4uegTbgfJ1GCtN5/hlJYaJt7e8mt1BVzIEcwRAIgXhgL5G81tXP7MAaKJtA0QaFu17bLocOGqxXmDoIfYUACIAOIynpoPS/dTz9Omg2h7v5kiql7ab0SPzWDdxpvpsUcAQAA",
|
||||
"result": "cHNidP8BAFICAAAAAb5UIQFSoXPjqxSmuiSZkM5PjaycnrXQ6VB+u2+MzbSGAAAAAAD/////ASBOAAAAAAAAFgAUXsVBEaHSlhycDORbHHtBKwDo4zIAAAAAAAEBHzB1AAAAAAAAFgAUvIgag7HZu7Rjd/ugmJC/MHlZmAYBCGsCRzBEAiBeGAvkbzW1c/swBoom0DRBoW7Xtsuhw4arFeYOgh9hQAIgA4jKemg9L91PP06aDaHu/mSKqXtpvRI/NYN3Gm+mxRwBIQLN1zezMD4c4uegTbgfJ1GCtN5/hlJYaJt7e8mt1BVzIAAA"
|
||||
},
|
||||
{
|
||||
"type": "P2WSH-P2PK",
|
||||
"psbt": "cHNidP8BAKYCAAAAAlwKQ3suPWwEJ/zQ9sZsIioOcHKU1KoLMxlMNSXVIkEWAAAAAAD/////YYDJMap+mYgbTrCNAdpWHN+EkKvl+XYao/6co/EQfwMAAAAAAP////8CkF8BAAAAAAAWABRnPBAmVHz2HL+8/1U+QG5L2thjmjhKAAAAAAAAIgAg700yfFRyhWzQnPHIUb/XQqsjlpf4A0uw682pCVWuQ8IAAAAAAAEBKzB1AAAAAAAAIgAgth9oE4cDfC5aV58VgkW5CptHsIxppYzJV8C5kT6aTo8iAgNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06UgwRQIhALO0xRpuqP3aVkm+DPykrtqe6fPNSgNblp9K9MAwmtHJAiAHV5ZvZN8Vi49n/o9ISFyvtHsPXXPKqBxC9m2m2HlpYgEBBSMhA182CcWcQ9L2zg9j8jlt7OlaIATNDgNFMBKB1J14wzTprAABASuAOAEAAAAAACIAILYfaBOHA3wuWlefFYJFuQqbR7CMaaWMyVfAuZE+mk6PIgIDXzYJxZxD0vbOD2PyOW3s6VogBM0OA0UwEoHUnXjDNOlIMEUCIQC6XN6tpo9mYlZej4BXSSh5D1K6aILBfQ4WBWXUrISx6wIgVaxFUsz8y59xJ1V4sZ1qarHX9pZ+MJmLKbl2ZSadisoBAQUjIQNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06awAAAA=",
|
||||
"result": "cHNidP8BAKYCAAAAAlwKQ3suPWwEJ/zQ9sZsIioOcHKU1KoLMxlMNSXVIkEWAAAAAAD/////YYDJMap+mYgbTrCNAdpWHN+EkKvl+XYao/6co/EQfwMAAAAAAP////8CkF8BAAAAAAAWABRnPBAmVHz2HL+8/1U+QG5L2thjmjhKAAAAAAAAIgAg700yfFRyhWzQnPHIUb/XQqsjlpf4A0uw682pCVWuQ8IAAAAAAAEBKzB1AAAAAAAAIgAgth9oE4cDfC5aV58VgkW5CptHsIxppYzJV8C5kT6aTo8BCG4CSDBFAiEAs7TFGm6o/dpWSb4M/KSu2p7p881KA1uWn0r0wDCa0ckCIAdXlm9k3xWLj2f+j0hIXK+0ew9dc8qoHEL2babYeWliASMhA182CcWcQ9L2zg9j8jlt7OlaIATNDgNFMBKB1J14wzTprAABASuAOAEAAAAAACIAILYfaBOHA3wuWlefFYJFuQqbR7CMaaWMyVfAuZE+mk6PAQhuAkgwRQIhALpc3q2mj2ZiVl6PgFdJKHkPUrpogsF9DhYFZdSshLHrAiBVrEVSzPzLn3EnVXixnWpqsdf2ln4wmYspuXZlJp2KygEjIQNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06awAAAA="
|
||||
}
|
||||
],
|
||||
"validateSignaturesOfInput": {
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||
"index": 0,
|
||||
"pubkey": "Buffer.from('029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f', 'hex')",
|
||||
"incorrectPubkey": "Buffer.from('029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e02a', 'hex')",
|
||||
"nonExistantIndex": 42
|
||||
},
|
||||
"getFeeRate": {
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||
"fee": 21
|
||||
},
|
||||
"cache": {
|
||||
"nonWitnessUtxo": {
|
||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEER1IhApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/IQLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU211KuIgYClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8Q2QxqTwAAAIAAAACAAAAAgCIGAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXENkMak8AAACAAAAAgAEAAIAAAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||
"nonWitnessUtxo": "Buffer.from('0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000', 'hex')",
|
||||
"inputIndex": 0
|
||||
}
|
||||
},
|
||||
"clone": {
|
||||
"psbt": "cHNidP8BAKYCAAAAAlwKQ3suPWwEJ/zQ9sZsIioOcHKU1KoLMxlMNSXVIkEWAAAAAAD/////YYDJMap+mYgbTrCNAdpWHN+EkKvl+XYao/6co/EQfwMAAAAAAP////8CkF8BAAAAAAAWABRnPBAmVHz2HL+8/1U+QG5L2thjmjhKAAAAAAAAIgAg700yfFRyhWzQnPHIUb/XQqsjlpf4A0uw682pCVWuQ8IAAAAAAAEBKzB1AAAAAAAAIgAgth9oE4cDfC5aV58VgkW5CptHsIxppYzJV8C5kT6aTo8iAgNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06UgwRQIhALO0xRpuqP3aVkm+DPykrtqe6fPNSgNblp9K9MAwmtHJAiAHV5ZvZN8Vi49n/o9ISFyvtHsPXXPKqBxC9m2m2HlpYgEBBSMhA182CcWcQ9L2zg9j8jlt7OlaIATNDgNFMBKB1J14wzTprAABASuAOAEAAAAAACIAILYfaBOHA3wuWlefFYJFuQqbR7CMaaWMyVfAuZE+mk6PIgIDXzYJxZxD0vbOD2PyOW3s6VogBM0OA0UwEoHUnXjDNOlIMEUCIQC6XN6tpo9mYlZej4BXSSh5D1K6aILBfQ4WBWXUrISx6wIgVaxFUsz8y59xJ1V4sZ1qarHX9pZ+MJmLKbl2ZSadisoBAQUjIQNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06awAAAA="
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ const bip65 = require('bip65')
|
|||
|
||||
const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest)
|
||||
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest)
|
||||
console.warn = () => {} // Silence the Deprecation Warning
|
||||
|
||||
describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
|
||||
// force update MTP
|
||||
|
|
|
@ -9,6 +9,7 @@ const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGk
|
|||
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest)
|
||||
const charles = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsMSb4Ubnf', regtest)
|
||||
const dave = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsMwS4pqnx', regtest)
|
||||
console.warn = () => {} // Silence the Deprecation Warning
|
||||
|
||||
describe('bitcoinjs-lib (transactions w/ CSV)', () => {
|
||||
// force update MTP
|
||||
|
|
|
@ -7,6 +7,7 @@ const keyPairs = [
|
|||
bitcoin.ECPair.makeRandom({ network: NETWORK }),
|
||||
bitcoin.ECPair.makeRandom({ network: NETWORK })
|
||||
]
|
||||
console.warn = () => {} // Silence the Deprecation Warning
|
||||
|
||||
async function buildAndSign (depends, prevOutput, redeemScript, witnessScript) {
|
||||
const unspent = await regtestUtils.faucetComplex(prevOutput, 5e4)
|
||||
|
|
550
test/integration/transactions-psbt.js
Normal file
550
test/integration/transactions-psbt.js
Normal file
|
@ -0,0 +1,550 @@
|
|||
const { describe, it } = require('mocha');
|
||||
const assert = require('assert');
|
||||
const bitcoin = require('../../');
|
||||
const bip32 = require('bip32');
|
||||
const rng = require('randombytes');
|
||||
const regtestUtils = require('./_regtest');
|
||||
const regtest = regtestUtils.network;
|
||||
|
||||
// See bottom of file for some helper functions used to make the payment objects needed.
|
||||
|
||||
describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||
it('can create a 1-to-1 Transaction', () => {
|
||||
const alice = bitcoin.ECPair.fromWIF(
|
||||
'L2uPYXe17xSTqbCjZvL2DsyXPCbXspvcu5mHLDYUgzdUbZGSKrSr',
|
||||
);
|
||||
const psbt = new bitcoin.Psbt();
|
||||
psbt.setVersion(2); // These are defaults. This line is not needed.
|
||||
psbt.setLocktime(0); // These are defaults. This line is not needed.
|
||||
psbt.addInput({
|
||||
// if hash is string, txid, if hash is Buffer, is reversed compared to txid
|
||||
hash: '7d067b4a697a09d2c3cff7d4d9506c9955e93bff41bf82d439da7d030382bc3e',
|
||||
index: 0,
|
||||
sequence: 0xffffffff, // These are defaults. This line is not needed.
|
||||
|
||||
// non-segwit inputs now require passing the whole previous tx as Buffer
|
||||
nonWitnessUtxo: Buffer.from(
|
||||
'0200000001f9f34e95b9d5c8abcd20fc5bd4a825d1517be62f0f775e5f36da944d9' +
|
||||
'452e550000000006b483045022100c86e9a111afc90f64b4904bd609e9eaed80d48' +
|
||||
'ca17c162b1aca0a788ac3526f002207bb79b60d4fc6526329bf18a77135dc566020' +
|
||||
'9e761da46e1c2f1152ec013215801210211755115eabf846720f5cb18f248666fec' +
|
||||
'631e5e1e66009ce3710ceea5b1ad13ffffffff01' +
|
||||
// value in satoshis (Int64LE) = 0x015f90 = 90000
|
||||
'905f010000000000' +
|
||||
// scriptPubkey length
|
||||
'19' +
|
||||
// scriptPubkey
|
||||
'76a9148bbc95d2709c71607c60ee3f097c1217482f518d88ac' +
|
||||
// locktime
|
||||
'00000000',
|
||||
'hex',
|
||||
),
|
||||
|
||||
// // If this input was segwit, instead of nonWitnessUtxo, you would add
|
||||
// // a witnessUtxo as follows. The scriptPubkey and the value only are needed.
|
||||
// witnessUtxo: {
|
||||
// script: Buffer.from(
|
||||
// '76a9148bbc95d2709c71607c60ee3f097c1217482f518d88ac',
|
||||
// 'hex',
|
||||
// ),
|
||||
// value: 90000,
|
||||
// },
|
||||
|
||||
// Not featured here:
|
||||
// redeemScript. A Buffer of the redeemScript for P2SH
|
||||
// witnessScript. A Buffer of the witnessScript for P2WSH
|
||||
});
|
||||
psbt.addOutput({
|
||||
address: '1KRMKfeZcmosxALVYESdPNez1AP1mEtywp',
|
||||
value: 80000,
|
||||
});
|
||||
psbt.signInput(0, alice);
|
||||
psbt.validateSignaturesOfInput(0);
|
||||
psbt.finalizeAllInputs();
|
||||
assert.strictEqual(
|
||||
psbt.extractTransaction().toHex(),
|
||||
'02000000013ebc8203037dda39d482bf41ff3be955996c50d9d4f7cfc3d2097a694a7' +
|
||||
'b067d000000006b483045022100931b6db94aed25d5486884d83fc37160f37f3368c0' +
|
||||
'd7f48c757112abefec983802205fda64cff98c849577026eb2ce916a50ea70626a766' +
|
||||
'9f8596dd89b720a26b4d501210365db9da3f8a260078a7e8f8b708a1161468fb2323f' +
|
||||
'fda5ec16b261ec1056f455ffffffff0180380100000000001976a914ca0d36044e0dc' +
|
||||
'08a22724efa6f6a07b0ec4c79aa88ac00000000',
|
||||
);
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a typical Transaction', async () => {
|
||||
// these are { payment: Payment; keys: ECPair[] }
|
||||
const alice1 = createPayment('p2pkh');
|
||||
const alice2 = createPayment('p2pkh');
|
||||
|
||||
// give Alice 2 unspent outputs
|
||||
const inputData1 = await getInputData(
|
||||
5e4,
|
||||
alice1.payment,
|
||||
false,
|
||||
'noredeem',
|
||||
);
|
||||
const inputData2 = await getInputData(
|
||||
7e4,
|
||||
alice2.payment,
|
||||
false,
|
||||
'noredeem',
|
||||
);
|
||||
{
|
||||
const {
|
||||
hash, // string of txid or Buffer of tx hash. (txid and hash are reverse order)
|
||||
index, // the output index of the txo you are spending
|
||||
nonWitnessUtxo, // the full previous transaction as a Buffer
|
||||
} = inputData1;
|
||||
assert.deepStrictEqual({ hash, index, nonWitnessUtxo }, inputData1);
|
||||
}
|
||||
|
||||
// network is only needed if you pass an address to addOutput
|
||||
// using script (Buffer of scriptPubkey) instead will avoid needed network.
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData1) // alice1 unspent
|
||||
.addInput(inputData2) // alice2 unspent
|
||||
.addOutput({
|
||||
address: 'mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf',
|
||||
value: 8e4,
|
||||
}) // the actual "spend"
|
||||
.addOutput({
|
||||
address: alice2.payment.address, // OR script, which is a Buffer.
|
||||
value: 1e4,
|
||||
}); // Alice's change
|
||||
// (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee
|
||||
|
||||
// Let's show a new feature with PSBT.
|
||||
// We can have multiple signers sign in parrallel and combine them.
|
||||
// (this is not necessary, but a nice feature)
|
||||
|
||||
// encode to send out to the signers
|
||||
const psbtBaseText = psbt.toBase64();
|
||||
|
||||
// each signer imports
|
||||
const signer1 = bitcoin.Psbt.fromBase64(psbtBaseText);
|
||||
const signer2 = bitcoin.Psbt.fromBase64(psbtBaseText);
|
||||
|
||||
// Alice signs each input with the respective private keys
|
||||
// signInput and signInputAsync are better
|
||||
// (They take the input index explicitly as the first arg)
|
||||
signer1.signAllInputs(alice1.keys[0]);
|
||||
signer2.signAllInputs(alice2.keys[0]);
|
||||
|
||||
// If your signer object's sign method returns a promise, use the following
|
||||
// await signer2.signAsync(alice2.keys[0])
|
||||
|
||||
// encode to send back to combiner (signer 1 and 2 are not near each other)
|
||||
const s1text = signer1.toBase64();
|
||||
const s2text = signer2.toBase64();
|
||||
|
||||
const final1 = bitcoin.Psbt.fromBase64(s1text);
|
||||
const final2 = bitcoin.Psbt.fromBase64(s2text);
|
||||
|
||||
// final1.combine(final2) would give the exact same result
|
||||
psbt.combine(final1, final2);
|
||||
|
||||
// Finalizer wants to check all signatures are valid before finalizing.
|
||||
// If the finalizer wants to check for specific pubkeys, the second arg
|
||||
// can be passed. See the first multisig example below.
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(1), true);
|
||||
|
||||
// This step it new. Since we separate the signing operation and
|
||||
// the creation of the scriptSig and witness stack, we are able to
|
||||
psbt.finalizeAllInputs();
|
||||
|
||||
// build and broadcast our RegTest network
|
||||
await regtestUtils.broadcast(psbt.extractTransaction().toHex());
|
||||
// to build and broadcast to the actual Bitcoin network, see https://github.com/bitcoinjs/bitcoinjs-lib/issues/839
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', async () => {
|
||||
const alice1 = createPayment('p2pkh');
|
||||
const inputData1 = await getInputData(
|
||||
2e5,
|
||||
alice1.payment,
|
||||
false,
|
||||
'noredeem',
|
||||
);
|
||||
|
||||
const data = Buffer.from('bitcoinjs-lib', 'utf8');
|
||||
const embed = bitcoin.payments.embed({ data: [data] });
|
||||
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData1)
|
||||
.addOutput({
|
||||
script: embed.output,
|
||||
value: 1000,
|
||||
})
|
||||
.addOutput({
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
value: 1e5,
|
||||
})
|
||||
.signInput(0, alice1.keys[0]);
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||
psbt.finalizeAllInputs();
|
||||
|
||||
// build and broadcast to the RegTest network
|
||||
await regtestUtils.broadcast(psbt.extractTransaction().toHex());
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2MS(2 of 4)) (multisig) input', async () => {
|
||||
const multisig = createPayment('p2sh-p2ms(2 of 4)');
|
||||
const inputData1 = await getInputData(2e4, multisig.payment, false, 'p2sh');
|
||||
{
|
||||
const {
|
||||
hash,
|
||||
index,
|
||||
nonWitnessUtxo,
|
||||
redeemScript, // NEW: P2SH needs to give redeemScript when adding an input.
|
||||
} = inputData1;
|
||||
assert.deepStrictEqual(
|
||||
{ hash, index, nonWitnessUtxo, redeemScript },
|
||||
inputData1,
|
||||
);
|
||||
}
|
||||
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData1)
|
||||
.addOutput({
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
value: 1e4,
|
||||
})
|
||||
.signInput(0, multisig.keys[0])
|
||||
.signInput(0, multisig.keys[2]);
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||
assert.strictEqual(
|
||||
psbt.validateSignaturesOfInput(0, multisig.keys[0].publicKey),
|
||||
true,
|
||||
);
|
||||
assert.throws(() => {
|
||||
psbt.validateSignaturesOfInput(0, multisig.keys[3].publicKey);
|
||||
}, new RegExp('No signatures for this pubkey'));
|
||||
psbt.finalizeAllInputs();
|
||||
|
||||
const tx = psbt.extractTransaction();
|
||||
|
||||
// build and broadcast to the Bitcoin RegTest network
|
||||
await regtestUtils.broadcast(tx.toHex());
|
||||
|
||||
await regtestUtils.verify({
|
||||
txId: tx.getId(),
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
vout: 0,
|
||||
value: 1e4,
|
||||
});
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input', async () => {
|
||||
const p2sh = createPayment('p2sh-p2wpkh');
|
||||
const inputData = await getInputData(5e4, p2sh.payment, true, 'p2sh');
|
||||
const inputData2 = await getInputData(5e4, p2sh.payment, true, 'p2sh');
|
||||
{
|
||||
const {
|
||||
hash,
|
||||
index,
|
||||
witnessUtxo, // NEW: this is an object of the output being spent { script: Buffer; value: Satoshis; }
|
||||
redeemScript,
|
||||
} = inputData;
|
||||
assert.deepStrictEqual(
|
||||
{ hash, index, witnessUtxo, redeemScript },
|
||||
inputData,
|
||||
);
|
||||
}
|
||||
const keyPair = p2sh.keys[0];
|
||||
const outputData = {
|
||||
script: p2sh.payment.output, // sending to myself for fun
|
||||
value: 2e4,
|
||||
};
|
||||
const outputData2 = {
|
||||
script: p2sh.payment.output, // sending to myself for fun
|
||||
value: 7e4,
|
||||
};
|
||||
|
||||
const tx = new bitcoin.Psbt()
|
||||
.addInputs([inputData, inputData2])
|
||||
.addOutputs([outputData, outputData2])
|
||||
.signAllInputs(keyPair)
|
||||
.finalizeAllInputs()
|
||||
.extractTransaction();
|
||||
|
||||
// build and broadcast to the Bitcoin RegTest network
|
||||
await regtestUtils.broadcast(tx.toHex());
|
||||
|
||||
await regtestUtils.verify({
|
||||
txId: tx.getId(),
|
||||
address: p2sh.payment.address,
|
||||
vout: 0,
|
||||
value: 2e4,
|
||||
});
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => {
|
||||
// the only thing that changes is you don't give a redeemscript for input data
|
||||
|
||||
const p2wpkh = createPayment('p2wpkh');
|
||||
const inputData = await getInputData(5e4, p2wpkh.payment, true, 'noredeem');
|
||||
{
|
||||
const { hash, index, witnessUtxo } = inputData;
|
||||
assert.deepStrictEqual({ hash, index, witnessUtxo }, inputData);
|
||||
}
|
||||
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData)
|
||||
.addOutput({
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
value: 2e4,
|
||||
})
|
||||
.signInput(0, p2wpkh.keys[0]);
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||
psbt.finalizeAllInputs();
|
||||
|
||||
const tx = psbt.extractTransaction();
|
||||
|
||||
// build and broadcast to the Bitcoin RegTest network
|
||||
await regtestUtils.broadcast(tx.toHex());
|
||||
|
||||
await regtestUtils.verify({
|
||||
txId: tx.getId(),
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
vout: 0,
|
||||
value: 2e4,
|
||||
});
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', async () => {
|
||||
const p2wsh = createPayment('p2wsh-p2pk');
|
||||
const inputData = await getInputData(5e4, p2wsh.payment, true, 'p2wsh');
|
||||
{
|
||||
const {
|
||||
hash,
|
||||
index,
|
||||
witnessUtxo,
|
||||
witnessScript, // NEW: A Buffer of the witnessScript
|
||||
} = inputData;
|
||||
assert.deepStrictEqual(
|
||||
{ hash, index, witnessUtxo, witnessScript },
|
||||
inputData,
|
||||
);
|
||||
}
|
||||
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData)
|
||||
.addOutput({
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
value: 2e4,
|
||||
})
|
||||
.signInput(0, p2wsh.keys[0]);
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||
psbt.finalizeAllInputs();
|
||||
|
||||
const tx = psbt.extractTransaction();
|
||||
|
||||
// build and broadcast to the Bitcoin RegTest network
|
||||
await regtestUtils.broadcast(tx.toHex());
|
||||
|
||||
await regtestUtils.verify({
|
||||
txId: tx.getId(),
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
vout: 0,
|
||||
value: 2e4,
|
||||
});
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input', async () => {
|
||||
const p2sh = createPayment('p2sh-p2wsh-p2ms(3 of 4)');
|
||||
const inputData = await getInputData(5e4, p2sh.payment, true, 'p2sh-p2wsh');
|
||||
{
|
||||
const {
|
||||
hash,
|
||||
index,
|
||||
witnessUtxo,
|
||||
redeemScript,
|
||||
witnessScript,
|
||||
} = inputData;
|
||||
assert.deepStrictEqual(
|
||||
{ hash, index, witnessUtxo, redeemScript, witnessScript },
|
||||
inputData,
|
||||
);
|
||||
}
|
||||
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData)
|
||||
.addOutput({
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
value: 2e4,
|
||||
})
|
||||
.signInput(0, p2sh.keys[0])
|
||||
.signInput(0, p2sh.keys[2])
|
||||
.signInput(0, p2sh.keys[3]);
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||
assert.strictEqual(
|
||||
psbt.validateSignaturesOfInput(0, p2sh.keys[3].publicKey),
|
||||
true,
|
||||
);
|
||||
assert.throws(() => {
|
||||
psbt.validateSignaturesOfInput(0, p2sh.keys[1].publicKey);
|
||||
}, new RegExp('No signatures for this pubkey'));
|
||||
psbt.finalizeAllInputs();
|
||||
|
||||
const tx = psbt.extractTransaction();
|
||||
|
||||
// build and broadcast to the Bitcoin RegTest network
|
||||
await regtestUtils.broadcast(tx.toHex());
|
||||
|
||||
await regtestUtils.verify({
|
||||
txId: tx.getId(),
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
vout: 0,
|
||||
value: 2e4,
|
||||
});
|
||||
});
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input using HD', async () => {
|
||||
const hdRoot = bip32.fromSeed(rng(64));
|
||||
const masterFingerprint = hdRoot.fingerprint;
|
||||
const path = "m/84'/0'/0'/0/0";
|
||||
const childNode = hdRoot.derivePath(path);
|
||||
const pubkey = childNode.publicKey;
|
||||
|
||||
// This information should be added to your input via updateInput
|
||||
// You can add multiple bip32Derivation objects for multisig, but
|
||||
// each must have a unique pubkey.
|
||||
//
|
||||
// This is useful because as long as you store the masterFingerprint on
|
||||
// the PSBT Creator's server, you can have the PSBT Creator do the heavy
|
||||
// lifting with derivation from your m/84'/0'/0' xpub, (deriving only 0/0 )
|
||||
// and your signer just needs to pass in an HDSigner interface (ie. bip32 library)
|
||||
const updateData = {
|
||||
bip32Derivation: [
|
||||
{
|
||||
masterFingerprint,
|
||||
path,
|
||||
pubkey,
|
||||
}
|
||||
]
|
||||
}
|
||||
const p2wpkh = createPayment('p2wpkh', [childNode]);
|
||||
const inputData = await getInputData(5e4, p2wpkh.payment, true, 'noredeem');
|
||||
{
|
||||
const { hash, index, witnessUtxo } = inputData;
|
||||
assert.deepStrictEqual({ hash, index, witnessUtxo }, inputData);
|
||||
}
|
||||
|
||||
// You can add extra attributes for updateData into the addInput(s) object(s)
|
||||
Object.assign(inputData, updateData)
|
||||
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData)
|
||||
// .updateInput(0, updateData) // if you didn't merge the bip32Derivation with inputData
|
||||
.addOutput({
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
value: 2e4,
|
||||
})
|
||||
.signInputHD(0, hdRoot); // must sign with root!!!
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(0, childNode.publicKey), true);
|
||||
psbt.finalizeAllInputs();
|
||||
|
||||
const tx = psbt.extractTransaction();
|
||||
|
||||
// build and broadcast to the Bitcoin RegTest network
|
||||
await regtestUtils.broadcast(tx.toHex());
|
||||
|
||||
await regtestUtils.verify({
|
||||
txId: tx.getId(),
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
vout: 0,
|
||||
value: 2e4,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createPayment(_type, myKeys, network) {
|
||||
network = network || regtest;
|
||||
const splitType = _type.split('-').reverse();
|
||||
const isMultisig = splitType[0].slice(0, 4) === 'p2ms';
|
||||
const keys = myKeys || [];
|
||||
let m;
|
||||
if (isMultisig) {
|
||||
const match = splitType[0].match(/^p2ms\((\d+) of (\d+)\)$/);
|
||||
m = parseInt(match[1]);
|
||||
let n = parseInt(match[2]);
|
||||
if (keys.length > 0 && keys.length !== n) {
|
||||
throw new Error('Need n keys for multisig')
|
||||
}
|
||||
while (!myKeys && n > 1) {
|
||||
keys.push(bitcoin.ECPair.makeRandom({ network }));
|
||||
n--;
|
||||
}
|
||||
}
|
||||
if (!myKeys) keys.push(bitcoin.ECPair.makeRandom({ network }));
|
||||
|
||||
let payment;
|
||||
splitType.forEach(type => {
|
||||
if (type.slice(0, 4) === 'p2ms') {
|
||||
payment = bitcoin.payments.p2ms({
|
||||
m,
|
||||
pubkeys: keys.map(key => key.publicKey).sort(),
|
||||
network,
|
||||
});
|
||||
} else if (['p2sh', 'p2wsh'].indexOf(type) > -1) {
|
||||
payment = bitcoin.payments[type]({
|
||||
redeem: payment,
|
||||
network,
|
||||
});
|
||||
} else {
|
||||
payment = bitcoin.payments[type]({
|
||||
pubkey: keys[0].publicKey,
|
||||
network,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
payment,
|
||||
keys,
|
||||
};
|
||||
}
|
||||
|
||||
function getWitnessUtxo(out) {
|
||||
delete out.address;
|
||||
out.script = Buffer.from(out.script, 'hex');
|
||||
return out;
|
||||
}
|
||||
|
||||
async function getInputData(amount, payment, isSegwit, redeemType) {
|
||||
const unspent = await regtestUtils.faucetComplex(payment.output, amount);
|
||||
const utx = await regtestUtils.fetch(unspent.txId);
|
||||
// for non segwit inputs, you must pass the full transaction buffer
|
||||
const nonWitnessUtxo = Buffer.from(utx.txHex, 'hex');
|
||||
// for segwit inputs, you only need the output script and value as an object.
|
||||
const witnessUtxo = getWitnessUtxo(utx.outs[unspent.vout]);
|
||||
const mixin = isSegwit ? { witnessUtxo } : { nonWitnessUtxo };
|
||||
const mixin2 = {};
|
||||
switch (redeemType) {
|
||||
case 'p2sh':
|
||||
mixin2.redeemScript = payment.redeem.output;
|
||||
break;
|
||||
case 'p2wsh':
|
||||
mixin2.witnessScript = payment.redeem.output;
|
||||
break;
|
||||
case 'p2sh-p2wsh':
|
||||
mixin2.witnessScript = payment.redeem.redeem.output;
|
||||
mixin2.redeemScript = payment.redeem.output;
|
||||
break;
|
||||
}
|
||||
return {
|
||||
hash: unspent.txId,
|
||||
index: unspent.vout,
|
||||
...mixin,
|
||||
...mixin2,
|
||||
};
|
||||
}
|
|
@ -3,6 +3,7 @@ const assert = require('assert')
|
|||
const bitcoin = require('../../')
|
||||
const regtestUtils = require('./_regtest')
|
||||
const regtest = regtestUtils.network
|
||||
console.warn = () => {} // Silence the Deprecation Warning
|
||||
|
||||
function rng () {
|
||||
return Buffer.from('YT8dAtK4d16A3P1z+TpwB2jJ4aFH3g9M1EioIBkLEV4=', 'base64')
|
||||
|
|
680
test/psbt.js
Normal file
680
test/psbt.js
Normal file
|
@ -0,0 +1,680 @@
|
|||
const { describe, it } = require('mocha')
|
||||
const assert = require('assert')
|
||||
|
||||
const bip32 = require('bip32')
|
||||
const ECPair = require('../src/ecpair')
|
||||
const Psbt = require('..').Psbt
|
||||
const NETWORKS = require('../src/networks')
|
||||
|
||||
const initBuffers = object => JSON.parse(JSON.stringify(object), (key, value) => {
|
||||
const regex = new RegExp(/^Buffer.from\(['"](.*)['"], ['"](.*)['"]\)$/)
|
||||
const result = regex.exec(value)
|
||||
if (!result) return value
|
||||
|
||||
const data = result[1]
|
||||
const encoding = result[2]
|
||||
|
||||
return Buffer.from(data, encoding)
|
||||
})
|
||||
|
||||
const fixtures = initBuffers(require('./fixtures/psbt'))
|
||||
|
||||
const upperCaseFirstLetter = str => str.replace(/^./, s => s.toUpperCase())
|
||||
|
||||
const b = hex => Buffer.from(hex, 'hex');
|
||||
|
||||
describe(`Psbt`, () => {
|
||||
describe('BIP174 Test Vectors', () => {
|
||||
fixtures.bip174.invalid.forEach(f => {
|
||||
it(`Invalid: ${f.description}`, () => {
|
||||
assert.throws(() => {
|
||||
Psbt.fromBase64(f.psbt)
|
||||
}, new RegExp(f.errorMessage))
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.valid.forEach(f => {
|
||||
it(`Valid: ${f.description}`, () => {
|
||||
assert.doesNotThrow(() => {
|
||||
Psbt.fromBase64(f.psbt)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.failSignChecks.forEach(f => {
|
||||
const keyPair = ECPair.makeRandom()
|
||||
it(`Fails Signer checks: ${f.description}`, () => {
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
assert.throws(() => {
|
||||
psbt.signInput(f.inputToCheck, keyPair)
|
||||
}, new RegExp(f.errorMessage))
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.creator.forEach(f => {
|
||||
it('Creates expected PSBT', () => {
|
||||
const psbt = new Psbt()
|
||||
for (const input of f.inputs) {
|
||||
psbt.addInput(input)
|
||||
}
|
||||
for (const output of f.outputs) {
|
||||
const script = Buffer.from(output.script, 'hex');
|
||||
psbt.addOutput({...output, script})
|
||||
}
|
||||
assert.strictEqual(psbt.toBase64(), f.result)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.updater.forEach(f => {
|
||||
it('Updates PSBT to the expected result', () => {
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
|
||||
for (const inputOrOutput of ['input', 'output']) {
|
||||
const fixtureData = f[`${inputOrOutput}Data`]
|
||||
if (fixtureData) {
|
||||
for (const [i, data] of fixtureData.entries()) {
|
||||
const txt = upperCaseFirstLetter(inputOrOutput)
|
||||
psbt[`update${txt}`](i, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert.strictEqual(psbt.toBase64(), f.result)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.signer.forEach(f => {
|
||||
it('Signs PSBT to the expected result', () => {
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
|
||||
f.keys.forEach(({inputToSign, WIF}) => {
|
||||
const keyPair = ECPair.fromWIF(WIF, NETWORKS.testnet);
|
||||
psbt.signInput(inputToSign, keyPair);
|
||||
})
|
||||
|
||||
assert.strictEqual(psbt.toBase64(), f.result)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.combiner.forEach(f => {
|
||||
it('Combines two PSBTs to the expected result', () => {
|
||||
const psbts = f.psbts.map(psbt => Psbt.fromBase64(psbt))
|
||||
|
||||
psbts[0].combine(psbts[1])
|
||||
|
||||
// Produces a different Base64 string due to implemetation specific key-value ordering.
|
||||
// That means this test will fail:
|
||||
// assert.strictEqual(psbts[0].toBase64(), f.result)
|
||||
// However, if we compare the actual PSBT properties we can see they are logically identical:
|
||||
assert.deepStrictEqual(psbts[0], Psbt.fromBase64(f.result))
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.finalizer.forEach(f => {
|
||||
it("Finalizes inputs and gives the expected PSBT", () => {
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
|
||||
psbt.finalizeAllInputs()
|
||||
|
||||
assert.strictEqual(psbt.toBase64(), f.result)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.bip174.extractor.forEach(f => {
|
||||
it('Extracts the expected transaction from a PSBT', () => {
|
||||
const psbt1 = Psbt.fromBase64(f.psbt)
|
||||
const transaction1 = psbt1.extractTransaction(true).toHex()
|
||||
|
||||
const psbt2 = Psbt.fromBase64(f.psbt)
|
||||
const transaction2 = psbt2.extractTransaction().toHex()
|
||||
|
||||
assert.strictEqual(transaction1, transaction2)
|
||||
assert.strictEqual(transaction1, f.transaction)
|
||||
|
||||
const psbt3 = Psbt.fromBase64(f.psbt)
|
||||
delete psbt3.data.inputs[0].finalScriptSig
|
||||
delete psbt3.data.inputs[0].finalScriptWitness
|
||||
assert.throws(() => {
|
||||
psbt3.extractTransaction()
|
||||
}, new RegExp('Not finalized'))
|
||||
|
||||
const psbt4 = Psbt.fromBase64(f.psbt)
|
||||
psbt4.setMaximumFeeRate(1)
|
||||
assert.throws(() => {
|
||||
psbt4.extractTransaction()
|
||||
}, new RegExp('Warning: You are paying around [\\d.]+ in fees'))
|
||||
|
||||
const psbt5 = Psbt.fromBase64(f.psbt)
|
||||
psbt5.extractTransaction(true)
|
||||
const fr1 = psbt5.getFeeRate()
|
||||
const fr2 = psbt5.getFeeRate()
|
||||
assert.strictEqual(fr1, fr2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signInputAsync', () => {
|
||||
fixtures.signInput.checks.forEach(f => {
|
||||
it(f.description, async () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotReject(async () => {
|
||||
await psbtThatShouldsign.signInputAsync(
|
||||
f.shouldSign.inputToCheck,
|
||||
ECPair.fromWIF(f.shouldSign.WIF),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signInputAsync(
|
||||
f.shouldThrow.inputToCheck,
|
||||
ECPair.fromWIF(f.shouldThrow.WIF),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp(f.shouldThrow.errorMessage))
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signInputAsync(
|
||||
f.shouldThrow.inputToCheck,
|
||||
)
|
||||
}, new RegExp('Need Signer to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signInput', () => {
|
||||
fixtures.signInput.checks.forEach(f => {
|
||||
it(f.description, () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotThrow(() => {
|
||||
psbtThatShouldsign.signInput(
|
||||
f.shouldSign.inputToCheck,
|
||||
ECPair.fromWIF(f.shouldSign.WIF),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signInput(
|
||||
f.shouldThrow.inputToCheck,
|
||||
ECPair.fromWIF(f.shouldThrow.WIF),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp(f.shouldThrow.errorMessage))
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signInput(
|
||||
f.shouldThrow.inputToCheck,
|
||||
)
|
||||
}, new RegExp('Need Signer to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signAsync', () => {
|
||||
fixtures.signInput.checks.forEach(f => {
|
||||
if (f.description === 'checks the input exists') return
|
||||
it(f.description, async () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotReject(async () => {
|
||||
await psbtThatShouldsign.signAsync(
|
||||
ECPair.fromWIF(f.shouldSign.WIF),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signAsync(
|
||||
ECPair.fromWIF(f.shouldThrow.WIF),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp('No inputs were signed'))
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signAsync()
|
||||
}, new RegExp('Need Signer to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signAllInputs', () => {
|
||||
fixtures.signInput.checks.forEach(f => {
|
||||
if (f.description === 'checks the input exists') return
|
||||
it(f.description, () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotThrow(() => {
|
||||
psbtThatShouldsign.signAllInputs(
|
||||
ECPair.fromWIF(f.shouldSign.WIF),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signAllInputs(
|
||||
ECPair.fromWIF(f.shouldThrow.WIF),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp('No inputs were signed'))
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signAllInputs()
|
||||
}, new RegExp('Need Signer to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signInputHDAsync', () => {
|
||||
fixtures.signInputHD.checks.forEach(f => {
|
||||
it(f.description, async () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotReject(async () => {
|
||||
await psbtThatShouldsign.signInputHDAsync(
|
||||
f.shouldSign.inputToCheck,
|
||||
bip32.fromBase58(f.shouldSign.xprv),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signInputHDAsync(
|
||||
f.shouldThrow.inputToCheck,
|
||||
bip32.fromBase58(f.shouldThrow.xprv),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp(f.shouldThrow.errorMessage))
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signInputHDAsync(
|
||||
f.shouldThrow.inputToCheck,
|
||||
)
|
||||
}, new RegExp('Need HDSigner to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signInputHD', () => {
|
||||
fixtures.signInputHD.checks.forEach(f => {
|
||||
it(f.description, () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotThrow(() => {
|
||||
psbtThatShouldsign.signInputHD(
|
||||
f.shouldSign.inputToCheck,
|
||||
bip32.fromBase58(f.shouldSign.xprv),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signInputHD(
|
||||
f.shouldThrow.inputToCheck,
|
||||
bip32.fromBase58(f.shouldThrow.xprv),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp(f.shouldThrow.errorMessage))
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signInputHD(
|
||||
f.shouldThrow.inputToCheck,
|
||||
)
|
||||
}, new RegExp('Need HDSigner to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signHDAsync', () => {
|
||||
fixtures.signInputHD.checks.forEach(f => {
|
||||
it(f.description, async () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotReject(async () => {
|
||||
await psbtThatShouldsign.signHDAsync(
|
||||
bip32.fromBase58(f.shouldSign.xprv),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signHDAsync(
|
||||
bip32.fromBase58(f.shouldThrow.xprv),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp('No inputs were signed'))
|
||||
assert.rejects(async () => {
|
||||
await psbtThatShouldThrow.signHDAsync()
|
||||
}, new RegExp('Need HDSigner to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('signAllInputsHD', () => {
|
||||
fixtures.signInputHD.checks.forEach(f => {
|
||||
it(f.description, () => {
|
||||
if (f.shouldSign) {
|
||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||
assert.doesNotThrow(() => {
|
||||
psbtThatShouldsign.signAllInputsHD(
|
||||
bip32.fromBase58(f.shouldSign.xprv),
|
||||
f.shouldSign.sighashTypes || undefined,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (f.shouldThrow) {
|
||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signAllInputsHD(
|
||||
bip32.fromBase58(f.shouldThrow.xprv),
|
||||
f.shouldThrow.sighashTypes || undefined,
|
||||
)
|
||||
}, new RegExp('No inputs were signed'))
|
||||
assert.throws(() => {
|
||||
psbtThatShouldThrow.signAllInputsHD()
|
||||
}, new RegExp('Need HDSigner to sign input'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('finalizeAllInputs', () => {
|
||||
fixtures.finalizeAllInputs.forEach(f => {
|
||||
it(`Finalizes inputs of type "${f.type}"`, () => {
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
|
||||
psbt.finalizeAllInputs()
|
||||
|
||||
assert.strictEqual(psbt.toBase64(), f.result)
|
||||
})
|
||||
})
|
||||
it('fails if no script found', () => {
|
||||
const psbt = new Psbt()
|
||||
psbt.addInput({
|
||||
hash: '0000000000000000000000000000000000000000000000000000000000000000',
|
||||
index: 0
|
||||
})
|
||||
assert.throws(() => {
|
||||
psbt.finalizeAllInputs()
|
||||
}, new RegExp('No script found for input #0'))
|
||||
psbt.updateInput(0, {
|
||||
witnessUtxo: {
|
||||
script: Buffer.from('0014d85c2b71d0060b09c9886aeb815e50991dda124d', 'hex'),
|
||||
value: 2e5
|
||||
}
|
||||
})
|
||||
assert.throws(() => {
|
||||
psbt.finalizeAllInputs()
|
||||
}, new RegExp('Can not finalize input #0'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('addInput', () => {
|
||||
fixtures.addInput.checks.forEach(f => {
|
||||
it(f.description, () => {
|
||||
const psbt = new Psbt()
|
||||
|
||||
if (f.exception) {
|
||||
assert.throws(() => {
|
||||
psbt.addInput(f.inputData)
|
||||
}, new RegExp(f.exception))
|
||||
assert.throws(() => {
|
||||
psbt.addInputs([f.inputData])
|
||||
}, new RegExp(f.exception))
|
||||
} else {
|
||||
assert.doesNotThrow(() => {
|
||||
psbt.addInputs([f.inputData])
|
||||
if (f.equals) {
|
||||
assert.strictEqual(psbt.toBase64(), f.equals)
|
||||
}
|
||||
})
|
||||
assert.throws(() => {
|
||||
psbt.addInput(f.inputData)
|
||||
}, new RegExp('Duplicate input detected.'))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('addOutput', () => {
|
||||
fixtures.addOutput.checks.forEach(f => {
|
||||
it(f.description, () => {
|
||||
const psbt = new Psbt()
|
||||
|
||||
if (f.exception) {
|
||||
assert.throws(() => {
|
||||
psbt.addOutput(f.outputData)
|
||||
}, new RegExp(f.exception))
|
||||
assert.throws(() => {
|
||||
psbt.addOutputs([f.outputData])
|
||||
}, new RegExp(f.exception))
|
||||
} else {
|
||||
assert.doesNotThrow(() => {
|
||||
psbt.addOutput(f.outputData)
|
||||
})
|
||||
assert.doesNotThrow(() => {
|
||||
psbt.addOutputs([f.outputData])
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('setVersion', () => {
|
||||
it('Sets the version value of the unsigned transaction', () => {
|
||||
const psbt = new Psbt()
|
||||
|
||||
assert.strictEqual(psbt.extractTransaction().version, 2)
|
||||
psbt.setVersion(1)
|
||||
assert.strictEqual(psbt.extractTransaction().version, 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('setLocktime', () => {
|
||||
it('Sets the nLockTime value of the unsigned transaction', () => {
|
||||
const psbt = new Psbt()
|
||||
|
||||
assert.strictEqual(psbt.extractTransaction().locktime, 0)
|
||||
psbt.setLocktime(1)
|
||||
assert.strictEqual(psbt.extractTransaction().locktime, 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('setInputSequence', () => {
|
||||
it('Sets the sequence number for a given input', () => {
|
||||
const psbt = new Psbt()
|
||||
psbt.addInput({
|
||||
hash: '0000000000000000000000000000000000000000000000000000000000000000',
|
||||
index: 0
|
||||
});
|
||||
|
||||
assert.strictEqual(psbt.inputCount, 1)
|
||||
assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0xffffffff)
|
||||
psbt.setInputSequence(0, 0)
|
||||
assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0)
|
||||
})
|
||||
|
||||
it('throws if input index is too high', () => {
|
||||
const psbt = new Psbt()
|
||||
psbt.addInput({
|
||||
hash: '0000000000000000000000000000000000000000000000000000000000000000',
|
||||
index: 0
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
psbt.setInputSequence(1, 0)
|
||||
}, new RegExp('Input index too high'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('clone', () => {
|
||||
it('Should clone a psbt exactly with no reference', () => {
|
||||
const f = fixtures.clone
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
const notAClone = Object.assign(new Psbt(), psbt) // references still active
|
||||
const clone = psbt.clone()
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfAllInputs(), true)
|
||||
|
||||
assert.strictEqual(clone.toBase64(), psbt.toBase64())
|
||||
assert.strictEqual(clone.toBase64(), notAClone.toBase64())
|
||||
assert.strictEqual(psbt.toBase64(), notAClone.toBase64())
|
||||
psbt.__CACHE.__TX.version |= 0xff0000
|
||||
assert.notStrictEqual(clone.toBase64(), psbt.toBase64())
|
||||
assert.notStrictEqual(clone.toBase64(), notAClone.toBase64())
|
||||
assert.strictEqual(psbt.toBase64(), notAClone.toBase64())
|
||||
})
|
||||
})
|
||||
|
||||
describe('setMaximumFeeRate', () => {
|
||||
it('Sets the maximumFeeRate value', () => {
|
||||
const psbt = new Psbt()
|
||||
|
||||
assert.strictEqual(psbt.opts.maximumFeeRate, 5000)
|
||||
psbt.setMaximumFeeRate(6000)
|
||||
assert.strictEqual(psbt.opts.maximumFeeRate, 6000)
|
||||
})
|
||||
})
|
||||
|
||||
describe('validateSignaturesOfInput', () => {
|
||||
const f = fixtures.validateSignaturesOfInput
|
||||
it('Correctly validates a signature', () => {
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(f.index), true)
|
||||
assert.throws(() => {
|
||||
psbt.validateSignaturesOfInput(f.nonExistantIndex)
|
||||
}, new RegExp('No signatures to validate'))
|
||||
})
|
||||
|
||||
it('Correctly validates a signature against a pubkey', () => {
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
assert.strictEqual(psbt.validateSignaturesOfInput(f.index, f.pubkey), true)
|
||||
assert.throws(() => {
|
||||
psbt.validateSignaturesOfInput(f.index, f.incorrectPubkey)
|
||||
}, new RegExp('No signatures for this pubkey'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('getFeeRate', () => {
|
||||
it('Throws error if called before inputs are finalized', () => {
|
||||
const f = fixtures.getFeeRate
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
|
||||
assert.throws(() => {
|
||||
psbt.getFeeRate()
|
||||
}, new RegExp('PSBT must be finalized to calculate fee rate'))
|
||||
|
||||
psbt.finalizeAllInputs()
|
||||
|
||||
assert.strictEqual(psbt.getFeeRate(), f.fee)
|
||||
psbt.__CACHE.__FEE_RATE = undefined
|
||||
assert.strictEqual(psbt.getFeeRate(), f.fee)
|
||||
})
|
||||
})
|
||||
|
||||
describe('create 1-to-1 transaction', () => {
|
||||
const alice = ECPair.fromWIF('L2uPYXe17xSTqbCjZvL2DsyXPCbXspvcu5mHLDYUgzdUbZGSKrSr')
|
||||
const psbt = new Psbt()
|
||||
psbt.addInput({
|
||||
hash: '7d067b4a697a09d2c3cff7d4d9506c9955e93bff41bf82d439da7d030382bc3e',
|
||||
index: 0,
|
||||
nonWitnessUtxo: Buffer.from(
|
||||
'0200000001f9f34e95b9d5c8abcd20fc5bd4a825d1517be62f0f775e5f36da944d9' +
|
||||
'452e550000000006b483045022100c86e9a111afc90f64b4904bd609e9eaed80d48' +
|
||||
'ca17c162b1aca0a788ac3526f002207bb79b60d4fc6526329bf18a77135dc566020' +
|
||||
'9e761da46e1c2f1152ec013215801210211755115eabf846720f5cb18f248666fec' +
|
||||
'631e5e1e66009ce3710ceea5b1ad13ffffffff01905f0100000000001976a9148bb' +
|
||||
'c95d2709c71607c60ee3f097c1217482f518d88ac00000000',
|
||||
'hex',
|
||||
),
|
||||
sighashType: 1,
|
||||
})
|
||||
psbt.addOutput({
|
||||
address: '1KRMKfeZcmosxALVYESdPNez1AP1mEtywp',
|
||||
value: 80000
|
||||
})
|
||||
psbt.signInput(0, alice)
|
||||
assert.throws(() => {
|
||||
psbt.setVersion(3)
|
||||
}, new RegExp('Can not modify transaction, signatures exist.'))
|
||||
psbt.validateSignaturesOfInput(0)
|
||||
psbt.finalizeAllInputs()
|
||||
assert.strictEqual(
|
||||
psbt.extractTransaction().toHex(),
|
||||
'02000000013ebc8203037dda39d482bf41ff3be955996c50d9d4f7cfc3d2097a694a7' +
|
||||
'b067d000000006b483045022100931b6db94aed25d5486884d83fc37160f37f3368c0' +
|
||||
'd7f48c757112abefec983802205fda64cff98c849577026eb2ce916a50ea70626a766' +
|
||||
'9f8596dd89b720a26b4d501210365db9da3f8a260078a7e8f8b708a1161468fb2323f' +
|
||||
'fda5ec16b261ec1056f455ffffffff0180380100000000001976a914ca0d36044e0dc' +
|
||||
'08a22724efa6f6a07b0ec4c79aa88ac00000000',
|
||||
)
|
||||
})
|
||||
|
||||
describe('Method return types', () => {
|
||||
it('fromBuffer returns Psbt type (not base class)', () => {
|
||||
const psbt = Psbt.fromBuffer(Buffer.from(
|
||||
'70736274ff01000a01000000000000000000000000', 'hex' //cHNidP8BAAoBAAAAAAAAAAAAAAAA
|
||||
));
|
||||
assert.strictEqual(psbt instanceof Psbt, true);
|
||||
assert.ok(psbt.__CACHE.__TX);
|
||||
})
|
||||
it('fromBase64 returns Psbt type (not base class)', () => {
|
||||
const psbt = Psbt.fromBase64('cHNidP8BAAoBAAAAAAAAAAAAAAAA');
|
||||
assert.strictEqual(psbt instanceof Psbt, true);
|
||||
assert.ok(psbt.__CACHE.__TX);
|
||||
})
|
||||
it('fromHex returns Psbt type (not base class)', () => {
|
||||
const psbt = Psbt.fromHex('70736274ff01000a01000000000000000000000000');
|
||||
assert.strictEqual(psbt instanceof Psbt, true);
|
||||
assert.ok(psbt.__CACHE.__TX);
|
||||
})
|
||||
})
|
||||
|
||||
describe('Cache', () => {
|
||||
it('non-witness UTXOs are cached', () => {
|
||||
const f = fixtures.cache.nonWitnessUtxo;
|
||||
const psbt = Psbt.fromBase64(f.psbt)
|
||||
const index = f.inputIndex;
|
||||
|
||||
// Cache is empty
|
||||
assert.strictEqual(psbt.__CACHE.__NON_WITNESS_UTXO_BUF_CACHE[index], undefined)
|
||||
|
||||
// Cache is populated
|
||||
psbt.updateInput(index, { nonWitnessUtxo: f.nonWitnessUtxo })
|
||||
const value = psbt.data.inputs[index].nonWitnessUtxo
|
||||
assert.ok(psbt.__CACHE.__NON_WITNESS_UTXO_BUF_CACHE[index].equals(value))
|
||||
assert.ok(psbt.__CACHE.__NON_WITNESS_UTXO_BUF_CACHE[index].equals(f.nonWitnessUtxo))
|
||||
|
||||
// Cache is rebuilt from internal transaction object when cleared
|
||||
psbt.data.inputs[index].nonWitnessUtxo = Buffer.from([1,2,3])
|
||||
psbt.__CACHE.__NON_WITNESS_UTXO_BUF_CACHE[index] = undefined
|
||||
assert.ok(psbt.data.inputs[index].nonWitnessUtxo.equals(value))
|
||||
})
|
||||
})
|
||||
})
|
|
@ -9,6 +9,8 @@ const Transaction = require('..').Transaction
|
|||
const TransactionBuilder = require('..').TransactionBuilder
|
||||
const NETWORKS = require('../src/networks')
|
||||
|
||||
console.warn = () => {} // Silence the Deprecation Warning
|
||||
|
||||
const fixtures = require('./fixtures/transaction_builder')
|
||||
|
||||
function constructSign (f, txb, useOldSignArgs) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import * as script from './script';
|
|||
export { ECPair, address, bip32, crypto, networks, payments, script };
|
||||
|
||||
export { Block } from './block';
|
||||
export { Psbt } from './psbt';
|
||||
export { OPS as opcodes } from './script';
|
||||
export { Transaction } from './transaction';
|
||||
export { TransactionBuilder } from './transaction_builder';
|
||||
|
|
1393
ts_src/psbt.ts
Normal file
1393
ts_src/psbt.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -146,6 +146,13 @@ export class TransactionBuilder {
|
|||
this.__TX = new Transaction();
|
||||
this.__TX.version = 2;
|
||||
this.__USE_LOW_R = false;
|
||||
console.warn(
|
||||
'Deprecation Warning: TransactionBuilder will be removed in the future. ' +
|
||||
'(v6.x.x or later) Please use the Psbt class instead. Examples of usage ' +
|
||||
'are available in the transactions-psbt.js integration test file on our ' +
|
||||
'Github. A high level explanation is available in the psbt.ts and psbt.js ' +
|
||||
'files as well.',
|
||||
);
|
||||
}
|
||||
|
||||
setLowR(setting?: boolean): boolean {
|
||||
|
|
1
types/index.d.ts
vendored
1
types/index.d.ts
vendored
|
@ -7,6 +7,7 @@ import * as payments from './payments';
|
|||
import * as script from './script';
|
||||
export { ECPair, address, bip32, crypto, networks, payments, script };
|
||||
export { Block } from './block';
|
||||
export { Psbt } from './psbt';
|
||||
export { OPS as opcodes } from './script';
|
||||
export { Transaction } from './transaction';
|
||||
export { TransactionBuilder } from './transaction_builder';
|
||||
|
|
116
types/psbt.d.ts
vendored
Normal file
116
types/psbt.d.ts
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
/// <reference types="node" />
|
||||
import { Psbt as PsbtBase } from 'bip174';
|
||||
import { KeyValue, PsbtGlobalUpdate, PsbtInputUpdate, PsbtOutputUpdate, TransactionInput, TransactionOutput } from 'bip174/src/lib/interfaces';
|
||||
import { Signer, SignerAsync } from './ecpair';
|
||||
import { Network } from './networks';
|
||||
import { Transaction } from './transaction';
|
||||
/**
|
||||
* Psbt class can parse and generate a PSBT binary based off of the BIP174.
|
||||
* There are 6 roles that this class fulfills. (Explained in BIP174)
|
||||
*
|
||||
* Creator: This can be done with `new Psbt()`
|
||||
* Updater: This can be done with `psbt.addInput(input)`, `psbt.addInputs(inputs)`,
|
||||
* `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to
|
||||
* add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`,
|
||||
* `psbt.updateInput(itemObject)`, `psbt.updateOutput(itemObject)`
|
||||
* addInput requires hash: Buffer | string; and index: number; as attributes
|
||||
* and can also include any attributes that are used in updateInput method.
|
||||
* addOutput requires script: Buffer; and value: number; and likewise can include
|
||||
* data for updateOutput.
|
||||
* For a list of what attributes should be what types. Check the bip174 library.
|
||||
* Also, check the integration tests for some examples of usage.
|
||||
* Signer: There are a few methods. signAllInputs and signAsync, which will search all input
|
||||
* information for your pubkey or pubkeyhash, and only sign inputs where it finds
|
||||
* your info. Or you can explicitly sign a specific input with signInput and
|
||||
* signInputAsync. For the async methods you can create a SignerAsync object
|
||||
* and use something like a hardware wallet to sign with. (You must implement this)
|
||||
* Combiner: psbts can be combined easily with `psbt.combine(psbt2, psbt3, psbt4 ...)`
|
||||
* the psbt calling combine will always have precedence when a conflict occurs.
|
||||
* Combine checks if the internal bitcoin transaction is the same, so be sure that
|
||||
* all sequences, version, locktime, etc. are the same before combining.
|
||||
* Input Finalizer: This role is fairly important. Not only does it need to construct
|
||||
* the input scriptSigs and witnesses, but it SHOULD verify the signatures etc.
|
||||
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateSignaturesOfAllInputs()`
|
||||
* Running any finalize method will delete any data in the input(s) that are no longer
|
||||
* needed due to the finalized scripts containing the information.
|
||||
* Transaction Extractor: This role will perform some checks before returning a
|
||||
* Transaction object. Such as fee rate not being larger than maximumFeeRate etc.
|
||||
*/
|
||||
export declare class Psbt {
|
||||
readonly data: PsbtBase;
|
||||
static fromBase64(data: string, opts?: PsbtOptsOptional): Psbt;
|
||||
static fromHex(data: string, opts?: PsbtOptsOptional): Psbt;
|
||||
static fromBuffer(buffer: Buffer, opts?: PsbtOptsOptional): Psbt;
|
||||
private __CACHE;
|
||||
private opts;
|
||||
constructor(opts?: PsbtOptsOptional, data?: PsbtBase);
|
||||
readonly inputCount: number;
|
||||
combine(...those: Psbt[]): this;
|
||||
clone(): Psbt;
|
||||
setMaximumFeeRate(satoshiPerByte: number): void;
|
||||
setVersion(version: number): this;
|
||||
setLocktime(locktime: number): this;
|
||||
setInputSequence(inputIndex: number, sequence: number): this;
|
||||
addInputs(inputDatas: TransactionInput[]): this;
|
||||
addInput(inputData: TransactionInput): this;
|
||||
addOutputs(outputDatas: TransactionOutput[]): this;
|
||||
addOutput(outputData: TransactionOutput): this;
|
||||
extractTransaction(disableFeeCheck?: boolean): Transaction;
|
||||
getFeeRate(): number;
|
||||
finalizeAllInputs(): this;
|
||||
finalizeInput(inputIndex: number): this;
|
||||
validateSignaturesOfAllInputs(): boolean;
|
||||
validateSignaturesOfInput(inputIndex: number, pubkey?: Buffer): boolean;
|
||||
signAllInputsHD(hdKeyPair: HDSigner, sighashTypes?: number[]): this;
|
||||
signHDAsync(hdKeyPair: HDSigner | HDSignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||
signInputHD(inputIndex: number, hdKeyPair: HDSigner, sighashTypes?: number[]): this;
|
||||
signInputHDAsync(inputIndex: number, hdKeyPair: HDSigner | HDSignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||
signAllInputs(keyPair: Signer, sighashTypes?: number[]): this;
|
||||
signAsync(keyPair: Signer | SignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||
signInput(inputIndex: number, keyPair: Signer, sighashTypes?: number[]): this;
|
||||
signInputAsync(inputIndex: number, keyPair: Signer | SignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||
toBuffer(): Buffer;
|
||||
toHex(): string;
|
||||
toBase64(): string;
|
||||
updateGlobal(updateData: PsbtGlobalUpdate): this;
|
||||
updateInput(inputIndex: number, updateData: PsbtInputUpdate): this;
|
||||
updateOutput(outputIndex: number, updateData: PsbtOutputUpdate): this;
|
||||
addUnknownKeyValToGlobal(keyVal: KeyValue): this;
|
||||
addUnknownKeyValToInput(inputIndex: number, keyVal: KeyValue): this;
|
||||
addUnknownKeyValToOutput(outputIndex: number, keyVal: KeyValue): this;
|
||||
clearFinalizedInput(inputIndex: number): this;
|
||||
}
|
||||
interface PsbtOptsOptional {
|
||||
network?: Network;
|
||||
maximumFeeRate?: number;
|
||||
}
|
||||
interface HDSignerBase {
|
||||
/**
|
||||
* DER format compressed publicKey buffer
|
||||
*/
|
||||
publicKey: Buffer;
|
||||
/**
|
||||
* The first 4 bytes of the sha256-ripemd160 of the publicKey
|
||||
*/
|
||||
fingerprint: Buffer;
|
||||
}
|
||||
interface HDSigner extends HDSignerBase {
|
||||
/**
|
||||
* The path string must match /^m(\/\d+'?)+$/
|
||||
* ex. m/44'/0'/0'/1/23 levels with ' must be hard derivations
|
||||
*/
|
||||
derivePath(path: string): HDSigner;
|
||||
/**
|
||||
* Input hash (the "message digest") for the signature algorithm
|
||||
* Return a 64 byte signature (32 byte r and 32 byte s in that order)
|
||||
*/
|
||||
sign(hash: Buffer): Buffer;
|
||||
}
|
||||
/**
|
||||
* Same as above but with async sign method
|
||||
*/
|
||||
interface HDSignerAsync extends HDSignerBase {
|
||||
derivePath(path: string): HDSignerAsync;
|
||||
sign(hash: Buffer): Promise<Buffer>;
|
||||
}
|
||||
export {};
|
Loading…
Reference in a new issue