From 0ff2022c6df68fb861c94d54eb0bdd42d0377a15 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Wed, 10 Feb 2016 20:06:05 -0600 Subject: [PATCH] Implementing OP_CHECKMULTISIG for base case of 0 signatures required --- .../script/crypto/CryptoInterpreter.scala | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/main/scala/org/scalacoin/script/crypto/CryptoInterpreter.scala b/src/main/scala/org/scalacoin/script/crypto/CryptoInterpreter.scala index 2d123f0719..69bacceba7 100644 --- a/src/main/scala/org/scalacoin/script/crypto/CryptoInterpreter.scala +++ b/src/main/scala/org/scalacoin/script/crypto/CryptoInterpreter.scala @@ -3,7 +3,7 @@ package org.scalacoin.script.crypto import org.scalacoin.protocol.script.ScriptPubKey import org.scalacoin.protocol.transaction.Transaction import org.scalacoin.script.{ScriptProgramFactory, ScriptProgramImpl, ScriptProgram} -import org.scalacoin.script.constant.{ScriptOperation, ScriptConstantImpl, ScriptConstant, ScriptToken} +import org.scalacoin.script.constant._ import org.scalacoin.util.{CryptoUtil, ScalacoinUtil} @@ -130,6 +130,12 @@ trait CryptoInterpreter extends ScalacoinUtil { ScriptProgramFactory.factory(program, hash :: program.stack.tail, program.script.tail) } + /** + * All of the signature checking words will only match signatures to the data + * after the most recently-executed OP_CODESEPARATOR. + * @param program + * @return + */ def opCodeSeparator(program : ScriptProgram) : ScriptProgram = { require(program.script.headOption.isDefined && program.script.head == OP_CODESEPARATOR, "Script top must be OP_CODESEPARATOR") @@ -138,6 +144,38 @@ trait CryptoInterpreter extends ScalacoinUtil { ScriptProgramFactory.factory(program,program.script.tail, ScriptProgramFactory.Script, codeSeparatorIndex) } + + /** + * Compares the first signature against each public key until it finds an ECDSA match. + * Starting with the subsequent public key, it compares the second signature against each remaining + * public key until it finds an ECDSA match. The process is repeated until all signatures have been + * checked or not enough public keys remain to produce a successful result. + * All signatures need to match a public key. + * Because public keys are not checked again if they fail any signature comparison, + * signatures must be placed in the scriptSig using the same order as their corresponding public keys + * were placed in the scriptPubKey or redeemScript. If all signatures are valid, 1 is returned, 0 otherwise. + * Due to a bug, one extra unused value is removed from the stack. + * @param program + * @return + */ + def opCheckMultiSig(program : ScriptProgram) : ScriptProgram = { + + val signatures = program.transaction.inputs.head.scriptSignature + + //head should be n for m/n + val n : Int = program.stack.head match { + case s : ScriptNumber => s.num.toInt + } + + val m : Int = program.stack(n.toInt+1) match { + case s : ScriptNumber => s.num.toInt + } + + if (m == 0) ScriptProgramFactory.factory(program, program.stack.slice(m + n + 3, + program.stack.size), program.script.tail,true) + else program + } + private def hashForSignature(inputScript : Seq[ScriptToken], spendingTx : Transaction, inputIndex : Int, hashType : HashType) : String = { require(inputIndex < spendingTx.inputs.size, "Given input index is out of range of the inputs in the spending tx")