Beispiel #1
0
        public string CreatPrimitiveTx(List <Input> lstInput, double dValue, string strPay2Hash, ref Transaction PrimitiveTx)
        {
            LogHelper.WriteMethodLog(true);


            double inputValue = 0;

            foreach (var item in lstInput)
            {
                UTXO   utxo       = new UTXO(item.PreTxHash, (uint)item.OutputIndex);
                Output tempoutput = this.CommitedUtxoPool.getTxOutput(utxo);
                inputValue += tempoutput.value;
            }
            if (inputValue != dValue)
            {
                LogHelper.WriteErrorLog(string.Format("Input Utxo's value not equal with output value, inputV:{0}, outputV:{1}", inputValue, dValue));
                return("Input Utxo's value not equal with output value");
            }

            PrimitiveTx.listInputs = lstInput;
            string Pay2Script = string.Format("OP_DUP OP_HASH160 {0} OP_EQUALVERIFY OP_CHECKSIG", strPay2Hash);
            Output output     = new Output(dValue, Pay2Script);

            PrimitiveTx.addOutput(output);

            LogHelper.WriteInfoLog("MultiSign TX: " + JsonHelper.Serializer <Transaction>(PrimitiveTx));
            LogHelper.WriteMethodLog(false);
            return(ConstHelper.BC_OK);
        }
Beispiel #2
0
        //
        // @return the transaction output corresponding to UTXO {@code utxo}, or null if {@code utxo} is
        //         not in the pool.

        public Output getTxOutput(UTXO ut)
        {
            Output optemp = new Output();

            if (dicUtxoPool.TryGetValue(ut, out optemp))
            {
                return(optemp);
            }

            return(null);
        }
Beispiel #3
0
 public void AddBaseCoin2UTxoPool(Transaction basetx)
 {
     try
     {
         UTXO utxo = new UTXO(basetx.getHash(), 0);
         CommitedUtxoPool.addUTXO(utxo, basetx.getOutput((int)0));
     }
     catch (Exception ex)
     {
         LogHelper.WriteErrorLog(ex.Message);
     }
 }
Beispiel #4
0
 public void removeInput(UTXO ut)
 {
     for (int i = 0; i < listInputs.Count(); i++)
     {
         Input inEnty = listInputs[i];
         UTXO  u      = new UTXO(inEnty.PreTxHash, (uint)inEnty.OutputIndex);
         if (u.Equals(ut))
         {
             listInputs.RemoveAt(i);
             return;
         }
     }
 }
Beispiel #5
0
        /// <summary>
        /// 根据block信息更新UTXO pool,同时返回该block生成的utxo list,用来提示该block收到了多少钱
        /// </summary>
        /// <param name="block"></param>
        /// <returns>just for update key corresponding value</returns>
        public UTXOPool BlockData2UTXOPool(bool bCommitedPool, Block block)
        {
            LogHelper.WriteMethodLog(true);
            LogHelper.WriteInfoLog("bCommitedPool: " + bCommitedPool.ToString());
            UTXOPool utxopoll = new UTXOPool();

            if (bCommitedPool)
            {
                utxopoll = this.CommitedUtxoPool;
            }
            else
            {
                utxopoll = this.UnCommitedUtxoPool;
            }



            UTXOPool sigleBlockPool = new UTXOPool();

            foreach (Transaction eTransaction in block.listTransactions)
            {
                foreach (Input eInput in eTransaction.listInputs)
                {
                    UTXO utxo = this.input2UTXO(eInput);
                    if (utxopoll.contains(utxo))
                    {
                        utxopoll.removeUTXO(utxo);
                    }
                    else
                    {
                        // 初始化时由于leveldb 树形结构第一个可能创世块,所以先记下来在后面再remove
                        if (utxo.getTxHash() != ConstHelper.BC_BaseCoinInputTxHash)
                        {
                            tempUTXOList.Add(utxo);
                        }
                    }
                }

                for (int i = 0; i < eTransaction.listOutputs.Count; i++)
                {
                    // hash is transaction hash
                    UTXO utxo1 = new UTXO(eTransaction.getHash(), (uint)i);

                    utxopoll.addUTXO(utxo1, eTransaction.listOutputs[i]);
                    sigleBlockPool.addUTXO(utxo1, eTransaction.listOutputs[i]);
                }
            }
            LogHelper.WriteMethodLog(false);
            return(sigleBlockPool);
        }
