forked from ecto/bitcore
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Sign.js
133 lines (110 loc) · 3.76 KB
/
Sign.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
function signOne(hash, addrStr, keys)
{
var keyObj = keys[addrStr];
var rawPrivKey = new Buffer(keyObj.priv, 'hex');
var key = new KeyModule.Key();
key.private = rawPrivKey;
var signature = key.signSync(hash);
return signature;
}
function signTxIn(nIn, tx, txInputs, network, keys, scripts)
{
// locate TX input needing a signature
var txin = tx.ins[nIn];
var scriptSig = txin.getScript();
// locate TX output, within txInputs
var txoutHash = txin.getOutpointHash();
if (!(txoutHash in txInputs))
throw new Error("signTxIn missing input hash");
var txFrom = txInputs[txoutHash];
var txoutIndex = txin.getOutpointIndex();
if (txFrom.outs.length >= txoutIndex)
throw new Error("signTxIn missing input index");
var txout = txFrom.outs[txoutIndex];
var scriptPubKey = txout.getScript();
// detect type of transaction, and extract useful elements
var txType = scriptPubKey.classify();
if (txType == TX_UNKNOWN)
throw new Error("unknown TX type");
var scriptData = scriptPubKey.capture();
// if P2SH, lookup the script
var subscriptRaw = undefined;
var subscript = undefined;
var subType = undefined;
var subData = undefined;
if (txType == TX_SCRIPTHASH) {
var addr = new Address(network.addressScript, scriptData[0]);
var addrStr = addr.toString();
if (!(addrStr in scripts))
throw new Error("unknown script hash address");
subscriptRaw = new Buffer(scripts[addrStr], 'hex');
subscript = new Script(subscriptRaw);
subType = subscript.classify();
if (subType == TX_UNKNOWN)
throw new Error("unknown subscript TX type");
subData = subscript.capture();
}
var hash = tx.hashForSignature(scriptPubKey, i, 0);
switch (txType) {
case TX_PUBKEY:
// already signed
if (scriptSig.chunks.length > 0)
return;
var pubkeyhash = util.sha256ripe160(scriptData[0]);
var addr = new Address(network.addressPubkey, pubkeyhash);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown pubkey");
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
break;
case TX_PUBKEYHASH:
// already signed
if (scriptSig.chunks.length > 0)
return;
var addr = new Address(network.addressPubkey, scriptData[0]);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown pubkey hash address");
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
scriptSig.writeBytes(key.public);
break;
case TX_SCRIPTHASH:
// already signed
if (scriptSig.chunks.length > 0)
return;
var addr = new Address(network.addressPubkey, subData[0]);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown script(pubkey hash) address");
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
scriptSig.writeBytes(key.public);
break;
case TX_MULTISIG:
while (scriptSig.chunks.length < scriptData.length) {
scriptSig.writeBytes(util.EMPTY_BUFFER);
}
for (var i = 0; i < scriptData.length; i++) {
// skip already signed
if (scriptSig.chunks[i].length > 0)
continue;
var pubkeyhash = util.sha256ripe160(scriptSig.chunks[i]);
var addr = new Address(network.addressPubkey, pubkeyhash);
var addrStr = addr.toString();
if (!(addrStr in keys))
continue;
var signature = signOne(hash, addrStr, keys);
scriptSig.chunks[i] = signature;
}
break;
}
if (txtype == TX_SCRIPTHASH)
scriptSig.writeBytes(subscriptRaw);
}
exports.Transaction = function Transaction(tx, txInputs, network, keys, scripts)
{
for (var i = 0; i < tx.ins.length; i++)
signTxIn(i, tx, txInputs, network, keys, scripts);
};