xpi-ts 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +516 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/lib/bitcore/address.d.ts +66 -0
- package/dist/lib/bitcore/address.d.ts.map +1 -0
- package/dist/lib/bitcore/address.js +407 -0
- package/dist/lib/bitcore/block/block.d.ts +57 -0
- package/dist/lib/bitcore/block/block.d.ts.map +1 -0
- package/dist/lib/bitcore/block/block.js +233 -0
- package/dist/lib/bitcore/block/blockheader.d.ts +82 -0
- package/dist/lib/bitcore/block/blockheader.d.ts.map +1 -0
- package/dist/lib/bitcore/block/blockheader.js +323 -0
- package/dist/lib/bitcore/block/index.d.ts +5 -0
- package/dist/lib/bitcore/block/index.d.ts.map +1 -0
- package/dist/lib/bitcore/block/index.js +2 -0
- package/dist/lib/bitcore/chunk.d.ts +22 -0
- package/dist/lib/bitcore/chunk.d.ts.map +1 -0
- package/dist/lib/bitcore/chunk.js +46 -0
- package/dist/lib/bitcore/crypto/bn.d.ts +53 -0
- package/dist/lib/bitcore/crypto/bn.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/bn.js +238 -0
- package/dist/lib/bitcore/crypto/ecdsa.d.ts +46 -0
- package/dist/lib/bitcore/crypto/ecdsa.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/ecdsa.js +247 -0
- package/dist/lib/bitcore/crypto/hash.d.ts +16 -0
- package/dist/lib/bitcore/crypto/hash.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/hash.js +87 -0
- package/dist/lib/bitcore/crypto/index.d.ts +9 -0
- package/dist/lib/bitcore/crypto/index.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/index.js +8 -0
- package/dist/lib/bitcore/crypto/musig2.d.ts +40 -0
- package/dist/lib/bitcore/crypto/musig2.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/musig2.js +236 -0
- package/dist/lib/bitcore/crypto/point.d.ts +20 -0
- package/dist/lib/bitcore/crypto/point.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/point.js +133 -0
- package/dist/lib/bitcore/crypto/random.d.ts +7 -0
- package/dist/lib/bitcore/crypto/random.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/random.js +30 -0
- package/dist/lib/bitcore/crypto/schnorr.d.ts +40 -0
- package/dist/lib/bitcore/crypto/schnorr.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/schnorr.js +185 -0
- package/dist/lib/bitcore/crypto/signature.d.ts +53 -0
- package/dist/lib/bitcore/crypto/signature.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/signature.js +300 -0
- package/dist/lib/bitcore/crypto/sigtype.d.ts +5 -0
- package/dist/lib/bitcore/crypto/sigtype.d.ts.map +1 -0
- package/dist/lib/bitcore/crypto/sigtype.js +18 -0
- package/dist/lib/bitcore/encoding/base58.d.ts +16 -0
- package/dist/lib/bitcore/encoding/base58.d.ts.map +1 -0
- package/dist/lib/bitcore/encoding/base58.js +55 -0
- package/dist/lib/bitcore/encoding/base58check.d.ts +9 -0
- package/dist/lib/bitcore/encoding/base58check.d.ts.map +1 -0
- package/dist/lib/bitcore/encoding/base58check.js +82 -0
- package/dist/lib/bitcore/encoding/bufferreader.d.ts +34 -0
- package/dist/lib/bitcore/encoding/bufferreader.d.ts.map +1 -0
- package/dist/lib/bitcore/encoding/bufferreader.js +198 -0
- package/dist/lib/bitcore/encoding/bufferwriter.d.ts +36 -0
- package/dist/lib/bitcore/encoding/bufferwriter.d.ts.map +1 -0
- package/dist/lib/bitcore/encoding/bufferwriter.js +189 -0
- package/dist/lib/bitcore/encoding/varint.d.ts +20 -0
- package/dist/lib/bitcore/encoding/varint.d.ts.map +1 -0
- package/dist/lib/bitcore/encoding/varint.js +61 -0
- package/dist/lib/bitcore/errors.d.ts +28 -0
- package/dist/lib/bitcore/errors.d.ts.map +1 -0
- package/dist/lib/bitcore/errors.js +325 -0
- package/dist/lib/bitcore/hdprivatekey.d.ts +78 -0
- package/dist/lib/bitcore/hdprivatekey.d.ts.map +1 -0
- package/dist/lib/bitcore/hdprivatekey.js +381 -0
- package/dist/lib/bitcore/hdpublickey.d.ts +98 -0
- package/dist/lib/bitcore/hdpublickey.d.ts.map +1 -0
- package/dist/lib/bitcore/hdpublickey.js +416 -0
- package/dist/lib/bitcore/index.d.ts +60 -0
- package/dist/lib/bitcore/index.d.ts.map +1 -0
- package/dist/lib/bitcore/index.js +44 -0
- package/dist/lib/bitcore/message.d.ts +23 -0
- package/dist/lib/bitcore/message.d.ts.map +1 -0
- package/dist/lib/bitcore/message.js +112 -0
- package/dist/lib/bitcore/mnemonic/errors.d.ts +7 -0
- package/dist/lib/bitcore/mnemonic/errors.d.ts.map +1 -0
- package/dist/lib/bitcore/mnemonic/errors.js +20 -0
- package/dist/lib/bitcore/mnemonic/index.d.ts +5 -0
- package/dist/lib/bitcore/mnemonic/index.d.ts.map +1 -0
- package/dist/lib/bitcore/mnemonic/index.js +4 -0
- package/dist/lib/bitcore/mnemonic/mnemonic.d.ts +23 -0
- package/dist/lib/bitcore/mnemonic/mnemonic.d.ts.map +1 -0
- package/dist/lib/bitcore/mnemonic/mnemonic.js +164 -0
- package/dist/lib/bitcore/mnemonic/pbkdf2.d.ts +2 -0
- package/dist/lib/bitcore/mnemonic/pbkdf2.d.ts.map +1 -0
- package/dist/lib/bitcore/mnemonic/pbkdf2.js +25 -0
- package/dist/lib/bitcore/mnemonic/words/english.d.ts +2 -0
- package/dist/lib/bitcore/mnemonic/words/english.d.ts.map +1 -0
- package/dist/lib/bitcore/mnemonic/words/english.js +2050 -0
- package/dist/lib/bitcore/mnemonic/words/index.d.ts +4 -0
- package/dist/lib/bitcore/mnemonic/words/index.d.ts.map +1 -0
- package/dist/lib/bitcore/mnemonic/words/index.js +4 -0
- package/dist/lib/bitcore/musig2/index.d.ts +3 -0
- package/dist/lib/bitcore/musig2/index.d.ts.map +1 -0
- package/dist/lib/bitcore/musig2/index.js +2 -0
- package/dist/lib/bitcore/musig2/session.d.ts +79 -0
- package/dist/lib/bitcore/musig2/session.d.ts.map +1 -0
- package/dist/lib/bitcore/musig2/session.js +346 -0
- package/dist/lib/bitcore/musig2/signer.d.ts +61 -0
- package/dist/lib/bitcore/musig2/signer.d.ts.map +1 -0
- package/dist/lib/bitcore/musig2/signer.js +146 -0
- package/dist/lib/bitcore/networks.d.ts +53 -0
- package/dist/lib/bitcore/networks.d.ts.map +1 -0
- package/dist/lib/bitcore/networks.js +150 -0
- package/dist/lib/bitcore/opcode.d.ts +250 -0
- package/dist/lib/bitcore/opcode.d.ts.map +1 -0
- package/dist/lib/bitcore/opcode.js +270 -0
- package/dist/lib/bitcore/privatekey.d.ts +56 -0
- package/dist/lib/bitcore/privatekey.d.ts.map +1 -0
- package/dist/lib/bitcore/privatekey.js +237 -0
- package/dist/lib/bitcore/publickey.d.ts +59 -0
- package/dist/lib/bitcore/publickey.d.ts.map +1 -0
- package/dist/lib/bitcore/publickey.js +263 -0
- package/dist/lib/bitcore/script/interpreter.d.ts +98 -0
- package/dist/lib/bitcore/script/interpreter.d.ts.map +1 -0
- package/dist/lib/bitcore/script/interpreter.js +1704 -0
- package/dist/lib/bitcore/script.d.ts +111 -0
- package/dist/lib/bitcore/script.d.ts.map +1 -0
- package/dist/lib/bitcore/script.js +1112 -0
- package/dist/lib/bitcore/taproot/musig2.d.ts +29 -0
- package/dist/lib/bitcore/taproot/musig2.d.ts.map +1 -0
- package/dist/lib/bitcore/taproot/musig2.js +104 -0
- package/dist/lib/bitcore/taproot/nft.d.ts +164 -0
- package/dist/lib/bitcore/taproot/nft.d.ts.map +1 -0
- package/dist/lib/bitcore/taproot/nft.js +407 -0
- package/dist/lib/bitcore/taproot.d.ts +65 -0
- package/dist/lib/bitcore/taproot.d.ts.map +1 -0
- package/dist/lib/bitcore/taproot.js +288 -0
- package/dist/lib/bitcore/transaction/index.d.ts +12 -0
- package/dist/lib/bitcore/transaction/index.d.ts.map +1 -0
- package/dist/lib/bitcore/transaction/index.js +6 -0
- package/dist/lib/bitcore/transaction/input.d.ts +202 -0
- package/dist/lib/bitcore/transaction/input.d.ts.map +1 -0
- package/dist/lib/bitcore/transaction/input.js +911 -0
- package/dist/lib/bitcore/transaction/output.d.ts +48 -0
- package/dist/lib/bitcore/transaction/output.d.ts.map +1 -0
- package/dist/lib/bitcore/transaction/output.js +231 -0
- package/dist/lib/bitcore/transaction/sighash.d.ts +32 -0
- package/dist/lib/bitcore/transaction/sighash.d.ts.map +1 -0
- package/dist/lib/bitcore/transaction/sighash.js +335 -0
- package/dist/lib/bitcore/transaction/signature.d.ts +36 -0
- package/dist/lib/bitcore/transaction/signature.d.ts.map +1 -0
- package/dist/lib/bitcore/transaction/signature.js +130 -0
- package/dist/lib/bitcore/transaction/transaction.d.ts +164 -0
- package/dist/lib/bitcore/transaction/transaction.d.ts.map +1 -0
- package/dist/lib/bitcore/transaction/transaction.js +1016 -0
- package/dist/lib/bitcore/transaction/unspentoutput.d.ts +58 -0
- package/dist/lib/bitcore/transaction/unspentoutput.d.ts.map +1 -0
- package/dist/lib/bitcore/transaction/unspentoutput.js +167 -0
- package/dist/lib/bitcore/unit.d.ts +44 -0
- package/dist/lib/bitcore/unit.d.ts.map +1 -0
- package/dist/lib/bitcore/unit.js +106 -0
- package/dist/lib/bitcore/uri.d.ts +29 -0
- package/dist/lib/bitcore/uri.d.ts.map +1 -0
- package/dist/lib/bitcore/uri.js +163 -0
- package/dist/lib/bitcore/util/base32.d.ts +5 -0
- package/dist/lib/bitcore/util/base32.d.ts.map +1 -0
- package/dist/lib/bitcore/util/base32.js +58 -0
- package/dist/lib/bitcore/util/buffer.d.ts +18 -0
- package/dist/lib/bitcore/util/buffer.d.ts.map +1 -0
- package/dist/lib/bitcore/util/buffer.js +76 -0
- package/dist/lib/bitcore/util/convertBits.d.ts +2 -0
- package/dist/lib/bitcore/util/convertBits.d.ts.map +1 -0
- package/dist/lib/bitcore/util/convertBits.js +26 -0
- package/dist/lib/bitcore/util/js.d.ts +9 -0
- package/dist/lib/bitcore/util/js.d.ts.map +1 -0
- package/dist/lib/bitcore/util/js.js +45 -0
- package/dist/lib/bitcore/util/preconditions.d.ts +6 -0
- package/dist/lib/bitcore/util/preconditions.d.ts.map +1 -0
- package/dist/lib/bitcore/util/preconditions.js +31 -0
- package/dist/lib/bitcore/util.d.ts +14 -0
- package/dist/lib/bitcore/util.d.ts.map +1 -0
- package/dist/lib/bitcore/util.js +13 -0
- package/dist/lib/bitcore/xaddress.d.ts +45 -0
- package/dist/lib/bitcore/xaddress.d.ts.map +1 -0
- package/dist/lib/bitcore/xaddress.js +279 -0
- package/dist/lib/rank/api.d.ts +75 -0
- package/dist/lib/rank/api.d.ts.map +1 -0
- package/dist/lib/rank/api.js +4 -0
- package/dist/lib/rank/index.d.ts +127 -0
- package/dist/lib/rank/index.d.ts.map +1 -0
- package/dist/lib/rank/index.js +421 -0
- package/dist/lib/rank/opcode.d.ts +23 -0
- package/dist/lib/rank/opcode.d.ts.map +1 -0
- package/dist/lib/rank/opcode.js +23 -0
- package/dist/lib/rank/script.d.ts +2 -0
- package/dist/lib/rank/script.d.ts.map +1 -0
- package/dist/lib/rank/script.js +7 -0
- package/dist/lib/rank/transaction.d.ts +3 -0
- package/dist/lib/rank/transaction.d.ts.map +1 -0
- package/dist/lib/rank/transaction.js +12 -0
- package/dist/lib/rpc.d.ts +136 -0
- package/dist/lib/rpc.d.ts.map +1 -0
- package/dist/lib/rpc.js +62 -0
- package/dist/utils/constants.d.ts +18 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +20 -0
- package/dist/utils/env.d.ts +3 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +8 -0
- package/dist/utils/string.d.ts +11 -0
- package/dist/utils/string.d.ts.map +1 -0
- package/dist/utils/string.js +47 -0
- package/dist/utils/types.d.ts +2 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +1 -0
- package/dist/utils/wallet.d.ts +12 -0
- package/dist/utils/wallet.d.ts.map +1 -0
- package/dist/utils/wallet.js +28 -0
- package/package.json +91 -0
|
@@ -0,0 +1,911 @@
|
|
|
1
|
+
import { Preconditions } from '../util/preconditions.js';
|
|
2
|
+
import { BitcoreError } from '../errors.js';
|
|
3
|
+
import { BufferWriter } from '../encoding/bufferwriter.js';
|
|
4
|
+
import { BufferUtil } from '../util/buffer.js';
|
|
5
|
+
import { JSUtil } from '../util/js.js';
|
|
6
|
+
import { Script, empty } from '../script.js';
|
|
7
|
+
import { Opcode } from '../opcode.js';
|
|
8
|
+
import { BN } from '../crypto/bn.js';
|
|
9
|
+
import { Output } from './output.js';
|
|
10
|
+
import { Signature } from '../crypto/signature.js';
|
|
11
|
+
import { TransactionSignature } from './signature.js';
|
|
12
|
+
import { sign, verify } from './sighash.js';
|
|
13
|
+
import { Hash } from '../crypto/hash.js';
|
|
14
|
+
import { tweakPrivateKey, TAPROOT_SIGHASH_TYPE, extractTaprootCommitment, } from '../taproot.js';
|
|
15
|
+
import { musigNonceAgg, musigSigAgg } from '../crypto/musig2.js';
|
|
16
|
+
export class Input {
|
|
17
|
+
static MAXINT = 0xffffffff;
|
|
18
|
+
static DEFAULT_SEQNUMBER = 0xffffffff;
|
|
19
|
+
static DEFAULT_LOCKTIME_SEQNUMBER = 0xfffffffe;
|
|
20
|
+
static DEFAULT_RBF_SEQNUMBER = 0xfffffffd;
|
|
21
|
+
static SEQUENCE_LOCKTIME_TYPE_FLAG = 0x400000;
|
|
22
|
+
static SEQUENCE_LOCKTIME_DISABLE_FLAG = 0x80000000;
|
|
23
|
+
static SEQUENCE_LOCKTIME_MASK = 0xffff;
|
|
24
|
+
static SEQUENCE_LOCKTIME_GRANULARITY = 512;
|
|
25
|
+
static SEQUENCE_BLOCKDIFF_LIMIT = 0xffff;
|
|
26
|
+
static PublicKey;
|
|
27
|
+
static PublicKeyHash;
|
|
28
|
+
static Multisig;
|
|
29
|
+
static MultisigScriptHash;
|
|
30
|
+
static Taproot;
|
|
31
|
+
static MuSigTaproot;
|
|
32
|
+
static P2PKH;
|
|
33
|
+
static P2SH;
|
|
34
|
+
static P2TR;
|
|
35
|
+
prevTxId;
|
|
36
|
+
outputIndex;
|
|
37
|
+
sequenceNumber;
|
|
38
|
+
_scriptBuffer;
|
|
39
|
+
_script;
|
|
40
|
+
output;
|
|
41
|
+
constructor(params) {
|
|
42
|
+
if (params) {
|
|
43
|
+
this._fromObject(params);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
static create(params) {
|
|
47
|
+
return new Input(params);
|
|
48
|
+
}
|
|
49
|
+
static fromObject(obj) {
|
|
50
|
+
Preconditions.checkArgument(typeof obj === 'object' && obj !== null, 'Must provide an object');
|
|
51
|
+
const input = new Input();
|
|
52
|
+
return input._fromObject(obj);
|
|
53
|
+
}
|
|
54
|
+
_fromObject(params) {
|
|
55
|
+
let prevTxId;
|
|
56
|
+
if (typeof params.prevTxId === 'string' && JSUtil.isHexa(params.prevTxId)) {
|
|
57
|
+
prevTxId = Buffer.from(params.prevTxId, 'hex');
|
|
58
|
+
}
|
|
59
|
+
else if (Buffer.isBuffer(params.prevTxId)) {
|
|
60
|
+
prevTxId = params.prevTxId;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
prevTxId = Buffer.alloc(0);
|
|
64
|
+
}
|
|
65
|
+
this.output = params.output;
|
|
66
|
+
this.prevTxId = prevTxId;
|
|
67
|
+
this.outputIndex = params.outputIndex ?? 0;
|
|
68
|
+
this.sequenceNumber =
|
|
69
|
+
params.sequenceNumber !== undefined
|
|
70
|
+
? params.sequenceNumber
|
|
71
|
+
: Input.DEFAULT_SEQNUMBER;
|
|
72
|
+
if (params.scriptBuffer === undefined && params.script === undefined) {
|
|
73
|
+
throw new BitcoreError.Transaction.Input.MissingScript();
|
|
74
|
+
}
|
|
75
|
+
this.setScript(params.scriptBuffer || params.script);
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
get script() {
|
|
79
|
+
if (this.isNull()) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
if (!this._script) {
|
|
83
|
+
this._script = new Script(this._scriptBuffer);
|
|
84
|
+
this._script._isInput = true;
|
|
85
|
+
}
|
|
86
|
+
return this._script;
|
|
87
|
+
}
|
|
88
|
+
get scriptBuffer() {
|
|
89
|
+
return this._scriptBuffer;
|
|
90
|
+
}
|
|
91
|
+
setScript(script) {
|
|
92
|
+
this._script = undefined;
|
|
93
|
+
if (script instanceof Script) {
|
|
94
|
+
this._script = script;
|
|
95
|
+
this._scriptBuffer = script.toBuffer();
|
|
96
|
+
}
|
|
97
|
+
else if (script === null) {
|
|
98
|
+
this._script = empty();
|
|
99
|
+
this._scriptBuffer = this._script.toBuffer();
|
|
100
|
+
}
|
|
101
|
+
else if (Buffer.isBuffer(script)) {
|
|
102
|
+
this._scriptBuffer = script;
|
|
103
|
+
this._script = Script.fromBuffer(script);
|
|
104
|
+
}
|
|
105
|
+
else if (typeof script === 'string') {
|
|
106
|
+
if (JSUtil.isHexa(script)) {
|
|
107
|
+
this._scriptBuffer = Buffer.from(script, 'hex');
|
|
108
|
+
this._script = Script.fromBuffer(this._scriptBuffer);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this._scriptBuffer = Buffer.from(script, 'utf8');
|
|
112
|
+
this._script = Script.fromBuffer(this._scriptBuffer);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
throw new TypeError('Invalid script type');
|
|
117
|
+
}
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
isNull() {
|
|
121
|
+
return (this.prevTxId.toString('hex') ===
|
|
122
|
+
'0000000000000000000000000000000000000000000000000000000000000000' &&
|
|
123
|
+
this.outputIndex === 0xffffffff);
|
|
124
|
+
}
|
|
125
|
+
isFinal() {
|
|
126
|
+
return this.sequenceNumber !== 4294967295;
|
|
127
|
+
}
|
|
128
|
+
hasSequence() {
|
|
129
|
+
return this.sequenceNumber !== Input.DEFAULT_SEQNUMBER;
|
|
130
|
+
}
|
|
131
|
+
hasRelativeLockTime() {
|
|
132
|
+
return ((this.sequenceNumber & Input.SEQUENCE_LOCKTIME_DISABLE_FLAG) !==
|
|
133
|
+
Input.SEQUENCE_LOCKTIME_DISABLE_FLAG &&
|
|
134
|
+
this.sequenceNumber !== Input.DEFAULT_SEQNUMBER);
|
|
135
|
+
}
|
|
136
|
+
getRelativeLockTime() {
|
|
137
|
+
if (!this.hasRelativeLockTime()) {
|
|
138
|
+
return BigInt(0);
|
|
139
|
+
}
|
|
140
|
+
return BigInt(this.sequenceNumber & Input.SEQUENCE_LOCKTIME_MASK);
|
|
141
|
+
}
|
|
142
|
+
isRelativeLockTimeInBlocks() {
|
|
143
|
+
if (!this.hasRelativeLockTime()) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return (this.sequenceNumber & Input.SEQUENCE_LOCKTIME_TYPE_FLAG) !== 0;
|
|
147
|
+
}
|
|
148
|
+
getRelativeLockTimeInBlocks() {
|
|
149
|
+
if (!this.isRelativeLockTimeInBlocks()) {
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
return Number(this.getRelativeLockTime());
|
|
153
|
+
}
|
|
154
|
+
getRelativeLockTimeInSeconds() {
|
|
155
|
+
if (this.isRelativeLockTimeInBlocks()) {
|
|
156
|
+
return 0;
|
|
157
|
+
}
|
|
158
|
+
return (Number(this.getRelativeLockTime()) *
|
|
159
|
+
Number(Input.SEQUENCE_LOCKTIME_GRANULARITY));
|
|
160
|
+
}
|
|
161
|
+
toObject() {
|
|
162
|
+
const obj = {
|
|
163
|
+
prevTxId: Buffer.from(this.prevTxId).toString('hex'),
|
|
164
|
+
outputIndex: this.outputIndex,
|
|
165
|
+
sequenceNumber: this.sequenceNumber,
|
|
166
|
+
script: this._scriptBuffer.toString('hex'),
|
|
167
|
+
};
|
|
168
|
+
if (this.script) {
|
|
169
|
+
;
|
|
170
|
+
obj.scriptString =
|
|
171
|
+
this.script.toASM();
|
|
172
|
+
}
|
|
173
|
+
if (this.output) {
|
|
174
|
+
;
|
|
175
|
+
obj.output = this.output;
|
|
176
|
+
}
|
|
177
|
+
return obj;
|
|
178
|
+
}
|
|
179
|
+
toJSON = this.toObject;
|
|
180
|
+
static fromBufferReader(br) {
|
|
181
|
+
const input = new Input();
|
|
182
|
+
input.prevTxId = br.readReverse(32);
|
|
183
|
+
input.outputIndex = br.readUInt32LE();
|
|
184
|
+
input._scriptBuffer = br.readVarLengthBuffer();
|
|
185
|
+
input.sequenceNumber = br.readUInt32LE();
|
|
186
|
+
return input;
|
|
187
|
+
}
|
|
188
|
+
toBuffer() {
|
|
189
|
+
const bw = new BufferWriter();
|
|
190
|
+
bw.writeReverse(this.prevTxId);
|
|
191
|
+
bw.writeUInt32LE(this.outputIndex);
|
|
192
|
+
bw.writeVarLengthBuffer(this._scriptBuffer);
|
|
193
|
+
bw.writeUInt32LE(this.sequenceNumber);
|
|
194
|
+
return bw.concat();
|
|
195
|
+
}
|
|
196
|
+
toBufferWriter(writer) {
|
|
197
|
+
if (!writer) {
|
|
198
|
+
writer = new BufferWriter();
|
|
199
|
+
}
|
|
200
|
+
writer.writeReverse(this.prevTxId);
|
|
201
|
+
writer.writeUInt32LE(this.outputIndex);
|
|
202
|
+
const script = this._scriptBuffer;
|
|
203
|
+
writer.writeVarintNum(script.length);
|
|
204
|
+
writer.write(script);
|
|
205
|
+
writer.writeUInt32LE(this.sequenceNumber);
|
|
206
|
+
return writer;
|
|
207
|
+
}
|
|
208
|
+
getSize() {
|
|
209
|
+
return (32 +
|
|
210
|
+
4 +
|
|
211
|
+
BufferWriter.varintBufNum(this._scriptBuffer.length).length +
|
|
212
|
+
this._scriptBuffer.length +
|
|
213
|
+
4);
|
|
214
|
+
}
|
|
215
|
+
isValid() {
|
|
216
|
+
if (this.isNull()) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
return (this.prevTxId.length === 32 &&
|
|
220
|
+
this.outputIndex >= 0 &&
|
|
221
|
+
this.outputIndex <= 0xffffffff &&
|
|
222
|
+
this._scriptBuffer.length > 0);
|
|
223
|
+
}
|
|
224
|
+
clone() {
|
|
225
|
+
return new Input({
|
|
226
|
+
prevTxId: Buffer.from(this.prevTxId),
|
|
227
|
+
outputIndex: this.outputIndex,
|
|
228
|
+
sequenceNumber: this.sequenceNumber,
|
|
229
|
+
scriptBuffer: Buffer.from(this._scriptBuffer),
|
|
230
|
+
output: this.output,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
getSignatures(transaction, privateKey, index, sigtype, hashData, signingMethod) {
|
|
234
|
+
Preconditions.checkState(this.output instanceof Output, 'Output is required');
|
|
235
|
+
sigtype = sigtype || Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID;
|
|
236
|
+
const publicKey = privateKey.publicKey;
|
|
237
|
+
if (this.output.script.isPublicKeyHashOut()) {
|
|
238
|
+
const addressHash = hashData || Hash.sha256ripemd160(publicKey.toBuffer());
|
|
239
|
+
if (BufferUtil.equals(addressHash, this.output.script.getPublicKeyHash())) {
|
|
240
|
+
return [
|
|
241
|
+
new TransactionSignature({
|
|
242
|
+
publicKey: publicKey,
|
|
243
|
+
prevTxId: this.prevTxId,
|
|
244
|
+
outputIndex: this.outputIndex,
|
|
245
|
+
inputIndex: index,
|
|
246
|
+
signature: sign(transaction, privateKey, sigtype, index, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod),
|
|
247
|
+
sigtype: sigtype,
|
|
248
|
+
}),
|
|
249
|
+
];
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else if (this.output.script.isPublicKeyOut()) {
|
|
253
|
+
if (publicKey.toString() ===
|
|
254
|
+
this.output.script.getPublicKey().toString('hex')) {
|
|
255
|
+
return [
|
|
256
|
+
new TransactionSignature({
|
|
257
|
+
publicKey: publicKey,
|
|
258
|
+
prevTxId: this.prevTxId,
|
|
259
|
+
outputIndex: this.outputIndex,
|
|
260
|
+
inputIndex: index,
|
|
261
|
+
signature: sign(transaction, privateKey, sigtype, index, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod),
|
|
262
|
+
sigtype: sigtype,
|
|
263
|
+
}),
|
|
264
|
+
];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return [];
|
|
268
|
+
}
|
|
269
|
+
isFullySigned() {
|
|
270
|
+
throw new Error('Input#isFullySigned');
|
|
271
|
+
}
|
|
272
|
+
addSignature(transaction, signature, signingMethod) {
|
|
273
|
+
Preconditions.checkState(this.isValidSignature(transaction, signature, signingMethod), 'Signature is invalid');
|
|
274
|
+
if (this.output?.script.isPublicKeyHashOut()) {
|
|
275
|
+
const script = new Script();
|
|
276
|
+
script.add(signature.signature.toTxFormat(signingMethod));
|
|
277
|
+
script.add(signature.publicKey.toBuffer());
|
|
278
|
+
this.setScript(script);
|
|
279
|
+
}
|
|
280
|
+
else if (this.output?.script.isPublicKeyOut()) {
|
|
281
|
+
const script = new Script();
|
|
282
|
+
script.add(signature.signature.toTxFormat(signingMethod));
|
|
283
|
+
this.setScript(script);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
const script = new Script();
|
|
287
|
+
script.add(signature.signature.toTxFormat(signingMethod));
|
|
288
|
+
if (signature.publicKey) {
|
|
289
|
+
script.add(signature.publicKey.toBuffer());
|
|
290
|
+
}
|
|
291
|
+
this.setScript(script);
|
|
292
|
+
}
|
|
293
|
+
return this;
|
|
294
|
+
}
|
|
295
|
+
clearSignatures() {
|
|
296
|
+
throw new Error('Input#clearSignatures');
|
|
297
|
+
}
|
|
298
|
+
isValidSignature(transaction, signature, signingMethod) {
|
|
299
|
+
signature.signature.nhashtype = signature.sigtype;
|
|
300
|
+
return verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod);
|
|
301
|
+
}
|
|
302
|
+
lockForSeconds(seconds) {
|
|
303
|
+
Preconditions.checkArgument(typeof seconds === 'number', 'seconds must be a number');
|
|
304
|
+
if (seconds < 0 ||
|
|
305
|
+
seconds >=
|
|
306
|
+
Input.SEQUENCE_LOCKTIME_GRANULARITY * Input.SEQUENCE_LOCKTIME_MASK) {
|
|
307
|
+
throw new Error('Lock time range error');
|
|
308
|
+
}
|
|
309
|
+
seconds = Math.floor(seconds / Input.SEQUENCE_LOCKTIME_GRANULARITY);
|
|
310
|
+
this.sequenceNumber = seconds | Input.SEQUENCE_LOCKTIME_TYPE_FLAG;
|
|
311
|
+
return this;
|
|
312
|
+
}
|
|
313
|
+
lockUntilBlockHeight(heightDiff) {
|
|
314
|
+
Preconditions.checkArgument(typeof heightDiff === 'number', 'heightDiff must be a number');
|
|
315
|
+
if (heightDiff < 0 || heightDiff >= Input.SEQUENCE_BLOCKDIFF_LIMIT) {
|
|
316
|
+
throw new Error('Block height out of range');
|
|
317
|
+
}
|
|
318
|
+
this.sequenceNumber = heightDiff;
|
|
319
|
+
return this;
|
|
320
|
+
}
|
|
321
|
+
getLockTime() {
|
|
322
|
+
if (this.sequenceNumber & Input.SEQUENCE_LOCKTIME_DISABLE_FLAG) {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
if (this.sequenceNumber & Input.SEQUENCE_LOCKTIME_TYPE_FLAG) {
|
|
326
|
+
const seconds = Input.SEQUENCE_LOCKTIME_GRANULARITY *
|
|
327
|
+
(this.sequenceNumber & Input.SEQUENCE_LOCKTIME_MASK);
|
|
328
|
+
return seconds;
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
const blockHeight = this.sequenceNumber & Input.SEQUENCE_LOCKTIME_MASK;
|
|
332
|
+
return blockHeight;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
_estimateSize() {
|
|
336
|
+
return this.toBufferWriter().toBuffer().length;
|
|
337
|
+
}
|
|
338
|
+
toString() {
|
|
339
|
+
if (this.isNull()) {
|
|
340
|
+
return 'Input(coinbase)';
|
|
341
|
+
}
|
|
342
|
+
return `Input(${this.prevTxId.toString('hex')}:${this.outputIndex})`;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
export class MultisigInput extends Input {
|
|
346
|
+
static OPCODES_SIZE = 1;
|
|
347
|
+
static SIGNATURE_SIZE = 73;
|
|
348
|
+
publicKeys;
|
|
349
|
+
threshold;
|
|
350
|
+
signatures;
|
|
351
|
+
publicKeyIndex;
|
|
352
|
+
constructor(input, pubkeys, threshold, signatures, opts) {
|
|
353
|
+
super({
|
|
354
|
+
prevTxId: input.prevTxId,
|
|
355
|
+
outputIndex: input.outputIndex,
|
|
356
|
+
sequenceNumber: input.sequenceNumber,
|
|
357
|
+
scriptBuffer: input.script?.toBuffer(),
|
|
358
|
+
output: input.output,
|
|
359
|
+
});
|
|
360
|
+
opts = opts || {};
|
|
361
|
+
pubkeys =
|
|
362
|
+
pubkeys || input.publicKeys;
|
|
363
|
+
threshold = threshold || input.threshold;
|
|
364
|
+
signatures =
|
|
365
|
+
signatures ||
|
|
366
|
+
input.signatures;
|
|
367
|
+
if (opts.noSorting) {
|
|
368
|
+
this.publicKeys = pubkeys;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
this.publicKeys = pubkeys.sort((a, b) => a.toString().localeCompare(b.toString()));
|
|
372
|
+
}
|
|
373
|
+
Preconditions.checkState(Script.buildMultisigOut(this.publicKeys, threshold).equals(this.output.script), "Provided public keys don't match to the provided output script");
|
|
374
|
+
this.publicKeyIndex = {};
|
|
375
|
+
this.publicKeys.forEach((publicKey, index) => {
|
|
376
|
+
this.publicKeyIndex[publicKey.toString()] = index;
|
|
377
|
+
});
|
|
378
|
+
this.threshold = threshold;
|
|
379
|
+
this.signatures = signatures
|
|
380
|
+
? this._deserializeSignatures(signatures)
|
|
381
|
+
: new Array(this.publicKeys.length);
|
|
382
|
+
}
|
|
383
|
+
toObject() {
|
|
384
|
+
const obj = super.toObject();
|
|
385
|
+
return {
|
|
386
|
+
...obj,
|
|
387
|
+
threshold: this.threshold,
|
|
388
|
+
publicKeys: this.publicKeys.map(pk => pk.toString()),
|
|
389
|
+
signatures: this._serializeSignatures(),
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
_deserializeSignatures(signatures) {
|
|
393
|
+
return signatures.map(signature => {
|
|
394
|
+
if (!signature) {
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
return new TransactionSignature(signature);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
_serializeSignatures() {
|
|
401
|
+
return this.signatures.map(signature => {
|
|
402
|
+
if (!signature) {
|
|
403
|
+
return undefined;
|
|
404
|
+
}
|
|
405
|
+
return signature.toObject();
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
getSignatures(transaction, privateKey, index, sigtype, hashData, signingMethod) {
|
|
409
|
+
Preconditions.checkState(this.output instanceof Output, 'Output is required');
|
|
410
|
+
sigtype = sigtype || Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID;
|
|
411
|
+
const results = [];
|
|
412
|
+
this.publicKeys.forEach(publicKey => {
|
|
413
|
+
if (publicKey.toString() === privateKey.publicKey.toString()) {
|
|
414
|
+
results.push(new TransactionSignature({
|
|
415
|
+
publicKey: privateKey.publicKey,
|
|
416
|
+
prevTxId: this.prevTxId,
|
|
417
|
+
outputIndex: this.outputIndex,
|
|
418
|
+
inputIndex: index,
|
|
419
|
+
signature: sign(transaction, privateKey, sigtype, index, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod),
|
|
420
|
+
sigtype: sigtype,
|
|
421
|
+
}));
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
return results;
|
|
425
|
+
}
|
|
426
|
+
addSignature(transaction, signature, signingMethod) {
|
|
427
|
+
Preconditions.checkState(!this.isFullySigned(), 'All needed signatures have already been added');
|
|
428
|
+
Preconditions.checkArgument(this.publicKeyIndex[signature.publicKey.toString()] !== undefined, 'Signature has no matching public key');
|
|
429
|
+
Preconditions.checkState(this.isValidSignature(transaction, signature, signingMethod), 'Invalid signature');
|
|
430
|
+
this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] =
|
|
431
|
+
signature;
|
|
432
|
+
this._updateScript(signingMethod);
|
|
433
|
+
return this;
|
|
434
|
+
}
|
|
435
|
+
_updateScript(signingMethod) {
|
|
436
|
+
const script = new Script();
|
|
437
|
+
script.add(Opcode.OP_0);
|
|
438
|
+
const signatures = this._createSignatures(signingMethod);
|
|
439
|
+
for (const sig of signatures) {
|
|
440
|
+
script.add(sig);
|
|
441
|
+
}
|
|
442
|
+
this.setScript(script);
|
|
443
|
+
return this;
|
|
444
|
+
}
|
|
445
|
+
_createSignatures(signingMethod) {
|
|
446
|
+
return this.signatures
|
|
447
|
+
.filter(signature => signature !== undefined)
|
|
448
|
+
.map(signature => {
|
|
449
|
+
return Buffer.concat([
|
|
450
|
+
signature.signature.toDER(signingMethod),
|
|
451
|
+
Buffer.from([signature.sigtype]),
|
|
452
|
+
]);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
clearSignatures() {
|
|
456
|
+
this.signatures = new Array(this.publicKeys.length);
|
|
457
|
+
this._updateScript();
|
|
458
|
+
return this;
|
|
459
|
+
}
|
|
460
|
+
isFullySigned() {
|
|
461
|
+
return this.countSignatures() === this.threshold;
|
|
462
|
+
}
|
|
463
|
+
countMissingSignatures() {
|
|
464
|
+
return this.threshold - this.countSignatures();
|
|
465
|
+
}
|
|
466
|
+
countSignatures() {
|
|
467
|
+
return this.signatures.reduce((sum, signature) => sum + (signature ? 1 : 0), 0);
|
|
468
|
+
}
|
|
469
|
+
publicKeysWithoutSignature() {
|
|
470
|
+
return this.publicKeys.filter(publicKey => {
|
|
471
|
+
return !this.signatures[this.publicKeyIndex[publicKey.toString()]];
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
isValidSignature(transaction, signature, signingMethod) {
|
|
475
|
+
signature.signature.nhashtype = signature.sigtype;
|
|
476
|
+
return verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod);
|
|
477
|
+
}
|
|
478
|
+
normalizeSignatures(transaction, input, inputIndex, signatures, publicKeys, signingMethod) {
|
|
479
|
+
return publicKeys
|
|
480
|
+
.map(pubKey => {
|
|
481
|
+
let signatureMatch = null;
|
|
482
|
+
signatures = signatures.filter(signatureBuffer => {
|
|
483
|
+
if (signatureMatch) {
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
const signature = new TransactionSignature({
|
|
487
|
+
signature: Signature.fromTxFormat(signatureBuffer),
|
|
488
|
+
publicKey: pubKey,
|
|
489
|
+
prevTxId: input.prevTxId,
|
|
490
|
+
outputIndex: input.outputIndex,
|
|
491
|
+
inputIndex: inputIndex,
|
|
492
|
+
sigtype: Signature.SIGHASH_ALL,
|
|
493
|
+
});
|
|
494
|
+
signature.signature.nhashtype = signature.sigtype;
|
|
495
|
+
const isMatch = verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, input.output.script, new BN(input.output.satoshis.toString()), undefined, signingMethod);
|
|
496
|
+
if (isMatch) {
|
|
497
|
+
signatureMatch = signature;
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
500
|
+
return true;
|
|
501
|
+
});
|
|
502
|
+
return signatureMatch ? signatureMatch : null;
|
|
503
|
+
})
|
|
504
|
+
.filter(sig => sig !== null);
|
|
505
|
+
}
|
|
506
|
+
_estimateSize() {
|
|
507
|
+
return (MultisigInput.OPCODES_SIZE + this.threshold * MultisigInput.SIGNATURE_SIZE);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
export class MultisigScriptHashInput extends Input {
|
|
511
|
+
static OPCODES_SIZE = 7;
|
|
512
|
+
static SIGNATURE_SIZE = 74;
|
|
513
|
+
static PUBKEY_SIZE = 34;
|
|
514
|
+
publicKeys;
|
|
515
|
+
threshold;
|
|
516
|
+
signatures;
|
|
517
|
+
redeemScript;
|
|
518
|
+
publicKeyIndex;
|
|
519
|
+
checkBitsField;
|
|
520
|
+
constructor(input, pubkeys, threshold, signatures, opts) {
|
|
521
|
+
super({
|
|
522
|
+
prevTxId: input.prevTxId,
|
|
523
|
+
outputIndex: input.outputIndex,
|
|
524
|
+
sequenceNumber: input.sequenceNumber,
|
|
525
|
+
scriptBuffer: input.script?.toBuffer(),
|
|
526
|
+
output: input.output,
|
|
527
|
+
});
|
|
528
|
+
opts = opts || {};
|
|
529
|
+
pubkeys =
|
|
530
|
+
pubkeys || input.publicKeys;
|
|
531
|
+
threshold = threshold || input.threshold;
|
|
532
|
+
signatures =
|
|
533
|
+
signatures ||
|
|
534
|
+
input.signatures;
|
|
535
|
+
if (opts.noSorting) {
|
|
536
|
+
this.publicKeys = pubkeys;
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
this.publicKeys = pubkeys.sort((a, b) => a.toString().localeCompare(b.toString()));
|
|
540
|
+
}
|
|
541
|
+
this.redeemScript = Script.buildMultisigOut(this.publicKeys, threshold, opts);
|
|
542
|
+
Preconditions.checkState(Script.buildScriptHashOut(this.redeemScript).equals(this.output.script), "Provided public keys don't hash to the provided output");
|
|
543
|
+
this.publicKeyIndex = {};
|
|
544
|
+
this.publicKeys.forEach((publicKey, index) => {
|
|
545
|
+
this.publicKeyIndex[publicKey.toString()] = index;
|
|
546
|
+
});
|
|
547
|
+
this.threshold = threshold;
|
|
548
|
+
this.signatures = signatures
|
|
549
|
+
? this._deserializeSignatures(signatures)
|
|
550
|
+
: new Array(this.publicKeys.length);
|
|
551
|
+
this.checkBitsField = new Uint8Array(this.publicKeys.length);
|
|
552
|
+
}
|
|
553
|
+
toObject() {
|
|
554
|
+
const obj = super.toObject();
|
|
555
|
+
return {
|
|
556
|
+
...obj,
|
|
557
|
+
threshold: this.threshold,
|
|
558
|
+
publicKeys: this.publicKeys.map(pk => pk.toString()),
|
|
559
|
+
signatures: this._serializeSignatures(),
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
_deserializeSignatures(signatures) {
|
|
563
|
+
return signatures.map(signature => {
|
|
564
|
+
if (!signature) {
|
|
565
|
+
return undefined;
|
|
566
|
+
}
|
|
567
|
+
return new TransactionSignature(signature);
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
_serializeSignatures() {
|
|
571
|
+
return this.signatures.map(signature => {
|
|
572
|
+
if (!signature) {
|
|
573
|
+
return undefined;
|
|
574
|
+
}
|
|
575
|
+
return signature.toObject();
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
getSignatures(transaction, privateKey, index, sigtype, hashData, signingMethod) {
|
|
579
|
+
Preconditions.checkState(this.output instanceof Output, 'Output is required');
|
|
580
|
+
sigtype = sigtype || Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID;
|
|
581
|
+
const results = [];
|
|
582
|
+
this.publicKeys.forEach(publicKey => {
|
|
583
|
+
if (publicKey.toString() === privateKey.publicKey.toString()) {
|
|
584
|
+
results.push(new TransactionSignature({
|
|
585
|
+
publicKey: privateKey.publicKey,
|
|
586
|
+
prevTxId: this.prevTxId,
|
|
587
|
+
outputIndex: this.outputIndex,
|
|
588
|
+
inputIndex: index,
|
|
589
|
+
signature: sign(transaction, privateKey, sigtype, index, this.redeemScript, new BN(this.output.satoshis.toString()), undefined, signingMethod),
|
|
590
|
+
sigtype: sigtype,
|
|
591
|
+
}));
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
return results;
|
|
595
|
+
}
|
|
596
|
+
addSignature(transaction, signature, signingMethod) {
|
|
597
|
+
Preconditions.checkState(!this.isFullySigned(), 'All needed signatures have already been added');
|
|
598
|
+
Preconditions.checkArgument(this.publicKeyIndex[signature.publicKey.toString()] !== undefined, 'Signature has no matching public key');
|
|
599
|
+
Preconditions.checkState(this.isValidSignature(transaction, signature, signingMethod), 'Invalid signature');
|
|
600
|
+
this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] =
|
|
601
|
+
signature;
|
|
602
|
+
this.checkBitsField[this.publicKeyIndex[signature.publicKey.toString()]] =
|
|
603
|
+
signature !== undefined ? 1 : 0;
|
|
604
|
+
this._updateScript(signingMethod, this.checkBitsField);
|
|
605
|
+
return this;
|
|
606
|
+
}
|
|
607
|
+
_updateScript(signingMethod, checkBitsField) {
|
|
608
|
+
const script = new Script();
|
|
609
|
+
script.add(Opcode.OP_0);
|
|
610
|
+
const signatures = this._createSignatures(signingMethod);
|
|
611
|
+
for (const sig of signatures) {
|
|
612
|
+
script.add(sig);
|
|
613
|
+
}
|
|
614
|
+
script.add(this.redeemScript.toBuffer());
|
|
615
|
+
this.setScript(script);
|
|
616
|
+
return this;
|
|
617
|
+
}
|
|
618
|
+
_createSignatures(signingMethod) {
|
|
619
|
+
return this.signatures
|
|
620
|
+
.filter(signature => signature !== undefined)
|
|
621
|
+
.map(signature => {
|
|
622
|
+
return Buffer.concat([
|
|
623
|
+
signature.signature.toDER(signingMethod),
|
|
624
|
+
Buffer.from([signature.sigtype]),
|
|
625
|
+
]);
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
clearSignatures() {
|
|
629
|
+
this.signatures = new Array(this.publicKeys.length);
|
|
630
|
+
this._updateScript();
|
|
631
|
+
return this;
|
|
632
|
+
}
|
|
633
|
+
isFullySigned() {
|
|
634
|
+
return this.countSignatures() === this.threshold;
|
|
635
|
+
}
|
|
636
|
+
countMissingSignatures() {
|
|
637
|
+
return this.threshold - this.countSignatures();
|
|
638
|
+
}
|
|
639
|
+
countSignatures() {
|
|
640
|
+
return this.signatures.reduce((sum, signature) => sum + (signature ? 1 : 0), 0);
|
|
641
|
+
}
|
|
642
|
+
publicKeysWithoutSignature() {
|
|
643
|
+
return this.publicKeys.filter(publicKey => {
|
|
644
|
+
return !this.signatures[this.publicKeyIndex[publicKey.toString()]];
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
isValidSignature(transaction, signature, signingMethod) {
|
|
648
|
+
signingMethod = signingMethod || 'ecdsa';
|
|
649
|
+
signature.signature.nhashtype = signature.sigtype;
|
|
650
|
+
return verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, this.redeemScript, new BN(this.output.satoshis.toString()), undefined, signingMethod);
|
|
651
|
+
}
|
|
652
|
+
normalizeSignatures(transaction, input, inputIndex, signatures, publicKeys, signingMethod) {
|
|
653
|
+
return [];
|
|
654
|
+
}
|
|
655
|
+
_estimateSize() {
|
|
656
|
+
return (MultisigScriptHashInput.OPCODES_SIZE +
|
|
657
|
+
this.threshold * MultisigScriptHashInput.SIGNATURE_SIZE +
|
|
658
|
+
this.publicKeys.length * MultisigScriptHashInput.PUBKEY_SIZE);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
export class PublicKeyInput extends Input {
|
|
662
|
+
static SCRIPT_MAX_SIZE = 73;
|
|
663
|
+
getSignatures(transaction, privateKey, index, sigtype, hashData, signingMethod) {
|
|
664
|
+
Preconditions.checkState(this.output instanceof Output, 'Output is required');
|
|
665
|
+
sigtype = sigtype || Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID;
|
|
666
|
+
const publicKey = privateKey.publicKey;
|
|
667
|
+
if (publicKey.toString() ===
|
|
668
|
+
this.output.script.getPublicKey().toString('hex')) {
|
|
669
|
+
return [
|
|
670
|
+
new TransactionSignature({
|
|
671
|
+
publicKey: publicKey,
|
|
672
|
+
prevTxId: this.prevTxId,
|
|
673
|
+
outputIndex: this.outputIndex,
|
|
674
|
+
inputIndex: index,
|
|
675
|
+
signature: sign(transaction, privateKey, sigtype, index, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod),
|
|
676
|
+
sigtype: sigtype,
|
|
677
|
+
}),
|
|
678
|
+
];
|
|
679
|
+
}
|
|
680
|
+
return [];
|
|
681
|
+
}
|
|
682
|
+
addSignature(transaction, signature, signingMethod) {
|
|
683
|
+
Preconditions.checkState(this.isValidSignature(transaction, signature, signingMethod), 'Signature is invalid');
|
|
684
|
+
const script = new Script();
|
|
685
|
+
script.add(signature.signature.toTxFormat(signingMethod));
|
|
686
|
+
this.setScript(script);
|
|
687
|
+
return this;
|
|
688
|
+
}
|
|
689
|
+
clearSignatures() {
|
|
690
|
+
this.setScript(new Script());
|
|
691
|
+
return this;
|
|
692
|
+
}
|
|
693
|
+
isFullySigned() {
|
|
694
|
+
return this.script.isPublicKeyIn();
|
|
695
|
+
}
|
|
696
|
+
_estimateSize() {
|
|
697
|
+
return PublicKeyInput.SCRIPT_MAX_SIZE;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
export class PublicKeyHashInput extends Input {
|
|
701
|
+
static SCRIPT_MAX_SIZE = 73 + 34;
|
|
702
|
+
getSignatures(transaction, privateKey, index, sigtype, hashData, signingMethod) {
|
|
703
|
+
Preconditions.checkState(this.output instanceof Output, 'Output is required');
|
|
704
|
+
hashData = hashData || Hash.sha256ripemd160(privateKey.publicKey.toBuffer());
|
|
705
|
+
sigtype = sigtype || Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID;
|
|
706
|
+
if (BufferUtil.equals(hashData, this.output.script.getPublicKeyHash())) {
|
|
707
|
+
return [
|
|
708
|
+
new TransactionSignature({
|
|
709
|
+
publicKey: privateKey.publicKey,
|
|
710
|
+
prevTxId: this.prevTxId,
|
|
711
|
+
outputIndex: this.outputIndex,
|
|
712
|
+
inputIndex: index,
|
|
713
|
+
signature: sign(transaction, privateKey, sigtype, index, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod),
|
|
714
|
+
sigtype: sigtype,
|
|
715
|
+
}),
|
|
716
|
+
];
|
|
717
|
+
}
|
|
718
|
+
return [];
|
|
719
|
+
}
|
|
720
|
+
addSignature(transaction, signature, signingMethod) {
|
|
721
|
+
Preconditions.checkState(this.isValidSignature(transaction, signature, signingMethod), 'Signature is invalid');
|
|
722
|
+
const script = new Script();
|
|
723
|
+
script.add(signature.signature.toTxFormat(signingMethod));
|
|
724
|
+
script.add(signature.publicKey.toBuffer());
|
|
725
|
+
this.setScript(script);
|
|
726
|
+
return this;
|
|
727
|
+
}
|
|
728
|
+
clearSignatures() {
|
|
729
|
+
this.setScript(new Script());
|
|
730
|
+
return this;
|
|
731
|
+
}
|
|
732
|
+
isFullySigned() {
|
|
733
|
+
return this.script.isPublicKeyHashIn();
|
|
734
|
+
}
|
|
735
|
+
_estimateSize() {
|
|
736
|
+
return PublicKeyHashInput.SCRIPT_MAX_SIZE;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
export class TaprootInput extends Input {
|
|
740
|
+
internalPubKey;
|
|
741
|
+
merkleRoot;
|
|
742
|
+
controlBlock;
|
|
743
|
+
tapScript;
|
|
744
|
+
constructor(params) {
|
|
745
|
+
super(params);
|
|
746
|
+
if (params) {
|
|
747
|
+
this.internalPubKey = params.internalPubKey;
|
|
748
|
+
this.merkleRoot = params.merkleRoot;
|
|
749
|
+
this.controlBlock = params.controlBlock;
|
|
750
|
+
this.tapScript = params.tapScript;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
getSignatures(transaction, privateKey, index, sigtype, hashData, signingMethod) {
|
|
754
|
+
sigtype = sigtype || TAPROOT_SIGHASH_TYPE;
|
|
755
|
+
signingMethod = signingMethod || 'schnorr';
|
|
756
|
+
Preconditions.checkState(this.output instanceof Output, 'Output is required');
|
|
757
|
+
Preconditions.checkState(this.output.script.isPayToTaproot(), 'Output must be Pay-To-Taproot');
|
|
758
|
+
sigtype ||= TAPROOT_SIGHASH_TYPE;
|
|
759
|
+
if ((sigtype & 0x60) !== Signature.SIGHASH_LOTUS) {
|
|
760
|
+
throw new Error('Taproot key spend signatures must use "SIGHASH_ALL | SIGHASH_LOTUS" (0x61)');
|
|
761
|
+
}
|
|
762
|
+
signingMethod ||= 'schnorr';
|
|
763
|
+
if (signingMethod !== 'schnorr') {
|
|
764
|
+
throw new Error('Taproot key spend signature must be Schnorr');
|
|
765
|
+
}
|
|
766
|
+
const merkleRoot = this.merkleRoot || Buffer.alloc(32);
|
|
767
|
+
const tweakedPrivateKey = tweakPrivateKey(privateKey, merkleRoot);
|
|
768
|
+
const signature = sign(transaction, tweakedPrivateKey, sigtype, index, this.output.script, new BN(this.output.satoshis.toString()), undefined, signingMethod);
|
|
769
|
+
return [
|
|
770
|
+
new TransactionSignature({
|
|
771
|
+
publicKey: tweakedPrivateKey.publicKey,
|
|
772
|
+
prevTxId: this.prevTxId,
|
|
773
|
+
outputIndex: this.outputIndex,
|
|
774
|
+
inputIndex: index,
|
|
775
|
+
signature: signature,
|
|
776
|
+
sigtype: sigtype,
|
|
777
|
+
}),
|
|
778
|
+
];
|
|
779
|
+
}
|
|
780
|
+
addSignature(transaction, signature, signingMethod) {
|
|
781
|
+
Preconditions.checkState(this.isValidSignature(transaction, signature, signingMethod), 'Signature is invalid');
|
|
782
|
+
const script = new Script();
|
|
783
|
+
if (!signature.signature.nhashtype && signature.sigtype) {
|
|
784
|
+
signature.signature.nhashtype = signature.sigtype;
|
|
785
|
+
}
|
|
786
|
+
script.add(signature.signature.toTxFormat('schnorr'));
|
|
787
|
+
this.setScript(script);
|
|
788
|
+
return this;
|
|
789
|
+
}
|
|
790
|
+
isValidSignature(transaction, signature, signingMethod) {
|
|
791
|
+
Preconditions.checkState(this.output instanceof Output, 'Output is required');
|
|
792
|
+
signingMethod = signingMethod || 'schnorr';
|
|
793
|
+
if (signingMethod !== 'schnorr') {
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
return transaction.verifySignature(signature.signature, signature.publicKey, signature.inputIndex, this.output.script, new BN(this.output.satoshis), undefined, signingMethod);
|
|
797
|
+
}
|
|
798
|
+
clearSignatures() {
|
|
799
|
+
this.setScript(new Script());
|
|
800
|
+
return this;
|
|
801
|
+
}
|
|
802
|
+
isFullySigned() {
|
|
803
|
+
return this.script !== null && this.script.chunks.length > 0;
|
|
804
|
+
}
|
|
805
|
+
_estimateSize() {
|
|
806
|
+
return 66;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
export class MuSigTaprootInput extends TaprootInput {
|
|
810
|
+
keyAggContext;
|
|
811
|
+
publicNonces;
|
|
812
|
+
aggregatedNonce;
|
|
813
|
+
partialSignatures;
|
|
814
|
+
mySignerIndex;
|
|
815
|
+
constructor(params) {
|
|
816
|
+
super(params);
|
|
817
|
+
if (params) {
|
|
818
|
+
this.keyAggContext = params.keyAggContext;
|
|
819
|
+
this.mySignerIndex = params.mySignerIndex;
|
|
820
|
+
this.publicNonces = new Map();
|
|
821
|
+
this.partialSignatures = new Map();
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
initMuSigSession(keyAggContext, mySignerIndex) {
|
|
825
|
+
this.keyAggContext = keyAggContext;
|
|
826
|
+
this.mySignerIndex = mySignerIndex;
|
|
827
|
+
this.publicNonces = new Map();
|
|
828
|
+
this.partialSignatures = new Map();
|
|
829
|
+
return this;
|
|
830
|
+
}
|
|
831
|
+
addPublicNonce(signerIndex, publicNonce) {
|
|
832
|
+
if (!this.publicNonces) {
|
|
833
|
+
this.publicNonces = new Map();
|
|
834
|
+
}
|
|
835
|
+
this.publicNonces.set(signerIndex, publicNonce);
|
|
836
|
+
return this;
|
|
837
|
+
}
|
|
838
|
+
hasAllNonces() {
|
|
839
|
+
if (!this.keyAggContext || !this.publicNonces) {
|
|
840
|
+
return false;
|
|
841
|
+
}
|
|
842
|
+
const numSigners = this.keyAggContext.pubkeys.length;
|
|
843
|
+
return this.publicNonces.size === numSigners;
|
|
844
|
+
}
|
|
845
|
+
aggregateNonces() {
|
|
846
|
+
if (!this.hasAllNonces()) {
|
|
847
|
+
throw new Error('Not all public nonces received');
|
|
848
|
+
}
|
|
849
|
+
const noncesArray = [];
|
|
850
|
+
for (let i = 0; i < this.keyAggContext.pubkeys.length; i++) {
|
|
851
|
+
const nonce = this.publicNonces.get(i);
|
|
852
|
+
if (!nonce) {
|
|
853
|
+
throw new Error(`Missing nonce for signer ${i}`);
|
|
854
|
+
}
|
|
855
|
+
noncesArray.push(nonce);
|
|
856
|
+
}
|
|
857
|
+
this.aggregatedNonce = musigNonceAgg(noncesArray);
|
|
858
|
+
return this;
|
|
859
|
+
}
|
|
860
|
+
addPartialSignature(signerIndex, partialSig) {
|
|
861
|
+
if (!this.partialSignatures) {
|
|
862
|
+
this.partialSignatures = new Map();
|
|
863
|
+
}
|
|
864
|
+
this.partialSignatures.set(signerIndex, partialSig);
|
|
865
|
+
return this;
|
|
866
|
+
}
|
|
867
|
+
hasAllPartialSignatures() {
|
|
868
|
+
if (!this.keyAggContext || !this.partialSignatures) {
|
|
869
|
+
return false;
|
|
870
|
+
}
|
|
871
|
+
const numSigners = this.keyAggContext.pubkeys.length;
|
|
872
|
+
return this.partialSignatures.size === numSigners;
|
|
873
|
+
}
|
|
874
|
+
finalizeMuSigSignature(transaction, message) {
|
|
875
|
+
if (!this.hasAllPartialSignatures()) {
|
|
876
|
+
throw new Error('Not all partial signatures received');
|
|
877
|
+
}
|
|
878
|
+
if (!this.aggregatedNonce) {
|
|
879
|
+
throw new Error('Nonces must be aggregated first');
|
|
880
|
+
}
|
|
881
|
+
const commitment = extractTaprootCommitment(this.output.script);
|
|
882
|
+
const partialSigsArray = [];
|
|
883
|
+
for (let i = 0; i < this.keyAggContext.pubkeys.length; i++) {
|
|
884
|
+
const partialSig = this.partialSignatures.get(i);
|
|
885
|
+
if (!partialSig) {
|
|
886
|
+
throw new Error(`Missing partial signature for signer ${i}`);
|
|
887
|
+
}
|
|
888
|
+
partialSigsArray.push(partialSig);
|
|
889
|
+
}
|
|
890
|
+
const finalSignature = musigSigAgg(partialSigsArray, this.aggregatedNonce, message, commitment);
|
|
891
|
+
const script = new Script();
|
|
892
|
+
script.add(finalSignature.toTxFormat('schnorr'));
|
|
893
|
+
this.setScript(script);
|
|
894
|
+
return this;
|
|
895
|
+
}
|
|
896
|
+
isFullySigned() {
|
|
897
|
+
return (super.isFullySigned() ||
|
|
898
|
+
(this.hasAllPartialSignatures() &&
|
|
899
|
+
this.script !== null &&
|
|
900
|
+
this.script.chunks.length > 0));
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
Input.PublicKey = PublicKeyInput;
|
|
904
|
+
Input.PublicKeyHash = PublicKeyHashInput;
|
|
905
|
+
Input.Multisig = MultisigInput;
|
|
906
|
+
Input.MultisigScriptHash = MultisigScriptHashInput;
|
|
907
|
+
Input.Taproot = TaprootInput;
|
|
908
|
+
Input.MuSigTaproot = MuSigTaprootInput;
|
|
909
|
+
Input.P2PKH = PublicKeyHashInput;
|
|
910
|
+
Input.P2SH = MultisigScriptHashInput;
|
|
911
|
+
Input.P2TR = TaprootInput;
|