Beispiel #6
0
        /**
         * Handles each epoch by receiving an unordered array of proposed transactions, checking each
         * transaction for correctness, returning a mutually valid array of accepted transactions, and
         * updating the current UTXO pool as appropriate.
         */
        public Transaction[] handleTxs(List <Transaction> possibleTxs)
        {
            // IMPLEMENT THIS
            HashSet <Transaction> txVis = new HashSet <Transaction>();

            //fixed point algorithm,iter untill no new transaction is valid
            while (true)
            {
                bool updated = false;
                foreach (Transaction tx in possibleTxs)
                {
                    if (txVis.Contains(tx))
                    {
                        continue;
                    }
                    if (isValidTx(tx))
                    {
                        txVis.Add(tx);
                        updated = true;
                        //add unspent coin
                        for (uint i = 0; i < tx.numOutputs(); ++i)
                        {
                            UTXO utxo = new UTXO(tx.getHash(), i);
                            CommitedUtxoPool.addUTXO(utxo, tx.getOutput((int)i));
                        }
                        //delete spent coin
                        for (int i = 0; i < tx.numInputs(); ++i)
                        {
                            Input input = tx.getInput(i);
                            UTXO  utxo  = new UTXO(input.PreTxHash, (uint)input.OutputIndex);
                            CommitedUtxoPool.removeUTXO(utxo);
                        }
                    }
                }
                if (!updated)
                {
                    break;
                }
            }
            ;
            Transaction[] ret = new Transaction[txVis.Count()];
            int           idx = 0;

            foreach (Transaction tx in txVis)
            {
                ret[idx++] = tx;
            }
            return(ret);
        }
Beispiel #7
0
 // Adds a mapping from UTXO {@code utxo} to transaction output @code{txOut} to the pool
 public void addUTXO(UTXO utxo, Output txOut)
 {
     try
     {
         if (!dicUtxoPool.ContainsKey(utxo))
         {
             dicUtxoPool.Add(utxo, txOut);
         }
     }
     catch (Exception ex)
     {
         string str = JsonHelper.Serializer <UTXO>(utxo);
         LogHelper.WriteErrorLog(str);
         LogHelper.WriteErrorLog(ex.Message);
     }
 }
Beispiel #8
0
        //Compares this UTXO to the one specified by {@code other}, considering them equal if they have
        // {@code txHash} arrays with equal contents and equal {@code index} values
        public override bool Equals(Object other)
        {
            if (other == null)
            {
                return(false);
            }
            UTXO otherUtxo = (UTXO)other;

            // 直接对比hash是否一致
            if (this.utoxHashCode() != otherUtxo.utoxHashCode())
            {
                return(false);
            }
            else
            {
                return(true);
            }
        }
Beispiel #9
0
        public Transaction CreatTransaction(string strPreHash, uint iIndex, double dValue,
                                            string strPaytoPKHash, string myPriKeyPath, string myPubkeyPath)
        {
            LogHelper.WriteMethodLog(true);

            string strPubKeyValuem = FileIOHelper.ReadFromText(myPubkeyPath);
            string strKeyHash      = Cryptor.SHA256(strPubKeyValuem, strPubKeyValuem.Length);
            string myPubScript     = string.Format("OP_DUP OP_HASH160 {0} OP_EQUALVERIFY OP_CHECKSIG", strKeyHash);


            UTXO utxo = new UTXO(strPreHash, iIndex);

            if (!this.CommitedUtxoPool.contains(utxo))
            {
                LogHelper.WriteErrorLog("not in utxo");
                return(null);
            }

            Transaction spendTrans = new Transaction();

            spendTrans.addInput(strPreHash, (int)iIndex);
            spendTrans.addOutput(dValue, strPaytoPKHash);

            Output preOutput = this.CommitedUtxoPool.getTxOutput(utxo);

            if (dValue < preOutput.value)
            {
                Output ctOutput = new Output();
                ctOutput.value        = preOutput.value - dValue;
                ctOutput.scriptPubKey = myPubScript;
                spendTrans.addOutput(ctOutput);
            }
            spendTrans.signTrans(myPriKeyPath, strPubKeyValuem);
            spendTrans.FinalSetTrans();

            LogHelper.WriteInfoLog("CreatTransaction: " + spendTrans.TxHash);
            return(spendTrans);
        }
