bitcore-lib-zcash/lib/Sign.js

129 lines
3.9 KiB
JavaScript

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.P2SHVersion, 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.addressVersion, 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.addressVersion, 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.addressVersion, 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.addressVersion, 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);
};