commit
492c435a1f
93 changed files with 1237 additions and 1065 deletions
245
package-lock.json
generated
245
package-lock.json
generated
|
@ -9,6 +9,59 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
|
||||||
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
|
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
|
||||||
},
|
},
|
||||||
|
"ansi-regex": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||||
|
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"argparse": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"sprintf-js": "~1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"babel-code-frame": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^1.1.3",
|
||||||
|
"esutils": "^2.0.2",
|
||||||
|
"js-tokens": "^3.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^2.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.2",
|
||||||
|
"has-ansi": "^2.0.0",
|
||||||
|
"strip-ansi": "^3.0.0",
|
||||||
|
"supports-color": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
|
@ -130,6 +183,34 @@
|
||||||
"safe-buffer": "^5.1.2"
|
"safe-buffer": "^5.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"builtin-modules": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"cipher-base": {
|
"cipher-base": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
|
||||||
|
@ -139,6 +220,21 @@
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"commander": {
|
"commander": {
|
||||||
"version": "2.15.1",
|
"version": "2.15.1",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||||
|
@ -220,44 +316,16 @@
|
||||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"eslint-plugin-typescript": {
|
"esprima": {
|
||||||
"version": "0.14.0",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-typescript/-/eslint-plugin-typescript-0.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
"integrity": "sha512-2u1WnnDF2mkWWgU1lFQ2RjypUlmRoBEvQN02y9u+IL12mjWlkKFGEBnVsjs9Y8190bfPQCvWly1c2rYYUSOxWw==",
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"requireindex": "~1.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"eslint-scope": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"esrecurse": "^4.1.0",
|
|
||||||
"estraverse": "^4.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"eslint-visitor-keys": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
|
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"esrecurse": {
|
"esutils": {
|
||||||
"version": "4.2.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
|
||||||
"integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
|
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"estraverse": "^4.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"estraverse": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
|
|
||||||
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
|
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"file-uri-to-path": {
|
"file-uri-to-path": {
|
||||||
|
@ -301,6 +369,15 @@
|
||||||
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
|
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"has-ansi": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-regex": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"has-flag": {
|
"has-flag": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
@ -368,12 +445,22 @@
|
||||||
"integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
|
"integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.unescape": {
|
"js-tokens": {
|
||||||
"version": "4.0.1",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||||
"integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
|
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"js-yaml": {
|
||||||
|
"version": "3.12.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.2.tgz",
|
||||||
|
"integrity": "sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^1.0.7",
|
||||||
|
"esprima": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"md5.js": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
|
@ -3174,12 +3261,6 @@
|
||||||
"safe-buffer": "^5.1.0"
|
"safe-buffer": "^5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"requireindex": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz",
|
|
||||||
"integrity": "sha1-5UBLgVV+91225JxacgBIk/4D4WI=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
|
||||||
|
@ -3218,12 +3299,27 @@
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sprintf-js": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"statuses": {
|
"statuses": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"strip-ansi": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-regex": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
"version": "5.4.0",
|
"version": "5.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
|
||||||
|
@ -3245,6 +3341,42 @@
|
||||||
"nan": "^2.10.0"
|
"nan": "^2.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"tslint": {
|
||||||
|
"version": "5.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.13.1.tgz",
|
||||||
|
"integrity": "sha512-fplQqb2miLbcPhyHoMV4FU9PtNRbgmm/zI5d3SZwwmJQM6V0eodju+hplpyfhLWpmwrDNfNYU57uYRb8s0zZoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-code-frame": "^6.22.0",
|
||||||
|
"builtin-modules": "^1.1.1",
|
||||||
|
"chalk": "^2.3.0",
|
||||||
|
"commander": "^2.12.1",
|
||||||
|
"diff": "^3.2.0",
|
||||||
|
"glob": "^7.1.1",
|
||||||
|
"js-yaml": "^3.7.0",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"resolve": "^1.3.2",
|
||||||
|
"semver": "^5.3.0",
|
||||||
|
"tslib": "^1.8.0",
|
||||||
|
"tsutils": "^2.27.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tsutils": {
|
||||||
|
"version": "2.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
|
||||||
|
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"typeforce": {
|
"typeforce": {
|
||||||
"version": "1.18.0",
|
"version": "1.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
|
||||||
|
@ -3256,27 +3388,6 @@
|
||||||
"integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==",
|
"integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"typescript-eslint-parser": {
|
|
||||||
"version": "21.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint-parser/-/typescript-eslint-parser-21.0.2.tgz",
|
|
||||||
"integrity": "sha512-u+pj4RVJBr4eTzj0n5npoXD/oRthvfUCjSKndhNI714MG0mQq2DJw5WP7qmonRNIFgmZuvdDOH3BHm9iOjIAfg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"eslint-scope": "^4.0.0",
|
|
||||||
"eslint-visitor-keys": "^1.0.0",
|
|
||||||
"typescript-estree": "5.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"typescript-estree": {
|
|
||||||
"version": "5.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript-estree/-/typescript-estree-5.3.0.tgz",
|
|
||||||
"integrity": "sha512-Vu0KmYdSCkpae+J48wsFC1ti19Hq3Wi/lODUaE+uesc3gzqhWbZ5itWbsjylLVbjNW4K41RqDzSfnaYNbmEiMQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"lodash.unescape": "4.0.1",
|
|
||||||
"semver": "5.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"unorm": {
|
"unorm": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/unorm/-/unorm-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/unorm/-/unorm-1.5.0.tgz",
|
||||||
|
|
10
package.json
10
package.json
|
@ -22,6 +22,7 @@
|
||||||
"format": "npm run prettier -- --write",
|
"format": "npm run prettier -- --write",
|
||||||
"format:ci": "npm run prettier -- --check",
|
"format:ci": "npm run prettier -- --check",
|
||||||
"integration": "npm run build && npm run nobuild:integration",
|
"integration": "npm run build && npm run nobuild:integration",
|
||||||
|
"lint": "tslint -p tsconfig.json -c tslint.json",
|
||||||
"nobuild:coverage-report": "nyc report --reporter=lcov",
|
"nobuild:coverage-report": "nyc report --reporter=lcov",
|
||||||
"nobuild:coverage-html": "nyc report --reporter=html",
|
"nobuild:coverage-html": "nyc report --reporter=html",
|
||||||
"nobuild:coverage": "nyc --check-coverage --branches 90 --functions 90 --lines 90 mocha",
|
"nobuild:coverage": "nyc --check-coverage --branches 90 --functions 90 --lines 90 mocha",
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
"nobuild:unit": "mocha",
|
"nobuild:unit": "mocha",
|
||||||
"prepare": "npm run build",
|
"prepare": "npm run build",
|
||||||
"prettier": "prettier 'ts_src/**/*.ts' --ignore-path ./.prettierignore",
|
"prettier": "prettier 'ts_src/**/*.ts' --ignore-path ./.prettierignore",
|
||||||
"test": "npm run build && npm run format:ci && npm run nobuild:coverage",
|
"test": "npm run build && npm run format:ci && npm run lint && npm run nobuild:coverage",
|
||||||
"unit": "npm run build && npm run nobuild:unit"
|
"unit": "npm run build && npm run nobuild:unit"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -64,15 +65,14 @@
|
||||||
"bn.js": "^4.11.8",
|
"bn.js": "^4.11.8",
|
||||||
"bs58": "^4.0.0",
|
"bs58": "^4.0.0",
|
||||||
"dhttp": "^3.0.0",
|
"dhttp": "^3.0.0",
|
||||||
"eslint-plugin-typescript": "^0.14.0",
|
|
||||||
"hoodwink": "^2.0.0",
|
"hoodwink": "^2.0.0",
|
||||||
"minimaldata": "^1.0.2",
|
"minimaldata": "^1.0.2",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
"nyc": "^11.8.0",
|
"nyc": "^11.8.0",
|
||||||
"prettier": "^1.16.4",
|
"prettier": "1.16.4",
|
||||||
"proxyquire": "^2.0.1",
|
"proxyquire": "^2.0.1",
|
||||||
"typescript": "3.2.2",
|
"tslint": "5.13.1",
|
||||||
"typescript-eslint-parser": "^21.0.2"
|
"typescript": "3.2.2"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const types = require("./types");
|
|
||||||
const bscript = require("./script");
|
|
||||||
const networks = require("./networks");
|
const networks = require("./networks");
|
||||||
const payments = require("./payments");
|
const payments = require("./payments");
|
||||||
|
const bscript = require("./script");
|
||||||
|
const types = require("./types");
|
||||||
const bech32 = require('bech32');
|
const bech32 = require('bech32');
|
||||||
const bs58check = require('bs58check');
|
const bs58check = require('bs58check');
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
|
@ -16,7 +16,7 @@ function fromBase58Check(address) {
|
||||||
throw new TypeError(address + ' is too long');
|
throw new TypeError(address + ' is too long');
|
||||||
const version = payload.readUInt8(0);
|
const version = payload.readUInt8(0);
|
||||||
const hash = payload.slice(1);
|
const hash = payload.slice(1);
|
||||||
return { version: version, hash: hash };
|
return { version, hash };
|
||||||
}
|
}
|
||||||
exports.fromBase58Check = fromBase58Check;
|
exports.fromBase58Check = fromBase58Check;
|
||||||
function fromBech32(address) {
|
function fromBech32(address) {
|
||||||
|
@ -44,7 +44,7 @@ function toBech32(data, version, prefix) {
|
||||||
}
|
}
|
||||||
exports.toBech32 = toBech32;
|
exports.toBech32 = toBech32;
|
||||||
function fromOutputScript(output, network) {
|
function fromOutputScript(output, network) {
|
||||||
//TODO: Network
|
// TODO: Network
|
||||||
network = network || networks.bitcoin;
|
network = network || networks.bitcoin;
|
||||||
try {
|
try {
|
||||||
return payments.p2pkh({ output, network }).address;
|
return payments.p2pkh({ output, network }).address;
|
||||||
|
@ -67,8 +67,8 @@ function fromOutputScript(output, network) {
|
||||||
exports.fromOutputScript = fromOutputScript;
|
exports.fromOutputScript = fromOutputScript;
|
||||||
function toOutputScript(address, network) {
|
function toOutputScript(address, network) {
|
||||||
network = network || networks.bitcoin;
|
network = network || networks.bitcoin;
|
||||||
let decodeBase58 = undefined;
|
let decodeBase58;
|
||||||
let decodeBech32 = undefined;
|
let decodeBech32;
|
||||||
try {
|
try {
|
||||||
decodeBase58 = fromBase58Check(address);
|
decodeBase58 = fromBase58Check(address);
|
||||||
}
|
}
|
||||||
|
|
44
src/block.js
44
src/block.js
|
@ -1,9 +1,9 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const bufferutils_1 = require("./bufferutils");
|
||||||
|
const bcrypto = require("./crypto");
|
||||||
const transaction_1 = require("./transaction");
|
const transaction_1 = require("./transaction");
|
||||||
const types = require("./types");
|
const types = require("./types");
|
||||||
const bcrypto = require("./crypto");
|
|
||||||
const bufferutils_1 = require("./bufferutils");
|
|
||||||
const fastMerkleRoot = require('merkle-lib/fastRoot');
|
const fastMerkleRoot = require('merkle-lib/fastRoot');
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
const varuint = require('varuint-bitcoin');
|
const varuint = require('varuint-bitcoin');
|
||||||
|
@ -28,16 +28,6 @@ function anyTxHasWitness(transactions) {
|
||||||
input.witness.length > 0)));
|
input.witness.length > 0)));
|
||||||
}
|
}
|
||||||
class Block {
|
class Block {
|
||||||
constructor() {
|
|
||||||
this.version = 1;
|
|
||||||
this.timestamp = 0;
|
|
||||||
this.bits = 0;
|
|
||||||
this.nonce = 0;
|
|
||||||
this.prevHash = undefined;
|
|
||||||
this.merkleRoot = undefined;
|
|
||||||
this.witnessCommit = undefined;
|
|
||||||
this.transactions = undefined;
|
|
||||||
}
|
|
||||||
static fromBuffer(buffer) {
|
static fromBuffer(buffer) {
|
||||||
if (buffer.length < 80)
|
if (buffer.length < 80)
|
||||||
throw new Error('Buffer too small (< 80 bytes)');
|
throw new Error('Buffer too small (< 80 bytes)');
|
||||||
|
@ -77,11 +67,11 @@ class Block {
|
||||||
};
|
};
|
||||||
const nTransactions = readVarInt();
|
const nTransactions = readVarInt();
|
||||||
block.transactions = [];
|
block.transactions = [];
|
||||||
for (var i = 0; i < nTransactions; ++i) {
|
for (let i = 0; i < nTransactions; ++i) {
|
||||||
const tx = readTransaction();
|
const tx = readTransaction();
|
||||||
block.transactions.push(tx);
|
block.transactions.push(tx);
|
||||||
}
|
}
|
||||||
let witnessCommit = block.getWitnessCommit();
|
const witnessCommit = block.getWitnessCommit();
|
||||||
// This Block contains a witness commit
|
// This Block contains a witness commit
|
||||||
if (witnessCommit)
|
if (witnessCommit)
|
||||||
block.witnessCommit = witnessCommit;
|
block.witnessCommit = witnessCommit;
|
||||||
|
@ -109,6 +99,16 @@ class Block {
|
||||||
? bcrypto.hash256(Buffer.concat([rootHash, transactions[0].ins[0].witness[0]]))
|
? bcrypto.hash256(Buffer.concat([rootHash, transactions[0].ins[0].witness[0]]))
|
||||||
: rootHash;
|
: rootHash;
|
||||||
}
|
}
|
||||||
|
constructor() {
|
||||||
|
this.version = 1;
|
||||||
|
this.timestamp = 0;
|
||||||
|
this.bits = 0;
|
||||||
|
this.nonce = 0;
|
||||||
|
this.prevHash = undefined;
|
||||||
|
this.merkleRoot = undefined;
|
||||||
|
this.witnessCommit = undefined;
|
||||||
|
this.transactions = undefined;
|
||||||
|
}
|
||||||
getWitnessCommit() {
|
getWitnessCommit() {
|
||||||
if (!txesHaveWitnessCommit(this.transactions))
|
if (!txesHaveWitnessCommit(this.transactions))
|
||||||
return null;
|
return null;
|
||||||
|
@ -116,11 +116,11 @@ class Block {
|
||||||
// There is no rule for the index of the output, so use filter to find it.
|
// There is no rule for the index of the output, so use filter to find it.
|
||||||
// The root is prepended with 0xaa21a9ed so check for 0x6a24aa21a9ed
|
// The root is prepended with 0xaa21a9ed so check for 0x6a24aa21a9ed
|
||||||
// If multiple commits are found, the output with highest index is assumed.
|
// If multiple commits are found, the output with highest index is assumed.
|
||||||
let witnessCommits = this.transactions[0].outs.filter(out => out.script.slice(0, 6).equals(Buffer.from('6a24aa21a9ed', 'hex'))).map(out => out.script.slice(6, 38));
|
const witnessCommits = this.transactions[0].outs.filter(out => out.script.slice(0, 6).equals(Buffer.from('6a24aa21a9ed', 'hex'))).map(out => out.script.slice(6, 38));
|
||||||
if (witnessCommits.length === 0)
|
if (witnessCommits.length === 0)
|
||||||
return null;
|
return null;
|
||||||
// Use the commit with the highest output (should only be one though)
|
// Use the commit with the highest output (should only be one though)
|
||||||
let result = witnessCommits[witnessCommits.length - 1];
|
const result = witnessCommits[witnessCommits.length - 1];
|
||||||
if (!(result instanceof Buffer && result.length === 32))
|
if (!(result instanceof Buffer && result.length === 32))
|
||||||
return null;
|
return null;
|
||||||
return result;
|
return result;
|
||||||
|
@ -193,7 +193,7 @@ class Block {
|
||||||
checkTxRoots() {
|
checkTxRoots() {
|
||||||
// If the Block has segwit transactions but no witness commit,
|
// If the Block has segwit transactions but no witness commit,
|
||||||
// there's no way it can be valid, so fail the check.
|
// there's no way it can be valid, so fail the check.
|
||||||
let hasWitnessCommit = this.hasWitnessCommit();
|
const hasWitnessCommit = this.hasWitnessCommit();
|
||||||
if (!hasWitnessCommit && this.hasWitness())
|
if (!hasWitnessCommit && this.hasWitness())
|
||||||
return false;
|
return false;
|
||||||
return (this.__checkMerkleRoot() &&
|
return (this.__checkMerkleRoot() &&
|
||||||
|
@ -204,6 +204,11 @@ class Block {
|
||||||
'deprecated in v5. Please use checkTxRoots instead.');
|
'deprecated in v5. Please use checkTxRoots instead.');
|
||||||
return this.checkTxRoots();
|
return this.checkTxRoots();
|
||||||
}
|
}
|
||||||
|
checkProofOfWork() {
|
||||||
|
const hash = bufferutils_1.reverseBuffer(this.getHash());
|
||||||
|
const target = Block.calculateTarget(this.bits);
|
||||||
|
return hash.compare(target) <= 0;
|
||||||
|
}
|
||||||
__checkMerkleRoot() {
|
__checkMerkleRoot() {
|
||||||
if (!this.transactions)
|
if (!this.transactions)
|
||||||
throw errorMerkleNoTxes;
|
throw errorMerkleNoTxes;
|
||||||
|
@ -218,10 +223,5 @@ class Block {
|
||||||
const actualWitnessCommit = Block.calculateMerkleRoot(this.transactions, true);
|
const actualWitnessCommit = Block.calculateMerkleRoot(this.transactions, true);
|
||||||
return this.witnessCommit.compare(actualWitnessCommit) === 0;
|
return this.witnessCommit.compare(actualWitnessCommit) === 0;
|
||||||
}
|
}
|
||||||
checkProofOfWork() {
|
|
||||||
const hash = bufferutils_1.reverseBuffer(this.getHash());
|
|
||||||
const target = Block.calculateTarget(this.bits);
|
|
||||||
return hash.compare(target) <= 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exports.Block = Block;
|
exports.Block = Block;
|
||||||
|
|
|
@ -6,9 +6,9 @@ const nullData = require("./templates/nulldata");
|
||||||
const pubKey = require("./templates/pubkey");
|
const pubKey = require("./templates/pubkey");
|
||||||
const pubKeyHash = require("./templates/pubkeyhash");
|
const pubKeyHash = require("./templates/pubkeyhash");
|
||||||
const scriptHash = require("./templates/scripthash");
|
const scriptHash = require("./templates/scripthash");
|
||||||
|
const witnessCommitment = require("./templates/witnesscommitment");
|
||||||
const witnessPubKeyHash = require("./templates/witnesspubkeyhash");
|
const witnessPubKeyHash = require("./templates/witnesspubkeyhash");
|
||||||
const witnessScriptHash = require("./templates/witnessscripthash");
|
const witnessScriptHash = require("./templates/witnessscripthash");
|
||||||
const witnessCommitment = require("./templates/witnesscommitment");
|
|
||||||
const types = {
|
const types = {
|
||||||
P2MS: 'multisig',
|
P2MS: 'multisig',
|
||||||
NONSTANDARD: 'nonstandard',
|
NONSTANDARD: 'nonstandard',
|
||||||
|
|
|
@ -17,30 +17,30 @@ class ECPair {
|
||||||
this.compressed =
|
this.compressed =
|
||||||
options.compressed === undefined ? true : options.compressed;
|
options.compressed === undefined ? true : options.compressed;
|
||||||
this.network = options.network || NETWORKS.bitcoin;
|
this.network = options.network || NETWORKS.bitcoin;
|
||||||
this.__d = undefined;
|
this.__D = undefined;
|
||||||
this.__Q = undefined;
|
this.__Q = undefined;
|
||||||
if (d !== undefined)
|
if (d !== undefined)
|
||||||
this.__d = d;
|
this.__D = d;
|
||||||
if (Q !== undefined)
|
if (Q !== undefined)
|
||||||
this.__Q = ecc.pointCompress(Q, this.compressed);
|
this.__Q = ecc.pointCompress(Q, this.compressed);
|
||||||
}
|
}
|
||||||
get privateKey() {
|
get privateKey() {
|
||||||
return this.__d;
|
return this.__D;
|
||||||
}
|
}
|
||||||
get publicKey() {
|
get publicKey() {
|
||||||
if (!this.__Q)
|
if (!this.__Q)
|
||||||
this.__Q = ecc.pointFromScalar(this.__d, this.compressed);
|
this.__Q = ecc.pointFromScalar(this.__D, this.compressed);
|
||||||
return this.__Q;
|
return this.__Q;
|
||||||
}
|
}
|
||||||
toWIF() {
|
toWIF() {
|
||||||
if (!this.__d)
|
if (!this.__D)
|
||||||
throw new Error('Missing private key');
|
throw new Error('Missing private key');
|
||||||
return wif.encode(this.network.wif, this.__d, this.compressed);
|
return wif.encode(this.network.wif, this.__D, this.compressed);
|
||||||
}
|
}
|
||||||
sign(hash) {
|
sign(hash) {
|
||||||
if (!this.__d)
|
if (!this.__D)
|
||||||
throw new Error('Missing private key');
|
throw new Error('Missing private key');
|
||||||
return ecc.sign(hash, this.__d);
|
return ecc.sign(hash, this.__D);
|
||||||
}
|
}
|
||||||
verify(hash, signature) {
|
verify(hash, signature) {
|
||||||
return ecc.verify(hash, this.publicKey, signature);
|
return ecc.verify(hash, this.publicKey, signature);
|
||||||
|
@ -60,13 +60,13 @@ function fromPublicKey(buffer, options) {
|
||||||
return new ECPair(undefined, buffer, options);
|
return new ECPair(undefined, buffer, options);
|
||||||
}
|
}
|
||||||
exports.fromPublicKey = fromPublicKey;
|
exports.fromPublicKey = fromPublicKey;
|
||||||
function fromWIF(string, network) {
|
function fromWIF(wifString, network) {
|
||||||
const decoded = wif.decode(string);
|
const decoded = wif.decode(wifString);
|
||||||
const version = decoded.version;
|
const version = decoded.version;
|
||||||
// list of networks?
|
// list of networks?
|
||||||
if (types.Array(network)) {
|
if (types.Array(network)) {
|
||||||
network = network
|
network = network
|
||||||
.filter(function (x) {
|
.filter((x) => {
|
||||||
return version === x.wif;
|
return version === x.wif;
|
||||||
})
|
})
|
||||||
.pop();
|
.pop();
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const bip32 = require("bip32");
|
const bip32 = require("bip32");
|
||||||
exports.bip32 = bip32;
|
exports.bip32 = bip32;
|
||||||
const ECPair = require("./ecpair");
|
|
||||||
exports.ECPair = ECPair;
|
|
||||||
const address = require("./address");
|
const address = require("./address");
|
||||||
exports.address = address;
|
exports.address = address;
|
||||||
const crypto = require("./crypto");
|
const crypto = require("./crypto");
|
||||||
exports.crypto = crypto;
|
exports.crypto = crypto;
|
||||||
|
const ECPair = require("./ecpair");
|
||||||
|
exports.ECPair = ECPair;
|
||||||
const networks = require("./networks");
|
const networks = require("./networks");
|
||||||
exports.networks = networks;
|
exports.networks = networks;
|
||||||
const payments = require("./payments");
|
const payments = require("./payments");
|
||||||
|
@ -16,9 +16,9 @@ const script = require("./script");
|
||||||
exports.script = script;
|
exports.script = script;
|
||||||
var block_1 = require("./block");
|
var block_1 = require("./block");
|
||||||
exports.Block = block_1.Block;
|
exports.Block = block_1.Block;
|
||||||
|
var script_1 = require("./script");
|
||||||
|
exports.opcodes = script_1.OPS;
|
||||||
var transaction_1 = require("./transaction");
|
var transaction_1 = require("./transaction");
|
||||||
exports.Transaction = transaction_1.Transaction;
|
exports.Transaction = transaction_1.Transaction;
|
||||||
var transaction_builder_1 = require("./transaction_builder");
|
var transaction_builder_1 = require("./transaction_builder");
|
||||||
exports.TransactionBuilder = transaction_builder_1.TransactionBuilder;
|
exports.TransactionBuilder = transaction_builder_1.TransactionBuilder;
|
||||||
var script_1 = require("./script");
|
|
||||||
exports.opcodes = script_1.OPS;
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const networks_1 = require("../networks");
|
||||||
const bscript = require("../script");
|
const bscript = require("../script");
|
||||||
const lazy = require("./lazy");
|
const lazy = require("./lazy");
|
||||||
const networks_1 = require("../networks");
|
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
function stacksEqual(a, b) {
|
function stacksEqual(a, b) {
|
||||||
if (a.length !== b.length)
|
if (a.length !== b.length)
|
||||||
return false;
|
return false;
|
||||||
return a.every(function (x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,12 @@ function p2data(a, opts) {
|
||||||
}, a);
|
}, a);
|
||||||
const network = a.network || networks_1.bitcoin;
|
const network = a.network || networks_1.bitcoin;
|
||||||
const o = { network };
|
const o = { network };
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!a.data)
|
if (!a.data)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([OPS.OP_RETURN].concat(a.data));
|
return bscript.compile([OPS.OP_RETURN].concat(a.data));
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'data', function () {
|
lazy.prop(o, 'data', () => {
|
||||||
if (!a.output)
|
if (!a.output)
|
||||||
return;
|
return;
|
||||||
return bscript.decompile(a.output).slice(1);
|
return bscript.decompile(a.output).slice(1);
|
||||||
|
|
|
@ -4,16 +4,16 @@ function prop(object, name, f) {
|
||||||
Object.defineProperty(object, name, {
|
Object.defineProperty(object, name, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: function () {
|
get() {
|
||||||
let value = f.call(this);
|
const _value = f.call(this);
|
||||||
this[name] = value;
|
this[name] = _value;
|
||||||
return value;
|
return _value;
|
||||||
},
|
},
|
||||||
set: function (value) {
|
set(_value) {
|
||||||
Object.defineProperty(this, name, {
|
Object.defineProperty(this, name, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
value: value,
|
value: _value,
|
||||||
writable: true,
|
writable: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -21,12 +21,12 @@ function prop(object, name, f) {
|
||||||
}
|
}
|
||||||
exports.prop = prop;
|
exports.prop = prop;
|
||||||
function value(f) {
|
function value(f) {
|
||||||
let value;
|
let _value;
|
||||||
return function () {
|
return () => {
|
||||||
if (value !== undefined)
|
if (_value !== undefined)
|
||||||
return value;
|
return _value;
|
||||||
value = f();
|
_value = f();
|
||||||
return value;
|
return _value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
exports.value = value;
|
exports.value = value;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const networks_1 = require("../networks");
|
||||||
const bscript = require("../script");
|
const bscript = require("../script");
|
||||||
const lazy = require("./lazy");
|
const lazy = require("./lazy");
|
||||||
const networks_1 = require("../networks");
|
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
@ -10,7 +10,7 @@ const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
|
||||||
function stacksEqual(a, b) {
|
function stacksEqual(a, b) {
|
||||||
if (a.length !== b.length)
|
if (a.length !== b.length)
|
||||||
return false;
|
return false;
|
||||||
return a.every(function (x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ function p2ms(a, opts) {
|
||||||
o.n = chunks[chunks.length - 2] - OP_INT_BASE;
|
o.n = chunks[chunks.length - 2] - OP_INT_BASE;
|
||||||
o.pubkeys = chunks.slice(1, -2);
|
o.pubkeys = chunks.slice(1, -2);
|
||||||
}
|
}
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!a.m)
|
if (!a.m)
|
||||||
return;
|
return;
|
||||||
if (!o.n)
|
if (!o.n)
|
||||||
|
@ -58,34 +58,34 @@ function p2ms(a, opts) {
|
||||||
return;
|
return;
|
||||||
return bscript.compile([].concat(OP_INT_BASE + a.m, a.pubkeys, OP_INT_BASE + o.n, OPS.OP_CHECKMULTISIG));
|
return bscript.compile([].concat(OP_INT_BASE + a.m, a.pubkeys, OP_INT_BASE + o.n, OPS.OP_CHECKMULTISIG));
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'm', function () {
|
lazy.prop(o, 'm', () => {
|
||||||
if (!o.output)
|
if (!o.output)
|
||||||
return;
|
return;
|
||||||
decode(o.output);
|
decode(o.output);
|
||||||
return o.m;
|
return o.m;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'n', function () {
|
lazy.prop(o, 'n', () => {
|
||||||
if (!o.pubkeys)
|
if (!o.pubkeys)
|
||||||
return;
|
return;
|
||||||
return o.pubkeys.length;
|
return o.pubkeys.length;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkeys', function () {
|
lazy.prop(o, 'pubkeys', () => {
|
||||||
if (!a.output)
|
if (!a.output)
|
||||||
return;
|
return;
|
||||||
decode(a.output);
|
decode(a.output);
|
||||||
return o.pubkeys;
|
return o.pubkeys;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signatures', function () {
|
lazy.prop(o, 'signatures', () => {
|
||||||
if (!a.input)
|
if (!a.input)
|
||||||
return;
|
return;
|
||||||
return bscript.decompile(a.input).slice(1);
|
return bscript.decompile(a.input).slice(1);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.signatures)
|
if (!a.signatures)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([OPS.OP_0].concat(a.signatures));
|
return bscript.compile([OPS.OP_0].concat(a.signatures));
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function () {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!o.input)
|
if (!o.input)
|
||||||
return;
|
return;
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const networks_1 = require("../networks");
|
||||||
const bscript = require("../script");
|
const bscript = require("../script");
|
||||||
const lazy = require("./lazy");
|
const lazy = require("./lazy");
|
||||||
const networks_1 = require("../networks");
|
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
@ -19,32 +19,32 @@ function p2pk(a, opts) {
|
||||||
signature: typef.maybe(bscript.isCanonicalScriptSignature),
|
signature: typef.maybe(bscript.isCanonicalScriptSignature),
|
||||||
input: typef.maybe(typef.Buffer),
|
input: typef.maybe(typef.Buffer),
|
||||||
}, a);
|
}, a);
|
||||||
const _chunks = lazy.value(function () {
|
const _chunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.input);
|
return bscript.decompile(a.input);
|
||||||
});
|
});
|
||||||
const network = a.network || networks_1.bitcoin;
|
const network = a.network || networks_1.bitcoin;
|
||||||
const o = { network };
|
const o = { network };
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!a.pubkey)
|
if (!a.pubkey)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([a.pubkey, OPS.OP_CHECKSIG]);
|
return bscript.compile([a.pubkey, OPS.OP_CHECKSIG]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkey', function () {
|
lazy.prop(o, 'pubkey', () => {
|
||||||
if (!a.output)
|
if (!a.output)
|
||||||
return;
|
return;
|
||||||
return a.output.slice(1, -1);
|
return a.output.slice(1, -1);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signature', function () {
|
lazy.prop(o, 'signature', () => {
|
||||||
if (!a.input)
|
if (!a.input)
|
||||||
return;
|
return;
|
||||||
return _chunks()[0];
|
return _chunks()[0];
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.signature)
|
if (!a.signature)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([a.signature]);
|
return bscript.compile([a.signature]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function () {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!o.input)
|
if (!o.input)
|
||||||
return;
|
return;
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const bscript = require("../script");
|
|
||||||
const bcrypto = require("../crypto");
|
const bcrypto = require("../crypto");
|
||||||
const lazy = require("./lazy");
|
|
||||||
const networks_1 = require("../networks");
|
const networks_1 = require("../networks");
|
||||||
|
const bscript = require("../script");
|
||||||
|
const lazy = require("./lazy");
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
@ -23,18 +23,18 @@ function p2pkh(a, opts) {
|
||||||
signature: typef.maybe(bscript.isCanonicalScriptSignature),
|
signature: typef.maybe(bscript.isCanonicalScriptSignature),
|
||||||
input: typef.maybe(typef.Buffer),
|
input: typef.maybe(typef.Buffer),
|
||||||
}, a);
|
}, a);
|
||||||
const _address = lazy.value(function () {
|
const _address = lazy.value(() => {
|
||||||
const payload = bs58check.decode(a.address);
|
const payload = bs58check.decode(a.address);
|
||||||
const version = payload.readUInt8(0);
|
const version = payload.readUInt8(0);
|
||||||
const hash = payload.slice(1);
|
const hash = payload.slice(1);
|
||||||
return { version, hash };
|
return { version, hash };
|
||||||
});
|
});
|
||||||
const _chunks = lazy.value(function () {
|
const _chunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.input);
|
return bscript.decompile(a.input);
|
||||||
});
|
});
|
||||||
const network = a.network || networks_1.bitcoin;
|
const network = a.network || networks_1.bitcoin;
|
||||||
const o = { network };
|
const o = { network };
|
||||||
lazy.prop(o, 'address', function () {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
const payload = Buffer.allocUnsafe(21);
|
const payload = Buffer.allocUnsafe(21);
|
||||||
|
@ -42,7 +42,7 @@ function p2pkh(a, opts) {
|
||||||
o.hash.copy(payload, 1);
|
o.hash.copy(payload, 1);
|
||||||
return bs58check.encode(payload);
|
return bs58check.encode(payload);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function () {
|
lazy.prop(o, 'hash', () => {
|
||||||
if (a.output)
|
if (a.output)
|
||||||
return a.output.slice(3, 23);
|
return a.output.slice(3, 23);
|
||||||
if (a.address)
|
if (a.address)
|
||||||
|
@ -50,7 +50,7 @@ function p2pkh(a, opts) {
|
||||||
if (a.pubkey || o.pubkey)
|
if (a.pubkey || o.pubkey)
|
||||||
return bcrypto.hash160(a.pubkey || o.pubkey);
|
return bcrypto.hash160(a.pubkey || o.pubkey);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([
|
return bscript.compile([
|
||||||
|
@ -61,24 +61,24 @@ function p2pkh(a, opts) {
|
||||||
OPS.OP_CHECKSIG,
|
OPS.OP_CHECKSIG,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkey', function () {
|
lazy.prop(o, 'pubkey', () => {
|
||||||
if (!a.input)
|
if (!a.input)
|
||||||
return;
|
return;
|
||||||
return _chunks()[1];
|
return _chunks()[1];
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signature', function () {
|
lazy.prop(o, 'signature', () => {
|
||||||
if (!a.input)
|
if (!a.input)
|
||||||
return;
|
return;
|
||||||
return _chunks()[0];
|
return _chunks()[0];
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.pubkey)
|
if (!a.pubkey)
|
||||||
return;
|
return;
|
||||||
if (!a.signature)
|
if (!a.signature)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([a.signature, a.pubkey]);
|
return bscript.compile([a.signature, a.pubkey]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function () {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!o.input)
|
if (!o.input)
|
||||||
return;
|
return;
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const bcrypto = require("../crypto");
|
||||||
const networks_1 = require("../networks");
|
const networks_1 = require("../networks");
|
||||||
const bscript = require("../script");
|
const bscript = require("../script");
|
||||||
const bcrypto = require("../crypto");
|
|
||||||
const lazy = require("./lazy");
|
const lazy = require("./lazy");
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
|
@ -10,7 +10,7 @@ const bs58check = require('bs58check');
|
||||||
function stacksEqual(a, b) {
|
function stacksEqual(a, b) {
|
||||||
if (a.length !== b.length)
|
if (a.length !== b.length)
|
||||||
return false;
|
return false;
|
||||||
return a.every(function (x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -40,16 +40,16 @@ function p2sh(a, opts) {
|
||||||
network = (a.redeem && a.redeem.network) || networks_1.bitcoin;
|
network = (a.redeem && a.redeem.network) || networks_1.bitcoin;
|
||||||
}
|
}
|
||||||
const o = { network };
|
const o = { network };
|
||||||
const _address = lazy.value(function () {
|
const _address = lazy.value(() => {
|
||||||
const payload = bs58check.decode(a.address);
|
const payload = bs58check.decode(a.address);
|
||||||
const version = payload.readUInt8(0);
|
const version = payload.readUInt8(0);
|
||||||
const hash = payload.slice(1);
|
const hash = payload.slice(1);
|
||||||
return { version, hash };
|
return { version, hash };
|
||||||
});
|
});
|
||||||
const _chunks = lazy.value(function () {
|
const _chunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.input);
|
return bscript.decompile(a.input);
|
||||||
});
|
});
|
||||||
const _redeem = lazy.value(function () {
|
const _redeem = lazy.value(() => {
|
||||||
const chunks = _chunks();
|
const chunks = _chunks();
|
||||||
return {
|
return {
|
||||||
network,
|
network,
|
||||||
|
@ -59,7 +59,7 @@ function p2sh(a, opts) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
// output dependents
|
// output dependents
|
||||||
lazy.prop(o, 'address', function () {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
const payload = Buffer.allocUnsafe(21);
|
const payload = Buffer.allocUnsafe(21);
|
||||||
|
@ -67,7 +67,7 @@ function p2sh(a, opts) {
|
||||||
o.hash.copy(payload, 1);
|
o.hash.copy(payload, 1);
|
||||||
return bs58check.encode(payload);
|
return bs58check.encode(payload);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function () {
|
lazy.prop(o, 'hash', () => {
|
||||||
// in order of least effort
|
// in order of least effort
|
||||||
if (a.output)
|
if (a.output)
|
||||||
return a.output.slice(2, 22);
|
return a.output.slice(2, 22);
|
||||||
|
@ -76,23 +76,23 @@ function p2sh(a, opts) {
|
||||||
if (o.redeem && o.redeem.output)
|
if (o.redeem && o.redeem.output)
|
||||||
return bcrypto.hash160(o.redeem.output);
|
return bcrypto.hash160(o.redeem.output);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([OPS.OP_HASH160, o.hash, OPS.OP_EQUAL]);
|
return bscript.compile([OPS.OP_HASH160, o.hash, OPS.OP_EQUAL]);
|
||||||
});
|
});
|
||||||
// input dependents
|
// input dependents
|
||||||
lazy.prop(o, 'redeem', function () {
|
lazy.prop(o, 'redeem', () => {
|
||||||
if (!a.input)
|
if (!a.input)
|
||||||
return;
|
return;
|
||||||
return _redeem();
|
return _redeem();
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.redeem || !a.redeem.input || !a.redeem.output)
|
if (!a.redeem || !a.redeem.input || !a.redeem.output)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([].concat(bscript.decompile(a.redeem.input), a.redeem.output));
|
return bscript.compile([].concat(bscript.decompile(a.redeem.input), a.redeem.output));
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function () {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (o.redeem && o.redeem.witness)
|
if (o.redeem && o.redeem.witness)
|
||||||
return o.redeem.witness;
|
return o.redeem.witness;
|
||||||
if (o.input)
|
if (o.input)
|
||||||
|
@ -126,7 +126,7 @@ function p2sh(a, opts) {
|
||||||
hash = hash2;
|
hash = hash2;
|
||||||
}
|
}
|
||||||
// inlined to prevent 'no-inner-declarations' failing
|
// inlined to prevent 'no-inner-declarations' failing
|
||||||
const checkRedeem = function (redeem) {
|
const checkRedeem = (redeem) => {
|
||||||
// is the redeem output empty/invalid?
|
// is the redeem output empty/invalid?
|
||||||
if (redeem.output) {
|
if (redeem.output) {
|
||||||
const decompile = bscript.decompile(redeem.output);
|
const decompile = bscript.decompile(redeem.output);
|
||||||
|
@ -147,7 +147,7 @@ function p2sh(a, opts) {
|
||||||
if (hasInput && hasWitness)
|
if (hasInput && hasWitness)
|
||||||
throw new TypeError('Input and witness provided');
|
throw new TypeError('Input and witness provided');
|
||||||
if (hasInput) {
|
if (hasInput) {
|
||||||
const richunks = (bscript.decompile(redeem.input));
|
const richunks = bscript.decompile(redeem.input);
|
||||||
if (!bscript.isPushOnly(richunks))
|
if (!bscript.isPushOnly(richunks))
|
||||||
throw new TypeError('Non push-only scriptSig');
|
throw new TypeError('Non push-only scriptSig');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const bscript = require("../script");
|
|
||||||
const bcrypto = require("../crypto");
|
const bcrypto = require("../crypto");
|
||||||
const lazy = require("./lazy");
|
|
||||||
const networks_1 = require("../networks");
|
const networks_1 = require("../networks");
|
||||||
|
const bscript = require("../script");
|
||||||
|
const lazy = require("./lazy");
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
@ -26,7 +26,7 @@ function p2wpkh(a, opts) {
|
||||||
signature: typef.maybe(bscript.isCanonicalScriptSignature),
|
signature: typef.maybe(bscript.isCanonicalScriptSignature),
|
||||||
witness: typef.maybe(typef.arrayOf(typef.Buffer)),
|
witness: typef.maybe(typef.arrayOf(typef.Buffer)),
|
||||||
}, a);
|
}, a);
|
||||||
const _address = lazy.value(function () {
|
const _address = lazy.value(() => {
|
||||||
const result = bech32.decode(a.address);
|
const result = bech32.decode(a.address);
|
||||||
const version = result.words.shift();
|
const version = result.words.shift();
|
||||||
const data = bech32.fromWords(result.words);
|
const data = bech32.fromWords(result.words);
|
||||||
|
@ -38,14 +38,14 @@ function p2wpkh(a, opts) {
|
||||||
});
|
});
|
||||||
const network = a.network || networks_1.bitcoin;
|
const network = a.network || networks_1.bitcoin;
|
||||||
const o = { network };
|
const o = { network };
|
||||||
lazy.prop(o, 'address', function () {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
const words = bech32.toWords(o.hash);
|
const words = bech32.toWords(o.hash);
|
||||||
words.unshift(0x00);
|
words.unshift(0x00);
|
||||||
return bech32.encode(network.bech32, words);
|
return bech32.encode(network.bech32, words);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function () {
|
lazy.prop(o, 'hash', () => {
|
||||||
if (a.output)
|
if (a.output)
|
||||||
return a.output.slice(2, 22);
|
return a.output.slice(2, 22);
|
||||||
if (a.address)
|
if (a.address)
|
||||||
|
@ -53,29 +53,29 @@ function p2wpkh(a, opts) {
|
||||||
if (a.pubkey || o.pubkey)
|
if (a.pubkey || o.pubkey)
|
||||||
return bcrypto.hash160(a.pubkey || o.pubkey);
|
return bcrypto.hash160(a.pubkey || o.pubkey);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([OPS.OP_0, o.hash]);
|
return bscript.compile([OPS.OP_0, o.hash]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkey', function () {
|
lazy.prop(o, 'pubkey', () => {
|
||||||
if (a.pubkey)
|
if (a.pubkey)
|
||||||
return a.pubkey;
|
return a.pubkey;
|
||||||
if (!a.witness)
|
if (!a.witness)
|
||||||
return;
|
return;
|
||||||
return a.witness[1];
|
return a.witness[1];
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signature', function () {
|
lazy.prop(o, 'signature', () => {
|
||||||
if (!a.witness)
|
if (!a.witness)
|
||||||
return;
|
return;
|
||||||
return a.witness[0];
|
return a.witness[0];
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!o.witness)
|
if (!o.witness)
|
||||||
return;
|
return;
|
||||||
return EMPTY_BUFFER;
|
return EMPTY_BUFFER;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function () {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!a.pubkey)
|
if (!a.pubkey)
|
||||||
return;
|
return;
|
||||||
if (!a.signature)
|
if (!a.signature)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const bcrypto = require("../crypto");
|
||||||
const networks_1 = require("../networks");
|
const networks_1 = require("../networks");
|
||||||
const bscript = require("../script");
|
const bscript = require("../script");
|
||||||
const bcrypto = require("../crypto");
|
|
||||||
const lazy = require("./lazy");
|
const lazy = require("./lazy");
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
|
@ -11,7 +11,7 @@ const EMPTY_BUFFER = Buffer.alloc(0);
|
||||||
function stacksEqual(a, b) {
|
function stacksEqual(a, b) {
|
||||||
if (a.length !== b.length)
|
if (a.length !== b.length)
|
||||||
return false;
|
return false;
|
||||||
return a.every(function (x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ function p2wsh(a, opts) {
|
||||||
input: typef.maybe(typef.BufferN(0)),
|
input: typef.maybe(typef.BufferN(0)),
|
||||||
witness: typef.maybe(typef.arrayOf(typef.Buffer)),
|
witness: typef.maybe(typef.arrayOf(typef.Buffer)),
|
||||||
}, a);
|
}, a);
|
||||||
const _address = lazy.value(function () {
|
const _address = lazy.value(() => {
|
||||||
const result = bech32.decode(a.address);
|
const result = bech32.decode(a.address);
|
||||||
const version = result.words.shift();
|
const version = result.words.shift();
|
||||||
const data = bech32.fromWords(result.words);
|
const data = bech32.fromWords(result.words);
|
||||||
|
@ -46,7 +46,7 @@ function p2wsh(a, opts) {
|
||||||
data: Buffer.from(data),
|
data: Buffer.from(data),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const _rchunks = lazy.value(function () {
|
const _rchunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.redeem.input);
|
return bscript.decompile(a.redeem.input);
|
||||||
});
|
});
|
||||||
let network = a.network;
|
let network = a.network;
|
||||||
|
@ -54,14 +54,14 @@ function p2wsh(a, opts) {
|
||||||
network = (a.redeem && a.redeem.network) || networks_1.bitcoin;
|
network = (a.redeem && a.redeem.network) || networks_1.bitcoin;
|
||||||
}
|
}
|
||||||
const o = { network };
|
const o = { network };
|
||||||
lazy.prop(o, 'address', function () {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
const words = bech32.toWords(o.hash);
|
const words = bech32.toWords(o.hash);
|
||||||
words.unshift(0x00);
|
words.unshift(0x00);
|
||||||
return bech32.encode(network.bech32, words);
|
return bech32.encode(network.bech32, words);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function () {
|
lazy.prop(o, 'hash', () => {
|
||||||
if (a.output)
|
if (a.output)
|
||||||
return a.output.slice(2);
|
return a.output.slice(2);
|
||||||
if (a.address)
|
if (a.address)
|
||||||
|
@ -69,12 +69,12 @@ function p2wsh(a, opts) {
|
||||||
if (o.redeem && o.redeem.output)
|
if (o.redeem && o.redeem.output)
|
||||||
return bcrypto.sha256(o.redeem.output);
|
return bcrypto.sha256(o.redeem.output);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash)
|
if (!o.hash)
|
||||||
return;
|
return;
|
||||||
return bscript.compile([OPS.OP_0, o.hash]);
|
return bscript.compile([OPS.OP_0, o.hash]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'redeem', function () {
|
lazy.prop(o, 'redeem', () => {
|
||||||
if (!a.witness)
|
if (!a.witness)
|
||||||
return;
|
return;
|
||||||
return {
|
return {
|
||||||
|
@ -83,12 +83,12 @@ function p2wsh(a, opts) {
|
||||||
witness: a.witness.slice(0, -1),
|
witness: a.witness.slice(0, -1),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!o.witness)
|
if (!o.witness)
|
||||||
return;
|
return;
|
||||||
return EMPTY_BUFFER;
|
return EMPTY_BUFFER;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function () {
|
lazy.prop(o, 'witness', () => {
|
||||||
// transform redeem input to witness stack?
|
// transform redeem input to witness stack?
|
||||||
if (a.redeem &&
|
if (a.redeem &&
|
||||||
a.redeem.input &&
|
a.redeem.input &&
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const types = require("./types");
|
|
||||||
const scriptNumber = require("./script_number");
|
const scriptNumber = require("./script_number");
|
||||||
const scriptSignature = require("./script_signature");
|
const scriptSignature = require("./script_signature");
|
||||||
|
const types = require("./types");
|
||||||
const bip66 = require('bip66');
|
const bip66 = require('bip66');
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
const pushdata = require('pushdata-bitcoin');
|
const pushdata = require('pushdata-bitcoin');
|
||||||
|
@ -47,7 +47,7 @@ function compile(chunks) {
|
||||||
if (chunksIsBuffer(chunks))
|
if (chunksIsBuffer(chunks))
|
||||||
return chunks;
|
return chunks;
|
||||||
typeforce(types.Array, chunks);
|
typeforce(types.Array, chunks);
|
||||||
const bufferSize = chunks.reduce(function (accum, chunk) {
|
const bufferSize = chunks.reduce((accum, chunk) => {
|
||||||
// data chunk
|
// data chunk
|
||||||
if (singleChunkIsBuffer(chunk)) {
|
if (singleChunkIsBuffer(chunk)) {
|
||||||
// adhere to BIP62.3, minimal push policy
|
// adhere to BIP62.3, minimal push policy
|
||||||
|
@ -61,7 +61,7 @@ function compile(chunks) {
|
||||||
}, 0.0);
|
}, 0.0);
|
||||||
const buffer = Buffer.allocUnsafe(bufferSize);
|
const buffer = Buffer.allocUnsafe(bufferSize);
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
chunks.forEach(function (chunk) {
|
chunks.forEach(chunk => {
|
||||||
// data chunk
|
// data chunk
|
||||||
if (singleChunkIsBuffer(chunk)) {
|
if (singleChunkIsBuffer(chunk)) {
|
||||||
// adhere to BIP62.3, minimal push policy
|
// adhere to BIP62.3, minimal push policy
|
||||||
|
@ -130,7 +130,7 @@ function toASM(chunks) {
|
||||||
chunks = decompile(chunks);
|
chunks = decompile(chunks);
|
||||||
}
|
}
|
||||||
return chunks
|
return chunks
|
||||||
.map(function (chunk) {
|
.map(chunk => {
|
||||||
// data?
|
// data?
|
||||||
if (singleChunkIsBuffer(chunk)) {
|
if (singleChunkIsBuffer(chunk)) {
|
||||||
const op = asMinimalOP(chunk);
|
const op = asMinimalOP(chunk);
|
||||||
|
@ -146,7 +146,7 @@ function toASM(chunks) {
|
||||||
exports.toASM = toASM;
|
exports.toASM = toASM;
|
||||||
function fromASM(asm) {
|
function fromASM(asm) {
|
||||||
typeforce(types.String, asm);
|
typeforce(types.String, asm);
|
||||||
return compile(asm.split(' ').map(function (chunkStr) {
|
return compile(asm.split(' ').map(chunkStr => {
|
||||||
// opcode?
|
// opcode?
|
||||||
if (exports.OPS[chunkStr] !== undefined)
|
if (exports.OPS[chunkStr] !== undefined)
|
||||||
return exports.OPS[chunkStr];
|
return exports.OPS[chunkStr];
|
||||||
|
@ -159,7 +159,7 @@ exports.fromASM = fromASM;
|
||||||
function toStack(chunks) {
|
function toStack(chunks) {
|
||||||
chunks = decompile(chunks);
|
chunks = decompile(chunks);
|
||||||
typeforce(isPushOnly, chunks);
|
typeforce(isPushOnly, chunks);
|
||||||
return chunks.map(function (op) {
|
return chunks.map(op => {
|
||||||
if (singleChunkIsBuffer(op))
|
if (singleChunkIsBuffer(op))
|
||||||
return op;
|
return op;
|
||||||
if (op === exports.OPS.OP_0)
|
if (op === exports.OPS.OP_0)
|
||||||
|
@ -186,5 +186,6 @@ function isCanonicalScriptSignature(buffer) {
|
||||||
return bip66.check(buffer.slice(0, -1));
|
return bip66.check(buffer.slice(0, -1));
|
||||||
}
|
}
|
||||||
exports.isCanonicalScriptSignature = isCanonicalScriptSignature;
|
exports.isCanonicalScriptSignature = isCanonicalScriptSignature;
|
||||||
|
// tslint:disable-next-line variable-name
|
||||||
exports.number = scriptNumber;
|
exports.number = scriptNumber;
|
||||||
exports.signature = scriptSignature;
|
exports.signature = scriptSignature;
|
||||||
|
|
|
@ -24,7 +24,7 @@ function decode(buffer, maxLength, minimal) {
|
||||||
}
|
}
|
||||||
// 32-bit / 24-bit / 16-bit / 8-bit
|
// 32-bit / 24-bit / 16-bit / 8-bit
|
||||||
let result = 0;
|
let result = 0;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
result |= buffer[i] << (8 * i);
|
result |= buffer[i] << (8 * i);
|
||||||
}
|
}
|
||||||
if (buffer[length - 1] & 0x80)
|
if (buffer[length - 1] & 0x80)
|
||||||
|
@ -45,12 +45,12 @@ function scriptNumSize(i) {
|
||||||
? 1
|
? 1
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
function encode(number) {
|
function encode(_number) {
|
||||||
let value = Math.abs(number);
|
let value = Math.abs(_number);
|
||||||
const size = scriptNumSize(value);
|
const size = scriptNumSize(value);
|
||||||
const buffer = Buffer.allocUnsafe(size);
|
const buffer = Buffer.allocUnsafe(size);
|
||||||
const negative = number < 0;
|
const negative = _number < 0;
|
||||||
for (var i = 0; i < size; ++i) {
|
for (let i = 0; i < size; ++i) {
|
||||||
buffer.writeUInt8(value & 0xff, i);
|
buffer.writeUInt8(value & 0xff, i);
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,11 @@ function decode(buffer) {
|
||||||
const hashTypeMod = hashType & ~0x80;
|
const hashTypeMod = hashType & ~0x80;
|
||||||
if (hashTypeMod <= 0 || hashTypeMod >= 4)
|
if (hashTypeMod <= 0 || hashTypeMod >= 4)
|
||||||
throw new Error('Invalid hashType ' + hashType);
|
throw new Error('Invalid hashType ' + hashType);
|
||||||
const decode = bip66.decode(buffer.slice(0, -1));
|
const decoded = bip66.decode(buffer.slice(0, -1));
|
||||||
const r = fromDER(decode.r);
|
const r = fromDER(decoded.r);
|
||||||
const s = fromDER(decode.s);
|
const s = fromDER(decoded.s);
|
||||||
return {
|
const signature = Buffer.concat([r, s], 64);
|
||||||
signature: Buffer.concat([r, s], 64),
|
return { signature, hashType };
|
||||||
hashType: hashType,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
exports.decode = decode;
|
exports.decode = decode;
|
||||||
function encode(signature, hashType) {
|
function encode(signature, hashType) {
|
||||||
|
|
|
@ -18,6 +18,6 @@ function check(script, allowIncomplete) {
|
||||||
return chunks.slice(1).every(bscript.isCanonicalScriptSignature);
|
return chunks.slice(1).every(bscript.isCanonicalScriptSignature);
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'multisig input';
|
return 'multisig input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// m [pubKeys ...] n OP_CHECKMULTISIG
|
// m [pubKeys ...] n OP_CHECKMULTISIG
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const bscript = require("../../script");
|
const bscript = require("../../script");
|
||||||
const types = require("../../types");
|
|
||||||
const script_1 = require("../../script");
|
const script_1 = require("../../script");
|
||||||
|
const types = require("../../types");
|
||||||
const OP_INT_BASE = script_1.OPS.OP_RESERVED; // OP_1 - 1
|
const OP_INT_BASE = script_1.OPS.OP_RESERVED; // OP_1 - 1
|
||||||
function check(script, allowIncomplete) {
|
function check(script, allowIncomplete) {
|
||||||
const chunks = bscript.decompile(script);
|
const chunks = bscript.decompile(script);
|
||||||
|
@ -31,6 +31,6 @@ function check(script, allowIncomplete) {
|
||||||
return keys.every(bscript.isCanonicalPubKey);
|
return keys.every(bscript.isCanonicalPubKey);
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'multi-sig output';
|
return 'multi-sig output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@ function check(script) {
|
||||||
return buffer.length > 1 && buffer[0] === OPS.OP_RETURN;
|
return buffer.length > 1 && buffer[0] === OPS.OP_RETURN;
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'null data output';
|
return 'null data output';
|
||||||
};
|
};
|
||||||
const output = { check };
|
const output = { check };
|
||||||
|
|
|
@ -4,9 +4,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const bscript = require("../../script");
|
const bscript = require("../../script");
|
||||||
function check(script) {
|
function check(script) {
|
||||||
const chunks = bscript.decompile(script);
|
const chunks = bscript.decompile(script);
|
||||||
return (chunks.length === 1 && bscript.isCanonicalScriptSignature(chunks[0]));
|
return (chunks.length === 1 &&
|
||||||
|
bscript.isCanonicalScriptSignature(chunks[0]));
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'pubKey input';
|
return 'pubKey input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,6 @@ function check(script) {
|
||||||
chunks[1] === script_1.OPS.OP_CHECKSIG);
|
chunks[1] === script_1.OPS.OP_CHECKSIG);
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'pubKey output';
|
return 'pubKey output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,6 @@ function check(script) {
|
||||||
bscript.isCanonicalPubKey(chunks[1]));
|
bscript.isCanonicalPubKey(chunks[1]));
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'pubKeyHash input';
|
return 'pubKeyHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,6 @@ function check(script) {
|
||||||
buffer[24] === script_1.OPS.OP_CHECKSIG);
|
buffer[24] === script_1.OPS.OP_CHECKSIG);
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'pubKeyHash output';
|
return 'pubKeyHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,6 @@ function check(script, allowIncomplete) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'scriptHash input';
|
return 'scriptHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,6 @@ function check(script) {
|
||||||
buffer[22] === script_1.OPS.OP_EQUAL);
|
buffer[22] === script_1.OPS.OP_EQUAL);
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'scriptHash output';
|
return 'scriptHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
// OP_RETURN {aa21a9ed} {commitment}
|
// OP_RETURN {aa21a9ed} {commitment}
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const bscript = require("../../script");
|
const bscript = require("../../script");
|
||||||
|
const script_1 = require("../../script");
|
||||||
const types = require("../../types");
|
const types = require("../../types");
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
const script_1 = require("../../script");
|
|
||||||
const HEADER = Buffer.from('aa21a9ed', 'hex');
|
const HEADER = Buffer.from('aa21a9ed', 'hex');
|
||||||
function check(script) {
|
function check(script) {
|
||||||
const buffer = bscript.compile(script);
|
const buffer = bscript.compile(script);
|
||||||
|
@ -14,7 +14,7 @@ function check(script) {
|
||||||
buffer.slice(2, 6).equals(HEADER));
|
buffer.slice(2, 6).equals(HEADER));
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'Witness commitment output';
|
return 'Witness commitment output';
|
||||||
};
|
};
|
||||||
function encode(commitment) {
|
function encode(commitment) {
|
||||||
|
|
|
@ -12,6 +12,6 @@ function check(script) {
|
||||||
isCompressedCanonicalPubKey(chunks[1]));
|
isCompressedCanonicalPubKey(chunks[1]));
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'witnessPubKeyHash input';
|
return 'witnessPubKeyHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,6 @@ function check(script) {
|
||||||
return buffer.length === 22 && buffer[0] === script_1.OPS.OP_0 && buffer[1] === 0x14;
|
return buffer.length === 22 && buffer[0] === script_1.OPS.OP_0 && buffer[1] === 0x14;
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'Witness pubKeyHash output';
|
return 'Witness pubKeyHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,6 @@ function check(chunks, allowIncomplete) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'witnessScriptHash input';
|
return 'witnessScriptHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,6 @@ function check(script) {
|
||||||
return buffer.length === 34 && buffer[0] === script_1.OPS.OP_0 && buffer[1] === 0x20;
|
return buffer.length === 34 && buffer[0] === script_1.OPS.OP_0 && buffer[1] === 0x20;
|
||||||
}
|
}
|
||||||
exports.check = check;
|
exports.check = check;
|
||||||
check.toJSON = function () {
|
check.toJSON = () => {
|
||||||
return 'Witness scriptHash output';
|
return 'Witness scriptHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const bcrypto = require("./crypto");
|
|
||||||
const bscript = require("./script");
|
|
||||||
const types = require("./types");
|
|
||||||
const bufferutils = require("./bufferutils");
|
const bufferutils = require("./bufferutils");
|
||||||
const bufferutils_1 = require("./bufferutils");
|
const bufferutils_1 = require("./bufferutils");
|
||||||
|
const bcrypto = require("./crypto");
|
||||||
|
const bscript = require("./script");
|
||||||
const script_1 = require("./script");
|
const script_1 = require("./script");
|
||||||
|
const types = require("./types");
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
const varuint = require('varuint-bitcoin');
|
const varuint = require('varuint-bitcoin');
|
||||||
function varSliceSize(someScript) {
|
function varSliceSize(someScript) {
|
||||||
|
@ -38,7 +38,7 @@ class Transaction {
|
||||||
this.ins = [];
|
this.ins = [];
|
||||||
this.outs = [];
|
this.outs = [];
|
||||||
}
|
}
|
||||||
static fromBuffer(buffer, __noStrict) {
|
static fromBuffer(buffer, _NO_STRICT) {
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
function readSlice(n) {
|
function readSlice(n) {
|
||||||
offset += n;
|
offset += n;
|
||||||
|
@ -70,7 +70,7 @@ class Transaction {
|
||||||
function readVector() {
|
function readVector() {
|
||||||
const count = readVarInt();
|
const count = readVarInt();
|
||||||
const vector = [];
|
const vector = [];
|
||||||
for (var i = 0; i < count; i++)
|
for (let i = 0; i < count; i++)
|
||||||
vector.push(readVarSlice());
|
vector.push(readVarSlice());
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ class Transaction {
|
||||||
hasWitnesses = true;
|
hasWitnesses = true;
|
||||||
}
|
}
|
||||||
const vinLen = readVarInt();
|
const vinLen = readVarInt();
|
||||||
for (var i = 0; i < vinLen; ++i) {
|
for (let i = 0; i < vinLen; ++i) {
|
||||||
tx.ins.push({
|
tx.ins.push({
|
||||||
hash: readSlice(32),
|
hash: readSlice(32),
|
||||||
index: readUInt32(),
|
index: readUInt32(),
|
||||||
|
@ -95,14 +95,14 @@ class Transaction {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const voutLen = readVarInt();
|
const voutLen = readVarInt();
|
||||||
for (i = 0; i < voutLen; ++i) {
|
for (let i = 0; i < voutLen; ++i) {
|
||||||
tx.outs.push({
|
tx.outs.push({
|
||||||
value: readUInt64(),
|
value: readUInt64(),
|
||||||
script: readVarSlice(),
|
script: readVarSlice(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (hasWitnesses) {
|
if (hasWitnesses) {
|
||||||
for (i = 0; i < vinLen; ++i) {
|
for (let i = 0; i < vinLen; ++i) {
|
||||||
tx.ins[i].witness = readVector();
|
tx.ins[i].witness = readVector();
|
||||||
}
|
}
|
||||||
// was this pointless?
|
// was this pointless?
|
||||||
|
@ -110,7 +110,7 @@ class Transaction {
|
||||||
throw new Error('Transaction has superfluous witness data');
|
throw new Error('Transaction has superfluous witness data');
|
||||||
}
|
}
|
||||||
tx.locktime = readUInt32();
|
tx.locktime = readUInt32();
|
||||||
if (__noStrict)
|
if (_NO_STRICT)
|
||||||
return tx;
|
return tx;
|
||||||
if (offset !== buffer.length)
|
if (offset !== buffer.length)
|
||||||
throw new Error('Transaction has unexpected data');
|
throw new Error('Transaction has unexpected data');
|
||||||
|
@ -121,7 +121,7 @@ class Transaction {
|
||||||
}
|
}
|
||||||
static isCoinbaseHash(buffer) {
|
static isCoinbaseHash(buffer) {
|
||||||
typeforce(types.Hash256bit, buffer);
|
typeforce(types.Hash256bit, buffer);
|
||||||
for (var i = 0; i < 32; ++i) {
|
for (let i = 0; i < 32; ++i) {
|
||||||
if (buffer[i] !== 0)
|
if (buffer[i] !== 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -137,8 +137,8 @@ class Transaction {
|
||||||
}
|
}
|
||||||
// Add the input and return the input's index
|
// Add the input and return the input's index
|
||||||
return (this.ins.push({
|
return (this.ins.push({
|
||||||
hash: hash,
|
hash,
|
||||||
index: index,
|
index,
|
||||||
script: scriptSig || EMPTY_SCRIPT,
|
script: scriptSig || EMPTY_SCRIPT,
|
||||||
sequence: sequence,
|
sequence: sequence,
|
||||||
witness: EMPTY_WITNESS,
|
witness: EMPTY_WITNESS,
|
||||||
|
@ -149,7 +149,7 @@ class Transaction {
|
||||||
// Add the output and return the output's index
|
// Add the output and return the output's index
|
||||||
return (this.outs.push({
|
return (this.outs.push({
|
||||||
script: scriptPubKey,
|
script: scriptPubKey,
|
||||||
value: value,
|
value,
|
||||||
}) - 1);
|
}) - 1);
|
||||||
}
|
}
|
||||||
hasWitnesses() {
|
hasWitnesses() {
|
||||||
|
@ -168,23 +168,6 @@ class Transaction {
|
||||||
byteLength() {
|
byteLength() {
|
||||||
return this.__byteLength(true);
|
return this.__byteLength(true);
|
||||||
}
|
}
|
||||||
__byteLength(__allowWitness) {
|
|
||||||
const hasWitnesses = __allowWitness && this.hasWitnesses();
|
|
||||||
return ((hasWitnesses ? 10 : 8) +
|
|
||||||
varuint.encodingLength(this.ins.length) +
|
|
||||||
varuint.encodingLength(this.outs.length) +
|
|
||||||
this.ins.reduce((sum, input) => {
|
|
||||||
return sum + 40 + varSliceSize(input.script);
|
|
||||||
}, 0) +
|
|
||||||
this.outs.reduce((sum, output) => {
|
|
||||||
return sum + 8 + varSliceSize(output.script);
|
|
||||||
}, 0) +
|
|
||||||
(hasWitnesses
|
|
||||||
? this.ins.reduce((sum, input) => {
|
|
||||||
return sum + vectorSize(input.witness);
|
|
||||||
}, 0)
|
|
||||||
: 0));
|
|
||||||
}
|
|
||||||
clone() {
|
clone() {
|
||||||
const newTx = new Transaction();
|
const newTx = new Transaction();
|
||||||
newTx.version = this.version;
|
newTx.version = this.version;
|
||||||
|
@ -242,7 +225,7 @@ class Transaction {
|
||||||
// truncate outputs after
|
// truncate outputs after
|
||||||
txTmp.outs.length = inIndex + 1;
|
txTmp.outs.length = inIndex + 1;
|
||||||
// "blank" outputs before
|
// "blank" outputs before
|
||||||
for (var i = 0; i < inIndex; i++) {
|
for (let i = 0; i < inIndex; i++) {
|
||||||
txTmp.outs[i] = BLANK_OUTPUT;
|
txTmp.outs[i] = BLANK_OUTPUT;
|
||||||
}
|
}
|
||||||
// ignore sequence numbers (except at inIndex)
|
// ignore sequence numbers (except at inIndex)
|
||||||
|
@ -365,9 +348,37 @@ class Transaction {
|
||||||
toBuffer(buffer, initialOffset) {
|
toBuffer(buffer, initialOffset) {
|
||||||
return this.__toBuffer(buffer, initialOffset, true);
|
return this.__toBuffer(buffer, initialOffset, true);
|
||||||
}
|
}
|
||||||
__toBuffer(buffer, initialOffset, __allowWitness) {
|
toHex() {
|
||||||
|
return this.toBuffer(undefined, undefined).toString('hex');
|
||||||
|
}
|
||||||
|
setInputScript(index, scriptSig) {
|
||||||
|
typeforce(types.tuple(types.Number, types.Buffer), arguments);
|
||||||
|
this.ins[index].script = scriptSig;
|
||||||
|
}
|
||||||
|
setWitness(index, witness) {
|
||||||
|
typeforce(types.tuple(types.Number, [types.Buffer]), arguments);
|
||||||
|
this.ins[index].witness = witness;
|
||||||
|
}
|
||||||
|
__byteLength(_ALLOW_WITNESS) {
|
||||||
|
const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
|
||||||
|
return ((hasWitnesses ? 10 : 8) +
|
||||||
|
varuint.encodingLength(this.ins.length) +
|
||||||
|
varuint.encodingLength(this.outs.length) +
|
||||||
|
this.ins.reduce((sum, input) => {
|
||||||
|
return sum + 40 + varSliceSize(input.script);
|
||||||
|
}, 0) +
|
||||||
|
this.outs.reduce((sum, output) => {
|
||||||
|
return sum + 8 + varSliceSize(output.script);
|
||||||
|
}, 0) +
|
||||||
|
(hasWitnesses
|
||||||
|
? this.ins.reduce((sum, input) => {
|
||||||
|
return sum + vectorSize(input.witness);
|
||||||
|
}, 0)
|
||||||
|
: 0));
|
||||||
|
}
|
||||||
|
__toBuffer(buffer, initialOffset, _ALLOW_WITNESS) {
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
buffer = Buffer.allocUnsafe(this.__byteLength(__allowWitness));
|
buffer = Buffer.allocUnsafe(this.__byteLength(_ALLOW_WITNESS));
|
||||||
let offset = initialOffset || 0;
|
let offset = initialOffset || 0;
|
||||||
function writeSlice(slice) {
|
function writeSlice(slice) {
|
||||||
offset += slice.copy(buffer, offset);
|
offset += slice.copy(buffer, offset);
|
||||||
|
@ -397,7 +408,7 @@ class Transaction {
|
||||||
vector.forEach(writeVarSlice);
|
vector.forEach(writeVarSlice);
|
||||||
}
|
}
|
||||||
writeInt32(this.version);
|
writeInt32(this.version);
|
||||||
const hasWitnesses = __allowWitness && this.hasWitnesses();
|
const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
|
||||||
if (hasWitnesses) {
|
if (hasWitnesses) {
|
||||||
writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER);
|
writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER);
|
||||||
writeUInt8(Transaction.ADVANCED_TRANSACTION_FLAG);
|
writeUInt8(Transaction.ADVANCED_TRANSACTION_FLAG);
|
||||||
|
@ -430,17 +441,6 @@ class Transaction {
|
||||||
return buffer.slice(initialOffset, offset);
|
return buffer.slice(initialOffset, offset);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
toHex() {
|
|
||||||
return this.toBuffer(undefined, undefined).toString('hex');
|
|
||||||
}
|
|
||||||
setInputScript(index, scriptSig) {
|
|
||||||
typeforce(types.tuple(types.Number, types.Buffer), arguments);
|
|
||||||
this.ins[index].script = scriptSig;
|
|
||||||
}
|
|
||||||
setWitness(index, witness) {
|
|
||||||
typeforce(types.tuple(types.Number, [types.Buffer]), arguments);
|
|
||||||
this.ins[index].witness = witness;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Transaction.DEFAULT_SEQUENCE = 0xffffffff;
|
Transaction.DEFAULT_SEQUENCE = 0xffffffff;
|
||||||
Transaction.SIGHASH_ALL = 0x01;
|
Transaction.SIGHASH_ALL = 0x01;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const networks = require("./networks");
|
|
||||||
const bufferutils_1 = require("./bufferutils");
|
|
||||||
const transaction_1 = require("./transaction");
|
|
||||||
const ECPair = require("./ecpair");
|
|
||||||
const types = require("./types");
|
|
||||||
const baddress = require("./address");
|
const baddress = require("./address");
|
||||||
const bcrypto = require("./crypto");
|
const bufferutils_1 = require("./bufferutils");
|
||||||
const bscript = require("./script");
|
|
||||||
const payments = require("./payments");
|
|
||||||
const classify = require("./classify");
|
const classify = require("./classify");
|
||||||
|
const bcrypto = require("./crypto");
|
||||||
|
const ECPair = require("./ecpair");
|
||||||
|
const networks = require("./networks");
|
||||||
|
const payments = require("./payments");
|
||||||
|
const bscript = require("./script");
|
||||||
const script_1 = require("./script");
|
const script_1 = require("./script");
|
||||||
|
const transaction_1 = require("./transaction");
|
||||||
|
const types = require("./types");
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
const SCRIPT_TYPES = classify.types;
|
const SCRIPT_TYPES = classify.types;
|
||||||
function txIsString(tx) {
|
function txIsString(tx) {
|
||||||
|
@ -20,15 +20,6 @@ function txIsTransaction(tx) {
|
||||||
return tx instanceof transaction_1.Transaction;
|
return tx instanceof transaction_1.Transaction;
|
||||||
}
|
}
|
||||||
class TransactionBuilder {
|
class TransactionBuilder {
|
||||||
constructor(network, maximumFeeRate) {
|
|
||||||
this.__prevTxSet = {};
|
|
||||||
this.network = network || networks.bitcoin;
|
|
||||||
// WARNING: This is __NOT__ to be relied on, its just another potential safety mechanism (safety in-depth)
|
|
||||||
this.maximumFeeRate = maximumFeeRate || 2500;
|
|
||||||
this.__inputs = [];
|
|
||||||
this.__tx = new transaction_1.Transaction();
|
|
||||||
this.__tx.version = 2;
|
|
||||||
}
|
|
||||||
static fromTransaction(transaction, network) {
|
static fromTransaction(transaction, network) {
|
||||||
const txb = new TransactionBuilder(network);
|
const txb = new TransactionBuilder(network);
|
||||||
// Copy transaction fields
|
// Copy transaction fields
|
||||||
|
@ -47,33 +38,42 @@ class TransactionBuilder {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// fix some things not possible through the public API
|
// fix some things not possible through the public API
|
||||||
txb.__inputs.forEach((input, i) => {
|
txb.__INPUTS.forEach((input, i) => {
|
||||||
fixMultisigOrder(input, transaction, i);
|
fixMultisigOrder(input, transaction, i);
|
||||||
});
|
});
|
||||||
return txb;
|
return txb;
|
||||||
}
|
}
|
||||||
|
constructor(network, maximumFeeRate) {
|
||||||
|
this.__PREV_TX_SET = {};
|
||||||
|
this.network = network || networks.bitcoin;
|
||||||
|
// WARNING: This is __NOT__ to be relied on, its just another potential safety mechanism (safety in-depth)
|
||||||
|
this.maximumFeeRate = maximumFeeRate || 2500;
|
||||||
|
this.__INPUTS = [];
|
||||||
|
this.__TX = new transaction_1.Transaction();
|
||||||
|
this.__TX.version = 2;
|
||||||
|
}
|
||||||
setLockTime(locktime) {
|
setLockTime(locktime) {
|
||||||
typeforce(types.UInt32, locktime);
|
typeforce(types.UInt32, locktime);
|
||||||
// if any signatures exist, throw
|
// if any signatures exist, throw
|
||||||
if (this.__inputs.some(input => {
|
if (this.__INPUTS.some(input => {
|
||||||
if (!input.signatures)
|
if (!input.signatures)
|
||||||
return false;
|
return false;
|
||||||
return input.signatures.some(s => s !== undefined);
|
return input.signatures.some(s => s !== undefined);
|
||||||
})) {
|
})) {
|
||||||
throw new Error('No, this would invalidate signatures');
|
throw new Error('No, this would invalidate signatures');
|
||||||
}
|
}
|
||||||
this.__tx.locktime = locktime;
|
this.__TX.locktime = locktime;
|
||||||
}
|
}
|
||||||
setVersion(version) {
|
setVersion(version) {
|
||||||
typeforce(types.UInt32, version);
|
typeforce(types.UInt32, version);
|
||||||
// XXX: this might eventually become more complex depending on what the versions represent
|
// XXX: this might eventually become more complex depending on what the versions represent
|
||||||
this.__tx.version = version;
|
this.__TX.version = version;
|
||||||
}
|
}
|
||||||
addInput(txHash, vout, sequence, prevOutScript) {
|
addInput(txHash, vout, sequence, prevOutScript) {
|
||||||
if (!this.__canModifyInputs()) {
|
if (!this.__canModifyInputs()) {
|
||||||
throw new Error('No, this would invalidate signatures');
|
throw new Error('No, this would invalidate signatures');
|
||||||
}
|
}
|
||||||
let value = undefined;
|
let value;
|
||||||
// is it a hex string?
|
// is it a hex string?
|
||||||
if (txIsString(txHash)) {
|
if (txIsString(txHash)) {
|
||||||
// transaction hashs's are displayed in reverse order, un-reverse it
|
// transaction hashs's are displayed in reverse order, un-reverse it
|
||||||
|
@ -87,17 +87,90 @@ class TransactionBuilder {
|
||||||
txHash = txHash.getHash(false);
|
txHash = txHash.getHash(false);
|
||||||
}
|
}
|
||||||
return this.__addInputUnsafe(txHash, vout, {
|
return this.__addInputUnsafe(txHash, vout, {
|
||||||
sequence: sequence,
|
sequence,
|
||||||
prevOutScript: prevOutScript,
|
prevOutScript,
|
||||||
value: value,
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
addOutput(scriptPubKey, value) {
|
||||||
|
if (!this.__canModifyOutputs()) {
|
||||||
|
throw new Error('No, this would invalidate signatures');
|
||||||
|
}
|
||||||
|
// Attempt to get a script if it's a base58 or bech32 address string
|
||||||
|
if (typeof scriptPubKey === 'string') {
|
||||||
|
scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network);
|
||||||
|
}
|
||||||
|
return this.__TX.addOutput(scriptPubKey, value);
|
||||||
|
}
|
||||||
|
build() {
|
||||||
|
return this.__build(false);
|
||||||
|
}
|
||||||
|
buildIncomplete() {
|
||||||
|
return this.__build(true);
|
||||||
|
}
|
||||||
|
sign(vin, keyPair, redeemScript, hashType, witnessValue, witnessScript) {
|
||||||
|
// TODO: remove keyPair.network matching in 4.0.0
|
||||||
|
if (keyPair.network && keyPair.network !== this.network)
|
||||||
|
throw new TypeError('Inconsistent network');
|
||||||
|
if (!this.__INPUTS[vin])
|
||||||
|
throw new Error('No input at index: ' + vin);
|
||||||
|
hashType = hashType || transaction_1.Transaction.SIGHASH_ALL;
|
||||||
|
if (this.__needsOutputs(hashType))
|
||||||
|
throw new Error('Transaction needs outputs');
|
||||||
|
const input = this.__INPUTS[vin];
|
||||||
|
// if redeemScript was previously provided, enforce consistency
|
||||||
|
if (input.redeemScript !== undefined &&
|
||||||
|
redeemScript &&
|
||||||
|
!input.redeemScript.equals(redeemScript)) {
|
||||||
|
throw new Error('Inconsistent redeemScript');
|
||||||
|
}
|
||||||
|
const ourPubKey = keyPair.publicKey || keyPair.getPublicKey();
|
||||||
|
if (!canSign(input)) {
|
||||||
|
if (witnessValue !== undefined) {
|
||||||
|
if (input.value !== undefined && input.value !== witnessValue)
|
||||||
|
throw new Error('Input did not match witnessValue');
|
||||||
|
typeforce(types.Satoshi, witnessValue);
|
||||||
|
input.value = witnessValue;
|
||||||
|
}
|
||||||
|
if (!canSign(input)) {
|
||||||
|
const prepared = prepareInput(input, ourPubKey, redeemScript, witnessScript);
|
||||||
|
// updates inline
|
||||||
|
Object.assign(input, prepared);
|
||||||
|
}
|
||||||
|
if (!canSign(input))
|
||||||
|
throw Error(input.prevOutType + ' not supported');
|
||||||
|
}
|
||||||
|
// ready to sign
|
||||||
|
let signatureHash;
|
||||||
|
if (input.hasWitness) {
|
||||||
|
signatureHash = this.__TX.hashForWitnessV0(vin, input.signScript, input.value, hashType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
signatureHash = this.__TX.hashForSignature(vin, input.signScript, hashType);
|
||||||
|
}
|
||||||
|
// enforce in order signing of public keys
|
||||||
|
const signed = input.pubkeys.some((pubKey, i) => {
|
||||||
|
if (!ourPubKey.equals(pubKey))
|
||||||
|
return false;
|
||||||
|
if (input.signatures[i])
|
||||||
|
throw new Error('Signature already exists');
|
||||||
|
// TODO: add tests
|
||||||
|
if (ourPubKey.length !== 33 && input.hasWitness) {
|
||||||
|
throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH');
|
||||||
|
}
|
||||||
|
const signature = keyPair.sign(signatureHash);
|
||||||
|
input.signatures[i] = bscript.signature.encode(signature, hashType);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (!signed)
|
||||||
|
throw new Error('Key pair cannot sign for this input');
|
||||||
|
}
|
||||||
__addInputUnsafe(txHash, vout, options) {
|
__addInputUnsafe(txHash, vout, options) {
|
||||||
if (transaction_1.Transaction.isCoinbaseHash(txHash)) {
|
if (transaction_1.Transaction.isCoinbaseHash(txHash)) {
|
||||||
throw new Error('coinbase inputs not supported');
|
throw new Error('coinbase inputs not supported');
|
||||||
}
|
}
|
||||||
const prevTxOut = txHash.toString('hex') + ':' + vout;
|
const prevTxOut = txHash.toString('hex') + ':' + vout;
|
||||||
if (this.__prevTxSet[prevTxOut] !== undefined)
|
if (this.__PREV_TX_SET[prevTxOut] !== undefined)
|
||||||
throw new Error('Duplicate TxOut: ' + prevTxOut);
|
throw new Error('Duplicate TxOut: ' + prevTxOut);
|
||||||
let input = {};
|
let input = {};
|
||||||
// derive what we can from the scriptSig
|
// derive what we can from the scriptSig
|
||||||
|
@ -122,37 +195,21 @@ class TransactionBuilder {
|
||||||
input.prevOutScript = options.prevOutScript;
|
input.prevOutScript = options.prevOutScript;
|
||||||
input.prevOutType = prevOutType || classify.output(options.prevOutScript);
|
input.prevOutType = prevOutType || classify.output(options.prevOutScript);
|
||||||
}
|
}
|
||||||
const vin = this.__tx.addInput(txHash, vout, options.sequence, options.scriptSig);
|
const vin = this.__TX.addInput(txHash, vout, options.sequence, options.scriptSig);
|
||||||
this.__inputs[vin] = input;
|
this.__INPUTS[vin] = input;
|
||||||
this.__prevTxSet[prevTxOut] = true;
|
this.__PREV_TX_SET[prevTxOut] = true;
|
||||||
return vin;
|
return vin;
|
||||||
}
|
}
|
||||||
addOutput(scriptPubKey, value) {
|
|
||||||
if (!this.__canModifyOutputs()) {
|
|
||||||
throw new Error('No, this would invalidate signatures');
|
|
||||||
}
|
|
||||||
// Attempt to get a script if it's a base58 or bech32 address string
|
|
||||||
if (typeof scriptPubKey === 'string') {
|
|
||||||
scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network);
|
|
||||||
}
|
|
||||||
return this.__tx.addOutput(scriptPubKey, value);
|
|
||||||
}
|
|
||||||
build() {
|
|
||||||
return this.__build(false);
|
|
||||||
}
|
|
||||||
buildIncomplete() {
|
|
||||||
return this.__build(true);
|
|
||||||
}
|
|
||||||
__build(allowIncomplete) {
|
__build(allowIncomplete) {
|
||||||
if (!allowIncomplete) {
|
if (!allowIncomplete) {
|
||||||
if (!this.__tx.ins.length)
|
if (!this.__TX.ins.length)
|
||||||
throw new Error('Transaction has no inputs');
|
throw new Error('Transaction has no inputs');
|
||||||
if (!this.__tx.outs.length)
|
if (!this.__TX.outs.length)
|
||||||
throw new Error('Transaction has no outputs');
|
throw new Error('Transaction has no outputs');
|
||||||
}
|
}
|
||||||
const tx = this.__tx.clone();
|
const tx = this.__TX.clone();
|
||||||
// create script signatures from inputs
|
// create script signatures from inputs
|
||||||
this.__inputs.forEach((input, i) => {
|
this.__INPUTS.forEach((input, i) => {
|
||||||
if (!input.prevOutType && !allowIncomplete)
|
if (!input.prevOutType && !allowIncomplete)
|
||||||
throw new Error('Transaction is not complete');
|
throw new Error('Transaction is not complete');
|
||||||
const result = build(input.prevOutType, input, allowIncomplete);
|
const result = build(input.prevOutType, input, allowIncomplete);
|
||||||
|
@ -174,65 +231,8 @@ class TransactionBuilder {
|
||||||
}
|
}
|
||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
sign(vin, keyPair, redeemScript, hashType, witnessValue, witnessScript) {
|
|
||||||
// TODO: remove keyPair.network matching in 4.0.0
|
|
||||||
if (keyPair.network && keyPair.network !== this.network)
|
|
||||||
throw new TypeError('Inconsistent network');
|
|
||||||
if (!this.__inputs[vin])
|
|
||||||
throw new Error('No input at index: ' + vin);
|
|
||||||
hashType = hashType || transaction_1.Transaction.SIGHASH_ALL;
|
|
||||||
if (this.__needsOutputs(hashType))
|
|
||||||
throw new Error('Transaction needs outputs');
|
|
||||||
const input = this.__inputs[vin];
|
|
||||||
// if redeemScript was previously provided, enforce consistency
|
|
||||||
if (input.redeemScript !== undefined &&
|
|
||||||
redeemScript &&
|
|
||||||
!input.redeemScript.equals(redeemScript)) {
|
|
||||||
throw new Error('Inconsistent redeemScript');
|
|
||||||
}
|
|
||||||
const ourPubKey = keyPair.publicKey || keyPair.getPublicKey();
|
|
||||||
if (!canSign(input)) {
|
|
||||||
if (witnessValue !== undefined) {
|
|
||||||
if (input.value !== undefined && input.value !== witnessValue)
|
|
||||||
throw new Error("Input didn't match witnessValue");
|
|
||||||
typeforce(types.Satoshi, witnessValue);
|
|
||||||
input.value = witnessValue;
|
|
||||||
}
|
|
||||||
if (!canSign(input)) {
|
|
||||||
const prepared = prepareInput(input, ourPubKey, redeemScript, witnessScript);
|
|
||||||
// updates inline
|
|
||||||
Object.assign(input, prepared);
|
|
||||||
}
|
|
||||||
if (!canSign(input))
|
|
||||||
throw Error(input.prevOutType + ' not supported');
|
|
||||||
}
|
|
||||||
// ready to sign
|
|
||||||
let signatureHash;
|
|
||||||
if (input.hasWitness) {
|
|
||||||
signatureHash = this.__tx.hashForWitnessV0(vin, input.signScript, input.value, hashType);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
signatureHash = this.__tx.hashForSignature(vin, input.signScript, hashType);
|
|
||||||
}
|
|
||||||
// enforce in order signing of public keys
|
|
||||||
const signed = input.pubkeys.some((pubKey, i) => {
|
|
||||||
if (!ourPubKey.equals(pubKey))
|
|
||||||
return false;
|
|
||||||
if (input.signatures[i])
|
|
||||||
throw new Error('Signature already exists');
|
|
||||||
// TODO: add tests
|
|
||||||
if (ourPubKey.length !== 33 && input.hasWitness) {
|
|
||||||
throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH');
|
|
||||||
}
|
|
||||||
const signature = keyPair.sign(signatureHash);
|
|
||||||
input.signatures[i] = bscript.signature.encode(signature, hashType);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (!signed)
|
|
||||||
throw new Error('Key pair cannot sign for this input');
|
|
||||||
}
|
|
||||||
__canModifyInputs() {
|
__canModifyInputs() {
|
||||||
return this.__inputs.every(input => {
|
return this.__INPUTS.every(input => {
|
||||||
if (!input.signatures)
|
if (!input.signatures)
|
||||||
return true;
|
return true;
|
||||||
return input.signatures.every(signature => {
|
return input.signatures.every(signature => {
|
||||||
|
@ -247,12 +247,12 @@ class TransactionBuilder {
|
||||||
}
|
}
|
||||||
__needsOutputs(signingHashType) {
|
__needsOutputs(signingHashType) {
|
||||||
if (signingHashType === transaction_1.Transaction.SIGHASH_ALL) {
|
if (signingHashType === transaction_1.Transaction.SIGHASH_ALL) {
|
||||||
return this.__tx.outs.length === 0;
|
return this.__TX.outs.length === 0;
|
||||||
}
|
}
|
||||||
// if inputs are being signed with SIGHASH_NONE, we don't strictly need outputs
|
// if inputs are being signed with SIGHASH_NONE, we don't strictly need outputs
|
||||||
// .build() will fail, but .buildIncomplete() is OK
|
// .build() will fail, but .buildIncomplete() is OK
|
||||||
return (this.__tx.outs.length === 0 &&
|
return (this.__TX.outs.length === 0 &&
|
||||||
this.__inputs.some(input => {
|
this.__INPUTS.some(input => {
|
||||||
if (!input.signatures)
|
if (!input.signatures)
|
||||||
return false;
|
return false;
|
||||||
return input.signatures.some(signature => {
|
return input.signatures.some(signature => {
|
||||||
|
@ -266,9 +266,9 @@ class TransactionBuilder {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
__canModifyOutputs() {
|
__canModifyOutputs() {
|
||||||
const nInputs = this.__tx.ins.length;
|
const nInputs = this.__TX.ins.length;
|
||||||
const nOutputs = this.__tx.outs.length;
|
const nOutputs = this.__TX.outs.length;
|
||||||
return this.__inputs.every(input => {
|
return this.__INPUTS.every(input => {
|
||||||
if (input.signatures === undefined)
|
if (input.signatures === undefined)
|
||||||
return true;
|
return true;
|
||||||
return input.signatures.every(signature => {
|
return input.signatures.every(signature => {
|
||||||
|
@ -290,10 +290,10 @@ class TransactionBuilder {
|
||||||
}
|
}
|
||||||
__overMaximumFees(bytes) {
|
__overMaximumFees(bytes) {
|
||||||
// not all inputs will have .value defined
|
// not all inputs will have .value defined
|
||||||
const incoming = this.__inputs.reduce((a, x) => a + (x.value >>> 0), 0);
|
const incoming = this.__INPUTS.reduce((a, x) => a + (x.value >>> 0), 0);
|
||||||
// but all outputs do, and if we have any input value
|
// but all outputs do, and if we have any input value
|
||||||
// we can immediately determine if the outputs are too small
|
// we can immediately determine if the outputs are too small
|
||||||
const outgoing = this.__tx.outs.reduce((a, x) => a + x.value, 0);
|
const outgoing = this.__TX.outs.reduce((a, x) => a + x.value, 0);
|
||||||
const fee = incoming - outgoing;
|
const fee = incoming - outgoing;
|
||||||
const feeRate = fee / bytes;
|
const feeRate = fee / bytes;
|
||||||
return feeRate > this.maximumFeeRate;
|
return feeRate > this.maximumFeeRate;
|
||||||
|
@ -350,8 +350,8 @@ function expandInput(scriptSig, witnessStack, type, scriptPubKey) {
|
||||||
}, { allowIncomplete: true });
|
}, { allowIncomplete: true });
|
||||||
return {
|
return {
|
||||||
prevOutType: SCRIPT_TYPES.P2MS,
|
prevOutType: SCRIPT_TYPES.P2MS,
|
||||||
pubkeys: pubkeys,
|
pubkeys,
|
||||||
signatures: signatures,
|
signatures,
|
||||||
maxSignatures: m,
|
maxSignatures: m,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -488,7 +488,9 @@ function expandOutput(script, ourPubKey) {
|
||||||
}
|
}
|
||||||
function prepareInput(input, ourPubKey, redeemScript, witnessScript) {
|
function prepareInput(input, ourPubKey, redeemScript, witnessScript) {
|
||||||
if (redeemScript && witnessScript) {
|
if (redeemScript && witnessScript) {
|
||||||
const p2wsh = (payments.p2wsh({ redeem: { output: witnessScript } }));
|
const p2wsh = payments.p2wsh({
|
||||||
|
redeem: { output: witnessScript },
|
||||||
|
});
|
||||||
const p2wshAlt = payments.p2wsh({ output: redeemScript });
|
const p2wshAlt = payments.p2wsh({ output: redeemScript });
|
||||||
const p2sh = payments.p2sh({ redeem: { output: redeemScript } });
|
const p2sh = payments.p2sh({ redeem: { output: redeemScript } });
|
||||||
const p2shAlt = payments.p2sh({ redeem: p2wsh });
|
const p2shAlt = payments.p2sh({ redeem: p2wsh });
|
||||||
|
@ -506,7 +508,7 @@ function prepareInput(input, ourPubKey, redeemScript, witnessScript) {
|
||||||
if (input.signatures && input.signatures.some(x => x !== undefined)) {
|
if (input.signatures && input.signatures.some(x => x !== undefined)) {
|
||||||
expanded.signatures = input.signatures;
|
expanded.signatures = input.signatures;
|
||||||
}
|
}
|
||||||
let signScript = witnessScript;
|
const signScript = witnessScript;
|
||||||
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
||||||
throw new Error('P2SH(P2WSH(P2WPKH)) is a consensus failure');
|
throw new Error('P2SH(P2WSH(P2WPKH)) is a consensus failure');
|
||||||
return {
|
return {
|
||||||
|
@ -579,7 +581,7 @@ function prepareInput(input, ourPubKey, redeemScript, witnessScript) {
|
||||||
if (input.signatures && input.signatures.some(x => x !== undefined)) {
|
if (input.signatures && input.signatures.some(x => x !== undefined)) {
|
||||||
expanded.signatures = input.signatures;
|
expanded.signatures = input.signatures;
|
||||||
}
|
}
|
||||||
let signScript = witnessScript;
|
const signScript = witnessScript;
|
||||||
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
||||||
throw new Error('P2WSH(P2WPKH) is a consensus failure');
|
throw new Error('P2WSH(P2WPKH) is a consensus failure');
|
||||||
return {
|
return {
|
||||||
|
@ -614,7 +616,8 @@ function prepareInput(input, ourPubKey, redeemScript, witnessScript) {
|
||||||
}
|
}
|
||||||
let signScript = input.prevOutScript;
|
let signScript = input.prevOutScript;
|
||||||
if (expanded.type === SCRIPT_TYPES.P2WPKH) {
|
if (expanded.type === SCRIPT_TYPES.P2WPKH) {
|
||||||
signScript = (payments.p2pkh({ pubkey: expanded.pubkeys[0] }).output);
|
signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] })
|
||||||
|
.output;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
prevOutType: expanded.type,
|
prevOutType: expanded.type,
|
||||||
|
@ -630,7 +633,7 @@ function prepareInput(input, ourPubKey, redeemScript, witnessScript) {
|
||||||
const prevOutScript = payments.p2pkh({ pubkey: ourPubKey }).output;
|
const prevOutScript = payments.p2pkh({ pubkey: ourPubKey }).output;
|
||||||
return {
|
return {
|
||||||
prevOutType: SCRIPT_TYPES.P2PKH,
|
prevOutType: SCRIPT_TYPES.P2PKH,
|
||||||
prevOutScript: prevOutScript,
|
prevOutScript,
|
||||||
hasWitness: false,
|
hasWitness: false,
|
||||||
signScript: prevOutScript,
|
signScript: prevOutScript,
|
||||||
signType: SCRIPT_TYPES.P2PKH,
|
signType: SCRIPT_TYPES.P2PKH,
|
||||||
|
|
|
@ -10,7 +10,7 @@ function BIP32Path(value) {
|
||||||
return typeforce.String(value) && !!value.match(/^(m\/)?(\d+'?\/)*\d+'?$/);
|
return typeforce.String(value) && !!value.match(/^(m\/)?(\d+'?\/)*\d+'?$/);
|
||||||
}
|
}
|
||||||
exports.BIP32Path = BIP32Path;
|
exports.BIP32Path = BIP32Path;
|
||||||
BIP32Path.toJSON = function () {
|
BIP32Path.toJSON = () => {
|
||||||
return 'BIP32 derivation path';
|
return 'BIP32 derivation path';
|
||||||
};
|
};
|
||||||
const SATOSHI_MAX = 21 * 1e14;
|
const SATOSHI_MAX = 21 * 1e14;
|
||||||
|
@ -34,10 +34,10 @@ exports.Network = typeforce.compile({
|
||||||
exports.Buffer256bit = typeforce.BufferN(32);
|
exports.Buffer256bit = typeforce.BufferN(32);
|
||||||
exports.Hash160bit = typeforce.BufferN(20);
|
exports.Hash160bit = typeforce.BufferN(20);
|
||||||
exports.Hash256bit = typeforce.BufferN(32);
|
exports.Hash256bit = typeforce.BufferN(32);
|
||||||
exports.Number = typeforce.Number;
|
exports.Number = typeforce.Number; // tslint:disable-line variable-name
|
||||||
exports.Array = typeforce.Array;
|
exports.Array = typeforce.Array;
|
||||||
exports.Boolean = typeforce.Boolean;
|
exports.Boolean = typeforce.Boolean; // tslint:disable-line variable-name
|
||||||
exports.String = typeforce.String;
|
exports.String = typeforce.String; // tslint:disable-line variable-name
|
||||||
exports.Buffer = typeforce.Buffer;
|
exports.Buffer = typeforce.Buffer;
|
||||||
exports.Hex = typeforce.Hex;
|
exports.Hex = typeforce.Hex;
|
||||||
exports.maybe = typeforce.maybe;
|
exports.maybe = typeforce.maybe;
|
||||||
|
|
|
@ -238,7 +238,7 @@ describe('ECPair', function () {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
it('throws if no private key is found', function () {
|
it('throws if no private key is found', function () {
|
||||||
delete keyPair.__d
|
delete keyPair.__D
|
||||||
|
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
keyPair.sign(hash)
|
keyPair.sign(hash)
|
||||||
|
|
2
test/fixtures/transaction_builder.json
vendored
2
test/fixtures/transaction_builder.json
vendored
|
@ -1976,7 +1976,7 @@
|
||||||
"sign": [
|
"sign": [
|
||||||
{
|
{
|
||||||
"description": "Transaction w/ witness value mismatch",
|
"description": "Transaction w/ witness value mismatch",
|
||||||
"exception": "Input didn\\'t match witnessValue",
|
"exception": "Input did not match witnessValue",
|
||||||
"network": "testnet",
|
"network": "testnet",
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,7 +164,7 @@ describe('TransactionBuilder', function () {
|
||||||
const tx = Transaction.fromHex(fixtures.valid.classification.hex)
|
const tx = Transaction.fromHex(fixtures.valid.classification.hex)
|
||||||
const txb = TransactionBuilder.fromTransaction(tx)
|
const txb = TransactionBuilder.fromTransaction(tx)
|
||||||
|
|
||||||
txb.__inputs.forEach(function (i) {
|
txb.__INPUTS.forEach(function (i) {
|
||||||
assert.strictEqual(i.prevOutType, 'scripthash')
|
assert.strictEqual(i.prevOutType, 'scripthash')
|
||||||
assert.strictEqual(i.redeemScriptType, 'multisig')
|
assert.strictEqual(i.redeemScriptType, 'multisig')
|
||||||
})
|
})
|
||||||
|
@ -191,22 +191,22 @@ describe('TransactionBuilder', function () {
|
||||||
const vin = txb.addInput(txHash, 1, 54)
|
const vin = txb.addInput(txHash, 1, 54)
|
||||||
assert.strictEqual(vin, 0)
|
assert.strictEqual(vin, 0)
|
||||||
|
|
||||||
const txIn = txb.__tx.ins[0]
|
const txIn = txb.__TX.ins[0]
|
||||||
assert.strictEqual(txIn.hash, txHash)
|
assert.strictEqual(txIn.hash, txHash)
|
||||||
assert.strictEqual(txIn.index, 1)
|
assert.strictEqual(txIn.index, 1)
|
||||||
assert.strictEqual(txIn.sequence, 54)
|
assert.strictEqual(txIn.sequence, 54)
|
||||||
assert.strictEqual(txb.__inputs[0].prevOutScript, undefined)
|
assert.strictEqual(txb.__INPUTS[0].prevOutScript, undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('accepts a txHash, index [, sequence number and scriptPubKey]', function () {
|
it('accepts a txHash, index [, sequence number and scriptPubKey]', function () {
|
||||||
const vin = txb.addInput(txHash, 1, 54, scripts[1])
|
const vin = txb.addInput(txHash, 1, 54, scripts[1])
|
||||||
assert.strictEqual(vin, 0)
|
assert.strictEqual(vin, 0)
|
||||||
|
|
||||||
const txIn = txb.__tx.ins[0]
|
const txIn = txb.__TX.ins[0]
|
||||||
assert.strictEqual(txIn.hash, txHash)
|
assert.strictEqual(txIn.hash, txHash)
|
||||||
assert.strictEqual(txIn.index, 1)
|
assert.strictEqual(txIn.index, 1)
|
||||||
assert.strictEqual(txIn.sequence, 54)
|
assert.strictEqual(txIn.sequence, 54)
|
||||||
assert.strictEqual(txb.__inputs[0].prevOutScript, scripts[1])
|
assert.strictEqual(txb.__INPUTS[0].prevOutScript, scripts[1])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('accepts a prevTx, index [and sequence number]', function () {
|
it('accepts a prevTx, index [and sequence number]', function () {
|
||||||
|
@ -217,11 +217,11 @@ describe('TransactionBuilder', function () {
|
||||||
const vin = txb.addInput(prevTx, 1, 54)
|
const vin = txb.addInput(prevTx, 1, 54)
|
||||||
assert.strictEqual(vin, 0)
|
assert.strictEqual(vin, 0)
|
||||||
|
|
||||||
const txIn = txb.__tx.ins[0]
|
const txIn = txb.__TX.ins[0]
|
||||||
assert.deepEqual(txIn.hash, prevTx.getHash())
|
assert.deepEqual(txIn.hash, prevTx.getHash())
|
||||||
assert.strictEqual(txIn.index, 1)
|
assert.strictEqual(txIn.index, 1)
|
||||||
assert.strictEqual(txIn.sequence, 54)
|
assert.strictEqual(txIn.sequence, 54)
|
||||||
assert.strictEqual(txb.__inputs[0].prevOutScript, scripts[1])
|
assert.strictEqual(txb.__INPUTS[0].prevOutScript, scripts[1])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns the input index', function () {
|
it('returns the input index', function () {
|
||||||
|
@ -251,7 +251,7 @@ describe('TransactionBuilder', function () {
|
||||||
const vout = txb.addOutput(address, 1000)
|
const vout = txb.addOutput(address, 1000)
|
||||||
assert.strictEqual(vout, 0)
|
assert.strictEqual(vout, 0)
|
||||||
|
|
||||||
const txout = txb.__tx.outs[0]
|
const txout = txb.__TX.outs[0]
|
||||||
assert.deepEqual(txout.script, scripts[0])
|
assert.deepEqual(txout.script, scripts[0])
|
||||||
assert.strictEqual(txout.value, 1000)
|
assert.strictEqual(txout.value, 1000)
|
||||||
})
|
})
|
||||||
|
@ -260,7 +260,7 @@ describe('TransactionBuilder', function () {
|
||||||
const vout = txb.addOutput(scripts[0], 1000)
|
const vout = txb.addOutput(scripts[0], 1000)
|
||||||
assert.strictEqual(vout, 0)
|
assert.strictEqual(vout, 0)
|
||||||
|
|
||||||
const txout = txb.__tx.outs[0]
|
const txout = txb.__TX.outs[0]
|
||||||
assert.deepEqual(txout.script, scripts[0])
|
assert.deepEqual(txout.script, scripts[0])
|
||||||
assert.strictEqual(txout.value, 1000)
|
assert.strictEqual(txout.value, 1000)
|
||||||
})
|
})
|
||||||
|
@ -533,10 +533,10 @@ describe('TransactionBuilder', function () {
|
||||||
'194a565cd6aa4cc38b8eaffa343402201c5b4b61d73fa38e49c1ee68cc0e6dfd2f5dae453dd86eb142e87a' +
|
'194a565cd6aa4cc38b8eaffa343402201c5b4b61d73fa38e49c1ee68cc0e6dfd2f5dae453dd86eb142e87a' +
|
||||||
'0bafb1bc8401210283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f44800000000'
|
'0bafb1bc8401210283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f44800000000'
|
||||||
const txb = TransactionBuilder.fromTransaction(Transaction.fromHex(rawtx))
|
const txb = TransactionBuilder.fromTransaction(Transaction.fromHex(rawtx))
|
||||||
txb.__inputs[0].value = 241530
|
txb.__INPUTS[0].value = 241530
|
||||||
txb.__inputs[1].value = 241530
|
txb.__INPUTS[1].value = 241530
|
||||||
txb.__inputs[2].value = 248920
|
txb.__INPUTS[2].value = 248920
|
||||||
txb.__inputs[3].value = 248920
|
txb.__INPUTS[3].value = 248920
|
||||||
|
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
txb.build()
|
txb.build()
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
import { Network } from './networks';
|
import { Network } from './networks';
|
||||||
import * as types from './types';
|
|
||||||
import * as bscript from './script';
|
|
||||||
import * as networks from './networks';
|
import * as networks from './networks';
|
||||||
import * as payments from './payments';
|
import * as payments from './payments';
|
||||||
|
import * as bscript from './script';
|
||||||
|
import * as types from './types';
|
||||||
|
|
||||||
const bech32 = require('bech32');
|
const bech32 = require('bech32');
|
||||||
const bs58check = require('bs58check');
|
const bs58check = require('bs58check');
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
|
|
||||||
export type Base58CheckResult = {
|
export interface Base58CheckResult {
|
||||||
hash: Buffer;
|
hash: Buffer;
|
||||||
version: number;
|
version: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type Bech32Result = {
|
export interface Bech32Result {
|
||||||
version: number;
|
version: number;
|
||||||
prefix: string;
|
prefix: string;
|
||||||
data: Buffer;
|
data: Buffer;
|
||||||
};
|
}
|
||||||
|
|
||||||
export function fromBase58Check(address: string): Base58CheckResult {
|
export function fromBase58Check(address: string): Base58CheckResult {
|
||||||
const payload = bs58check.decode(address);
|
const payload = bs58check.decode(address);
|
||||||
|
@ -29,7 +29,7 @@ export function fromBase58Check(address: string): Base58CheckResult {
|
||||||
const version = payload.readUInt8(0);
|
const version = payload.readUInt8(0);
|
||||||
const hash = payload.slice(1);
|
const hash = payload.slice(1);
|
||||||
|
|
||||||
return { version: version, hash: hash };
|
return { version, hash };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromBech32(address: string): Bech32Result {
|
export function fromBech32(address: string): Bech32Result {
|
||||||
|
@ -65,20 +65,20 @@ export function toBech32(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromOutputScript(output: Buffer, network: Network): string {
|
export function fromOutputScript(output: Buffer, network: Network): string {
|
||||||
//TODO: Network
|
// TODO: Network
|
||||||
network = network || networks.bitcoin;
|
network = network || networks.bitcoin;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return <string>payments.p2pkh({ output, network }).address;
|
return payments.p2pkh({ output, network }).address as string;
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
try {
|
try {
|
||||||
return <string>payments.p2sh({ output, network }).address;
|
return payments.p2sh({ output, network }).address as string;
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
try {
|
try {
|
||||||
return <string>payments.p2wpkh({ output, network }).address;
|
return payments.p2wpkh({ output, network }).address as string;
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
try {
|
try {
|
||||||
return <string>payments.p2wsh({ output, network }).address;
|
return payments.p2wsh({ output, network }).address as string;
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
throw new Error(bscript.toASM(output) + ' has no matching Address');
|
throw new Error(bscript.toASM(output) + ' has no matching Address');
|
||||||
|
@ -87,17 +87,17 @@ export function fromOutputScript(output: Buffer, network: Network): string {
|
||||||
export function toOutputScript(address: string, network: Network): Buffer {
|
export function toOutputScript(address: string, network: Network): Buffer {
|
||||||
network = network || networks.bitcoin;
|
network = network || networks.bitcoin;
|
||||||
|
|
||||||
let decodeBase58: Base58CheckResult | undefined = undefined;
|
let decodeBase58: Base58CheckResult | undefined;
|
||||||
let decodeBech32: Bech32Result | undefined = undefined;
|
let decodeBech32: Bech32Result | undefined;
|
||||||
try {
|
try {
|
||||||
decodeBase58 = fromBase58Check(address);
|
decodeBase58 = fromBase58Check(address);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
if (decodeBase58) {
|
if (decodeBase58) {
|
||||||
if (decodeBase58.version === network.pubKeyHash)
|
if (decodeBase58.version === network.pubKeyHash)
|
||||||
return <Buffer>payments.p2pkh({ hash: decodeBase58.hash }).output;
|
return payments.p2pkh({ hash: decodeBase58.hash }).output as Buffer;
|
||||||
if (decodeBase58.version === network.scriptHash)
|
if (decodeBase58.version === network.scriptHash)
|
||||||
return <Buffer>payments.p2sh({ hash: decodeBase58.hash }).output;
|
return payments.p2sh({ hash: decodeBase58.hash }).output as Buffer;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
decodeBech32 = fromBech32(address);
|
decodeBech32 = fromBech32(address);
|
||||||
|
@ -108,9 +108,9 @@ export function toOutputScript(address: string, network: Network): Buffer {
|
||||||
throw new Error(address + ' has an invalid prefix');
|
throw new Error(address + ' has an invalid prefix');
|
||||||
if (decodeBech32.version === 0) {
|
if (decodeBech32.version === 0) {
|
||||||
if (decodeBech32.data.length === 20)
|
if (decodeBech32.data.length === 20)
|
||||||
return <Buffer>payments.p2wpkh({ hash: decodeBech32.data }).output;
|
return payments.p2wpkh({ hash: decodeBech32.data }).output as Buffer;
|
||||||
if (decodeBech32.data.length === 32)
|
if (decodeBech32.data.length === 32)
|
||||||
return <Buffer>payments.p2wsh({ hash: decodeBech32.data }).output;
|
return payments.p2wsh({ hash: decodeBech32.data }).output as Buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import { reverseBuffer } from './bufferutils';
|
||||||
|
import * as bcrypto from './crypto';
|
||||||
import { Transaction } from './transaction';
|
import { Transaction } from './transaction';
|
||||||
import * as types from './types';
|
import * as types from './types';
|
||||||
import * as bcrypto from './crypto';
|
|
||||||
import { reverseBuffer } from './bufferutils';
|
|
||||||
|
|
||||||
const fastMerkleRoot = require('merkle-lib/fastRoot');
|
const fastMerkleRoot = require('merkle-lib/fastRoot');
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
|
@ -14,7 +14,7 @@ const errorWitnessNotSegwit = new TypeError(
|
||||||
'Cannot compute witness commit for non-segwit block',
|
'Cannot compute witness commit for non-segwit block',
|
||||||
);
|
);
|
||||||
|
|
||||||
function txesHaveWitnessCommit(transactions: Array<Transaction>): boolean {
|
function txesHaveWitnessCommit(transactions: Transaction[]): boolean {
|
||||||
return (
|
return (
|
||||||
transactions instanceof Array &&
|
transactions instanceof Array &&
|
||||||
transactions[0] &&
|
transactions[0] &&
|
||||||
|
@ -27,7 +27,7 @@ function txesHaveWitnessCommit(transactions: Array<Transaction>): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function anyTxHasWitness(transactions: Array<Transaction>): boolean {
|
function anyTxHasWitness(transactions: Transaction[]): boolean {
|
||||||
return (
|
return (
|
||||||
transactions instanceof Array &&
|
transactions instanceof Array &&
|
||||||
transactions.some(
|
transactions.some(
|
||||||
|
@ -45,26 +45,6 @@ function anyTxHasWitness(transactions: Array<Transaction>): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Block {
|
export class Block {
|
||||||
version: number;
|
|
||||||
prevHash?: Buffer;
|
|
||||||
merkleRoot?: Buffer;
|
|
||||||
timestamp: number;
|
|
||||||
witnessCommit?: Buffer;
|
|
||||||
bits: number;
|
|
||||||
nonce: number;
|
|
||||||
transactions?: Array<Transaction>;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.version = 1;
|
|
||||||
this.timestamp = 0;
|
|
||||||
this.bits = 0;
|
|
||||||
this.nonce = 0;
|
|
||||||
this.prevHash = undefined;
|
|
||||||
this.merkleRoot = undefined;
|
|
||||||
this.witnessCommit = undefined;
|
|
||||||
this.transactions = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromBuffer(buffer: Buffer): Block {
|
static fromBuffer(buffer: Buffer): Block {
|
||||||
if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)');
|
if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)');
|
||||||
|
|
||||||
|
@ -111,12 +91,12 @@ export class Block {
|
||||||
const nTransactions = readVarInt();
|
const nTransactions = readVarInt();
|
||||||
block.transactions = [];
|
block.transactions = [];
|
||||||
|
|
||||||
for (var i = 0; i < nTransactions; ++i) {
|
for (let i = 0; i < nTransactions; ++i) {
|
||||||
const tx = readTransaction();
|
const tx = readTransaction();
|
||||||
block.transactions.push(tx);
|
block.transactions.push(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let witnessCommit = block.getWitnessCommit();
|
const witnessCommit = block.getWitnessCommit();
|
||||||
// This Block contains a witness commit
|
// This Block contains a witness commit
|
||||||
if (witnessCommit) block.witnessCommit = witnessCommit;
|
if (witnessCommit) block.witnessCommit = witnessCommit;
|
||||||
|
|
||||||
|
@ -136,7 +116,7 @@ export class Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
static calculateMerkleRoot(
|
static calculateMerkleRoot(
|
||||||
transactions: Array<Transaction>,
|
transactions: Transaction[],
|
||||||
forWitness?: boolean,
|
forWitness?: boolean,
|
||||||
): Buffer {
|
): Buffer {
|
||||||
typeforce([{ getHash: types.Function }], transactions);
|
typeforce([{ getHash: types.Function }], transactions);
|
||||||
|
@ -157,6 +137,26 @@ export class Block {
|
||||||
: rootHash;
|
: rootHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version: number;
|
||||||
|
prevHash?: Buffer;
|
||||||
|
merkleRoot?: Buffer;
|
||||||
|
timestamp: number;
|
||||||
|
witnessCommit?: Buffer;
|
||||||
|
bits: number;
|
||||||
|
nonce: number;
|
||||||
|
transactions?: Transaction[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.version = 1;
|
||||||
|
this.timestamp = 0;
|
||||||
|
this.bits = 0;
|
||||||
|
this.nonce = 0;
|
||||||
|
this.prevHash = undefined;
|
||||||
|
this.merkleRoot = undefined;
|
||||||
|
this.witnessCommit = undefined;
|
||||||
|
this.transactions = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
getWitnessCommit(): Buffer | null {
|
getWitnessCommit(): Buffer | null {
|
||||||
if (!txesHaveWitnessCommit(this.transactions!)) return null;
|
if (!txesHaveWitnessCommit(this.transactions!)) return null;
|
||||||
|
|
||||||
|
@ -164,12 +164,12 @@ export class Block {
|
||||||
// There is no rule for the index of the output, so use filter to find it.
|
// There is no rule for the index of the output, so use filter to find it.
|
||||||
// The root is prepended with 0xaa21a9ed so check for 0x6a24aa21a9ed
|
// The root is prepended with 0xaa21a9ed so check for 0x6a24aa21a9ed
|
||||||
// If multiple commits are found, the output with highest index is assumed.
|
// If multiple commits are found, the output with highest index is assumed.
|
||||||
let witnessCommits = this.transactions![0].outs.filter(out =>
|
const witnessCommits = this.transactions![0].outs.filter(out =>
|
||||||
out.script.slice(0, 6).equals(Buffer.from('6a24aa21a9ed', 'hex')),
|
out.script.slice(0, 6).equals(Buffer.from('6a24aa21a9ed', 'hex')),
|
||||||
).map(out => out.script.slice(6, 38));
|
).map(out => out.script.slice(6, 38));
|
||||||
if (witnessCommits.length === 0) return null;
|
if (witnessCommits.length === 0) return null;
|
||||||
// Use the commit with the highest output (should only be one though)
|
// Use the commit with the highest output (should only be one though)
|
||||||
let result = witnessCommits[witnessCommits.length - 1];
|
const result = witnessCommits[witnessCommits.length - 1];
|
||||||
|
|
||||||
if (!(result instanceof Buffer && result.length === 32)) return null;
|
if (!(result instanceof Buffer && result.length === 32)) return null;
|
||||||
return result;
|
return result;
|
||||||
|
@ -261,7 +261,7 @@ export class Block {
|
||||||
checkTxRoots(): boolean {
|
checkTxRoots(): boolean {
|
||||||
// If the Block has segwit transactions but no witness commit,
|
// If the Block has segwit transactions but no witness commit,
|
||||||
// there's no way it can be valid, so fail the check.
|
// there's no way it can be valid, so fail the check.
|
||||||
let hasWitnessCommit = this.hasWitnessCommit();
|
const hasWitnessCommit = this.hasWitnessCommit();
|
||||||
if (!hasWitnessCommit && this.hasWitness()) return false;
|
if (!hasWitnessCommit && this.hasWitness()) return false;
|
||||||
return (
|
return (
|
||||||
this.__checkMerkleRoot() &&
|
this.__checkMerkleRoot() &&
|
||||||
|
@ -277,14 +277,21 @@ export class Block {
|
||||||
return this.checkTxRoots();
|
return this.checkTxRoots();
|
||||||
}
|
}
|
||||||
|
|
||||||
__checkMerkleRoot(): boolean {
|
checkProofOfWork(): boolean {
|
||||||
|
const hash: Buffer = reverseBuffer(this.getHash());
|
||||||
|
const target = Block.calculateTarget(this.bits);
|
||||||
|
|
||||||
|
return hash.compare(target) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private __checkMerkleRoot(): boolean {
|
||||||
if (!this.transactions) throw errorMerkleNoTxes;
|
if (!this.transactions) throw errorMerkleNoTxes;
|
||||||
|
|
||||||
const actualMerkleRoot = Block.calculateMerkleRoot(this.transactions);
|
const actualMerkleRoot = Block.calculateMerkleRoot(this.transactions);
|
||||||
return this.merkleRoot!.compare(actualMerkleRoot) === 0;
|
return this.merkleRoot!.compare(actualMerkleRoot) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__checkWitnessCommit(): boolean {
|
private __checkWitnessCommit(): boolean {
|
||||||
if (!this.transactions) throw errorMerkleNoTxes;
|
if (!this.transactions) throw errorMerkleNoTxes;
|
||||||
if (!this.hasWitnessCommit()) throw errorWitnessNotSegwit;
|
if (!this.hasWitnessCommit()) throw errorWitnessNotSegwit;
|
||||||
|
|
||||||
|
@ -294,11 +301,4 @@ export class Block {
|
||||||
);
|
);
|
||||||
return this.witnessCommit!.compare(actualWitnessCommit) === 0;
|
return this.witnessCommit!.compare(actualWitnessCommit) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkProofOfWork(): boolean {
|
|
||||||
const hash: Buffer = reverseBuffer(this.getHash());
|
|
||||||
const target = Block.calculateTarget(this.bits);
|
|
||||||
|
|
||||||
return hash.compare(target) <= 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,20 @@ import * as nullData from './templates/nulldata';
|
||||||
import * as pubKey from './templates/pubkey';
|
import * as pubKey from './templates/pubkey';
|
||||||
import * as pubKeyHash from './templates/pubkeyhash';
|
import * as pubKeyHash from './templates/pubkeyhash';
|
||||||
import * as scriptHash from './templates/scripthash';
|
import * as scriptHash from './templates/scripthash';
|
||||||
|
import * as witnessCommitment from './templates/witnesscommitment';
|
||||||
import * as witnessPubKeyHash from './templates/witnesspubkeyhash';
|
import * as witnessPubKeyHash from './templates/witnesspubkeyhash';
|
||||||
import * as witnessScriptHash from './templates/witnessscripthash';
|
import * as witnessScriptHash from './templates/witnessscripthash';
|
||||||
import * as witnessCommitment from './templates/witnesscommitment';
|
|
||||||
|
|
||||||
const types = {
|
const types = {
|
||||||
P2MS: <string>'multisig',
|
P2MS: 'multisig' as string,
|
||||||
NONSTANDARD: <string>'nonstandard',
|
NONSTANDARD: 'nonstandard' as string,
|
||||||
NULLDATA: <string>'nulldata',
|
NULLDATA: 'nulldata' as string,
|
||||||
P2PK: <string>'pubkey',
|
P2PK: 'pubkey' as string,
|
||||||
P2PKH: <string>'pubkeyhash',
|
P2PKH: 'pubkeyhash' as string,
|
||||||
P2SH: <string>'scripthash',
|
P2SH: 'scripthash' as string,
|
||||||
P2WPKH: <string>'witnesspubkeyhash',
|
P2WPKH: 'witnesspubkeyhash' as string,
|
||||||
P2WSH: <string>'witnessscripthash',
|
P2WSH: 'witnessscripthash' as string,
|
||||||
WITNESS_COMMITMENT: <string>'witnesscommitment',
|
WITNESS_COMMITMENT: 'witnesscommitment' as string,
|
||||||
};
|
};
|
||||||
|
|
||||||
function classifyOutput(script: Buffer): string {
|
function classifyOutput(script: Buffer): string {
|
||||||
|
@ -51,16 +51,13 @@ function classifyInput(script: Buffer, allowIncomplete: boolean): string {
|
||||||
return types.NONSTANDARD;
|
return types.NONSTANDARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
function classifyWitness(
|
function classifyWitness(script: Buffer[], allowIncomplete: boolean): string {
|
||||||
script: Array<Buffer>,
|
|
||||||
allowIncomplete: boolean,
|
|
||||||
): string {
|
|
||||||
// XXX: optimization, below functions .decompile before use
|
// XXX: optimization, below functions .decompile before use
|
||||||
const chunks = decompile(script);
|
const chunks = decompile(script);
|
||||||
if (!chunks) throw new TypeError('Invalid script');
|
if (!chunks) throw new TypeError('Invalid script');
|
||||||
|
|
||||||
if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH;
|
if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH;
|
||||||
if (witnessScriptHash.input.check(<Array<Buffer>>chunks, allowIncomplete))
|
if (witnessScriptHash.input.check(chunks as Buffer[], allowIncomplete))
|
||||||
return types.P2WSH;
|
return types.P2WSH;
|
||||||
|
|
||||||
return types.NONSTANDARD;
|
return types.NONSTANDARD;
|
||||||
|
|
|
@ -33,7 +33,7 @@ export interface ECPairInterface {
|
||||||
class ECPair implements ECPairInterface {
|
class ECPair implements ECPairInterface {
|
||||||
compressed: boolean;
|
compressed: boolean;
|
||||||
network: Network;
|
network: Network;
|
||||||
private __d?: Buffer;
|
private __D?: Buffer;
|
||||||
private __Q?: Buffer;
|
private __Q?: Buffer;
|
||||||
|
|
||||||
constructor(d?: Buffer, Q?: Buffer, options?: ECPairOptions) {
|
constructor(d?: Buffer, Q?: Buffer, options?: ECPairOptions) {
|
||||||
|
@ -42,29 +42,29 @@ class ECPair implements ECPairInterface {
|
||||||
options.compressed === undefined ? true : options.compressed;
|
options.compressed === undefined ? true : options.compressed;
|
||||||
this.network = options.network || NETWORKS.bitcoin;
|
this.network = options.network || NETWORKS.bitcoin;
|
||||||
|
|
||||||
this.__d = undefined;
|
this.__D = undefined;
|
||||||
this.__Q = undefined;
|
this.__Q = undefined;
|
||||||
if (d !== undefined) this.__d = d;
|
if (d !== undefined) this.__D = d;
|
||||||
if (Q !== undefined) this.__Q = ecc.pointCompress(Q, this.compressed);
|
if (Q !== undefined) this.__Q = ecc.pointCompress(Q, this.compressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
get privateKey(): Buffer | undefined {
|
get privateKey(): Buffer | undefined {
|
||||||
return this.__d;
|
return this.__D;
|
||||||
}
|
}
|
||||||
|
|
||||||
get publicKey(): Buffer | undefined {
|
get publicKey(): Buffer | undefined {
|
||||||
if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__d, this.compressed);
|
if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__D, this.compressed);
|
||||||
return this.__Q;
|
return this.__Q;
|
||||||
}
|
}
|
||||||
|
|
||||||
toWIF(): string {
|
toWIF(): string {
|
||||||
if (!this.__d) throw new Error('Missing private key');
|
if (!this.__D) throw new Error('Missing private key');
|
||||||
return wif.encode(this.network.wif, this.__d, this.compressed);
|
return wif.encode(this.network.wif, this.__D, this.compressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
sign(hash: Buffer): Buffer {
|
sign(hash: Buffer): Buffer {
|
||||||
if (!this.__d) throw new Error('Missing private key');
|
if (!this.__D) throw new Error('Missing private key');
|
||||||
return ecc.sign(hash, this.__d);
|
return ecc.sign(hash, this.__D);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(hash: Buffer, signature: Buffer): Buffer {
|
verify(hash: Buffer, signature: Buffer): Buffer {
|
||||||
|
@ -78,26 +78,26 @@ function fromPrivateKey(buffer: Buffer, options?: ECPairOptions): ECPair {
|
||||||
throw new TypeError('Private key not in range [1, n)');
|
throw new TypeError('Private key not in range [1, n)');
|
||||||
typeforce(isOptions, options);
|
typeforce(isOptions, options);
|
||||||
|
|
||||||
return new ECPair(buffer, undefined, <ECPairOptions>options);
|
return new ECPair(buffer, undefined, options as ECPairOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromPublicKey(buffer: Buffer, options?: ECPairOptions): ECPair {
|
function fromPublicKey(buffer: Buffer, options?: ECPairOptions): ECPair {
|
||||||
typeforce(ecc.isPoint, buffer);
|
typeforce(ecc.isPoint, buffer);
|
||||||
typeforce(isOptions, options);
|
typeforce(isOptions, options);
|
||||||
return new ECPair(undefined, buffer, <ECPairOptions>options);
|
return new ECPair(undefined, buffer, options as ECPairOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromWIF(string: string, network?: Network | Array<Network>): ECPair {
|
function fromWIF(wifString: string, network?: Network | Network[]): ECPair {
|
||||||
const decoded = wif.decode(string);
|
const decoded = wif.decode(wifString);
|
||||||
const version = decoded.version;
|
const version = decoded.version;
|
||||||
|
|
||||||
// list of networks?
|
// list of networks?
|
||||||
if (types.Array(network)) {
|
if (types.Array(network)) {
|
||||||
network = <Network>(<Array<Network>>network)
|
network = (network as Network[])
|
||||||
.filter(function(x: Network) {
|
.filter((x: Network) => {
|
||||||
return version === x.wif;
|
return version === x.wif;
|
||||||
})
|
})
|
||||||
.pop();
|
.pop() as Network;
|
||||||
|
|
||||||
if (!network) throw new Error('Unknown network version');
|
if (!network) throw new Error('Unknown network version');
|
||||||
|
|
||||||
|
@ -105,13 +105,13 @@ function fromWIF(string: string, network?: Network | Array<Network>): ECPair {
|
||||||
} else {
|
} else {
|
||||||
network = network || NETWORKS.bitcoin;
|
network = network || NETWORKS.bitcoin;
|
||||||
|
|
||||||
if (version !== (<Network>network).wif)
|
if (version !== (network as Network).wif)
|
||||||
throw new Error('Invalid network version');
|
throw new Error('Invalid network version');
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromPrivateKey(decoded.privateKey, {
|
return fromPrivateKey(decoded.privateKey, {
|
||||||
compressed: decoded.compressed,
|
compressed: decoded.compressed,
|
||||||
network: <Network>network,
|
network: network as Network,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as bip32 from 'bip32';
|
import * as bip32 from 'bip32';
|
||||||
import * as ECPair from './ecpair';
|
|
||||||
import * as address from './address';
|
import * as address from './address';
|
||||||
import * as crypto from './crypto';
|
import * as crypto from './crypto';
|
||||||
|
import * as ECPair from './ecpair';
|
||||||
import * as networks from './networks';
|
import * as networks from './networks';
|
||||||
import * as payments from './payments';
|
import * as payments from './payments';
|
||||||
import * as script from './script';
|
import * as script from './script';
|
||||||
|
@ -9,12 +9,12 @@ import * as script from './script';
|
||||||
export { ECPair, address, bip32, crypto, networks, payments, script };
|
export { ECPair, address, bip32, crypto, networks, payments, script };
|
||||||
|
|
||||||
export { Block } from './block';
|
export { Block } from './block';
|
||||||
|
export { OPS as opcodes } from './script';
|
||||||
export { Transaction } from './transaction';
|
export { Transaction } from './transaction';
|
||||||
export { TransactionBuilder } from './transaction_builder';
|
export { TransactionBuilder } from './transaction_builder';
|
||||||
export { OPS as opcodes } from './script';
|
|
||||||
|
|
||||||
export { Payment, PaymentOpts } from './payments';
|
|
||||||
export { Input as TxInput, Output as TxOutput } from './transaction';
|
|
||||||
export { Network } from './networks';
|
|
||||||
export { OpCode } from './script';
|
|
||||||
export { BIP32Interface } from 'bip32';
|
export { BIP32Interface } from 'bip32';
|
||||||
|
export { Network } from './networks';
|
||||||
|
export { Payment, PaymentOpts } from './payments';
|
||||||
|
export { OpCode } from './script';
|
||||||
|
export { Input as TxInput, Output as TxOutput } from './transaction';
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
// https://en.bitcoin.it/wiki/List_of_address_prefixes
|
// https://en.bitcoin.it/wiki/List_of_address_prefixes
|
||||||
// Dogecoin BIP32 is a proposed standard: https://bitcointalk.org/index.php?topic=409731
|
// Dogecoin BIP32 is a proposed standard: https://bitcointalk.org/index.php?topic=409731
|
||||||
export type Network = {
|
export interface Network {
|
||||||
messagePrefix: string;
|
messagePrefix: string;
|
||||||
bech32: string;
|
bech32: string;
|
||||||
bip32: bip32;
|
bip32: Bip32;
|
||||||
pubKeyHash: number;
|
pubKeyHash: number;
|
||||||
scriptHash: number;
|
scriptHash: number;
|
||||||
wif: number;
|
wif: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
type bip32 = {
|
interface Bip32 {
|
||||||
public: number;
|
public: number;
|
||||||
private: number;
|
private: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
export const bitcoin: Network = {
|
export const bitcoin: Network = {
|
||||||
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import { Payment, PaymentOpts } from './index';
|
|
||||||
import * as bscript from '../script';
|
|
||||||
import * as lazy from './lazy';
|
|
||||||
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
||||||
|
import * as bscript from '../script';
|
||||||
|
import { Payment, PaymentOpts, Stack } from './index';
|
||||||
|
import * as lazy from './lazy';
|
||||||
|
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
|
|
||||||
function stacksEqual(a: Array<Buffer>, b: Array<Buffer>): boolean {
|
function stacksEqual(a: Buffer[], b: Buffer[]): boolean {
|
||||||
if (a.length !== b.length) return false;
|
if (a.length !== b.length) return false;
|
||||||
|
|
||||||
return a.every(function(x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -28,15 +29,13 @@ export function p2data(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
);
|
);
|
||||||
|
|
||||||
const network = a.network || BITCOIN_NETWORK;
|
const network = a.network || BITCOIN_NETWORK;
|
||||||
const o = <Payment>{ network };
|
const o = { network } as Payment;
|
||||||
|
|
||||||
lazy.prop(o, 'output', function() {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!a.data) return;
|
if (!a.data) return;
|
||||||
return bscript.compile(
|
return bscript.compile(([OPS.OP_RETURN] as Stack).concat(a.data));
|
||||||
(<Array<Buffer | number>>[OPS.OP_RETURN]).concat(a.data),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'data', function() {
|
lazy.prop(o, 'data', () => {
|
||||||
if (!a.output) return;
|
if (!a.output) return;
|
||||||
return bscript.decompile(a.output)!.slice(1);
|
return bscript.decompile(a.output)!.slice(1);
|
||||||
});
|
});
|
||||||
|
@ -50,7 +49,7 @@ export function p2data(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
if (!chunks!.slice(1).every(typef.Buffer))
|
if (!chunks!.slice(1).every(typef.Buffer))
|
||||||
throw new TypeError('Output is invalid');
|
throw new TypeError('Output is invalid');
|
||||||
|
|
||||||
if (a.data && !stacksEqual(a.data, <Array<Buffer>>o.data))
|
if (a.data && !stacksEqual(a.data, o.data as Buffer[]))
|
||||||
throw new TypeError('Data mismatch');
|
throw new TypeError('Data mismatch');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,25 +10,31 @@ import { p2wsh } from './p2wsh';
|
||||||
export interface Payment {
|
export interface Payment {
|
||||||
network?: Network;
|
network?: Network;
|
||||||
output?: Buffer;
|
output?: Buffer;
|
||||||
data?: Array<Buffer>;
|
data?: Buffer[];
|
||||||
m?: number;
|
m?: number;
|
||||||
n?: number;
|
n?: number;
|
||||||
pubkeys?: Array<Buffer>;
|
pubkeys?: Buffer[];
|
||||||
input?: Buffer;
|
input?: Buffer;
|
||||||
signatures?: Array<Buffer>;
|
signatures?: Buffer[];
|
||||||
pubkey?: Buffer;
|
pubkey?: Buffer;
|
||||||
signature?: Buffer;
|
signature?: Buffer;
|
||||||
address?: string;
|
address?: string;
|
||||||
hash?: Buffer;
|
hash?: Buffer;
|
||||||
redeem?: Payment;
|
redeem?: Payment;
|
||||||
witness?: Array<Buffer>;
|
witness?: Buffer[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PaymentFunction = () => Payment;
|
||||||
|
|
||||||
export interface PaymentOpts {
|
export interface PaymentOpts {
|
||||||
validate?: boolean;
|
validate?: boolean;
|
||||||
allowIncomplete?: boolean;
|
allowIncomplete?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type StackElement = Buffer | number;
|
||||||
|
export type Stack = StackElement[];
|
||||||
|
export type StackFunction = () => Stack;
|
||||||
|
|
||||||
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh };
|
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh };
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
export function prop(object: Object, name: string, f: () => any): void {
|
export function prop(object: {}, name: string, f: () => any): void {
|
||||||
Object.defineProperty(object, name, {
|
Object.defineProperty(object, name, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: function() {
|
get() {
|
||||||
let value = f.call(this);
|
const _value = f.call(this);
|
||||||
this[name] = value;
|
this[name] = _value;
|
||||||
return value;
|
return _value;
|
||||||
},
|
},
|
||||||
set: function(value) {
|
set(_value) {
|
||||||
Object.defineProperty(this, name, {
|
Object.defineProperty(this, name, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
value: value,
|
value: _value,
|
||||||
writable: true,
|
writable: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -19,10 +19,10 @@ export function prop(object: Object, name: string, f: () => any): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function value<T>(f: () => T): () => T {
|
export function value<T>(f: () => T): () => T {
|
||||||
let value: T;
|
let _value: T;
|
||||||
return function(): T {
|
return (): T => {
|
||||||
if (value !== undefined) return value;
|
if (_value !== undefined) return _value;
|
||||||
value = f();
|
_value = f();
|
||||||
return value;
|
return _value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import { Payment, PaymentOpts } from './index';
|
|
||||||
import * as bscript from '../script';
|
|
||||||
import * as lazy from './lazy';
|
|
||||||
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
||||||
|
import * as bscript from '../script';
|
||||||
|
import { Payment, PaymentOpts, Stack } from './index';
|
||||||
|
import * as lazy from './lazy';
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
|
||||||
const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
|
const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
|
||||||
|
|
||||||
function stacksEqual(a: Array<Buffer>, b: Array<Buffer>): boolean {
|
function stacksEqual(a: Buffer[], b: Buffer[]): boolean {
|
||||||
if (a.length !== b.length) return false;
|
if (a.length !== b.length) return false;
|
||||||
|
|
||||||
return a.every(function(x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ export function p2ms(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
|
|
||||||
function isAcceptableSignature(x: Buffer | number) {
|
function isAcceptableSignature(x: Buffer | number) {
|
||||||
return (
|
return (
|
||||||
bscript.isCanonicalScriptSignature(<Buffer>x) ||
|
bscript.isCanonicalScriptSignature(x as Buffer) ||
|
||||||
(opts!.allowIncomplete && <number>x === OPS.OP_0) !== undefined
|
(opts!.allowIncomplete && (x as number) === OPS.OP_0) !== undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,23 +52,23 @@ export function p2ms(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
const network = a.network || BITCOIN_NETWORK;
|
const network = a.network || BITCOIN_NETWORK;
|
||||||
const o: Payment = { network };
|
const o: Payment = { network };
|
||||||
|
|
||||||
let chunks: Array<Buffer | number> = [];
|
let chunks: Stack = [];
|
||||||
let decoded = false;
|
let decoded = false;
|
||||||
function decode(output: Buffer | Array<Buffer | number>): void {
|
function decode(output: Buffer | Stack): void {
|
||||||
if (decoded) return;
|
if (decoded) return;
|
||||||
decoded = true;
|
decoded = true;
|
||||||
chunks = <Array<Buffer | number>>bscript.decompile(output);
|
chunks = bscript.decompile(output) as Stack;
|
||||||
o.m = <number>chunks[0] - OP_INT_BASE;
|
o.m = (chunks[0] as number) - OP_INT_BASE;
|
||||||
o.n = <number>chunks[chunks.length - 2] - OP_INT_BASE;
|
o.n = (chunks[chunks.length - 2] as number) - OP_INT_BASE;
|
||||||
o.pubkeys = <Array<Buffer>>chunks.slice(1, -2);
|
o.pubkeys = chunks.slice(1, -2) as Buffer[];
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy.prop(o, 'output', function() {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!a.m) return;
|
if (!a.m) return;
|
||||||
if (!o.n) return;
|
if (!o.n) return;
|
||||||
if (!a.pubkeys) return;
|
if (!a.pubkeys) return;
|
||||||
return bscript.compile(
|
return bscript.compile(
|
||||||
(<Array<Buffer | number>>[]).concat(
|
([] as Stack).concat(
|
||||||
OP_INT_BASE + a.m,
|
OP_INT_BASE + a.m,
|
||||||
a.pubkeys,
|
a.pubkeys,
|
||||||
OP_INT_BASE + o.n,
|
OP_INT_BASE + o.n,
|
||||||
|
@ -76,31 +76,29 @@ export function p2ms(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'm', function() {
|
lazy.prop(o, 'm', () => {
|
||||||
if (!o.output) return;
|
if (!o.output) return;
|
||||||
decode(o.output);
|
decode(o.output);
|
||||||
return o.m;
|
return o.m;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'n', function() {
|
lazy.prop(o, 'n', () => {
|
||||||
if (!o.pubkeys) return;
|
if (!o.pubkeys) return;
|
||||||
return o.pubkeys.length;
|
return o.pubkeys.length;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkeys', function() {
|
lazy.prop(o, 'pubkeys', () => {
|
||||||
if (!a.output) return;
|
if (!a.output) return;
|
||||||
decode(a.output);
|
decode(a.output);
|
||||||
return o.pubkeys;
|
return o.pubkeys;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signatures', function() {
|
lazy.prop(o, 'signatures', () => {
|
||||||
if (!a.input) return;
|
if (!a.input) return;
|
||||||
return bscript.decompile(a.input)!.slice(1);
|
return bscript.decompile(a.input)!.slice(1);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function() {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.signatures) return;
|
if (!a.signatures) return;
|
||||||
return bscript.compile(
|
return bscript.compile(([OPS.OP_0] as Stack).concat(a.signatures));
|
||||||
(<Array<Buffer | number>>[OPS.OP_0]).concat(a.signatures),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function() {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!o.input) return;
|
if (!o.input) return;
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Payment, PaymentOpts } from './index';
|
|
||||||
import * as bscript from '../script';
|
|
||||||
import * as lazy from './lazy';
|
|
||||||
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
||||||
|
import * as bscript from '../script';
|
||||||
|
import { Payment, PaymentOpts, StackFunction } from './index';
|
||||||
|
import * as lazy from './lazy';
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
@ -25,30 +25,30 @@ export function p2pk(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
a,
|
a,
|
||||||
);
|
);
|
||||||
|
|
||||||
const _chunks = <() => Array<Buffer | number>>lazy.value(function() {
|
const _chunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.input!);
|
return bscript.decompile(a.input!);
|
||||||
});
|
}) as StackFunction;
|
||||||
|
|
||||||
const network = a.network || BITCOIN_NETWORK;
|
const network = a.network || BITCOIN_NETWORK;
|
||||||
const o: Payment = { network };
|
const o: Payment = { network };
|
||||||
|
|
||||||
lazy.prop(o, 'output', function() {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!a.pubkey) return;
|
if (!a.pubkey) return;
|
||||||
return bscript.compile([a.pubkey, OPS.OP_CHECKSIG]);
|
return bscript.compile([a.pubkey, OPS.OP_CHECKSIG]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkey', function() {
|
lazy.prop(o, 'pubkey', () => {
|
||||||
if (!a.output) return;
|
if (!a.output) return;
|
||||||
return a.output.slice(1, -1);
|
return a.output.slice(1, -1);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signature', function() {
|
lazy.prop(o, 'signature', () => {
|
||||||
if (!a.input) return;
|
if (!a.input) return;
|
||||||
return <Buffer>_chunks()[0];
|
return _chunks()[0] as Buffer;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function() {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.signature) return;
|
if (!a.signature) return;
|
||||||
return bscript.compile([a.signature]);
|
return bscript.compile([a.signature]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function() {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!o.input) return;
|
if (!o.input) return;
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Payment, PaymentOpts } from './index';
|
|
||||||
import * as bscript from '../script';
|
|
||||||
import * as bcrypto from '../crypto';
|
import * as bcrypto from '../crypto';
|
||||||
import * as lazy from './lazy';
|
|
||||||
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
||||||
|
import * as bscript from '../script';
|
||||||
|
import { Payment, PaymentOpts, StackFunction } from './index';
|
||||||
|
import * as lazy from './lazy';
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
@ -30,20 +30,20 @@ export function p2pkh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
a,
|
a,
|
||||||
);
|
);
|
||||||
|
|
||||||
const _address = lazy.value(function() {
|
const _address = lazy.value(() => {
|
||||||
const payload = bs58check.decode(a.address);
|
const payload = bs58check.decode(a.address);
|
||||||
const version = payload.readUInt8(0);
|
const version = payload.readUInt8(0);
|
||||||
const hash = payload.slice(1);
|
const hash = payload.slice(1);
|
||||||
return { version, hash };
|
return { version, hash };
|
||||||
});
|
});
|
||||||
const _chunks = <() => Array<Buffer | number>>lazy.value(function() {
|
const _chunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.input!);
|
return bscript.decompile(a.input!);
|
||||||
});
|
}) as StackFunction;
|
||||||
|
|
||||||
const network = a.network || BITCOIN_NETWORK;
|
const network = a.network || BITCOIN_NETWORK;
|
||||||
const o: Payment = { network };
|
const o: Payment = { network };
|
||||||
|
|
||||||
lazy.prop(o, 'address', function() {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
|
|
||||||
const payload = Buffer.allocUnsafe(21);
|
const payload = Buffer.allocUnsafe(21);
|
||||||
|
@ -51,12 +51,12 @@ export function p2pkh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
o.hash.copy(payload, 1);
|
o.hash.copy(payload, 1);
|
||||||
return bs58check.encode(payload);
|
return bs58check.encode(payload);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function() {
|
lazy.prop(o, 'hash', () => {
|
||||||
if (a.output) return a.output.slice(3, 23);
|
if (a.output) return a.output.slice(3, 23);
|
||||||
if (a.address) return _address().hash;
|
if (a.address) return _address().hash;
|
||||||
if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey! || o.pubkey!);
|
if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey! || o.pubkey!);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function() {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
return bscript.compile([
|
return bscript.compile([
|
||||||
OPS.OP_DUP,
|
OPS.OP_DUP,
|
||||||
|
@ -66,20 +66,20 @@ export function p2pkh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
OPS.OP_CHECKSIG,
|
OPS.OP_CHECKSIG,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkey', function() {
|
lazy.prop(o, 'pubkey', () => {
|
||||||
if (!a.input) return;
|
if (!a.input) return;
|
||||||
return <Buffer>_chunks()[1];
|
return _chunks()[1] as Buffer;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signature', function() {
|
lazy.prop(o, 'signature', () => {
|
||||||
if (!a.input) return;
|
if (!a.input) return;
|
||||||
return <Buffer>_chunks()[0];
|
return _chunks()[0] as Buffer;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function() {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.pubkey) return;
|
if (!a.pubkey) return;
|
||||||
if (!a.signature) return;
|
if (!a.signature) return;
|
||||||
return bscript.compile([a.signature, a.pubkey]);
|
return bscript.compile([a.signature, a.pubkey]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function() {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!o.input) return;
|
if (!o.input) return;
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
@ -127,17 +127,17 @@ export function p2pkh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
if (a.input) {
|
if (a.input) {
|
||||||
const chunks = _chunks();
|
const chunks = _chunks();
|
||||||
if (chunks.length !== 2) throw new TypeError('Input is invalid');
|
if (chunks.length !== 2) throw new TypeError('Input is invalid');
|
||||||
if (!bscript.isCanonicalScriptSignature(<Buffer>chunks[0]))
|
if (!bscript.isCanonicalScriptSignature(chunks[0] as Buffer))
|
||||||
throw new TypeError('Input has invalid signature');
|
throw new TypeError('Input has invalid signature');
|
||||||
if (!ecc.isPoint(chunks[1]))
|
if (!ecc.isPoint(chunks[1]))
|
||||||
throw new TypeError('Input has invalid pubkey');
|
throw new TypeError('Input has invalid pubkey');
|
||||||
|
|
||||||
if (a.signature && !a.signature.equals(<Buffer>chunks[0]))
|
if (a.signature && !a.signature.equals(chunks[0] as Buffer))
|
||||||
throw new TypeError('Signature mismatch');
|
throw new TypeError('Signature mismatch');
|
||||||
if (a.pubkey && !a.pubkey.equals(<Buffer>chunks[1]))
|
if (a.pubkey && !a.pubkey.equals(chunks[1] as Buffer))
|
||||||
throw new TypeError('Pubkey mismatch');
|
throw new TypeError('Pubkey mismatch');
|
||||||
|
|
||||||
const pkh = bcrypto.hash160(<Buffer>chunks[1]);
|
const pkh = bcrypto.hash160(chunks[1] as Buffer);
|
||||||
if (hash.length > 0 && !hash.equals(pkh))
|
if (hash.length > 0 && !hash.equals(pkh))
|
||||||
throw new TypeError('Hash mismatch');
|
throw new TypeError('Hash mismatch');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
import { Payment, PaymentOpts } from './index';
|
import * as bcrypto from '../crypto';
|
||||||
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
||||||
import * as bscript from '../script';
|
import * as bscript from '../script';
|
||||||
import * as bcrypto from '../crypto';
|
import {
|
||||||
|
Payment,
|
||||||
|
PaymentFunction,
|
||||||
|
PaymentOpts,
|
||||||
|
Stack,
|
||||||
|
StackFunction,
|
||||||
|
} from './index';
|
||||||
import * as lazy from './lazy';
|
import * as lazy from './lazy';
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
|
|
||||||
const bs58check = require('bs58check');
|
const bs58check = require('bs58check');
|
||||||
|
|
||||||
function stacksEqual(a: Array<Buffer>, b: Array<Buffer>): boolean {
|
function stacksEqual(a: Buffer[], b: Buffer[]): boolean {
|
||||||
if (a.length !== b.length) return false;
|
if (a.length !== b.length) return false;
|
||||||
|
|
||||||
return a.every(function(x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -51,27 +57,29 @@ export function p2sh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
|
|
||||||
const o: Payment = { network };
|
const o: Payment = { network };
|
||||||
|
|
||||||
const _address = lazy.value(function() {
|
const _address = lazy.value(() => {
|
||||||
const payload = bs58check.decode(a.address);
|
const payload = bs58check.decode(a.address);
|
||||||
const version = payload.readUInt8(0);
|
const version = payload.readUInt8(0);
|
||||||
const hash = payload.slice(1);
|
const hash = payload.slice(1);
|
||||||
return { version, hash };
|
return { version, hash };
|
||||||
});
|
});
|
||||||
const _chunks = <() => Array<Buffer | number>>lazy.value(function() {
|
const _chunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.input!);
|
return bscript.decompile(a.input!);
|
||||||
});
|
}) as StackFunction;
|
||||||
const _redeem = lazy.value(function(): Payment {
|
const _redeem = lazy.value(
|
||||||
|
(): Payment => {
|
||||||
const chunks = _chunks();
|
const chunks = _chunks();
|
||||||
return {
|
return {
|
||||||
network,
|
network,
|
||||||
output: <Buffer>chunks[chunks.length - 1],
|
output: chunks[chunks.length - 1] as Buffer,
|
||||||
input: bscript.compile(chunks.slice(0, -1)),
|
input: bscript.compile(chunks.slice(0, -1)),
|
||||||
witness: a.witness || [],
|
witness: a.witness || [],
|
||||||
};
|
};
|
||||||
});
|
},
|
||||||
|
) as PaymentFunction;
|
||||||
|
|
||||||
// output dependents
|
// output dependents
|
||||||
lazy.prop(o, 'address', function() {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
|
|
||||||
const payload = Buffer.allocUnsafe(21);
|
const payload = Buffer.allocUnsafe(21);
|
||||||
|
@ -79,32 +87,32 @@ export function p2sh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
o.hash.copy(payload, 1);
|
o.hash.copy(payload, 1);
|
||||||
return bs58check.encode(payload);
|
return bs58check.encode(payload);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function() {
|
lazy.prop(o, 'hash', () => {
|
||||||
// in order of least effort
|
// in order of least effort
|
||||||
if (a.output) return a.output.slice(2, 22);
|
if (a.output) return a.output.slice(2, 22);
|
||||||
if (a.address) return _address().hash;
|
if (a.address) return _address().hash;
|
||||||
if (o.redeem && o.redeem.output) return bcrypto.hash160(o.redeem.output);
|
if (o.redeem && o.redeem.output) return bcrypto.hash160(o.redeem.output);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function() {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
return bscript.compile([OPS.OP_HASH160, o.hash, OPS.OP_EQUAL]);
|
return bscript.compile([OPS.OP_HASH160, o.hash, OPS.OP_EQUAL]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// input dependents
|
// input dependents
|
||||||
lazy.prop(o, 'redeem', function() {
|
lazy.prop(o, 'redeem', () => {
|
||||||
if (!a.input) return;
|
if (!a.input) return;
|
||||||
return _redeem();
|
return _redeem();
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function() {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!a.redeem || !a.redeem.input || !a.redeem.output) return;
|
if (!a.redeem || !a.redeem.input || !a.redeem.output) return;
|
||||||
return bscript.compile(
|
return bscript.compile(
|
||||||
(<Array<Buffer | number>>[]).concat(
|
([] as Stack).concat(
|
||||||
<Array<Buffer | number>>bscript.decompile(a.redeem.input),
|
bscript.decompile(a.redeem.input) as Stack,
|
||||||
a.redeem.output,
|
a.redeem.output,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function() {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (o.redeem && o.redeem.witness) return o.redeem.witness;
|
if (o.redeem && o.redeem.witness) return o.redeem.witness;
|
||||||
if (o.input) return [];
|
if (o.input) return [];
|
||||||
});
|
});
|
||||||
|
@ -140,7 +148,7 @@ export function p2sh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
}
|
}
|
||||||
|
|
||||||
// inlined to prevent 'no-inner-declarations' failing
|
// inlined to prevent 'no-inner-declarations' failing
|
||||||
const checkRedeem = function(redeem: Payment): void {
|
const checkRedeem = (redeem: Payment): void => {
|
||||||
// is the redeem output empty/invalid?
|
// is the redeem output empty/invalid?
|
||||||
if (redeem.output) {
|
if (redeem.output) {
|
||||||
const decompile = bscript.decompile(redeem.output);
|
const decompile = bscript.decompile(redeem.output);
|
||||||
|
@ -161,9 +169,7 @@ export function p2sh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
if (hasInput && hasWitness)
|
if (hasInput && hasWitness)
|
||||||
throw new TypeError('Input and witness provided');
|
throw new TypeError('Input and witness provided');
|
||||||
if (hasInput) {
|
if (hasInput) {
|
||||||
const richunks = <Array<Buffer | number>>(
|
const richunks = bscript.decompile(redeem.input) as Stack;
|
||||||
bscript.decompile(redeem.input)
|
|
||||||
);
|
|
||||||
if (!bscript.isPushOnly(richunks))
|
if (!bscript.isPushOnly(richunks))
|
||||||
throw new TypeError('Non push-only scriptSig');
|
throw new TypeError('Non push-only scriptSig');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Payment, PaymentOpts } from './index';
|
|
||||||
import * as bscript from '../script';
|
|
||||||
import * as bcrypto from '../crypto';
|
import * as bcrypto from '../crypto';
|
||||||
import * as lazy from './lazy';
|
|
||||||
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
||||||
|
import * as bscript from '../script';
|
||||||
|
import { Payment, PaymentOpts } from './index';
|
||||||
|
import * as lazy from './lazy';
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
|
@ -33,7 +33,7 @@ export function p2wpkh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
a,
|
a,
|
||||||
);
|
);
|
||||||
|
|
||||||
const _address = lazy.value(function() {
|
const _address = lazy.value(() => {
|
||||||
const result = bech32.decode(a.address);
|
const result = bech32.decode(a.address);
|
||||||
const version = result.words.shift();
|
const version = result.words.shift();
|
||||||
const data = bech32.fromWords(result.words);
|
const data = bech32.fromWords(result.words);
|
||||||
|
@ -47,36 +47,36 @@ export function p2wpkh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
const network = a.network || BITCOIN_NETWORK;
|
const network = a.network || BITCOIN_NETWORK;
|
||||||
const o: Payment = { network };
|
const o: Payment = { network };
|
||||||
|
|
||||||
lazy.prop(o, 'address', function() {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
|
|
||||||
const words = bech32.toWords(o.hash);
|
const words = bech32.toWords(o.hash);
|
||||||
words.unshift(0x00);
|
words.unshift(0x00);
|
||||||
return bech32.encode(network.bech32, words);
|
return bech32.encode(network.bech32, words);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function() {
|
lazy.prop(o, 'hash', () => {
|
||||||
if (a.output) return a.output.slice(2, 22);
|
if (a.output) return a.output.slice(2, 22);
|
||||||
if (a.address) return _address().data;
|
if (a.address) return _address().data;
|
||||||
if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey! || o.pubkey!);
|
if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey! || o.pubkey!);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function() {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
return bscript.compile([OPS.OP_0, o.hash]);
|
return bscript.compile([OPS.OP_0, o.hash]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'pubkey', function() {
|
lazy.prop(o, 'pubkey', () => {
|
||||||
if (a.pubkey) return a.pubkey;
|
if (a.pubkey) return a.pubkey;
|
||||||
if (!a.witness) return;
|
if (!a.witness) return;
|
||||||
return a.witness[1];
|
return a.witness[1];
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'signature', function() {
|
lazy.prop(o, 'signature', () => {
|
||||||
if (!a.witness) return;
|
if (!a.witness) return;
|
||||||
return a.witness[0];
|
return a.witness[0];
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function() {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!o.witness) return;
|
if (!o.witness) return;
|
||||||
return EMPTY_BUFFER;
|
return EMPTY_BUFFER;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function() {
|
lazy.prop(o, 'witness', () => {
|
||||||
if (!a.pubkey) return;
|
if (!a.pubkey) return;
|
||||||
if (!a.signature) return;
|
if (!a.signature) return;
|
||||||
return [a.signature, a.pubkey];
|
return [a.signature, a.pubkey];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Payment, PaymentOpts } from './index';
|
import * as bcrypto from '../crypto';
|
||||||
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
import { bitcoin as BITCOIN_NETWORK } from '../networks';
|
||||||
import * as bscript from '../script';
|
import * as bscript from '../script';
|
||||||
import * as bcrypto from '../crypto';
|
import { Payment, PaymentOpts, StackFunction } from './index';
|
||||||
import * as lazy from './lazy';
|
import * as lazy from './lazy';
|
||||||
const typef = require('typeforce');
|
const typef = require('typeforce');
|
||||||
const OPS = bscript.OPS;
|
const OPS = bscript.OPS;
|
||||||
|
@ -10,10 +10,10 @@ const bech32 = require('bech32');
|
||||||
|
|
||||||
const EMPTY_BUFFER = Buffer.alloc(0);
|
const EMPTY_BUFFER = Buffer.alloc(0);
|
||||||
|
|
||||||
function stacksEqual(a: Array<Buffer>, b: Array<Buffer>): boolean {
|
function stacksEqual(a: Buffer[], b: Buffer[]): boolean {
|
||||||
if (a.length !== b.length) return false;
|
if (a.length !== b.length) return false;
|
||||||
|
|
||||||
return a.every(function(x, i) {
|
return a.every((x, i) => {
|
||||||
return x.equals(b[i]);
|
return x.equals(b[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
a,
|
a,
|
||||||
);
|
);
|
||||||
|
|
||||||
const _address = lazy.value(function() {
|
const _address = lazy.value(() => {
|
||||||
const result = bech32.decode(a.address);
|
const result = bech32.decode(a.address);
|
||||||
const version = result.words.shift();
|
const version = result.words.shift();
|
||||||
const data = bech32.fromWords(result.words);
|
const data = bech32.fromWords(result.words);
|
||||||
|
@ -56,9 +56,9 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
data: Buffer.from(data),
|
data: Buffer.from(data),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const _rchunks = <() => Array<Buffer | number>>lazy.value(function() {
|
const _rchunks = lazy.value(() => {
|
||||||
return bscript.decompile(a.redeem!.input!);
|
return bscript.decompile(a.redeem!.input!);
|
||||||
});
|
}) as StackFunction;
|
||||||
|
|
||||||
let network = a.network;
|
let network = a.network;
|
||||||
if (!network) {
|
if (!network) {
|
||||||
|
@ -67,22 +67,22 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
|
|
||||||
const o: Payment = { network };
|
const o: Payment = { network };
|
||||||
|
|
||||||
lazy.prop(o, 'address', function() {
|
lazy.prop(o, 'address', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
const words = bech32.toWords(o.hash);
|
const words = bech32.toWords(o.hash);
|
||||||
words.unshift(0x00);
|
words.unshift(0x00);
|
||||||
return bech32.encode(network!.bech32, words);
|
return bech32.encode(network!.bech32, words);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'hash', function() {
|
lazy.prop(o, 'hash', () => {
|
||||||
if (a.output) return a.output.slice(2);
|
if (a.output) return a.output.slice(2);
|
||||||
if (a.address) return _address().data;
|
if (a.address) return _address().data;
|
||||||
if (o.redeem && o.redeem.output) return bcrypto.sha256(o.redeem.output);
|
if (o.redeem && o.redeem.output) return bcrypto.sha256(o.redeem.output);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'output', function() {
|
lazy.prop(o, 'output', () => {
|
||||||
if (!o.hash) return;
|
if (!o.hash) return;
|
||||||
return bscript.compile([OPS.OP_0, o.hash]);
|
return bscript.compile([OPS.OP_0, o.hash]);
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'redeem', function() {
|
lazy.prop(o, 'redeem', () => {
|
||||||
if (!a.witness) return;
|
if (!a.witness) return;
|
||||||
return {
|
return {
|
||||||
output: a.witness[a.witness.length - 1],
|
output: a.witness[a.witness.length - 1],
|
||||||
|
@ -90,11 +90,11 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
witness: a.witness.slice(0, -1),
|
witness: a.witness.slice(0, -1),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'input', function() {
|
lazy.prop(o, 'input', () => {
|
||||||
if (!o.witness) return;
|
if (!o.witness) return;
|
||||||
return EMPTY_BUFFER;
|
return EMPTY_BUFFER;
|
||||||
});
|
});
|
||||||
lazy.prop(o, 'witness', function() {
|
lazy.prop(o, 'witness', () => {
|
||||||
// transform redeem input to witness stack?
|
// transform redeem input to witness stack?
|
||||||
if (
|
if (
|
||||||
a.redeem &&
|
a.redeem &&
|
||||||
|
@ -108,13 +108,13 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
|
||||||
// assign, and blank the existing input
|
// assign, and blank the existing input
|
||||||
o.redeem = Object.assign({ witness: stack }, a.redeem);
|
o.redeem = Object.assign({ witness: stack }, a.redeem);
|
||||||
o.redeem.input = EMPTY_BUFFER;
|
o.redeem.input = EMPTY_BUFFER;
|
||||||
return (<Array<Buffer>>[]).concat(stack, a.redeem.output);
|
return ([] as Buffer[]).concat(stack, a.redeem.output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!a.redeem) return;
|
if (!a.redeem) return;
|
||||||
if (!a.redeem.output) return;
|
if (!a.redeem.output) return;
|
||||||
if (!a.redeem.witness) return;
|
if (!a.redeem.witness) return;
|
||||||
return (<Array<Buffer>>[]).concat(a.redeem.witness, a.redeem.output);
|
return ([] as Buffer[]).concat(a.redeem.witness, a.redeem.output);
|
||||||
});
|
});
|
||||||
|
|
||||||
// extended validation
|
// extended validation
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
import * as types from './types';
|
import { Stack } from './payments';
|
||||||
import * as scriptNumber from './script_number';
|
import * as scriptNumber from './script_number';
|
||||||
import * as scriptSignature from './script_signature';
|
import * as scriptSignature from './script_signature';
|
||||||
|
import * as types from './types';
|
||||||
const bip66 = require('bip66');
|
const bip66 = require('bip66');
|
||||||
const ecc = require('tiny-secp256k1');
|
const ecc = require('tiny-secp256k1');
|
||||||
const pushdata = require('pushdata-bitcoin');
|
const pushdata = require('pushdata-bitcoin');
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
|
|
||||||
export type OpCode = number;
|
export type OpCode = number;
|
||||||
export const OPS = <{ [index: string]: OpCode }>require('bitcoin-ops');
|
export const OPS = require('bitcoin-ops') as { [index: string]: OpCode };
|
||||||
|
|
||||||
const REVERSE_OPS = <{ [index: number]: string }>require('bitcoin-ops/map');
|
const REVERSE_OPS = require('bitcoin-ops/map') as { [index: number]: string };
|
||||||
const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
|
const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
|
||||||
|
|
||||||
function isOPInt(value: number): boolean {
|
function isOPInt(value: number): boolean {
|
||||||
|
@ -22,10 +23,10 @@ function isOPInt(value: number): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPushOnlyChunk(value: number | Buffer): boolean {
|
function isPushOnlyChunk(value: number | Buffer): boolean {
|
||||||
return types.Buffer(value) || isOPInt(<number>value);
|
return types.Buffer(value) || isOPInt(value as number);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPushOnly(value: Array<number | Buffer>) {
|
export function isPushOnly(value: Stack) {
|
||||||
return types.Array(value) && value.every(isPushOnlyChunk);
|
return types.Array(value) && value.every(isPushOnlyChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,13 +37,11 @@ function asMinimalOP(buffer: Buffer): number | void {
|
||||||
if (buffer[0] === 0x81) return OPS.OP_1NEGATE;
|
if (buffer[0] === 0x81) return OPS.OP_1NEGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
function chunksIsBuffer(buf: Buffer | Array<number | Buffer>): buf is Buffer {
|
function chunksIsBuffer(buf: Buffer | Stack): buf is Buffer {
|
||||||
return Buffer.isBuffer(buf);
|
return Buffer.isBuffer(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
function chunksIsArray(
|
function chunksIsArray(buf: Buffer | Stack): buf is Stack {
|
||||||
buf: Buffer | Array<number | Buffer>,
|
|
||||||
): buf is Array<number | Buffer> {
|
|
||||||
return types.Array(buf);
|
return types.Array(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +49,13 @@ function singleChunkIsBuffer(buf: number | Buffer): buf is Buffer {
|
||||||
return Buffer.isBuffer(buf);
|
return Buffer.isBuffer(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compile(chunks: Buffer | Array<number | Buffer>): Buffer {
|
export function compile(chunks: Buffer | Stack): Buffer {
|
||||||
// TODO: remove me
|
// TODO: remove me
|
||||||
if (chunksIsBuffer(chunks)) return chunks;
|
if (chunksIsBuffer(chunks)) return chunks;
|
||||||
|
|
||||||
typeforce(types.Array, chunks);
|
typeforce(types.Array, chunks);
|
||||||
|
|
||||||
const bufferSize = chunks.reduce(function(accum: number, chunk) {
|
const bufferSize = chunks.reduce((accum: number, chunk) => {
|
||||||
// data chunk
|
// data chunk
|
||||||
if (singleChunkIsBuffer(chunk)) {
|
if (singleChunkIsBuffer(chunk)) {
|
||||||
// adhere to BIP62.3, minimal push policy
|
// adhere to BIP62.3, minimal push policy
|
||||||
|
@ -74,7 +73,7 @@ export function compile(chunks: Buffer | Array<number | Buffer>): Buffer {
|
||||||
const buffer = Buffer.allocUnsafe(bufferSize);
|
const buffer = Buffer.allocUnsafe(bufferSize);
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
|
|
||||||
chunks.forEach(function(chunk) {
|
chunks.forEach(chunk => {
|
||||||
// data chunk
|
// data chunk
|
||||||
if (singleChunkIsBuffer(chunk)) {
|
if (singleChunkIsBuffer(chunk)) {
|
||||||
// adhere to BIP62.3, minimal push policy
|
// adhere to BIP62.3, minimal push policy
|
||||||
|
@ -149,16 +148,16 @@ export function decompile(
|
||||||
|
|
||||||
export function toASM(chunks: Buffer | Array<number | Buffer>): string {
|
export function toASM(chunks: Buffer | Array<number | Buffer>): string {
|
||||||
if (chunksIsBuffer(chunks)) {
|
if (chunksIsBuffer(chunks)) {
|
||||||
chunks = <Array<number | Buffer>>decompile(chunks);
|
chunks = decompile(chunks) as Stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunks
|
return chunks
|
||||||
.map(function(chunk) {
|
.map(chunk => {
|
||||||
// data?
|
// data?
|
||||||
if (singleChunkIsBuffer(chunk)) {
|
if (singleChunkIsBuffer(chunk)) {
|
||||||
const op = asMinimalOP(chunk);
|
const op = asMinimalOP(chunk);
|
||||||
if (op === undefined) return chunk.toString('hex');
|
if (op === undefined) return chunk.toString('hex');
|
||||||
chunk = <number>op;
|
chunk = op as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// opcode!
|
// opcode!
|
||||||
|
@ -171,7 +170,7 @@ export function fromASM(asm: string): Buffer {
|
||||||
typeforce(types.String, asm);
|
typeforce(types.String, asm);
|
||||||
|
|
||||||
return compile(
|
return compile(
|
||||||
asm.split(' ').map(function(chunkStr) {
|
asm.split(' ').map(chunkStr => {
|
||||||
// opcode?
|
// opcode?
|
||||||
if (OPS[chunkStr] !== undefined) return OPS[chunkStr];
|
if (OPS[chunkStr] !== undefined) return OPS[chunkStr];
|
||||||
typeforce(types.Hex, chunkStr);
|
typeforce(types.Hex, chunkStr);
|
||||||
|
@ -182,13 +181,11 @@ export function fromASM(asm: string): Buffer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toStack(
|
export function toStack(chunks: Buffer | Array<number | Buffer>): Buffer[] {
|
||||||
chunks: Buffer | Array<number | Buffer>,
|
chunks = decompile(chunks) as Stack;
|
||||||
): Array<Buffer> {
|
|
||||||
chunks = <Array<number | Buffer>>decompile(chunks);
|
|
||||||
typeforce(isPushOnly, chunks);
|
typeforce(isPushOnly, chunks);
|
||||||
|
|
||||||
return chunks.map(function(op) {
|
return chunks.map(op => {
|
||||||
if (singleChunkIsBuffer(op)) return op;
|
if (singleChunkIsBuffer(op)) return op;
|
||||||
if (op === OPS.OP_0) return Buffer.allocUnsafe(0);
|
if (op === OPS.OP_0) return Buffer.allocUnsafe(0);
|
||||||
|
|
||||||
|
@ -214,5 +211,6 @@ export function isCanonicalScriptSignature(buffer: Buffer): boolean {
|
||||||
return bip66.check(buffer.slice(0, -1));
|
return bip66.check(buffer.slice(0, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line variable-name
|
||||||
export const number = scriptNumber;
|
export const number = scriptNumber;
|
||||||
export const signature = scriptSignature;
|
export const signature = scriptSignature;
|
||||||
|
|
|
@ -27,7 +27,7 @@ export function decode(
|
||||||
|
|
||||||
// 32-bit / 24-bit / 16-bit / 8-bit
|
// 32-bit / 24-bit / 16-bit / 8-bit
|
||||||
let result = 0;
|
let result = 0;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
result |= buffer[i] << (8 * i);
|
result |= buffer[i] << (8 * i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +50,13 @@ function scriptNumSize(i: number): number {
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encode(number: number): Buffer {
|
export function encode(_number: number): Buffer {
|
||||||
let value = Math.abs(number);
|
let value = Math.abs(_number);
|
||||||
const size = scriptNumSize(value);
|
const size = scriptNumSize(value);
|
||||||
const buffer = Buffer.allocUnsafe(size);
|
const buffer = Buffer.allocUnsafe(size);
|
||||||
const negative = number < 0;
|
const negative = _number < 0;
|
||||||
|
|
||||||
for (var i = 0; i < size; ++i) {
|
for (let i = 0; i < size; ++i) {
|
||||||
buffer.writeUInt8(value & 0xff, i);
|
buffer.writeUInt8(value & 0xff, i);
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,14 +33,12 @@ export function decode(buffer: Buffer): ScriptSignature {
|
||||||
if (hashTypeMod <= 0 || hashTypeMod >= 4)
|
if (hashTypeMod <= 0 || hashTypeMod >= 4)
|
||||||
throw new Error('Invalid hashType ' + hashType);
|
throw new Error('Invalid hashType ' + hashType);
|
||||||
|
|
||||||
const decode = bip66.decode(buffer.slice(0, -1));
|
const decoded = bip66.decode(buffer.slice(0, -1));
|
||||||
const r = fromDER(decode.r);
|
const r = fromDER(decoded.r);
|
||||||
const s = fromDER(decode.s);
|
const s = fromDER(decoded.s);
|
||||||
|
const signature = Buffer.concat([r, s], 64);
|
||||||
|
|
||||||
return {
|
return { signature, hashType };
|
||||||
signature: Buffer.concat([r, s], 64),
|
|
||||||
hashType: hashType,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encode(signature: Buffer, hashType: number): Buffer {
|
export function encode(signature: Buffer, hashType: number): Buffer {
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
// OP_0 [signatures ...]
|
// OP_0 [signatures ...]
|
||||||
|
|
||||||
|
import { Stack } from '../../payments';
|
||||||
import * as bscript from '../../script';
|
import * as bscript from '../../script';
|
||||||
import { OPS } from '../../script';
|
import { OPS } from '../../script';
|
||||||
|
|
||||||
function partialSignature(value: number | Buffer): boolean {
|
function partialSignature(value: number | Buffer): boolean {
|
||||||
return (
|
return (
|
||||||
value === OPS.OP_0 || bscript.isCanonicalScriptSignature(<Buffer>value)
|
value === OPS.OP_0 || bscript.isCanonicalScriptSignature(value as Buffer)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function check(
|
export function check(
|
||||||
script: Buffer | Array<number | Buffer>,
|
script: Buffer | Stack,
|
||||||
allowIncomplete?: boolean,
|
allowIncomplete?: boolean,
|
||||||
): boolean {
|
): boolean {
|
||||||
const chunks = <Array<number | Buffer>>bscript.decompile(script);
|
const chunks = bscript.decompile(script) as Stack;
|
||||||
if (chunks.length < 2) return false;
|
if (chunks.length < 2) return false;
|
||||||
if (chunks[0] !== OPS.OP_0) return false;
|
if (chunks[0] !== OPS.OP_0) return false;
|
||||||
|
|
||||||
|
@ -21,10 +22,10 @@ export function check(
|
||||||
return chunks.slice(1).every(partialSignature);
|
return chunks.slice(1).every(partialSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<Array<Buffer>>chunks.slice(1)).every(
|
return (chunks.slice(1) as Buffer[]).every(
|
||||||
bscript.isCanonicalScriptSignature,
|
bscript.isCanonicalScriptSignature,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'multisig input';
|
return 'multisig input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
// m [pubKeys ...] n OP_CHECKMULTISIG
|
// m [pubKeys ...] n OP_CHECKMULTISIG
|
||||||
|
|
||||||
|
import { Stack } from '../../payments';
|
||||||
import * as bscript from '../../script';
|
import * as bscript from '../../script';
|
||||||
import * as types from '../../types';
|
|
||||||
import { OPS } from '../../script';
|
import { OPS } from '../../script';
|
||||||
|
import * as types from '../../types';
|
||||||
const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
|
const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
|
||||||
|
|
||||||
export function check(
|
export function check(
|
||||||
script: Buffer | Array<number | Buffer>,
|
script: Buffer | Stack,
|
||||||
allowIncomplete?: boolean,
|
allowIncomplete?: boolean,
|
||||||
): boolean {
|
): boolean {
|
||||||
const chunks = <Array<number | Buffer>>bscript.decompile(script);
|
const chunks = bscript.decompile(script) as Stack;
|
||||||
|
|
||||||
if (chunks.length < 4) return false;
|
if (chunks.length < 4) return false;
|
||||||
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false;
|
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false;
|
||||||
if (!types.Number(chunks[0])) return false;
|
if (!types.Number(chunks[0])) return false;
|
||||||
if (!types.Number(chunks[chunks.length - 2])) return false;
|
if (!types.Number(chunks[chunks.length - 2])) return false;
|
||||||
const m = <number>chunks[0] - OP_INT_BASE;
|
const m = (chunks[0] as number) - OP_INT_BASE;
|
||||||
const n = <number>chunks[chunks.length - 2] - OP_INT_BASE;
|
const n = (chunks[chunks.length - 2] as number) - OP_INT_BASE;
|
||||||
|
|
||||||
if (m <= 0) return false;
|
if (m <= 0) return false;
|
||||||
if (n > 16) return false;
|
if (n > 16) return false;
|
||||||
|
@ -24,9 +25,9 @@ export function check(
|
||||||
if (n !== chunks.length - 3) return false;
|
if (n !== chunks.length - 3) return false;
|
||||||
if (allowIncomplete) return true;
|
if (allowIncomplete) return true;
|
||||||
|
|
||||||
const keys = <Array<Buffer>>chunks.slice(1, -2);
|
const keys = chunks.slice(1, -2) as Buffer[];
|
||||||
return keys.every(bscript.isCanonicalPubKey);
|
return keys.every(bscript.isCanonicalPubKey);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'multi-sig output';
|
return 'multi-sig output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@ export function check(script: Buffer | Array<number | Buffer>): boolean {
|
||||||
|
|
||||||
return buffer.length > 1 && buffer[0] === OPS.OP_RETURN;
|
return buffer.length > 1 && buffer[0] === OPS.OP_RETURN;
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'null data output';
|
return 'null data output';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
// {signature}
|
// {signature}
|
||||||
|
|
||||||
|
import { Stack } from '../../payments';
|
||||||
import * as bscript from '../../script';
|
import * as bscript from '../../script';
|
||||||
|
|
||||||
export function check(script: Buffer | Array<number | Buffer>): boolean {
|
export function check(script: Buffer | Stack): boolean {
|
||||||
const chunks = <Array<number | Buffer>>bscript.decompile(script);
|
const chunks = bscript.decompile(script) as Stack;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
chunks.length === 1 && bscript.isCanonicalScriptSignature(<Buffer>chunks[0])
|
chunks.length === 1 &&
|
||||||
|
bscript.isCanonicalScriptSignature(chunks[0] as Buffer)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'pubKey input';
|
return 'pubKey input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
// {pubKey} OP_CHECKSIG
|
// {pubKey} OP_CHECKSIG
|
||||||
|
|
||||||
|
import { Stack } from '../../payments';
|
||||||
import * as bscript from '../../script';
|
import * as bscript from '../../script';
|
||||||
import { OPS } from '../../script';
|
import { OPS } from '../../script';
|
||||||
|
|
||||||
export function check(script: Buffer | Array<number | Buffer>): boolean {
|
export function check(script: Buffer | Stack): boolean {
|
||||||
const chunks = <Array<number | Buffer>>bscript.decompile(script);
|
const chunks = bscript.decompile(script) as Stack;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
chunks.length === 2 &&
|
chunks.length === 2 &&
|
||||||
bscript.isCanonicalPubKey(<Buffer>chunks[0]) &&
|
bscript.isCanonicalPubKey(chunks[0] as Buffer) &&
|
||||||
chunks[1] === OPS.OP_CHECKSIG
|
chunks[1] === OPS.OP_CHECKSIG
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'pubKey output';
|
return 'pubKey output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
// {signature} {pubKey}
|
// {signature} {pubKey}
|
||||||
|
|
||||||
|
import { Stack } from '../../payments';
|
||||||
import * as bscript from '../../script';
|
import * as bscript from '../../script';
|
||||||
|
|
||||||
export function check(script: Buffer | Array<number | Buffer>): boolean {
|
export function check(script: Buffer | Stack): boolean {
|
||||||
const chunks = <Array<number | Buffer>>bscript.decompile(script);
|
const chunks = bscript.decompile(script) as Stack;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
chunks.length === 2 &&
|
chunks.length === 2 &&
|
||||||
bscript.isCanonicalScriptSignature(<Buffer>chunks[0]) &&
|
bscript.isCanonicalScriptSignature(chunks[0] as Buffer) &&
|
||||||
bscript.isCanonicalPubKey(<Buffer>chunks[1])
|
bscript.isCanonicalPubKey(chunks[1] as Buffer)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'pubKeyHash input';
|
return 'pubKeyHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,6 @@ export function check(script: Buffer | Array<number | Buffer>): boolean {
|
||||||
buffer[24] === OPS.OP_CHECKSIG
|
buffer[24] === OPS.OP_CHECKSIG
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'pubKeyHash output';
|
return 'pubKeyHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,6 +56,6 @@ export function check(
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'scriptHash input';
|
return 'scriptHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,6 @@ export function check(script: Buffer | Array<number | Buffer>): boolean {
|
||||||
buffer[22] === OPS.OP_EQUAL
|
buffer[22] === OPS.OP_EQUAL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'scriptHash output';
|
return 'scriptHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// OP_RETURN {aa21a9ed} {commitment}
|
// OP_RETURN {aa21a9ed} {commitment}
|
||||||
|
|
||||||
import * as bscript from '../../script';
|
import * as bscript from '../../script';
|
||||||
|
import { OPS } from '../../script';
|
||||||
import * as types from '../../types';
|
import * as types from '../../types';
|
||||||
|
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
import { OPS } from '../../script';
|
|
||||||
|
|
||||||
const HEADER: Buffer = Buffer.from('aa21a9ed', 'hex');
|
const HEADER: Buffer = Buffer.from('aa21a9ed', 'hex');
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ export function check(script: Buffer | Array<number | Buffer>): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'Witness commitment output';
|
return 'Witness commitment output';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,5 +36,5 @@ export function encode(commitment: Buffer): Buffer {
|
||||||
export function decode(buffer: Buffer): Buffer {
|
export function decode(buffer: Buffer): Buffer {
|
||||||
typeforce(check, buffer);
|
typeforce(check, buffer);
|
||||||
|
|
||||||
return (<Buffer>bscript.decompile(buffer)![1]).slice(4, 36);
|
return (bscript.decompile(buffer)![1] as Buffer).slice(4, 36);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
// {signature} {pubKey}
|
// {signature} {pubKey}
|
||||||
|
|
||||||
|
import { Stack } from '../../payments';
|
||||||
import * as bscript from '../../script';
|
import * as bscript from '../../script';
|
||||||
|
|
||||||
function isCompressedCanonicalPubKey(pubKey: Buffer): boolean {
|
function isCompressedCanonicalPubKey(pubKey: Buffer): boolean {
|
||||||
return bscript.isCanonicalPubKey(pubKey) && pubKey.length === 33;
|
return bscript.isCanonicalPubKey(pubKey) && pubKey.length === 33;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function check(script: Buffer | Array<number | Buffer>): boolean {
|
export function check(script: Buffer | Stack): boolean {
|
||||||
const chunks = <Array<number | Buffer>>bscript.decompile(script);
|
const chunks = bscript.decompile(script) as Stack;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
chunks.length === 2 &&
|
chunks.length === 2 &&
|
||||||
bscript.isCanonicalScriptSignature(<Buffer>chunks[0]) &&
|
bscript.isCanonicalScriptSignature(chunks[0] as Buffer) &&
|
||||||
isCompressedCanonicalPubKey(<Buffer>chunks[1])
|
isCompressedCanonicalPubKey(chunks[1] as Buffer)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'witnessPubKeyHash input';
|
return 'witnessPubKeyHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,6 @@ export function check(script: Buffer | Array<number | Buffer>): boolean {
|
||||||
|
|
||||||
return buffer.length === 22 && buffer[0] === OPS.OP_0 && buffer[1] === 0x14;
|
return buffer.length === 22 && buffer[0] === OPS.OP_0 && buffer[1] === 0x14;
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'Witness pubKeyHash output';
|
return 'Witness pubKeyHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,10 +7,7 @@ import * as p2ms from '../multisig';
|
||||||
import * as p2pk from '../pubkey';
|
import * as p2pk from '../pubkey';
|
||||||
import * as p2pkh from '../pubkeyhash';
|
import * as p2pkh from '../pubkeyhash';
|
||||||
|
|
||||||
export function check(
|
export function check(chunks: Buffer[], allowIncomplete?: boolean): boolean {
|
||||||
chunks: Array<Buffer>,
|
|
||||||
allowIncomplete?: boolean,
|
|
||||||
): boolean {
|
|
||||||
typeforce(typeforce.Array, chunks);
|
typeforce(typeforce.Array, chunks);
|
||||||
if (chunks.length < 1) return false;
|
if (chunks.length < 1) return false;
|
||||||
|
|
||||||
|
@ -45,6 +42,6 @@ export function check(
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'witnessScriptHash input';
|
return 'witnessScriptHash input';
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,6 @@ export function check(script: Buffer | Array<number | Buffer>): boolean {
|
||||||
|
|
||||||
return buffer.length === 34 && buffer[0] === OPS.OP_0 && buffer[1] === 0x20;
|
return buffer.length === 34 && buffer[0] === OPS.OP_0 && buffer[1] === 0x20;
|
||||||
}
|
}
|
||||||
check.toJSON = function() {
|
check.toJSON = () => {
|
||||||
return 'Witness scriptHash output';
|
return 'Witness scriptHash output';
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as bcrypto from './crypto';
|
|
||||||
import * as bscript from './script';
|
|
||||||
import * as types from './types';
|
|
||||||
import * as bufferutils from './bufferutils';
|
import * as bufferutils from './bufferutils';
|
||||||
import { reverseBuffer } from './bufferutils';
|
import { reverseBuffer } from './bufferutils';
|
||||||
|
import * as bcrypto from './crypto';
|
||||||
|
import * as bscript from './script';
|
||||||
import { OPS as opcodes } from './script';
|
import { OPS as opcodes } from './script';
|
||||||
|
import * as types from './types';
|
||||||
|
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
const varuint = require('varuint-bitcoin');
|
const varuint = require('varuint-bitcoin');
|
||||||
|
@ -14,7 +14,7 @@ function varSliceSize(someScript: Buffer): number {
|
||||||
return varuint.encodingLength(length) + length;
|
return varuint.encodingLength(length) + length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function vectorSize(someVector: Array<Buffer>): number {
|
function vectorSize(someVector: Buffer[]): number {
|
||||||
const length = someVector.length;
|
const length = someVector.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -26,7 +26,7 @@ function vectorSize(someVector: Array<Buffer>): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
const EMPTY_SCRIPT: Buffer = Buffer.allocUnsafe(0);
|
const EMPTY_SCRIPT: Buffer = Buffer.allocUnsafe(0);
|
||||||
const EMPTY_WITNESS: Array<Buffer> = [];
|
const EMPTY_WITNESS: Buffer[] = [];
|
||||||
const ZERO: Buffer = Buffer.from(
|
const ZERO: Buffer = Buffer.from(
|
||||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'hex',
|
'hex',
|
||||||
|
@ -42,33 +42,30 @@ const BLANK_OUTPUT: BlankOutput = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function isOutput(out: Output | BlankOutput): out is Output {
|
function isOutput(out: Output | BlankOutput): out is Output {
|
||||||
return (<Output>out).value !== undefined;
|
return (out as Output).value !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BlankOutput = {
|
export interface BlankOutput {
|
||||||
script: Buffer;
|
script: Buffer;
|
||||||
valueBuffer: Buffer;
|
valueBuffer: Buffer;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type Output = {
|
export interface Output {
|
||||||
script: Buffer;
|
script: Buffer;
|
||||||
value: number;
|
value: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type Input = {
|
type OpenOutput = Output | BlankOutput;
|
||||||
|
|
||||||
|
export interface Input {
|
||||||
hash: Buffer;
|
hash: Buffer;
|
||||||
index: number;
|
index: number;
|
||||||
script: Buffer;
|
script: Buffer;
|
||||||
sequence: number;
|
sequence: number;
|
||||||
witness: Array<Buffer>;
|
witness: Buffer[];
|
||||||
};
|
}
|
||||||
|
|
||||||
export class Transaction {
|
export class Transaction {
|
||||||
version: number;
|
|
||||||
locktime: number;
|
|
||||||
ins: Array<Input>;
|
|
||||||
outs: Array<Output | BlankOutput>;
|
|
||||||
|
|
||||||
static readonly DEFAULT_SEQUENCE = 0xffffffff;
|
static readonly DEFAULT_SEQUENCE = 0xffffffff;
|
||||||
static readonly SIGHASH_ALL = 0x01;
|
static readonly SIGHASH_ALL = 0x01;
|
||||||
static readonly SIGHASH_NONE = 0x02;
|
static readonly SIGHASH_NONE = 0x02;
|
||||||
|
@ -77,14 +74,7 @@ export class Transaction {
|
||||||
static readonly ADVANCED_TRANSACTION_MARKER = 0x00;
|
static readonly ADVANCED_TRANSACTION_MARKER = 0x00;
|
||||||
static readonly ADVANCED_TRANSACTION_FLAG = 0x01;
|
static readonly ADVANCED_TRANSACTION_FLAG = 0x01;
|
||||||
|
|
||||||
constructor() {
|
static fromBuffer(buffer: Buffer, _NO_STRICT?: boolean): Transaction {
|
||||||
this.version = 1;
|
|
||||||
this.locktime = 0;
|
|
||||||
this.ins = [];
|
|
||||||
this.outs = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromBuffer(buffer: Buffer, __noStrict?: boolean): Transaction {
|
|
||||||
let offset: number = 0;
|
let offset: number = 0;
|
||||||
|
|
||||||
function readSlice(n: number): Buffer {
|
function readSlice(n: number): Buffer {
|
||||||
|
@ -120,10 +110,10 @@ export class Transaction {
|
||||||
return readSlice(readVarInt());
|
return readSlice(readVarInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
function readVector(): Array<Buffer> {
|
function readVector(): Buffer[] {
|
||||||
const count = readVarInt();
|
const count = readVarInt();
|
||||||
const vector: Array<Buffer> = [];
|
const vector: Buffer[] = [];
|
||||||
for (var i = 0; i < count; i++) vector.push(readVarSlice());
|
for (let i = 0; i < count; i++) vector.push(readVarSlice());
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +133,7 @@ export class Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
const vinLen = readVarInt();
|
const vinLen = readVarInt();
|
||||||
for (var i = 0; i < vinLen; ++i) {
|
for (let i = 0; i < vinLen; ++i) {
|
||||||
tx.ins.push({
|
tx.ins.push({
|
||||||
hash: readSlice(32),
|
hash: readSlice(32),
|
||||||
index: readUInt32(),
|
index: readUInt32(),
|
||||||
|
@ -154,7 +144,7 @@ export class Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
const voutLen = readVarInt();
|
const voutLen = readVarInt();
|
||||||
for (i = 0; i < voutLen; ++i) {
|
for (let i = 0; i < voutLen; ++i) {
|
||||||
tx.outs.push({
|
tx.outs.push({
|
||||||
value: readUInt64(),
|
value: readUInt64(),
|
||||||
script: readVarSlice(),
|
script: readVarSlice(),
|
||||||
|
@ -162,7 +152,7 @@ export class Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasWitnesses) {
|
if (hasWitnesses) {
|
||||||
for (i = 0; i < vinLen; ++i) {
|
for (let i = 0; i < vinLen; ++i) {
|
||||||
tx.ins[i].witness = readVector();
|
tx.ins[i].witness = readVector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +163,7 @@ export class Transaction {
|
||||||
|
|
||||||
tx.locktime = readUInt32();
|
tx.locktime = readUInt32();
|
||||||
|
|
||||||
if (__noStrict) return tx;
|
if (_NO_STRICT) return tx;
|
||||||
if (offset !== buffer.length)
|
if (offset !== buffer.length)
|
||||||
throw new Error('Transaction has unexpected data');
|
throw new Error('Transaction has unexpected data');
|
||||||
|
|
||||||
|
@ -186,12 +176,24 @@ export class Transaction {
|
||||||
|
|
||||||
static isCoinbaseHash(buffer: Buffer): boolean {
|
static isCoinbaseHash(buffer: Buffer): boolean {
|
||||||
typeforce(types.Hash256bit, buffer);
|
typeforce(types.Hash256bit, buffer);
|
||||||
for (var i = 0; i < 32; ++i) {
|
for (let i = 0; i < 32; ++i) {
|
||||||
if (buffer[i] !== 0) return false;
|
if (buffer[i] !== 0) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version: number;
|
||||||
|
locktime: number;
|
||||||
|
ins: Input[];
|
||||||
|
outs: OpenOutput[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.version = 1;
|
||||||
|
this.locktime = 0;
|
||||||
|
this.ins = [];
|
||||||
|
this.outs = [];
|
||||||
|
}
|
||||||
|
|
||||||
isCoinbase(): boolean {
|
isCoinbase(): boolean {
|
||||||
return (
|
return (
|
||||||
this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash)
|
this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash)
|
||||||
|
@ -221,10 +223,10 @@ export class Transaction {
|
||||||
// Add the input and return the input's index
|
// Add the input and return the input's index
|
||||||
return (
|
return (
|
||||||
this.ins.push({
|
this.ins.push({
|
||||||
hash: hash,
|
hash,
|
||||||
index: index,
|
index,
|
||||||
script: scriptSig || EMPTY_SCRIPT,
|
script: scriptSig || EMPTY_SCRIPT,
|
||||||
sequence: <number>sequence,
|
sequence: sequence as number,
|
||||||
witness: EMPTY_WITNESS,
|
witness: EMPTY_WITNESS,
|
||||||
}) - 1
|
}) - 1
|
||||||
);
|
);
|
||||||
|
@ -237,7 +239,7 @@ export class Transaction {
|
||||||
return (
|
return (
|
||||||
this.outs.push({
|
this.outs.push({
|
||||||
script: scriptPubKey,
|
script: scriptPubKey,
|
||||||
value: value,
|
value,
|
||||||
}) - 1
|
}) - 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -262,27 +264,6 @@ export class Transaction {
|
||||||
return this.__byteLength(true);
|
return this.__byteLength(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private __byteLength(__allowWitness: boolean): number {
|
|
||||||
const hasWitnesses = __allowWitness && this.hasWitnesses();
|
|
||||||
|
|
||||||
return (
|
|
||||||
(hasWitnesses ? 10 : 8) +
|
|
||||||
varuint.encodingLength(this.ins.length) +
|
|
||||||
varuint.encodingLength(this.outs.length) +
|
|
||||||
this.ins.reduce((sum, input) => {
|
|
||||||
return sum + 40 + varSliceSize(input.script);
|
|
||||||
}, 0) +
|
|
||||||
this.outs.reduce((sum, output) => {
|
|
||||||
return sum + 8 + varSliceSize(output.script);
|
|
||||||
}, 0) +
|
|
||||||
(hasWitnesses
|
|
||||||
? this.ins.reduce((sum, input) => {
|
|
||||||
return sum + vectorSize(input.witness);
|
|
||||||
}, 0)
|
|
||||||
: 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
clone(): Transaction {
|
clone(): Transaction {
|
||||||
const newTx = new Transaction();
|
const newTx = new Transaction();
|
||||||
newTx.version = this.version;
|
newTx.version = this.version;
|
||||||
|
@ -301,7 +282,7 @@ export class Transaction {
|
||||||
newTx.outs = this.outs.map(txOut => {
|
newTx.outs = this.outs.map(txOut => {
|
||||||
return {
|
return {
|
||||||
script: txOut.script,
|
script: txOut.script,
|
||||||
value: (<Output>txOut).value,
|
value: (txOut as Output).value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -358,7 +339,7 @@ export class Transaction {
|
||||||
txTmp.outs.length = inIndex + 1;
|
txTmp.outs.length = inIndex + 1;
|
||||||
|
|
||||||
// "blank" outputs before
|
// "blank" outputs before
|
||||||
for (var i = 0; i < inIndex; i++) {
|
for (let i = 0; i < inIndex; i++) {
|
||||||
txTmp.outs[i] = BLANK_OUTPUT;
|
txTmp.outs[i] = BLANK_OUTPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,7 +452,7 @@ export class Transaction {
|
||||||
toffset = 0;
|
toffset = 0;
|
||||||
|
|
||||||
this.outs.forEach(out => {
|
this.outs.forEach(out => {
|
||||||
writeUInt64((<Output>out).value);
|
writeUInt64((out as Output).value);
|
||||||
writeVarSlice(out.script);
|
writeVarSlice(out.script);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -484,7 +465,7 @@ export class Transaction {
|
||||||
|
|
||||||
tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script));
|
tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script));
|
||||||
toffset = 0;
|
toffset = 0;
|
||||||
writeUInt64((<Output>output).value);
|
writeUInt64((output as Output).value);
|
||||||
writeVarSlice(output.script);
|
writeVarSlice(output.script);
|
||||||
|
|
||||||
hashOutputs = bcrypto.hash256(tbuffer);
|
hashOutputs = bcrypto.hash256(tbuffer);
|
||||||
|
@ -523,13 +504,50 @@ export class Transaction {
|
||||||
return this.__toBuffer(buffer, initialOffset, true);
|
return this.__toBuffer(buffer, initialOffset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toHex() {
|
||||||
|
return this.toBuffer(undefined, undefined).toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
setInputScript(index: number, scriptSig: Buffer) {
|
||||||
|
typeforce(types.tuple(types.Number, types.Buffer), arguments);
|
||||||
|
|
||||||
|
this.ins[index].script = scriptSig;
|
||||||
|
}
|
||||||
|
|
||||||
|
setWitness(index: number, witness: Buffer[]) {
|
||||||
|
typeforce(types.tuple(types.Number, [types.Buffer]), arguments);
|
||||||
|
|
||||||
|
this.ins[index].witness = witness;
|
||||||
|
}
|
||||||
|
|
||||||
|
private __byteLength(_ALLOW_WITNESS: boolean): number {
|
||||||
|
const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
|
||||||
|
|
||||||
|
return (
|
||||||
|
(hasWitnesses ? 10 : 8) +
|
||||||
|
varuint.encodingLength(this.ins.length) +
|
||||||
|
varuint.encodingLength(this.outs.length) +
|
||||||
|
this.ins.reduce((sum, input) => {
|
||||||
|
return sum + 40 + varSliceSize(input.script);
|
||||||
|
}, 0) +
|
||||||
|
this.outs.reduce((sum, output) => {
|
||||||
|
return sum + 8 + varSliceSize(output.script);
|
||||||
|
}, 0) +
|
||||||
|
(hasWitnesses
|
||||||
|
? this.ins.reduce((sum, input) => {
|
||||||
|
return sum + vectorSize(input.witness);
|
||||||
|
}, 0)
|
||||||
|
: 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private __toBuffer(
|
private __toBuffer(
|
||||||
buffer?: Buffer,
|
buffer?: Buffer,
|
||||||
initialOffset?: number,
|
initialOffset?: number,
|
||||||
__allowWitness?: boolean,
|
_ALLOW_WITNESS?: boolean,
|
||||||
): Buffer {
|
): Buffer {
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
buffer = <Buffer>Buffer.allocUnsafe(this.__byteLength(__allowWitness!));
|
buffer = Buffer.allocUnsafe(this.__byteLength(_ALLOW_WITNESS!)) as Buffer;
|
||||||
|
|
||||||
let offset = initialOffset || 0;
|
let offset = initialOffset || 0;
|
||||||
|
|
||||||
|
@ -563,14 +581,14 @@ export class Transaction {
|
||||||
writeSlice(slice);
|
writeSlice(slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeVector(vector: Array<Buffer>) {
|
function writeVector(vector: Buffer[]) {
|
||||||
writeVarInt(vector.length);
|
writeVarInt(vector.length);
|
||||||
vector.forEach(writeVarSlice);
|
vector.forEach(writeVarSlice);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeInt32(this.version);
|
writeInt32(this.version);
|
||||||
|
|
||||||
const hasWitnesses = __allowWitness && this.hasWitnesses();
|
const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
|
||||||
|
|
||||||
if (hasWitnesses) {
|
if (hasWitnesses) {
|
||||||
writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER);
|
writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER);
|
||||||
|
@ -609,20 +627,4 @@ export class Transaction {
|
||||||
if (initialOffset !== undefined) return buffer.slice(initialOffset, offset);
|
if (initialOffset !== undefined) return buffer.slice(initialOffset, offset);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
toHex() {
|
|
||||||
return this.toBuffer(undefined, undefined).toString('hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
setInputScript(index: number, scriptSig: Buffer) {
|
|
||||||
typeforce(types.tuple(types.Number, types.Buffer), arguments);
|
|
||||||
|
|
||||||
this.ins[index].script = scriptSig;
|
|
||||||
}
|
|
||||||
|
|
||||||
setWitness(index: number, witness: Array<Buffer>) {
|
|
||||||
typeforce(types.tuple(types.Number, [types.Buffer]), arguments);
|
|
||||||
|
|
||||||
this.ins[index].witness = witness;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,25 @@
|
||||||
import { Network } from './networks';
|
import * as baddress from './address';
|
||||||
import * as networks from './networks';
|
|
||||||
import { reverseBuffer } from './bufferutils';
|
import { reverseBuffer } from './bufferutils';
|
||||||
import { Transaction, Output } from './transaction';
|
import * as classify from './classify';
|
||||||
|
import * as bcrypto from './crypto';
|
||||||
import { ECPairInterface } from './ecpair';
|
import { ECPairInterface } from './ecpair';
|
||||||
import * as ECPair from './ecpair';
|
import * as ECPair from './ecpair';
|
||||||
import * as types from './types';
|
import { Network } from './networks';
|
||||||
import * as baddress from './address';
|
import * as networks from './networks';
|
||||||
import * as bcrypto from './crypto';
|
|
||||||
import * as bscript from './script';
|
|
||||||
import { Payment } from './payments';
|
import { Payment } from './payments';
|
||||||
import * as payments from './payments';
|
import * as payments from './payments';
|
||||||
import * as classify from './classify';
|
import * as bscript from './script';
|
||||||
import { OPS as ops } from './script';
|
import { OPS as ops } from './script';
|
||||||
|
import { Output, Transaction } from './transaction';
|
||||||
|
import * as types from './types';
|
||||||
const typeforce = require('typeforce');
|
const typeforce = require('typeforce');
|
||||||
|
|
||||||
const SCRIPT_TYPES = classify.types;
|
const SCRIPT_TYPES = classify.types;
|
||||||
|
|
||||||
type TxbSignatures = Array<Buffer> | Array<Buffer | undefined>;
|
type MaybeBuffer = Buffer | undefined;
|
||||||
type TxbPubkeys = Array<Buffer | undefined>;
|
type TxbSignatures = Buffer[] | MaybeBuffer[];
|
||||||
type TxbWitness = Array<Buffer>;
|
type TxbPubkeys = MaybeBuffer[];
|
||||||
|
type TxbWitness = Buffer[];
|
||||||
type TxbScriptType = string;
|
type TxbScriptType = string;
|
||||||
type TxbScript = Buffer;
|
type TxbScript = Buffer;
|
||||||
|
|
||||||
|
@ -58,24 +59,6 @@ function txIsTransaction(tx: Buffer | string | Transaction): tx is Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TransactionBuilder {
|
export class TransactionBuilder {
|
||||||
network: Network;
|
|
||||||
maximumFeeRate: number;
|
|
||||||
private __prevTxSet: { [index: string]: boolean };
|
|
||||||
private __inputs: Array<TxbInput>;
|
|
||||||
private __tx: Transaction;
|
|
||||||
|
|
||||||
constructor(network?: Network, maximumFeeRate?: number) {
|
|
||||||
this.__prevTxSet = {};
|
|
||||||
this.network = network || networks.bitcoin;
|
|
||||||
|
|
||||||
// WARNING: This is __NOT__ to be relied on, its just another potential safety mechanism (safety in-depth)
|
|
||||||
this.maximumFeeRate = maximumFeeRate || 2500;
|
|
||||||
|
|
||||||
this.__inputs = [];
|
|
||||||
this.__tx = new Transaction();
|
|
||||||
this.__tx.version = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromTransaction(
|
static fromTransaction(
|
||||||
transaction: Transaction,
|
transaction: Transaction,
|
||||||
network?: Network,
|
network?: Network,
|
||||||
|
@ -88,7 +71,7 @@ export class TransactionBuilder {
|
||||||
|
|
||||||
// Copy outputs (done first to avoid signature invalidation)
|
// Copy outputs (done first to avoid signature invalidation)
|
||||||
transaction.outs.forEach(txOut => {
|
transaction.outs.forEach(txOut => {
|
||||||
txb.addOutput(txOut.script, (<Output>txOut).value);
|
txb.addOutput(txOut.script, (txOut as Output).value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Copy inputs
|
// Copy inputs
|
||||||
|
@ -101,19 +84,37 @@ export class TransactionBuilder {
|
||||||
});
|
});
|
||||||
|
|
||||||
// fix some things not possible through the public API
|
// fix some things not possible through the public API
|
||||||
txb.__inputs.forEach((input, i) => {
|
txb.__INPUTS.forEach((input, i) => {
|
||||||
fixMultisigOrder(input, transaction, i);
|
fixMultisigOrder(input, transaction, i);
|
||||||
});
|
});
|
||||||
|
|
||||||
return txb;
|
return txb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
network: Network;
|
||||||
|
maximumFeeRate: number;
|
||||||
|
private __PREV_TX_SET: { [index: string]: boolean };
|
||||||
|
private __INPUTS: TxbInput[];
|
||||||
|
private __TX: Transaction;
|
||||||
|
|
||||||
|
constructor(network?: Network, maximumFeeRate?: number) {
|
||||||
|
this.__PREV_TX_SET = {};
|
||||||
|
this.network = network || networks.bitcoin;
|
||||||
|
|
||||||
|
// WARNING: This is __NOT__ to be relied on, its just another potential safety mechanism (safety in-depth)
|
||||||
|
this.maximumFeeRate = maximumFeeRate || 2500;
|
||||||
|
|
||||||
|
this.__INPUTS = [];
|
||||||
|
this.__TX = new Transaction();
|
||||||
|
this.__TX.version = 2;
|
||||||
|
}
|
||||||
|
|
||||||
setLockTime(locktime: number): void {
|
setLockTime(locktime: number): void {
|
||||||
typeforce(types.UInt32, locktime);
|
typeforce(types.UInt32, locktime);
|
||||||
|
|
||||||
// if any signatures exist, throw
|
// if any signatures exist, throw
|
||||||
if (
|
if (
|
||||||
this.__inputs.some(input => {
|
this.__INPUTS.some(input => {
|
||||||
if (!input.signatures) return false;
|
if (!input.signatures) return false;
|
||||||
|
|
||||||
return input.signatures.some(s => s !== undefined);
|
return input.signatures.some(s => s !== undefined);
|
||||||
|
@ -122,14 +123,14 @@ export class TransactionBuilder {
|
||||||
throw new Error('No, this would invalidate signatures');
|
throw new Error('No, this would invalidate signatures');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.__tx.locktime = locktime;
|
this.__TX.locktime = locktime;
|
||||||
}
|
}
|
||||||
|
|
||||||
setVersion(version: number): void {
|
setVersion(version: number): void {
|
||||||
typeforce(types.UInt32, version);
|
typeforce(types.UInt32, version);
|
||||||
|
|
||||||
// XXX: this might eventually become more complex depending on what the versions represent
|
// XXX: this might eventually become more complex depending on what the versions represent
|
||||||
this.__tx.version = version;
|
this.__TX.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
addInput(
|
addInput(
|
||||||
|
@ -142,7 +143,7 @@ export class TransactionBuilder {
|
||||||
throw new Error('No, this would invalidate signatures');
|
throw new Error('No, this would invalidate signatures');
|
||||||
}
|
}
|
||||||
|
|
||||||
let value: number | undefined = undefined;
|
let value: number | undefined;
|
||||||
|
|
||||||
// is it a hex string?
|
// is it a hex string?
|
||||||
if (txIsString(txHash)) {
|
if (txIsString(txHash)) {
|
||||||
|
@ -153,18 +154,128 @@ export class TransactionBuilder {
|
||||||
} else if (txIsTransaction(txHash)) {
|
} else if (txIsTransaction(txHash)) {
|
||||||
const txOut = txHash.outs[vout];
|
const txOut = txHash.outs[vout];
|
||||||
prevOutScript = txOut.script;
|
prevOutScript = txOut.script;
|
||||||
value = (<Output>txOut).value;
|
value = (txOut as Output).value;
|
||||||
|
|
||||||
txHash = <Buffer>txHash.getHash(false);
|
txHash = txHash.getHash(false) as Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.__addInputUnsafe(txHash, vout, {
|
return this.__addInputUnsafe(txHash, vout, {
|
||||||
sequence: sequence,
|
sequence,
|
||||||
prevOutScript: prevOutScript,
|
prevOutScript,
|
||||||
value: value,
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addOutput(scriptPubKey: string | Buffer, value: number): number {
|
||||||
|
if (!this.__canModifyOutputs()) {
|
||||||
|
throw new Error('No, this would invalidate signatures');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to get a script if it's a base58 or bech32 address string
|
||||||
|
if (typeof scriptPubKey === 'string') {
|
||||||
|
scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.__TX.addOutput(scriptPubKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
build(): Transaction {
|
||||||
|
return this.__build(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildIncomplete(): Transaction {
|
||||||
|
return this.__build(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
sign(
|
||||||
|
vin: number,
|
||||||
|
keyPair: ECPairInterface,
|
||||||
|
redeemScript: Buffer,
|
||||||
|
hashType: number,
|
||||||
|
witnessValue: number,
|
||||||
|
witnessScript: Buffer,
|
||||||
|
) {
|
||||||
|
// TODO: remove keyPair.network matching in 4.0.0
|
||||||
|
if (keyPair.network && keyPair.network !== this.network)
|
||||||
|
throw new TypeError('Inconsistent network');
|
||||||
|
if (!this.__INPUTS[vin]) throw new Error('No input at index: ' + vin);
|
||||||
|
|
||||||
|
hashType = hashType || Transaction.SIGHASH_ALL;
|
||||||
|
if (this.__needsOutputs(hashType))
|
||||||
|
throw new Error('Transaction needs outputs');
|
||||||
|
|
||||||
|
const input = this.__INPUTS[vin];
|
||||||
|
|
||||||
|
// if redeemScript was previously provided, enforce consistency
|
||||||
|
if (
|
||||||
|
input.redeemScript !== undefined &&
|
||||||
|
redeemScript &&
|
||||||
|
!input.redeemScript.equals(redeemScript)
|
||||||
|
) {
|
||||||
|
throw new Error('Inconsistent redeemScript');
|
||||||
|
}
|
||||||
|
|
||||||
|
const ourPubKey = keyPair.publicKey || keyPair.getPublicKey!();
|
||||||
|
if (!canSign(input)) {
|
||||||
|
if (witnessValue !== undefined) {
|
||||||
|
if (input.value !== undefined && input.value !== witnessValue)
|
||||||
|
throw new Error('Input did not match witnessValue');
|
||||||
|
typeforce(types.Satoshi, witnessValue);
|
||||||
|
input.value = witnessValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canSign(input)) {
|
||||||
|
const prepared = prepareInput(
|
||||||
|
input,
|
||||||
|
ourPubKey,
|
||||||
|
redeemScript,
|
||||||
|
witnessScript,
|
||||||
|
);
|
||||||
|
|
||||||
|
// updates inline
|
||||||
|
Object.assign(input, prepared);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canSign(input)) throw Error(input.prevOutType + ' not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ready to sign
|
||||||
|
let signatureHash: Buffer;
|
||||||
|
if (input.hasWitness) {
|
||||||
|
signatureHash = this.__TX.hashForWitnessV0(
|
||||||
|
vin,
|
||||||
|
input.signScript as Buffer,
|
||||||
|
input.value as number,
|
||||||
|
hashType,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
signatureHash = this.__TX.hashForSignature(
|
||||||
|
vin,
|
||||||
|
input.signScript as Buffer,
|
||||||
|
hashType,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// enforce in order signing of public keys
|
||||||
|
const signed = input.pubkeys!.some((pubKey, i) => {
|
||||||
|
if (!ourPubKey.equals(pubKey!)) return false;
|
||||||
|
if (input.signatures![i]) throw new Error('Signature already exists');
|
||||||
|
|
||||||
|
// TODO: add tests
|
||||||
|
if (ourPubKey.length !== 33 && input.hasWitness) {
|
||||||
|
throw new Error(
|
||||||
|
'BIP143 rejects uncompressed public keys in P2WPKH or P2WSH',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const signature = keyPair.sign(signatureHash);
|
||||||
|
input.signatures![i] = bscript.signature.encode(signature, hashType);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!signed) throw new Error('Key pair cannot sign for this input');
|
||||||
|
}
|
||||||
|
|
||||||
private __addInputUnsafe(
|
private __addInputUnsafe(
|
||||||
txHash: Buffer,
|
txHash: Buffer,
|
||||||
vout: number,
|
vout: number,
|
||||||
|
@ -175,10 +286,10 @@ export class TransactionBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
const prevTxOut = txHash.toString('hex') + ':' + vout;
|
const prevTxOut = txHash.toString('hex') + ':' + vout;
|
||||||
if (this.__prevTxSet[prevTxOut] !== undefined)
|
if (this.__PREV_TX_SET[prevTxOut] !== undefined)
|
||||||
throw new Error('Duplicate TxOut: ' + prevTxOut);
|
throw new Error('Duplicate TxOut: ' + prevTxOut);
|
||||||
|
|
||||||
let input = <TxbInput>{};
|
let input: TxbInput = {};
|
||||||
|
|
||||||
// derive what we can from the scriptSig
|
// derive what we can from the scriptSig
|
||||||
if (options.script !== undefined) {
|
if (options.script !== undefined) {
|
||||||
|
@ -208,48 +319,27 @@ export class TransactionBuilder {
|
||||||
input.prevOutType = prevOutType || classify.output(options.prevOutScript);
|
input.prevOutType = prevOutType || classify.output(options.prevOutScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vin = this.__tx.addInput(
|
const vin = this.__TX.addInput(
|
||||||
txHash,
|
txHash,
|
||||||
vout,
|
vout,
|
||||||
options.sequence,
|
options.sequence,
|
||||||
options.scriptSig,
|
options.scriptSig,
|
||||||
);
|
);
|
||||||
this.__inputs[vin] = input;
|
this.__INPUTS[vin] = input;
|
||||||
this.__prevTxSet[prevTxOut] = true;
|
this.__PREV_TX_SET[prevTxOut] = true;
|
||||||
return vin;
|
return vin;
|
||||||
}
|
}
|
||||||
|
|
||||||
addOutput(scriptPubKey: string | Buffer, value: number): number {
|
|
||||||
if (!this.__canModifyOutputs()) {
|
|
||||||
throw new Error('No, this would invalidate signatures');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to get a script if it's a base58 or bech32 address string
|
|
||||||
if (typeof scriptPubKey === 'string') {
|
|
||||||
scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.__tx.addOutput(scriptPubKey, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
build(): Transaction {
|
|
||||||
return this.__build(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
buildIncomplete(): Transaction {
|
|
||||||
return this.__build(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private __build(allowIncomplete?: boolean): Transaction {
|
private __build(allowIncomplete?: boolean): Transaction {
|
||||||
if (!allowIncomplete) {
|
if (!allowIncomplete) {
|
||||||
if (!this.__tx.ins.length) throw new Error('Transaction has no inputs');
|
if (!this.__TX.ins.length) throw new Error('Transaction has no inputs');
|
||||||
if (!this.__tx.outs.length) throw new Error('Transaction has no outputs');
|
if (!this.__TX.outs.length) throw new Error('Transaction has no outputs');
|
||||||
}
|
}
|
||||||
|
|
||||||
const tx = this.__tx.clone();
|
const tx = this.__TX.clone();
|
||||||
|
|
||||||
// create script signatures from inputs
|
// create script signatures from inputs
|
||||||
this.__inputs.forEach((input, i) => {
|
this.__INPUTS.forEach((input, i) => {
|
||||||
if (!input.prevOutType && !allowIncomplete)
|
if (!input.prevOutType && !allowIncomplete)
|
||||||
throw new Error('Transaction is not complete');
|
throw new Error('Transaction is not complete');
|
||||||
|
|
||||||
|
@ -275,97 +365,8 @@ export class TransactionBuilder {
|
||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
sign(
|
|
||||||
vin: number,
|
|
||||||
keyPair: ECPairInterface,
|
|
||||||
redeemScript: Buffer,
|
|
||||||
hashType: number,
|
|
||||||
witnessValue: number,
|
|
||||||
witnessScript: Buffer,
|
|
||||||
) {
|
|
||||||
// TODO: remove keyPair.network matching in 4.0.0
|
|
||||||
if (keyPair.network && keyPair.network !== this.network)
|
|
||||||
throw new TypeError('Inconsistent network');
|
|
||||||
if (!this.__inputs[vin]) throw new Error('No input at index: ' + vin);
|
|
||||||
|
|
||||||
hashType = hashType || Transaction.SIGHASH_ALL;
|
|
||||||
if (this.__needsOutputs(hashType))
|
|
||||||
throw new Error('Transaction needs outputs');
|
|
||||||
|
|
||||||
const input = this.__inputs[vin];
|
|
||||||
|
|
||||||
// if redeemScript was previously provided, enforce consistency
|
|
||||||
if (
|
|
||||||
input.redeemScript !== undefined &&
|
|
||||||
redeemScript &&
|
|
||||||
!input.redeemScript.equals(redeemScript)
|
|
||||||
) {
|
|
||||||
throw new Error('Inconsistent redeemScript');
|
|
||||||
}
|
|
||||||
|
|
||||||
const ourPubKey = keyPair.publicKey || keyPair.getPublicKey!();
|
|
||||||
if (!canSign(input)) {
|
|
||||||
if (witnessValue !== undefined) {
|
|
||||||
if (input.value !== undefined && input.value !== witnessValue)
|
|
||||||
throw new Error("Input didn't match witnessValue");
|
|
||||||
typeforce(types.Satoshi, witnessValue);
|
|
||||||
input.value = witnessValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canSign(input)) {
|
|
||||||
const prepared = prepareInput(
|
|
||||||
input,
|
|
||||||
ourPubKey,
|
|
||||||
redeemScript,
|
|
||||||
witnessScript,
|
|
||||||
);
|
|
||||||
|
|
||||||
// updates inline
|
|
||||||
Object.assign(input, prepared);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canSign(input)) throw Error(input.prevOutType + ' not supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
// ready to sign
|
|
||||||
let signatureHash: Buffer;
|
|
||||||
if (input.hasWitness) {
|
|
||||||
signatureHash = this.__tx.hashForWitnessV0(
|
|
||||||
vin,
|
|
||||||
<Buffer>input.signScript,
|
|
||||||
<number>input.value,
|
|
||||||
hashType,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
signatureHash = this.__tx.hashForSignature(
|
|
||||||
vin,
|
|
||||||
<Buffer>input.signScript,
|
|
||||||
hashType,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// enforce in order signing of public keys
|
|
||||||
const signed = input.pubkeys!.some((pubKey, i) => {
|
|
||||||
if (!ourPubKey.equals(pubKey!)) return false;
|
|
||||||
if (input.signatures![i]) throw new Error('Signature already exists');
|
|
||||||
|
|
||||||
// TODO: add tests
|
|
||||||
if (ourPubKey.length !== 33 && input.hasWitness) {
|
|
||||||
throw new Error(
|
|
||||||
'BIP143 rejects uncompressed public keys in P2WPKH or P2WSH',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const signature = keyPair.sign(signatureHash);
|
|
||||||
input.signatures![i] = bscript.signature.encode(signature, hashType);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!signed) throw new Error('Key pair cannot sign for this input');
|
|
||||||
}
|
|
||||||
|
|
||||||
private __canModifyInputs(): boolean {
|
private __canModifyInputs(): boolean {
|
||||||
return this.__inputs.every(input => {
|
return this.__INPUTS.every(input => {
|
||||||
if (!input.signatures) return true;
|
if (!input.signatures) return true;
|
||||||
|
|
||||||
return input.signatures.every(signature => {
|
return input.signatures.every(signature => {
|
||||||
|
@ -381,14 +382,14 @@ export class TransactionBuilder {
|
||||||
|
|
||||||
private __needsOutputs(signingHashType: number): boolean {
|
private __needsOutputs(signingHashType: number): boolean {
|
||||||
if (signingHashType === Transaction.SIGHASH_ALL) {
|
if (signingHashType === Transaction.SIGHASH_ALL) {
|
||||||
return this.__tx.outs.length === 0;
|
return this.__TX.outs.length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if inputs are being signed with SIGHASH_NONE, we don't strictly need outputs
|
// if inputs are being signed with SIGHASH_NONE, we don't strictly need outputs
|
||||||
// .build() will fail, but .buildIncomplete() is OK
|
// .build() will fail, but .buildIncomplete() is OK
|
||||||
return (
|
return (
|
||||||
this.__tx.outs.length === 0 &&
|
this.__TX.outs.length === 0 &&
|
||||||
this.__inputs.some(input => {
|
this.__INPUTS.some(input => {
|
||||||
if (!input.signatures) return false;
|
if (!input.signatures) return false;
|
||||||
|
|
||||||
return input.signatures.some(signature => {
|
return input.signatures.some(signature => {
|
||||||
|
@ -402,10 +403,10 @@ export class TransactionBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private __canModifyOutputs(): boolean {
|
private __canModifyOutputs(): boolean {
|
||||||
const nInputs = this.__tx.ins.length;
|
const nInputs = this.__TX.ins.length;
|
||||||
const nOutputs = this.__tx.outs.length;
|
const nOutputs = this.__TX.outs.length;
|
||||||
|
|
||||||
return this.__inputs.every(input => {
|
return this.__INPUTS.every(input => {
|
||||||
if (input.signatures === undefined) return true;
|
if (input.signatures === undefined) return true;
|
||||||
|
|
||||||
return input.signatures.every(signature => {
|
return input.signatures.every(signature => {
|
||||||
|
@ -427,11 +428,14 @@ export class TransactionBuilder {
|
||||||
|
|
||||||
private __overMaximumFees(bytes: number): boolean {
|
private __overMaximumFees(bytes: number): boolean {
|
||||||
// not all inputs will have .value defined
|
// not all inputs will have .value defined
|
||||||
const incoming = this.__inputs.reduce((a, x) => a + (x.value! >>> 0), 0);
|
const incoming = this.__INPUTS.reduce((a, x) => a + (x.value! >>> 0), 0);
|
||||||
|
|
||||||
// but all outputs do, and if we have any input value
|
// but all outputs do, and if we have any input value
|
||||||
// we can immediately determine if the outputs are too small
|
// we can immediately determine if the outputs are too small
|
||||||
const outgoing = this.__tx.outs.reduce((a, x) => a + (<Output>x).value, 0);
|
const outgoing = this.__TX.outs.reduce(
|
||||||
|
(a, x) => a + (x as Output).value,
|
||||||
|
0,
|
||||||
|
);
|
||||||
const fee = incoming - outgoing;
|
const fee = incoming - outgoing;
|
||||||
const feeRate = fee / bytes;
|
const feeRate = fee / bytes;
|
||||||
|
|
||||||
|
@ -441,7 +445,7 @@ export class TransactionBuilder {
|
||||||
|
|
||||||
function expandInput(
|
function expandInput(
|
||||||
scriptSig: Buffer,
|
scriptSig: Buffer,
|
||||||
witnessStack: Array<Buffer>,
|
witnessStack: Buffer[],
|
||||||
type?: string,
|
type?: string,
|
||||||
scriptPubKey?: Buffer,
|
scriptPubKey?: Buffer,
|
||||||
): TxbInput {
|
): TxbInput {
|
||||||
|
@ -502,8 +506,8 @@ function expandInput(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
prevOutType: SCRIPT_TYPES.P2MS,
|
prevOutType: SCRIPT_TYPES.P2MS,
|
||||||
pubkeys: pubkeys,
|
pubkeys,
|
||||||
signatures: signatures,
|
signatures,
|
||||||
maxSignatures: m,
|
maxSignatures: m,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -681,12 +685,12 @@ function prepareInput(
|
||||||
witnessScript: Buffer,
|
witnessScript: Buffer,
|
||||||
): TxbInput {
|
): TxbInput {
|
||||||
if (redeemScript && witnessScript) {
|
if (redeemScript && witnessScript) {
|
||||||
const p2wsh = <Payment>(
|
const p2wsh = payments.p2wsh({
|
||||||
payments.p2wsh({ redeem: { output: witnessScript } })
|
redeem: { output: witnessScript },
|
||||||
);
|
}) as Payment;
|
||||||
const p2wshAlt = <Payment>payments.p2wsh({ output: redeemScript });
|
const p2wshAlt = payments.p2wsh({ output: redeemScript }) as Payment;
|
||||||
const p2sh = <Payment>payments.p2sh({ redeem: { output: redeemScript } });
|
const p2sh = payments.p2sh({ redeem: { output: redeemScript } }) as Payment;
|
||||||
const p2shAlt = <Payment>payments.p2sh({ redeem: p2wsh });
|
const p2shAlt = payments.p2sh({ redeem: p2wsh }) as Payment;
|
||||||
|
|
||||||
// enforces P2SH(P2WSH(...))
|
// enforces P2SH(P2WSH(...))
|
||||||
if (!p2wsh.hash!.equals(p2wshAlt.hash!))
|
if (!p2wsh.hash!.equals(p2wshAlt.hash!))
|
||||||
|
@ -706,7 +710,7 @@ function prepareInput(
|
||||||
expanded.signatures = input.signatures;
|
expanded.signatures = input.signatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
let signScript = witnessScript;
|
const signScript = witnessScript;
|
||||||
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
||||||
throw new Error('P2SH(P2WSH(P2WPKH)) is a consensus failure');
|
throw new Error('P2SH(P2WSH(P2WPKH)) is a consensus failure');
|
||||||
|
|
||||||
|
@ -731,12 +735,12 @@ function prepareInput(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redeemScript) {
|
if (redeemScript) {
|
||||||
const p2sh = <Payment>payments.p2sh({ redeem: { output: redeemScript } });
|
const p2sh = payments.p2sh({ redeem: { output: redeemScript } }) as Payment;
|
||||||
|
|
||||||
if (input.prevOutScript) {
|
if (input.prevOutScript) {
|
||||||
let p2shAlt;
|
let p2shAlt;
|
||||||
try {
|
try {
|
||||||
p2shAlt = <Payment>payments.p2sh({ output: input.prevOutScript });
|
p2shAlt = payments.p2sh({ output: input.prevOutScript }) as Payment;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('PrevOutScript must be P2SH');
|
throw new Error('PrevOutScript must be P2SH');
|
||||||
}
|
}
|
||||||
|
@ -799,7 +803,7 @@ function prepareInput(
|
||||||
expanded.signatures = input.signatures;
|
expanded.signatures = input.signatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
let signScript = witnessScript;
|
const signScript = witnessScript;
|
||||||
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
if (expanded.type === SCRIPT_TYPES.P2WPKH)
|
||||||
throw new Error('P2WSH(P2WPKH) is a consensus failure');
|
throw new Error('P2WSH(P2WPKH) is a consensus failure');
|
||||||
|
|
||||||
|
@ -846,9 +850,8 @@ function prepareInput(
|
||||||
|
|
||||||
let signScript = input.prevOutScript;
|
let signScript = input.prevOutScript;
|
||||||
if (expanded.type === SCRIPT_TYPES.P2WPKH) {
|
if (expanded.type === SCRIPT_TYPES.P2WPKH) {
|
||||||
signScript = <Buffer>(
|
signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] })
|
||||||
payments.p2pkh({ pubkey: expanded.pubkeys[0] }).output
|
.output as Buffer;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -868,7 +871,7 @@ function prepareInput(
|
||||||
const prevOutScript = payments.p2pkh({ pubkey: ourPubKey }).output;
|
const prevOutScript = payments.p2pkh({ pubkey: ourPubKey }).output;
|
||||||
return {
|
return {
|
||||||
prevOutType: SCRIPT_TYPES.P2PKH,
|
prevOutType: SCRIPT_TYPES.P2PKH,
|
||||||
prevOutScript: prevOutScript,
|
prevOutScript,
|
||||||
|
|
||||||
hasWitness: false,
|
hasWitness: false,
|
||||||
signScript: prevOutScript,
|
signScript: prevOutScript,
|
||||||
|
@ -884,8 +887,8 @@ function build(
|
||||||
input: TxbInput,
|
input: TxbInput,
|
||||||
allowIncomplete?: boolean,
|
allowIncomplete?: boolean,
|
||||||
): Payment | undefined {
|
): Payment | undefined {
|
||||||
const pubkeys = <Array<Buffer>>(input.pubkeys || []);
|
const pubkeys = (input.pubkeys || []) as Buffer[];
|
||||||
let signatures = <Array<Buffer>>(input.signatures || []);
|
let signatures = (input.signatures || []) as Buffer[];
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SCRIPT_TYPES.P2PKH: {
|
case SCRIPT_TYPES.P2PKH: {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export function UInt31(value: number): boolean {
|
||||||
export function BIP32Path(value: string): boolean {
|
export function BIP32Path(value: string): boolean {
|
||||||
return typeforce.String(value) && !!value.match(/^(m\/)?(\d+'?\/)*\d+'?$/);
|
return typeforce.String(value) && !!value.match(/^(m\/)?(\d+'?\/)*\d+'?$/);
|
||||||
}
|
}
|
||||||
BIP32Path.toJSON = function() {
|
BIP32Path.toJSON = () => {
|
||||||
return 'BIP32 derivation path';
|
return 'BIP32 derivation path';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ export const Network = typeforce.compile({
|
||||||
export const Buffer256bit = typeforce.BufferN(32);
|
export const Buffer256bit = typeforce.BufferN(32);
|
||||||
export const Hash160bit = typeforce.BufferN(20);
|
export const Hash160bit = typeforce.BufferN(20);
|
||||||
export const Hash256bit = typeforce.BufferN(32);
|
export const Hash256bit = typeforce.BufferN(32);
|
||||||
export const Number = typeforce.Number;
|
export const Number = typeforce.Number; // tslint:disable-line variable-name
|
||||||
export const Array = typeforce.Array;
|
export const Array = typeforce.Array;
|
||||||
export const Boolean = typeforce.Boolean;
|
export const Boolean = typeforce.Boolean; // tslint:disable-line variable-name
|
||||||
export const String = typeforce.String;
|
export const String = typeforce.String; // tslint:disable-line variable-name
|
||||||
export const Buffer = typeforce.Buffer;
|
export const Buffer = typeforce.Buffer;
|
||||||
export const Hex = typeforce.Hex;
|
export const Hex = typeforce.Hex;
|
||||||
export const maybe = typeforce.maybe;
|
export const maybe = typeforce.maybe;
|
||||||
|
|
34
tslint.json
Normal file
34
tslint.json
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"defaultSeverity": "error",
|
||||||
|
"extends": ["tslint:recommended"],
|
||||||
|
"rules": {
|
||||||
|
"arrow-parens": [true, "ban-single-arg-parens"],
|
||||||
|
"curly": false,
|
||||||
|
"indent": [
|
||||||
|
true,
|
||||||
|
"spaces",
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"interface-name": [false],
|
||||||
|
"match-default-export-name": true,
|
||||||
|
"max-classes-per-file": [false],
|
||||||
|
"member-access": [true, "no-public"],
|
||||||
|
"no-bitwise": false,
|
||||||
|
"no-console": false,
|
||||||
|
"no-empty": [true, "allow-empty-catch"],
|
||||||
|
"no-implicit-dependencies": true,
|
||||||
|
"no-return-await": true,
|
||||||
|
"no-var-requires": false,
|
||||||
|
"no-unused-expression": false,
|
||||||
|
"object-literal-sort-keys": false,
|
||||||
|
"quotemark": [true, "single"],
|
||||||
|
"variable-name": [
|
||||||
|
true,
|
||||||
|
"ban-keywords",
|
||||||
|
"check-format",
|
||||||
|
"allow-leading-underscore",
|
||||||
|
"allow-pascal-case"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rulesDirectory": []
|
||||||
|
}
|
8
types/address.d.ts
vendored
8
types/address.d.ts
vendored
|
@ -1,14 +1,14 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
import { Network } from './networks';
|
import { Network } from './networks';
|
||||||
export declare type Base58CheckResult = {
|
export interface Base58CheckResult {
|
||||||
hash: Buffer;
|
hash: Buffer;
|
||||||
version: number;
|
version: number;
|
||||||
};
|
}
|
||||||
export declare type Bech32Result = {
|
export interface Bech32Result {
|
||||||
version: number;
|
version: number;
|
||||||
prefix: string;
|
prefix: string;
|
||||||
data: Buffer;
|
data: Buffer;
|
||||||
};
|
}
|
||||||
export declare function fromBase58Check(address: string): Base58CheckResult;
|
export declare function fromBase58Check(address: string): Base58CheckResult;
|
||||||
export declare function fromBech32(address: string): Bech32Result;
|
export declare function fromBech32(address: string): Bech32Result;
|
||||||
export declare function toBase58Check(hash: Buffer, version: number): string;
|
export declare function toBase58Check(hash: Buffer, version: number): string;
|
||||||
|
|
14
types/block.d.ts
vendored
14
types/block.d.ts
vendored
|
@ -1,6 +1,10 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
import { Transaction } from './transaction';
|
import { Transaction } from './transaction';
|
||||||
export declare class Block {
|
export declare class Block {
|
||||||
|
static fromBuffer(buffer: Buffer): Block;
|
||||||
|
static fromHex(hex: string): Block;
|
||||||
|
static calculateTarget(bits: number): Buffer;
|
||||||
|
static calculateMerkleRoot(transactions: Transaction[], forWitness?: boolean): Buffer;
|
||||||
version: number;
|
version: number;
|
||||||
prevHash?: Buffer;
|
prevHash?: Buffer;
|
||||||
merkleRoot?: Buffer;
|
merkleRoot?: Buffer;
|
||||||
|
@ -8,12 +12,8 @@ export declare class Block {
|
||||||
witnessCommit?: Buffer;
|
witnessCommit?: Buffer;
|
||||||
bits: number;
|
bits: number;
|
||||||
nonce: number;
|
nonce: number;
|
||||||
transactions?: Array<Transaction>;
|
transactions?: Transaction[];
|
||||||
constructor();
|
constructor();
|
||||||
static fromBuffer(buffer: Buffer): Block;
|
|
||||||
static fromHex(hex: string): Block;
|
|
||||||
static calculateTarget(bits: number): Buffer;
|
|
||||||
static calculateMerkleRoot(transactions: Array<Transaction>, forWitness?: boolean): Buffer;
|
|
||||||
getWitnessCommit(): Buffer | null;
|
getWitnessCommit(): Buffer | null;
|
||||||
hasWitnessCommit(): boolean;
|
hasWitnessCommit(): boolean;
|
||||||
hasWitness(): boolean;
|
hasWitness(): boolean;
|
||||||
|
@ -25,7 +25,7 @@ export declare class Block {
|
||||||
toHex(headersOnly: boolean): string;
|
toHex(headersOnly: boolean): string;
|
||||||
checkTxRoots(): boolean;
|
checkTxRoots(): boolean;
|
||||||
checkMerkleRoot(): boolean;
|
checkMerkleRoot(): boolean;
|
||||||
__checkMerkleRoot(): boolean;
|
|
||||||
__checkWitnessCommit(): boolean;
|
|
||||||
checkProofOfWork(): boolean;
|
checkProofOfWork(): boolean;
|
||||||
|
private __checkMerkleRoot;
|
||||||
|
private __checkWitnessCommit;
|
||||||
}
|
}
|
||||||
|
|
2
types/classify.d.ts
vendored
2
types/classify.d.ts
vendored
|
@ -12,5 +12,5 @@ declare const types: {
|
||||||
};
|
};
|
||||||
declare function classifyOutput(script: Buffer): string;
|
declare function classifyOutput(script: Buffer): string;
|
||||||
declare function classifyInput(script: Buffer, allowIncomplete: boolean): string;
|
declare function classifyInput(script: Buffer, allowIncomplete: boolean): string;
|
||||||
declare function classifyWitness(script: Array<Buffer>, allowIncomplete: boolean): string;
|
declare function classifyWitness(script: Buffer[], allowIncomplete: boolean): string;
|
||||||
export { classifyInput as input, classifyOutput as output, classifyWitness as witness, types, };
|
export { classifyInput as input, classifyOutput as output, classifyWitness as witness, types, };
|
||||||
|
|
4
types/ecpair.d.ts
vendored
4
types/ecpair.d.ts
vendored
|
@ -18,7 +18,7 @@ export interface ECPairInterface {
|
||||||
declare class ECPair implements ECPairInterface {
|
declare class ECPair implements ECPairInterface {
|
||||||
compressed: boolean;
|
compressed: boolean;
|
||||||
network: Network;
|
network: Network;
|
||||||
private __d?;
|
private __D?;
|
||||||
private __Q?;
|
private __Q?;
|
||||||
constructor(d?: Buffer, Q?: Buffer, options?: ECPairOptions);
|
constructor(d?: Buffer, Q?: Buffer, options?: ECPairOptions);
|
||||||
readonly privateKey: Buffer | undefined;
|
readonly privateKey: Buffer | undefined;
|
||||||
|
@ -29,6 +29,6 @@ declare class ECPair implements ECPairInterface {
|
||||||
}
|
}
|
||||||
declare function fromPrivateKey(buffer: Buffer, options?: ECPairOptions): ECPair;
|
declare function fromPrivateKey(buffer: Buffer, options?: ECPairOptions): ECPair;
|
||||||
declare function fromPublicKey(buffer: Buffer, options?: ECPairOptions): ECPair;
|
declare function fromPublicKey(buffer: Buffer, options?: ECPairOptions): ECPair;
|
||||||
declare function fromWIF(string: string, network?: Network | Array<Network>): ECPair;
|
declare function fromWIF(wifString: string, network?: Network | Network[]): ECPair;
|
||||||
declare function makeRandom(options?: ECPairOptions): ECPair;
|
declare function makeRandom(options?: ECPairOptions): ECPair;
|
||||||
export { makeRandom, fromPrivateKey, fromPublicKey, fromWIF };
|
export { makeRandom, fromPrivateKey, fromPublicKey, fromWIF };
|
||||||
|
|
12
types/index.d.ts
vendored
12
types/index.d.ts
vendored
|
@ -1,17 +1,17 @@
|
||||||
import * as bip32 from 'bip32';
|
import * as bip32 from 'bip32';
|
||||||
import * as ECPair from './ecpair';
|
|
||||||
import * as address from './address';
|
import * as address from './address';
|
||||||
import * as crypto from './crypto';
|
import * as crypto from './crypto';
|
||||||
|
import * as ECPair from './ecpair';
|
||||||
import * as networks from './networks';
|
import * as networks from './networks';
|
||||||
import * as payments from './payments';
|
import * as payments from './payments';
|
||||||
import * as script from './script';
|
import * as script from './script';
|
||||||
export { ECPair, address, bip32, crypto, networks, payments, script };
|
export { ECPair, address, bip32, crypto, networks, payments, script };
|
||||||
export { Block } from './block';
|
export { Block } from './block';
|
||||||
|
export { OPS as opcodes } from './script';
|
||||||
export { Transaction } from './transaction';
|
export { Transaction } from './transaction';
|
||||||
export { TransactionBuilder } from './transaction_builder';
|
export { TransactionBuilder } from './transaction_builder';
|
||||||
export { OPS as opcodes } from './script';
|
|
||||||
export { Payment, PaymentOpts } from './payments';
|
|
||||||
export { Input as TxInput, Output as TxOutput } from './transaction';
|
|
||||||
export { Network } from './networks';
|
|
||||||
export { OpCode } from './script';
|
|
||||||
export { BIP32Interface } from 'bip32';
|
export { BIP32Interface } from 'bip32';
|
||||||
|
export { Network } from './networks';
|
||||||
|
export { Payment, PaymentOpts } from './payments';
|
||||||
|
export { OpCode } from './script';
|
||||||
|
export { Input as TxInput, Output as TxOutput } from './transaction';
|
||||||
|
|
10
types/networks.d.ts
vendored
10
types/networks.d.ts
vendored
|
@ -1,15 +1,15 @@
|
||||||
export declare type Network = {
|
export interface Network {
|
||||||
messagePrefix: string;
|
messagePrefix: string;
|
||||||
bech32: string;
|
bech32: string;
|
||||||
bip32: bip32;
|
bip32: Bip32;
|
||||||
pubKeyHash: number;
|
pubKeyHash: number;
|
||||||
scriptHash: number;
|
scriptHash: number;
|
||||||
wif: number;
|
wif: number;
|
||||||
};
|
}
|
||||||
declare type bip32 = {
|
interface Bip32 {
|
||||||
public: number;
|
public: number;
|
||||||
private: number;
|
private: number;
|
||||||
};
|
}
|
||||||
export declare const bitcoin: Network;
|
export declare const bitcoin: Network;
|
||||||
export declare const regtest: Network;
|
export declare const regtest: Network;
|
||||||
export declare const testnet: Network;
|
export declare const testnet: Network;
|
||||||
|
|
12
types/payments/index.d.ts
vendored
12
types/payments/index.d.ts
vendored
|
@ -10,21 +10,25 @@ import { p2wsh } from './p2wsh';
|
||||||
export interface Payment {
|
export interface Payment {
|
||||||
network?: Network;
|
network?: Network;
|
||||||
output?: Buffer;
|
output?: Buffer;
|
||||||
data?: Array<Buffer>;
|
data?: Buffer[];
|
||||||
m?: number;
|
m?: number;
|
||||||
n?: number;
|
n?: number;
|
||||||
pubkeys?: Array<Buffer>;
|
pubkeys?: Buffer[];
|
||||||
input?: Buffer;
|
input?: Buffer;
|
||||||
signatures?: Array<Buffer>;
|
signatures?: Buffer[];
|
||||||
pubkey?: Buffer;
|
pubkey?: Buffer;
|
||||||
signature?: Buffer;
|
signature?: Buffer;
|
||||||
address?: string;
|
address?: string;
|
||||||
hash?: Buffer;
|
hash?: Buffer;
|
||||||
redeem?: Payment;
|
redeem?: Payment;
|
||||||
witness?: Array<Buffer>;
|
witness?: Buffer[];
|
||||||
}
|
}
|
||||||
|
export declare type PaymentFunction = () => Payment;
|
||||||
export interface PaymentOpts {
|
export interface PaymentOpts {
|
||||||
validate?: boolean;
|
validate?: boolean;
|
||||||
allowIncomplete?: boolean;
|
allowIncomplete?: boolean;
|
||||||
}
|
}
|
||||||
|
export declare type StackElement = Buffer | number;
|
||||||
|
export declare type Stack = StackElement[];
|
||||||
|
export declare type StackFunction = () => Stack;
|
||||||
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh };
|
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh };
|
||||||
|
|
2
types/payments/lazy.d.ts
vendored
2
types/payments/lazy.d.ts
vendored
|
@ -1,2 +1,2 @@
|
||||||
export declare function prop(object: Object, name: string, f: () => any): void;
|
export declare function prop(object: {}, name: string, f: () => any): void;
|
||||||
export declare function value<T>(f: () => T): () => T;
|
export declare function value<T>(f: () => T): () => T;
|
||||||
|
|
7
types/script.d.ts
vendored
7
types/script.d.ts
vendored
|
@ -1,16 +1,17 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
|
import { Stack } from './payments';
|
||||||
import * as scriptNumber from './script_number';
|
import * as scriptNumber from './script_number';
|
||||||
import * as scriptSignature from './script_signature';
|
import * as scriptSignature from './script_signature';
|
||||||
export declare type OpCode = number;
|
export declare type OpCode = number;
|
||||||
export declare const OPS: {
|
export declare const OPS: {
|
||||||
[index: string]: number;
|
[index: string]: number;
|
||||||
};
|
};
|
||||||
export declare function isPushOnly(value: Array<number | Buffer>): boolean;
|
export declare function isPushOnly(value: Stack): boolean;
|
||||||
export declare function compile(chunks: Buffer | Array<number | Buffer>): Buffer;
|
export declare function compile(chunks: Buffer | Stack): Buffer;
|
||||||
export declare function decompile(buffer: Buffer | Array<number | Buffer>): Array<number | Buffer> | null;
|
export declare function decompile(buffer: Buffer | Array<number | Buffer>): Array<number | Buffer> | null;
|
||||||
export declare function toASM(chunks: Buffer | Array<number | Buffer>): string;
|
export declare function toASM(chunks: Buffer | Array<number | Buffer>): string;
|
||||||
export declare function fromASM(asm: string): Buffer;
|
export declare function fromASM(asm: string): Buffer;
|
||||||
export declare function toStack(chunks: Buffer | Array<number | Buffer>): Array<Buffer>;
|
export declare function toStack(chunks: Buffer | Array<number | Buffer>): Buffer[];
|
||||||
export declare function isCanonicalPubKey(buffer: Buffer): boolean;
|
export declare function isCanonicalPubKey(buffer: Buffer): boolean;
|
||||||
export declare function isDefinedHashType(hashType: number): boolean;
|
export declare function isDefinedHashType(hashType: number): boolean;
|
||||||
export declare function isCanonicalScriptSignature(buffer: Buffer): boolean;
|
export declare function isCanonicalScriptSignature(buffer: Buffer): boolean;
|
||||||
|
|
2
types/script_number.d.ts
vendored
2
types/script_number.d.ts
vendored
|
@ -1,3 +1,3 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): number;
|
export declare function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): number;
|
||||||
export declare function encode(number: number): Buffer;
|
export declare function encode(_number: number): Buffer;
|
||||||
|
|
3
types/templates/multisig/input.d.ts
vendored
3
types/templates/multisig/input.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function check(script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean;
|
import { Stack } from '../../payments';
|
||||||
|
export declare function check(script: Buffer | Stack, allowIncomplete?: boolean): boolean;
|
||||||
export declare namespace check {
|
export declare namespace check {
|
||||||
var toJSON: () => string;
|
var toJSON: () => string;
|
||||||
}
|
}
|
||||||
|
|
3
types/templates/multisig/output.d.ts
vendored
3
types/templates/multisig/output.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function check(script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean;
|
import { Stack } from '../../payments';
|
||||||
|
export declare function check(script: Buffer | Stack, allowIncomplete?: boolean): boolean;
|
||||||
export declare namespace check {
|
export declare namespace check {
|
||||||
var toJSON: () => string;
|
var toJSON: () => string;
|
||||||
}
|
}
|
||||||
|
|
3
types/templates/pubkey/input.d.ts
vendored
3
types/templates/pubkey/input.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function check(script: Buffer | Array<number | Buffer>): boolean;
|
import { Stack } from '../../payments';
|
||||||
|
export declare function check(script: Buffer | Stack): boolean;
|
||||||
export declare namespace check {
|
export declare namespace check {
|
||||||
var toJSON: () => string;
|
var toJSON: () => string;
|
||||||
}
|
}
|
||||||
|
|
3
types/templates/pubkey/output.d.ts
vendored
3
types/templates/pubkey/output.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function check(script: Buffer | Array<number | Buffer>): boolean;
|
import { Stack } from '../../payments';
|
||||||
|
export declare function check(script: Buffer | Stack): boolean;
|
||||||
export declare namespace check {
|
export declare namespace check {
|
||||||
var toJSON: () => string;
|
var toJSON: () => string;
|
||||||
}
|
}
|
||||||
|
|
3
types/templates/pubkeyhash/input.d.ts
vendored
3
types/templates/pubkeyhash/input.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function check(script: Buffer | Array<number | Buffer>): boolean;
|
import { Stack } from '../../payments';
|
||||||
|
export declare function check(script: Buffer | Stack): boolean;
|
||||||
export declare namespace check {
|
export declare namespace check {
|
||||||
var toJSON: () => string;
|
var toJSON: () => string;
|
||||||
}
|
}
|
||||||
|
|
3
types/templates/witnesspubkeyhash/input.d.ts
vendored
3
types/templates/witnesspubkeyhash/input.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function check(script: Buffer | Array<number | Buffer>): boolean;
|
import { Stack } from '../../payments';
|
||||||
|
export declare function check(script: Buffer | Stack): boolean;
|
||||||
export declare namespace check {
|
export declare namespace check {
|
||||||
var toJSON: () => string;
|
var toJSON: () => string;
|
||||||
}
|
}
|
||||||
|
|
2
types/templates/witnessscripthash/input.d.ts
vendored
2
types/templates/witnessscripthash/input.d.ts
vendored
|
@ -1,5 +1,5 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare function check(chunks: Array<Buffer>, allowIncomplete?: boolean): boolean;
|
export declare function check(chunks: Buffer[], allowIncomplete?: boolean): boolean;
|
||||||
export declare namespace check {
|
export declare namespace check {
|
||||||
var toJSON: () => string;
|
var toJSON: () => string;
|
||||||
}
|
}
|
||||||
|
|
34
types/transaction.d.ts
vendored
34
types/transaction.d.ts
vendored
|
@ -1,24 +1,21 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
export declare type BlankOutput = {
|
export interface BlankOutput {
|
||||||
script: Buffer;
|
script: Buffer;
|
||||||
valueBuffer: Buffer;
|
valueBuffer: Buffer;
|
||||||
};
|
}
|
||||||
export declare type Output = {
|
export interface Output {
|
||||||
script: Buffer;
|
script: Buffer;
|
||||||
value: number;
|
value: number;
|
||||||
};
|
}
|
||||||
export declare type Input = {
|
declare type OpenOutput = Output | BlankOutput;
|
||||||
|
export interface Input {
|
||||||
hash: Buffer;
|
hash: Buffer;
|
||||||
index: number;
|
index: number;
|
||||||
script: Buffer;
|
script: Buffer;
|
||||||
sequence: number;
|
sequence: number;
|
||||||
witness: Array<Buffer>;
|
witness: Buffer[];
|
||||||
};
|
}
|
||||||
export declare class Transaction {
|
export declare class Transaction {
|
||||||
version: number;
|
|
||||||
locktime: number;
|
|
||||||
ins: Array<Input>;
|
|
||||||
outs: Array<Output | BlankOutput>;
|
|
||||||
static readonly DEFAULT_SEQUENCE = 4294967295;
|
static readonly DEFAULT_SEQUENCE = 4294967295;
|
||||||
static readonly SIGHASH_ALL = 1;
|
static readonly SIGHASH_ALL = 1;
|
||||||
static readonly SIGHASH_NONE = 2;
|
static readonly SIGHASH_NONE = 2;
|
||||||
|
@ -26,10 +23,14 @@ export declare class Transaction {
|
||||||
static readonly SIGHASH_ANYONECANPAY = 128;
|
static readonly SIGHASH_ANYONECANPAY = 128;
|
||||||
static readonly ADVANCED_TRANSACTION_MARKER = 0;
|
static readonly ADVANCED_TRANSACTION_MARKER = 0;
|
||||||
static readonly ADVANCED_TRANSACTION_FLAG = 1;
|
static readonly ADVANCED_TRANSACTION_FLAG = 1;
|
||||||
constructor();
|
static fromBuffer(buffer: Buffer, _NO_STRICT?: boolean): Transaction;
|
||||||
static fromBuffer(buffer: Buffer, __noStrict?: boolean): Transaction;
|
|
||||||
static fromHex(hex: string): Transaction;
|
static fromHex(hex: string): Transaction;
|
||||||
static isCoinbaseHash(buffer: Buffer): boolean;
|
static isCoinbaseHash(buffer: Buffer): boolean;
|
||||||
|
version: number;
|
||||||
|
locktime: number;
|
||||||
|
ins: Input[];
|
||||||
|
outs: OpenOutput[];
|
||||||
|
constructor();
|
||||||
isCoinbase(): boolean;
|
isCoinbase(): boolean;
|
||||||
addInput(hash: Buffer, index: number, sequence?: number, scriptSig?: Buffer): number;
|
addInput(hash: Buffer, index: number, sequence?: number, scriptSig?: Buffer): number;
|
||||||
addOutput(scriptPubKey: Buffer, value: number): number;
|
addOutput(scriptPubKey: Buffer, value: number): number;
|
||||||
|
@ -37,7 +38,6 @@ export declare class Transaction {
|
||||||
weight(): number;
|
weight(): number;
|
||||||
virtualSize(): number;
|
virtualSize(): number;
|
||||||
byteLength(): number;
|
byteLength(): number;
|
||||||
private __byteLength;
|
|
||||||
clone(): Transaction;
|
clone(): Transaction;
|
||||||
/**
|
/**
|
||||||
* Hash transaction for signing a specific input.
|
* Hash transaction for signing a specific input.
|
||||||
|
@ -52,8 +52,10 @@ export declare class Transaction {
|
||||||
getHash(forWitness?: boolean): Buffer;
|
getHash(forWitness?: boolean): Buffer;
|
||||||
getId(): string;
|
getId(): string;
|
||||||
toBuffer(buffer?: Buffer, initialOffset?: number): Buffer;
|
toBuffer(buffer?: Buffer, initialOffset?: number): Buffer;
|
||||||
private __toBuffer;
|
|
||||||
toHex(): string;
|
toHex(): string;
|
||||||
setInputScript(index: number, scriptSig: Buffer): void;
|
setInputScript(index: number, scriptSig: Buffer): void;
|
||||||
setWitness(index: number, witness: Array<Buffer>): void;
|
setWitness(index: number, witness: Buffer[]): void;
|
||||||
|
private __byteLength;
|
||||||
|
private __toBuffer;
|
||||||
}
|
}
|
||||||
|
export {};
|
||||||
|
|
14
types/transaction_builder.d.ts
vendored
14
types/transaction_builder.d.ts
vendored
|
@ -1,24 +1,24 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
|
import { ECPairInterface } from './ecpair';
|
||||||
import { Network } from './networks';
|
import { Network } from './networks';
|
||||||
import { Transaction } from './transaction';
|
import { Transaction } from './transaction';
|
||||||
import { ECPairInterface } from './ecpair';
|
|
||||||
export declare class TransactionBuilder {
|
export declare class TransactionBuilder {
|
||||||
|
static fromTransaction(transaction: Transaction, network?: Network): TransactionBuilder;
|
||||||
network: Network;
|
network: Network;
|
||||||
maximumFeeRate: number;
|
maximumFeeRate: number;
|
||||||
private __prevTxSet;
|
private __PREV_TX_SET;
|
||||||
private __inputs;
|
private __INPUTS;
|
||||||
private __tx;
|
private __TX;
|
||||||
constructor(network?: Network, maximumFeeRate?: number);
|
constructor(network?: Network, maximumFeeRate?: number);
|
||||||
static fromTransaction(transaction: Transaction, network?: Network): TransactionBuilder;
|
|
||||||
setLockTime(locktime: number): void;
|
setLockTime(locktime: number): void;
|
||||||
setVersion(version: number): void;
|
setVersion(version: number): void;
|
||||||
addInput(txHash: Buffer | string | Transaction, vout: number, sequence: number, prevOutScript: Buffer): number;
|
addInput(txHash: Buffer | string | Transaction, vout: number, sequence: number, prevOutScript: Buffer): number;
|
||||||
private __addInputUnsafe;
|
|
||||||
addOutput(scriptPubKey: string | Buffer, value: number): number;
|
addOutput(scriptPubKey: string | Buffer, value: number): number;
|
||||||
build(): Transaction;
|
build(): Transaction;
|
||||||
buildIncomplete(): Transaction;
|
buildIncomplete(): Transaction;
|
||||||
private __build;
|
|
||||||
sign(vin: number, keyPair: ECPairInterface, redeemScript: Buffer, hashType: number, witnessValue: number, witnessScript: Buffer): void;
|
sign(vin: number, keyPair: ECPairInterface, redeemScript: Buffer, hashType: number, witnessValue: number, witnessScript: Buffer): void;
|
||||||
|
private __addInputUnsafe;
|
||||||
|
private __build;
|
||||||
private __canModifyInputs;
|
private __canModifyInputs;
|
||||||
private __needsOutputs;
|
private __needsOutputs;
|
||||||
private __canModifyOutputs;
|
private __canModifyOutputs;
|
||||||
|
|
Loading…
Reference in a new issue