Beispiel #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="signedPrimitiveTx"></param>
        /// <returns>0:succ, -1:not multiSign, -2:sign not enough -3: signature more than M </returns>
        public int CheckMultiSignCount(Transaction signedPrimitiveTx, ref string errorMsg)
        {
            int i = 0;

            foreach (var item in signedPrimitiveTx.listInputs)
            {
                UTXO   utxo1     = new UTXO(item.PreTxHash, (uint)item.OutputIndex);
                Output output1   = this.CommitedUtxoPool.getTxOutput(utxo1);
                var    lstScript = output1.scriptPubKey.Split(' ').ToList <string>();
                if (lstScript.Last() != "OP_CHECKMULTISIG")
                {
                    LogHelper.WriteErrorLog("input isn't MultiSign Tx ");
                    errorMsg = "one of inputs isn't MultiSign Tx";
                    return(-1);
                }
                string OP_N = lstScript.First();
                string OP_M = lstScript[lstScript.Count - 2];
                int    N    = int.Parse(OP_N.Substring(3));
                int    M    = int.Parse(OP_M.Substring(3));
                if (item.lstScriptSig.Count < N)
                {
                    LogHelper.WriteErrorLog(string.Format("input[{0}] signature count not meet mini request", i));
                    errorMsg = string.Format("input:[{0}]\r\n is a {1}/{2} Tx.\r\nThe number of signatures({3}) did not meet the minimum requirements",
                                             item.PreTxHash, N, M, item.lstScriptSig.Count);
                    return(-2);
                }
                else if (item.lstScriptSig.Count > M)
                {
                    LogHelper.WriteErrorLog(string.Format("input[{0}] signature more than M", i));
                    errorMsg = "The number of signatures more than M";
                    return(-3);
                }
                i++;
            }

            return(0);
        }
Beispiel #11
0
 public string  handleTxs(Transaction tx)
 {
     try
     {
         string sRet = ConstHelper.BC_OK;
         if (isValidTx(tx))
         {
             //add unspent coin
             for (uint i = 0; i < tx.numOutputs(); ++i)
             {
                 UTXO utxo = new UTXO(tx.getHash(), i);
                 UnCommitedUtxoPool.addUTXO(utxo, tx.getOutput((int)i));
                 LogHelper.WriteInfoLog(string.Format("Add utxo to uncommited pool, utxoHash:{0}", utxo.utoxHashCode()));
             }
             //delete spent coin
             for (int i = 0; i < tx.numInputs(); ++i)
             {
                 Input input = tx.getInput(i);
                 UTXO  utxo  = new UTXO(input.PreTxHash, (uint)input.OutputIndex);
                 CommitedUtxoPool.removeUTXO(utxo);
                 LogHelper.WriteInfoLog(string.Format("Remove utxo from commited pool, utxoHash:{0}", utxo.utoxHashCode()));
             }
         }
         else
         {
             sRet = "invalid transaction";
         }
         LogHelper.WriteInfoLog("handleTxs result:" + sRet);
         return(sRet);
     }
     catch (Exception ex)
     {
         LogHelper.WriteErrorLog(ex.Message);
         return("HandleTxs catch an exception ");
     }
 }
Beispiel #12
0
        //暂时不用
        public bool SignPrimitiveTx(Dictionary <UTXO, keyPair> dicUTXO, ref Transaction PrimitiveTx)
        {
            int iInputCount = PrimitiveTx.listInputs.Count;

            for (int i = 0; i < iInputCount; i++)
            {
                if (PrimitiveTx.listInputs[i].ScriptSig == null)
                {
                    UTXO utxo = new UTXO(PrimitiveTx.listInputs[i].PreTxHash, (uint)PrimitiveTx.listInputs[i].OutputIndex);
                    if (dicUTXO.ContainsKey(utxo))
                    {
                        keyPair kp = new keyPair();
                        dicUTXO.TryGetValue(utxo, out kp);
                        string strPriKPath = Path.Combine(AppSettings.XXPKeysFolder, kp.PriKeyNmae);
                        string strPubKPath = Path.Combine(AppSettings.XXPKeysFolder, kp.PubKeyNmae);
                        string strPubValue = FileIOHelper.ReadFromText(strPubKPath);

                        PrimitiveTx.signTrans(strPriKPath, strPubValue, i);
                    }
                }
            }

            return(true);
        }
Beispiel #13
0
 // @return true if UTXO {@code utxo} is in the pool and false otherwise
 public bool contains(UTXO utxo)
 {
     return(dicUtxoPool.ContainsKey(utxo));
 }
