Stephen Pair
11 years ago
8 changed files with 233 additions and 22 deletions
@ -0,0 +1,133 @@ |
|||||
|
|
||||
|
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); |
||||
|
}; |
||||
|
|
@ -0,0 +1,7 @@ |
|||||
|
[ |
||||
|
[ "0", "0" ], |
||||
|
[ "1.0", "100000000" ], |
||||
|
[ "0.1", "10000000" ], |
||||
|
[ ".1", "10000000" ], |
||||
|
[ "0.0005", "50000" ] |
||||
|
] |
Loading…
Reference in new issue