Beispiel #14
0
        public string SignPrimitiveTx(Dictionary <string, keyPair> KeyHashKeypair, ref Transaction PrimitiveTx)
        {
            LogHelper.WriteMethodLog(true);
            bool bHaveSigned = true;

            foreach (var item in PrimitiveTx.listInputs)
            {
                // 只要input有一个没有签名list,就认为没有签名
                if (item.lstScriptSig == null)
                {
                    bHaveSigned = false;
                    break;
                }
                else
                {   // 有签名list后 判断自己是否已经签名,
                    bHaveSigned = false;
                    foreach (var item1 in item.lstScriptSig)
                    {
                        string strKeyHash = Cryptor.SHA256(item1.PubKey, item1.PubKey.Length);
                        if (KeyHashKeypair.ContainsKey(strKeyHash))
                        {
                            bHaveSigned = true;
                        }
                    }
                }
            }
            if (bHaveSigned)
            {
                return("Current Primitive Tx'inputs Have signed");
            }

            int iInputCount = PrimitiveTx.listInputs.Count;

            for (int i = 0; i < iInputCount; i++)
            {
                UTXO utxo = new UTXO(PrimitiveTx.listInputs[i].PreTxHash, (uint)PrimitiveTx.listInputs[i].OutputIndex);

                if (!CommitedUtxoPool.contains(utxo))
                {
                    LogHelper.WriteInfoLog(" utxoPool not contain utxo:");
                    return("Invalid utxo"); //check (1),utox 包含该交易返回false
                }
                Output        output    = CommitedUtxoPool.getTxOutput(utxo);
                List <string> lstScript = output.scriptPubKey.Split(' ').ToList <string>();

                var lstPKHash = (from x in lstScript
                                 where x.Substring(0, 3) != "OP_"
                                 select x).ToList();


                foreach (var item in lstPKHash)
                {
                    if (KeyHashKeypair.ContainsKey(item))
                    {
                        keyPair kp = new keyPair();
                        KeyHashKeypair.TryGetValue(item, out kp);
                        string strPriKPath = Path.Combine(AppSettings.XXPKeysFolder, kp.PriKeyNmae);
                        string strPubKPath = Path.Combine(AppSettings.XXPKeysFolder, kp.PubKeyNmae);
                        string strPubValue = FileIOHelper.ReadFromText(strPubKPath);
                        PrimitiveTx.MultiSignTrans(strPriKPath, strPubValue, i);
                    }
                }
            }
            LogHelper.WriteMethodLog(false);
            return(ConstHelper.BC_OK);
        }
Beispiel #15
0
        /**
         * @return true if:
         * (1) all outputs claimed by {@code tx} are in the current UTXO pool,
         * (2) the signatures on each input of {@code tx} are valid,
         * (3) no UTXO is claimed multiple times by {@code tx},
         * (4) all of {@code tx}s output values are non-negative, and
         * (5) the sum of {@code tx}s input values is greater than or equal to the sum of its output
         *     values; and false otherwise.
         */
        public bool isValidTx(Transaction tx)
        {
            LogHelper.WriteMethodLog(true);
            if (tx.listInputs.Count == 0 || tx.listOutputs.Count == 0)
            {
                LogHelper.WriteInfoLog("empty input|output");
                return(false);
            }

            // IMPLEMENT THIS
            double sumOut = 0;
            double sumIn  = 0;

            Dictionary <string, UTXO> dicUsed = new Dictionary <string, UTXO>();

            for (int i = 0; i < tx.numInputs(); i++)
            {
                Input input = tx.getInput(i);

                UTXO utxo = new UTXO(input.PreTxHash, (uint)input.OutputIndex);
                if (!CommitedUtxoPool.contains(utxo))
                {
                    LogHelper.WriteInfoLog(" utxoPool not contain utxo:");
                    return(false); //check (1),utox 包含该交易返回false
                }

                Output PreOutput = CommitedUtxoPool.getTxOutput(utxo); // the consume coin correspond prev output coin;
                sumIn += PreOutput.value;                              //(5) 计算input 指向的pre output 的value,最后保证输入的value等于该笔交易输出的
                string strOriginalTxt = tx.getRawDataToSign(i);
                if (!Cryptor.VerifySignature(input.ScriptSig, PreOutput.scriptPubKey, strOriginalTxt))
                {
                    LogHelper.WriteInfoLog(" VerifySignature fail");
                    return(false);//check(2)
                }


                bool bIsContain = dicUsed.ContainsKey(utxo.utoxHashCode());
                if (!bIsContain) // UTXO不会被重复添加
                {
                    dicUsed.Add(utxo.utoxHashCode(), utxo);
                }
                else
                {
                    LogHelper.WriteInfoLog(" double spend :" + utxo.utoxHashCode());
                    return(false);
                }
            }
            foreach (Output output in tx.getOutputs())
            {
                if (output.value < 0)
                {
                    LogHelper.WriteInfoLog(" output.value < 0 ");
                    return(false);//check(5)
                }
                sumOut += output.value;
            }
            if (sumIn < sumOut)
            {
                LogHelper.WriteInfoLog(" sumIn < sumOut ");
                return(false);//check(5);
            }
            LogHelper.WriteInfoLog("Valid Tx");
            return(true);
        }
Beispiel #16
0
        public UTXO input2UTXO(Input einput)
        {
            UTXO utxo = new UTXO(einput.PreTxHash, (uint)einput.OutputIndex);

            return(utxo);
        }
Beispiel #17
0
 // Removes the UTXO {@code utxo} from the pool
 public void removeUTXO(UTXO utxo)
 {
     dicUtxoPool.Remove(utxo);
 }